125991f7dSEd Tanous #include "filter_expr_executor.hpp"
225991f7dSEd Tanous #include "filter_expr_parser_ast.hpp"
325991f7dSEd Tanous #include "filter_expr_printer.hpp"
425991f7dSEd Tanous 
525991f7dSEd Tanous #include <optional>
625991f7dSEd Tanous #include <string_view>
725991f7dSEd Tanous 
825991f7dSEd Tanous #include "gmock/gmock.h"
925991f7dSEd Tanous 
1025991f7dSEd Tanous namespace redfish
1125991f7dSEd Tanous {
1225991f7dSEd Tanous 
filterTrue(std::string_view filterExpr,nlohmann::json json)1325991f7dSEd Tanous static void filterTrue(std::string_view filterExpr, nlohmann::json json)
1425991f7dSEd Tanous {
1525991f7dSEd Tanous     std::optional<filter_ast::LogicalAnd> ast = parseFilter(filterExpr);
1625991f7dSEd Tanous     EXPECT_TRUE(ast);
1725991f7dSEd Tanous     if (!ast)
1825991f7dSEd Tanous     {
1925991f7dSEd Tanous         return;
2025991f7dSEd Tanous     }
2125991f7dSEd Tanous     EXPECT_EQ(json["Members"].size(), 1);
2225991f7dSEd Tanous     EXPECT_TRUE(applyFilter(json, *ast));
2325991f7dSEd Tanous     EXPECT_EQ(json["Members"].size(), 1);
2425991f7dSEd Tanous }
2525991f7dSEd Tanous 
filterFalse(std::string_view filterExpr,nlohmann::json json)2625991f7dSEd Tanous static void filterFalse(std::string_view filterExpr, nlohmann::json json)
2725991f7dSEd Tanous {
2825991f7dSEd Tanous     std::optional<filter_ast::LogicalAnd> ast = parseFilter(filterExpr);
2925991f7dSEd Tanous     EXPECT_TRUE(ast);
3025991f7dSEd Tanous     if (!ast)
3125991f7dSEd Tanous     {
3225991f7dSEd Tanous         return;
3325991f7dSEd Tanous     }
3425991f7dSEd Tanous     EXPECT_EQ(json["Members"].size(), 1);
3525991f7dSEd Tanous     EXPECT_TRUE(applyFilter(json, *ast));
3625991f7dSEd Tanous     EXPECT_EQ(json["Members"].size(), 0);
3725991f7dSEd Tanous }
3825991f7dSEd Tanous 
TEST(FilterParser,Integers)3925991f7dSEd Tanous TEST(FilterParser, Integers)
4025991f7dSEd Tanous {
4125991f7dSEd Tanous     const nlohmann::json members = R"({"Members": [{"Count": 2}]})"_json;
4225991f7dSEd Tanous     // Forward true conditions
4325991f7dSEd Tanous     filterTrue("Count eq 2", members);
4425991f7dSEd Tanous     filterTrue("Count ne 3", members);
4525991f7dSEd Tanous     filterTrue("Count gt 1", members);
4625991f7dSEd Tanous     filterTrue("Count ge 2", members);
4725991f7dSEd Tanous     filterTrue("Count lt 3", members);
4825991f7dSEd Tanous     filterTrue("Count le 2", members);
4925991f7dSEd Tanous 
5025991f7dSEd Tanous     // Reverse true conditions
5125991f7dSEd Tanous     filterTrue("2 eq Count", members);
5225991f7dSEd Tanous     filterTrue("3 ne Count", members);
5325991f7dSEd Tanous     filterTrue("3 gt Count", members);
5425991f7dSEd Tanous     filterTrue("2 ge Count", members);
5525991f7dSEd Tanous     filterTrue("1 lt Count", members);
5625991f7dSEd Tanous     filterTrue("2 le Count", members);
5725991f7dSEd Tanous 
5825991f7dSEd Tanous     // Forward false conditions
5925991f7dSEd Tanous     filterFalse("Count eq 3", members);
6025991f7dSEd Tanous     filterFalse("Count ne 2", members);
6125991f7dSEd Tanous     filterFalse("Count gt 2", members);
6225991f7dSEd Tanous     filterFalse("Count ge 3", members);
6325991f7dSEd Tanous     filterFalse("Count lt 2", members);
6425991f7dSEd Tanous     filterFalse("Count le 1", members);
6525991f7dSEd Tanous 
6625991f7dSEd Tanous     // Reverse false conditions
6725991f7dSEd Tanous     filterFalse("3 eq Count", members);
6825991f7dSEd Tanous     filterFalse("2 ne Count", members);
6925991f7dSEd Tanous     filterFalse("2 gt Count", members);
7025991f7dSEd Tanous     filterFalse("1 ge Count", members);
7125991f7dSEd Tanous     filterFalse("2 lt Count", members);
7225991f7dSEd Tanous     filterFalse("3 le Count", members);
7325991f7dSEd Tanous }
7425991f7dSEd Tanous 
TEST(FilterParser,FloatingPointToInteger)7525991f7dSEd Tanous TEST(FilterParser, FloatingPointToInteger)
7625991f7dSEd Tanous {
7725991f7dSEd Tanous     const nlohmann::json members = R"({"Members": [{"Count": 2.0}]})"_json;
7825991f7dSEd Tanous     // Forward true conditions
7925991f7dSEd Tanous     filterTrue("Count eq 2", members);
8025991f7dSEd Tanous     filterTrue("Count ne 3", members);
8125991f7dSEd Tanous     filterTrue("Count gt 1", members);
8225991f7dSEd Tanous     filterTrue("Count ge 2", members);
8325991f7dSEd Tanous     filterTrue("Count lt 3", members);
8425991f7dSEd Tanous     filterTrue("Count le 2", members);
8525991f7dSEd Tanous 
8625991f7dSEd Tanous     // Reverse true conditions
8725991f7dSEd Tanous     filterTrue("2 eq Count", members);
8825991f7dSEd Tanous     filterTrue("3 ne Count", members);
8925991f7dSEd Tanous     filterTrue("3 gt Count", members);
9025991f7dSEd Tanous     filterTrue("2 ge Count", members);
9125991f7dSEd Tanous     filterTrue("1 lt Count", members);
9225991f7dSEd Tanous     filterTrue("2 le Count", members);
9325991f7dSEd Tanous 
9425991f7dSEd Tanous     // Forward false conditions
9525991f7dSEd Tanous     filterFalse("Count eq 3", members);
9625991f7dSEd Tanous     filterFalse("Count ne 2", members);
9725991f7dSEd Tanous     filterFalse("Count gt 2", members);
9825991f7dSEd Tanous     filterFalse("Count ge 3", members);
9925991f7dSEd Tanous     filterFalse("Count lt 2", members);
10025991f7dSEd Tanous     filterFalse("Count le 1", members);
10125991f7dSEd Tanous 
10225991f7dSEd Tanous     // Reverse false conditions
10325991f7dSEd Tanous     filterFalse("3 eq Count", members);
10425991f7dSEd Tanous     filterFalse("2 ne Count", members);
10525991f7dSEd Tanous     filterFalse("2 gt Count", members);
10625991f7dSEd Tanous     filterFalse("1 ge Count", members);
10725991f7dSEd Tanous     filterFalse("2 lt Count", members);
10825991f7dSEd Tanous     filterFalse("3 le Count", members);
10925991f7dSEd Tanous }
11025991f7dSEd Tanous 
TEST(FilterParser,FloatingPointToFloatingPoint)11125991f7dSEd Tanous TEST(FilterParser, FloatingPointToFloatingPoint)
11225991f7dSEd Tanous {
11325991f7dSEd Tanous     const nlohmann::json members = R"({"Members": [{"Count": 2.0}]})"_json;
11425991f7dSEd Tanous     // Forward true conditions
11525991f7dSEd Tanous     filterTrue("Count eq 2.0", members);
11625991f7dSEd Tanous     filterTrue("Count ne 3.0", members);
11725991f7dSEd Tanous     filterTrue("Count gt 1.0", members);
11825991f7dSEd Tanous     filterTrue("Count ge 2.0", members);
11925991f7dSEd Tanous     filterTrue("Count lt 3.0", members);
12025991f7dSEd Tanous     filterTrue("Count le 2.0", members);
12125991f7dSEd Tanous 
12225991f7dSEd Tanous     // Reverse true conditions
12325991f7dSEd Tanous     filterTrue("2.0 eq Count", members);
12425991f7dSEd Tanous     filterTrue("3.0 ne Count", members);
12525991f7dSEd Tanous     filterTrue("3.0 gt Count", members);
12625991f7dSEd Tanous     filterTrue("2.0 ge Count", members);
12725991f7dSEd Tanous     filterTrue("1.0 lt Count", members);
12825991f7dSEd Tanous     filterTrue("2.0 le Count", members);
12925991f7dSEd Tanous 
13025991f7dSEd Tanous     // Forward false conditions
13125991f7dSEd Tanous     filterFalse("Count eq 3.0", members);
13225991f7dSEd Tanous     filterFalse("Count ne 2.0", members);
13325991f7dSEd Tanous     filterFalse("Count gt 2.0", members);
13425991f7dSEd Tanous     filterFalse("Count ge 3.0", members);
13525991f7dSEd Tanous     filterFalse("Count lt 2.0", members);
13625991f7dSEd Tanous     filterFalse("Count le 1.0", members);
13725991f7dSEd Tanous 
13825991f7dSEd Tanous     // Reverse false conditions
13925991f7dSEd Tanous     filterFalse("3.0 eq Count", members);
14025991f7dSEd Tanous     filterFalse("2.0 ne Count", members);
14125991f7dSEd Tanous     filterFalse("2.0 gt Count", members);
14225991f7dSEd Tanous     filterFalse("1.0 ge Count", members);
14325991f7dSEd Tanous     filterFalse("2.0 lt Count", members);
14425991f7dSEd Tanous     filterFalse("3.0 le Count", members);
14525991f7dSEd Tanous }
14625991f7dSEd Tanous 
TEST(FilterParser,String)14725991f7dSEd Tanous TEST(FilterParser, String)
14825991f7dSEd Tanous {
14925991f7dSEd Tanous     const nlohmann::json members =
150*1cf82313SEd Tanous         R"({"Members": [{"SerialNumber": "1234"}]})"_json;
15125991f7dSEd Tanous     // Forward true conditions
152*1cf82313SEd Tanous     filterTrue("SerialNumber eq '1234'", members);
15325991f7dSEd Tanous     filterTrue("SerialNumber ne 'NotFoo'", members);
154*1cf82313SEd Tanous     filterTrue("SerialNumber gt '1233'", members);
155*1cf82313SEd Tanous     filterTrue("SerialNumber ge '1234'", members);
156*1cf82313SEd Tanous     filterTrue("SerialNumber lt '1235'", members);
157*1cf82313SEd Tanous     filterTrue("SerialNumber le '1234'", members);
15825991f7dSEd Tanous 
15925991f7dSEd Tanous     // Reverse true conditions
160*1cf82313SEd Tanous     filterTrue("'1234' eq SerialNumber", members);
16125991f7dSEd Tanous     filterTrue("'NotFoo' ne SerialNumber", members);
162*1cf82313SEd Tanous     filterTrue("'1235' gt SerialNumber", members);
163*1cf82313SEd Tanous     filterTrue("'1234' ge SerialNumber", members);
164*1cf82313SEd Tanous     filterTrue("'1233' lt SerialNumber", members);
165*1cf82313SEd Tanous     filterTrue("'1234' le SerialNumber", members);
16625991f7dSEd Tanous 
16725991f7dSEd Tanous     // Forward false conditions
16825991f7dSEd Tanous     filterFalse("SerialNumber eq 'NotFoo'", members);
169*1cf82313SEd Tanous     filterFalse("SerialNumber ne '1234'", members);
170*1cf82313SEd Tanous     filterFalse("SerialNumber gt '1234'", members);
171*1cf82313SEd Tanous     filterFalse("SerialNumber ge '1235'", members);
172*1cf82313SEd Tanous     filterFalse("SerialNumber lt '1234'", members);
173*1cf82313SEd Tanous     filterFalse("SerialNumber le '1233'", members);
17425991f7dSEd Tanous 
17525991f7dSEd Tanous     // Reverse false conditions
17625991f7dSEd Tanous     filterFalse("'NotFoo' eq SerialNumber", members);
177*1cf82313SEd Tanous     filterFalse("'1234' ne SerialNumber", members);
178*1cf82313SEd Tanous     filterFalse("'1234' gt SerialNumber", members);
179*1cf82313SEd Tanous     filterFalse("'1233' ge SerialNumber", members);
180*1cf82313SEd Tanous     filterFalse("'1234' lt SerialNumber", members);
181*1cf82313SEd Tanous     filterFalse("'1235' le SerialNumber", members);
182*1cf82313SEd Tanous }
183*1cf82313SEd Tanous 
TEST(FilterParser,StringHuman)184*1cf82313SEd Tanous TEST(FilterParser, StringHuman)
185*1cf82313SEd Tanous {
186*1cf82313SEd Tanous     // Ensure that we're sorting based on human facing numbers, not
187*1cf82313SEd Tanous     // lexicographic comparison
188*1cf82313SEd Tanous 
189*1cf82313SEd Tanous     const nlohmann::json members = R"({"Members": [{}]})"_json;
190*1cf82313SEd Tanous     // Forward true conditions
191*1cf82313SEd Tanous     filterFalse("'20' eq '3'", members);
192*1cf82313SEd Tanous     filterTrue("'20' ne '3'", members);
193*1cf82313SEd Tanous     filterTrue("'20' gt '3'", members);
194*1cf82313SEd Tanous     filterTrue("'20' ge '3'", members);
195*1cf82313SEd Tanous     filterFalse("'20' lt '3'", members);
196*1cf82313SEd Tanous     filterFalse("'20' le '3'", members);
197*1cf82313SEd Tanous }
198*1cf82313SEd Tanous 
TEST(FilterParser,StringSemver)199*1cf82313SEd Tanous TEST(FilterParser, StringSemver)
200*1cf82313SEd Tanous {
201*1cf82313SEd Tanous     const nlohmann::json members =
202*1cf82313SEd Tanous         R"({"Members": [{"Version": "20.0.2"}]})"_json;
203*1cf82313SEd Tanous     // Forward true conditions
204*1cf82313SEd Tanous     filterTrue("Version eq '20.0.2'", members);
205*1cf82313SEd Tanous     filterTrue("Version ne '20.2.0'", members);
206*1cf82313SEd Tanous     filterTrue("Version gt '20.0.1'", members);
207*1cf82313SEd Tanous     filterTrue("Version gt '1.9.9'", members);
208*1cf82313SEd Tanous     filterTrue("Version gt '10.9.9'", members);
209*1cf82313SEd Tanous }
210*1cf82313SEd Tanous 
TEST(FilterParser,Dates)211*1cf82313SEd Tanous TEST(FilterParser, Dates)
212*1cf82313SEd Tanous {
213*1cf82313SEd Tanous     const nlohmann::json members =
214*1cf82313SEd Tanous         R"({"Members": [{"Created": "2021-11-30T22:41:35.123+00:00"}]})"_json;
215*1cf82313SEd Tanous 
216*1cf82313SEd Tanous     // Note, all comparisons below differ by a single millisecond
217*1cf82313SEd Tanous     // Forward true conditions
218*1cf82313SEd Tanous     filterTrue("Created eq '2021-11-30T22:41:35.123+00:00'", members);
219*1cf82313SEd Tanous     filterTrue("Created ne '2021-11-30T22:41:35.122+00:00'", members);
220*1cf82313SEd Tanous     filterTrue("Created gt '2021-11-30T22:41:35.122+00:00'", members);
221*1cf82313SEd Tanous     filterTrue("Created ge '2021-11-30T22:41:35.123+00:00'", members);
222*1cf82313SEd Tanous     filterTrue("Created lt '2021-11-30T22:41:35.124+00:00'", members);
223*1cf82313SEd Tanous     filterTrue("Created le '2021-11-30T22:41:35.123+00:00'", members);
224*1cf82313SEd Tanous 
225*1cf82313SEd Tanous     // Reverse true conditions
226*1cf82313SEd Tanous     filterTrue("'2021-11-30T22:41:35.123+00:00' eq Created", members);
227*1cf82313SEd Tanous     filterTrue("'2021-11-30T22:41:35.122+00:00' ne Created", members);
228*1cf82313SEd Tanous     filterTrue("'2021-11-30T22:41:35.124+00:00' gt Created", members);
229*1cf82313SEd Tanous     filterTrue("'2021-11-30T22:41:35.123+00:00' ge Created", members);
230*1cf82313SEd Tanous     filterTrue("'2021-11-30T22:41:35.122+00:00' lt Created", members);
231*1cf82313SEd Tanous     filterTrue("'2021-11-30T22:41:35.123+00:00' le Created", members);
232*1cf82313SEd Tanous 
233*1cf82313SEd Tanous     // Forward false conditions
234*1cf82313SEd Tanous     filterFalse("Created eq '2021-11-30T22:41:35.122+00:00'", members);
235*1cf82313SEd Tanous     filterFalse("Created ne '2021-11-30T22:41:35.123+00:00'", members);
236*1cf82313SEd Tanous     filterFalse("Created gt '2021-11-30T22:41:35.123+00:00'", members);
237*1cf82313SEd Tanous     filterFalse("Created ge '2021-11-30T22:41:35.124+00:00'", members);
238*1cf82313SEd Tanous     filterFalse("Created lt '2021-11-30T22:41:35.123+00:00'", members);
239*1cf82313SEd Tanous     filterFalse("Created le '2021-11-30T22:41:35.122+00:00'", members);
240*1cf82313SEd Tanous 
241*1cf82313SEd Tanous     // Reverse false conditions
242*1cf82313SEd Tanous     filterFalse("'2021-11-30T22:41:35.122+00:00' eq Created", members);
243*1cf82313SEd Tanous     filterFalse("'2021-11-30T22:41:35.123+00:00' ne Created", members);
244*1cf82313SEd Tanous     filterFalse("'2021-11-30T22:41:35.123+00:00' gt Created", members);
245*1cf82313SEd Tanous     filterFalse("'2021-11-30T22:41:35.122+00:00' ge Created", members);
246*1cf82313SEd Tanous     filterFalse("'2021-11-30T22:41:35.123+00:00' lt Created", members);
247*1cf82313SEd Tanous     filterFalse("'2021-11-30T22:41:35.124+00:00' le Created", members);
24825991f7dSEd Tanous }
24925991f7dSEd Tanous 
25025991f7dSEd Tanous } // namespace redfish
251