1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
#include "FilterParser.h"
#include "3rd-party/catch.hpp"
TEST_CASE(
"FilterParser doesn't crash parsing expression with invalid character "
"in operator",
"[FilterParser]")
{
FilterParser fp;
REQUIRE_FALSE(fp.parse_string("title =¯ \"foo\""));
}
TEST_CASE("FilterParser raises errors on invalid queries", "[FilterParser]")
{
FilterParser fp;
SECTION("incorrect string quoting") {
REQUIRE_FALSE(fp.parse_string("a = \"b"));
}
SECTION("non-value to the right of equality check operator") {
REQUIRE_FALSE(fp.parse_string("a = b"));
}
SECTION("unbalanced parentheses") {
REQUIRE_FALSE(fp.parse_string("((a=\"b\")))"));
}
SECTION("non-existent operator") {
REQUIRE_FALSE(fp.parse_string("a !! \"b\""));
}
SECTION("incorrect syntax for range") {
REQUIRE_FALSE(fp.parse_string("AAAA between 0:15:30"));
}
SECTION("no whitespace after the `and` operator") {
REQUIRE_FALSE(fp.parse_string("x = 42andy=0"));
REQUIRE_FALSE(fp.parse_string("x = 42 andy=0"));
}
SECTION("operator without arguments") {
REQUIRE_FALSE(fp.parse_string("=!"));
}
}
TEST_CASE("FilterParser doesn't raise errors on valid queries",
"[FilterParser]")
{
FilterParser fp;
SECTION("test parser") {
REQUIRE(fp.parse_string("a = \"b\""));
REQUIRE(fp.parse_string("(a=\"b\")"));
REQUIRE(fp.parse_string("((a=\"b\"))"));
}
SECTION("test operators") {
REQUIRE(fp.parse_string("a != \"b\""));
REQUIRE(fp.parse_string("a =~ \"b\""));
REQUIRE(fp.parse_string("a !~ \"b\""));
}
SECTION("Parse string of complex query") {
REQUIRE(fp.parse_string(
"( a = \"b\") and ( b = \"c\" ) or ( ( c != \"d\" ) "
"and ( c !~ \"asdf\" )) or c != \"xx\""));
}
}
TEST_CASE("Both = and == are accepted", "[FilterParser]")
{
FilterParser fp;
REQUIRE(fp.parse_string("a = \"abc\""));
REQUIRE(fp.parse_string("a == \"abc\""));
}
TEST_CASE("FilterParser disallows NUL byte inside filter expressions",
"[FilterParser]")
{
FilterParser fp;
REQUIRE_FALSE(fp.parse_string(std::string("attri\0bute = 0", 14)));
REQUIRE_FALSE(fp.parse_string(std::string("attribute\0= 0", 13)));
REQUIRE_FALSE(fp.parse_string(std::string("attribute = \0", 13)));
REQUIRE_FALSE(fp.parse_string(std::string("attribute = \\\"\0\\\"", 17)));
// The following shouldn't pass, but it does. Further REQUIREs explain why:
// the NUL byte silently terminates parsing.
REQUIRE(fp.parse_string(std::string("attribute = \"hello\0world\"", 25)));
REQUIRE(fp.get_root()->op == MATCHOP_EQ);
REQUIRE(fp.get_root()->name == "attribute");
REQUIRE(fp.get_root()->literal == "\"hello");
}
TEST_CASE("FilterParser parses empty string literals", "[FilterParser]")
{
FilterParser fp;
REQUIRE(fp.parse_string("title==\"\""));
REQUIRE(fp.get_root()->op == MATCHOP_EQ);
REQUIRE(fp.get_root()->name == "title");
REQUIRE(fp.get_root()->literal == "");
}
TEST_CASE("Logical operators require space or paren after them",
"[FilterParser]")
{
FilterParser fp;
const auto verify_tree = [&fp](int op) {
REQUIRE(fp.get_root()->op == op);
REQUIRE(fp.get_root()->l->op == MATCHOP_EQ);
REQUIRE(fp.get_root()->l->name == "a");
REQUIRE(fp.get_root()->l->literal == "42");
REQUIRE(fp.get_root()->r->op == MATCHOP_EQ);
REQUIRE(fp.get_root()->r->name == "y");
REQUIRE(fp.get_root()->r->literal == "0");
};
SECTION("`and`") {
REQUIRE_FALSE(fp.parse_string("a=42andy=0"));
REQUIRE_FALSE(fp.parse_string("(a=42)andy=0"));
REQUIRE_FALSE(fp.parse_string("a=42 andy=0"));
REQUIRE(fp.parse_string("a=42and(y=0)"));
verify_tree(LOGOP_AND);
REQUIRE(fp.parse_string("(a=42)and(y=0)"));
verify_tree(LOGOP_AND);
REQUIRE(fp.parse_string("a=42and y=0"));
verify_tree(LOGOP_AND);
}
SECTION("`or`") {
REQUIRE_FALSE(fp.parse_string("a=42ory=0"));
REQUIRE_FALSE(fp.parse_string("(a=42)ory=0"));
REQUIRE_FALSE(fp.parse_string("a=42 ory=0"));
REQUIRE(fp.parse_string("a=42or(y=0)"));
verify_tree(LOGOP_OR);
REQUIRE(fp.parse_string("(a=42)or(y=0)"));
verify_tree(LOGOP_OR);
REQUIRE(fp.parse_string("a=42or y=0"));
verify_tree(LOGOP_OR);
}
}
|