1 #include "filter_expr_executor.hpp"
2 #include "filter_expr_parser_ast.hpp"
3 #include "filter_expr_printer.hpp"
4
5 #include <optional>
6 #include <string_view>
7
8 #include "gmock/gmock.h"
9
10 namespace redfish
11 {
12
filterTrue(std::string_view filterExpr,nlohmann::json json)13 static void filterTrue(std::string_view filterExpr, nlohmann::json json)
14 {
15 std::optional<filter_ast::LogicalAnd> ast = parseFilter(filterExpr);
16 EXPECT_TRUE(ast);
17 if (!ast)
18 {
19 return;
20 }
21 EXPECT_EQ(json["Members"].size(), 1);
22 EXPECT_TRUE(applyFilter(json, *ast));
23 EXPECT_EQ(json["Members"].size(), 1);
24 }
25
filterFalse(std::string_view filterExpr,nlohmann::json json)26 static void filterFalse(std::string_view filterExpr, nlohmann::json json)
27 {
28 std::optional<filter_ast::LogicalAnd> ast = parseFilter(filterExpr);
29 EXPECT_TRUE(ast);
30 if (!ast)
31 {
32 return;
33 }
34 EXPECT_EQ(json["Members"].size(), 1);
35 EXPECT_TRUE(applyFilter(json, *ast));
36 EXPECT_EQ(json["Members"].size(), 0);
37 }
38
TEST(FilterParser,Integers)39 TEST(FilterParser, Integers)
40 {
41 const nlohmann::json members = R"({"Members": [{"Count": 2}]})"_json;
42 // Forward true conditions
43 filterTrue("Count eq 2", members);
44 filterTrue("Count ne 3", members);
45 filterTrue("Count gt 1", members);
46 filterTrue("Count ge 2", members);
47 filterTrue("Count lt 3", members);
48 filterTrue("Count le 2", members);
49
50 // Reverse true conditions
51 filterTrue("2 eq Count", members);
52 filterTrue("3 ne Count", members);
53 filterTrue("3 gt Count", members);
54 filterTrue("2 ge Count", members);
55 filterTrue("1 lt Count", members);
56 filterTrue("2 le Count", members);
57
58 // Forward false conditions
59 filterFalse("Count eq 3", members);
60 filterFalse("Count ne 2", members);
61 filterFalse("Count gt 2", members);
62 filterFalse("Count ge 3", members);
63 filterFalse("Count lt 2", members);
64 filterFalse("Count le 1", members);
65
66 // Reverse false conditions
67 filterFalse("3 eq Count", members);
68 filterFalse("2 ne Count", members);
69 filterFalse("2 gt Count", members);
70 filterFalse("1 ge Count", members);
71 filterFalse("2 lt Count", members);
72 filterFalse("3 le Count", members);
73 }
74
TEST(FilterParser,FloatingPointToInteger)75 TEST(FilterParser, FloatingPointToInteger)
76 {
77 const nlohmann::json members = R"({"Members": [{"Count": 2.0}]})"_json;
78 // Forward true conditions
79 filterTrue("Count eq 2", members);
80 filterTrue("Count ne 3", members);
81 filterTrue("Count gt 1", members);
82 filterTrue("Count ge 2", members);
83 filterTrue("Count lt 3", members);
84 filterTrue("Count le 2", members);
85
86 // Reverse true conditions
87 filterTrue("2 eq Count", members);
88 filterTrue("3 ne Count", members);
89 filterTrue("3 gt Count", members);
90 filterTrue("2 ge Count", members);
91 filterTrue("1 lt Count", members);
92 filterTrue("2 le Count", members);
93
94 // Forward false conditions
95 filterFalse("Count eq 3", members);
96 filterFalse("Count ne 2", members);
97 filterFalse("Count gt 2", members);
98 filterFalse("Count ge 3", members);
99 filterFalse("Count lt 2", members);
100 filterFalse("Count le 1", members);
101
102 // Reverse false conditions
103 filterFalse("3 eq Count", members);
104 filterFalse("2 ne Count", members);
105 filterFalse("2 gt Count", members);
106 filterFalse("1 ge Count", members);
107 filterFalse("2 lt Count", members);
108 filterFalse("3 le Count", members);
109 }
110
TEST(FilterParser,FloatingPointToFloatingPoint)111 TEST(FilterParser, FloatingPointToFloatingPoint)
112 {
113 const nlohmann::json members = R"({"Members": [{"Count": 2.0}]})"_json;
114 // Forward true conditions
115 filterTrue("Count eq 2.0", members);
116 filterTrue("Count ne 3.0", members);
117 filterTrue("Count gt 1.0", members);
118 filterTrue("Count ge 2.0", members);
119 filterTrue("Count lt 3.0", members);
120 filterTrue("Count le 2.0", members);
121
122 // Reverse true conditions
123 filterTrue("2.0 eq Count", members);
124 filterTrue("3.0 ne Count", members);
125 filterTrue("3.0 gt Count", members);
126 filterTrue("2.0 ge Count", members);
127 filterTrue("1.0 lt Count", members);
128 filterTrue("2.0 le Count", members);
129
130 // Forward false conditions
131 filterFalse("Count eq 3.0", members);
132 filterFalse("Count ne 2.0", members);
133 filterFalse("Count gt 2.0", members);
134 filterFalse("Count ge 3.0", members);
135 filterFalse("Count lt 2.0", members);
136 filterFalse("Count le 1.0", members);
137
138 // Reverse false conditions
139 filterFalse("3.0 eq Count", members);
140 filterFalse("2.0 ne Count", members);
141 filterFalse("2.0 gt Count", members);
142 filterFalse("1.0 ge Count", members);
143 filterFalse("2.0 lt Count", members);
144 filterFalse("3.0 le Count", members);
145 }
146
TEST(FilterParser,String)147 TEST(FilterParser, String)
148 {
149 const nlohmann::json members =
150 R"({"Members": [{"SerialNumber": "1234"}]})"_json;
151 // Forward true conditions
152 filterTrue("SerialNumber eq '1234'", members);
153 filterTrue("SerialNumber ne 'NotFoo'", members);
154 filterTrue("SerialNumber gt '1233'", members);
155 filterTrue("SerialNumber ge '1234'", members);
156 filterTrue("SerialNumber lt '1235'", members);
157 filterTrue("SerialNumber le '1234'", members);
158
159 // Reverse true conditions
160 filterTrue("'1234' eq SerialNumber", members);
161 filterTrue("'NotFoo' ne SerialNumber", members);
162 filterTrue("'1235' gt SerialNumber", members);
163 filterTrue("'1234' ge SerialNumber", members);
164 filterTrue("'1233' lt SerialNumber", members);
165 filterTrue("'1234' le SerialNumber", members);
166
167 // Forward false conditions
168 filterFalse("SerialNumber eq 'NotFoo'", members);
169 filterFalse("SerialNumber ne '1234'", members);
170 filterFalse("SerialNumber gt '1234'", members);
171 filterFalse("SerialNumber ge '1235'", members);
172 filterFalse("SerialNumber lt '1234'", members);
173 filterFalse("SerialNumber le '1233'", members);
174
175 // Reverse false conditions
176 filterFalse("'NotFoo' eq SerialNumber", members);
177 filterFalse("'1234' ne SerialNumber", members);
178 filterFalse("'1234' gt SerialNumber", members);
179 filterFalse("'1233' ge SerialNumber", members);
180 filterFalse("'1234' lt SerialNumber", members);
181 filterFalse("'1235' le SerialNumber", members);
182 }
183
TEST(FilterParser,StringHuman)184 TEST(FilterParser, StringHuman)
185 {
186 // Ensure that we're sorting based on human facing numbers, not
187 // lexicographic comparison
188
189 const nlohmann::json members = R"({"Members": [{}]})"_json;
190 // Forward true conditions
191 filterFalse("'20' eq '3'", members);
192 filterTrue("'20' ne '3'", members);
193 filterTrue("'20' gt '3'", members);
194 filterTrue("'20' ge '3'", members);
195 filterFalse("'20' lt '3'", members);
196 filterFalse("'20' le '3'", members);
197 }
198
TEST(FilterParser,StringSemver)199 TEST(FilterParser, StringSemver)
200 {
201 const nlohmann::json members =
202 R"({"Members": [{"Version": "20.0.2"}]})"_json;
203 // Forward true conditions
204 filterTrue("Version eq '20.0.2'", members);
205 filterTrue("Version ne '20.2.0'", members);
206 filterTrue("Version gt '20.0.1'", members);
207 filterTrue("Version gt '1.9.9'", members);
208 filterTrue("Version gt '10.9.9'", members);
209 }
210
TEST(FilterParser,Dates)211 TEST(FilterParser, Dates)
212 {
213 const nlohmann::json members =
214 R"({"Members": [{"Created": "2021-11-30T22:41:35.123+00:00"}]})"_json;
215
216 // Note, all comparisons below differ by a single millisecond
217 // Forward true conditions
218 filterTrue("Created eq '2021-11-30T22:41:35.123+00:00'", members);
219 filterTrue("Created ne '2021-11-30T22:41:35.122+00:00'", members);
220 filterTrue("Created gt '2021-11-30T22:41:35.122+00:00'", members);
221 filterTrue("Created ge '2021-11-30T22:41:35.123+00:00'", members);
222 filterTrue("Created lt '2021-11-30T22:41:35.124+00:00'", members);
223 filterTrue("Created le '2021-11-30T22:41:35.123+00:00'", members);
224
225 // Reverse true conditions
226 filterTrue("'2021-11-30T22:41:35.123+00:00' eq Created", members);
227 filterTrue("'2021-11-30T22:41:35.122+00:00' ne Created", members);
228 filterTrue("'2021-11-30T22:41:35.124+00:00' gt Created", members);
229 filterTrue("'2021-11-30T22:41:35.123+00:00' ge Created", members);
230 filterTrue("'2021-11-30T22:41:35.122+00:00' lt Created", members);
231 filterTrue("'2021-11-30T22:41:35.123+00:00' le Created", members);
232
233 // Forward false conditions
234 filterFalse("Created eq '2021-11-30T22:41:35.122+00:00'", members);
235 filterFalse("Created ne '2021-11-30T22:41:35.123+00:00'", members);
236 filterFalse("Created gt '2021-11-30T22:41:35.123+00:00'", members);
237 filterFalse("Created ge '2021-11-30T22:41:35.124+00:00'", members);
238 filterFalse("Created lt '2021-11-30T22:41:35.123+00:00'", members);
239 filterFalse("Created le '2021-11-30T22:41:35.122+00:00'", members);
240
241 // Reverse false conditions
242 filterFalse("'2021-11-30T22:41:35.122+00:00' eq Created", members);
243 filterFalse("'2021-11-30T22:41:35.123+00:00' ne Created", members);
244 filterFalse("'2021-11-30T22:41:35.123+00:00' gt Created", members);
245 filterFalse("'2021-11-30T22:41:35.122+00:00' ge Created", members);
246 filterFalse("'2021-11-30T22:41:35.123+00:00' lt Created", members);
247 filterFalse("'2021-11-30T22:41:35.124+00:00' le Created", members);
248 }
249
250 } // namespace redfish
251