1 #include "filter_expr_parser_ast.hpp"
2 #include "filter_expr_printer.hpp"
3 
4 #include <optional>
5 #include <string_view>
6 
7 #include "gmock/gmock.h"
8 
9 namespace redfish
10 {
11 
parse(std::string_view filterExpression,std::string_view outputAst)12 static void parse(std::string_view filterExpression, std::string_view outputAst)
13 {
14     std::optional<filter_ast::LogicalAnd> ast = parseFilter(filterExpression);
15     FilterExpressionPrinter pr;
16     EXPECT_TRUE(ast);
17     if (ast)
18     {
19         EXPECT_EQ(pr(*ast), outputAst);
20     }
21 }
22 
TEST(FilterParser,SpecificationExamples)23 TEST(FilterParser, SpecificationExamples)
24 {
25     parse("ProcessorSummary/Count eq 2",
26           "unquoted_string(\"ProcessorSummary/Count\") Equals int(2)");
27     parse(
28         "ProcessorSummary/Count ge 2",
29         "unquoted_string(\"ProcessorSummary/Count\") Greater Than Or Equal int(2)");
30     parse("ProcessorSummary/Count gt 2",
31           "unquoted_string(\"ProcessorSummary/Count\") Greater Than int(2)");
32     parse(
33         "MemorySummary/TotalSystemMemoryGiB le 64",
34         "unquoted_string(\"MemorySummary/TotalSystemMemoryGiB\") Less Than Or Equal int(64)");
35     parse(
36         "MemorySummary/TotalSystemMemoryGiB lt 64",
37         "unquoted_string(\"MemorySummary/TotalSystemMemoryGiB\") Less Than int(64)");
38     parse(
39         "SystemType ne 'Physical'",
40         R"(unquoted_string("SystemType") Not Equal quoted_string("Physical"))");
41     parse(
42         "ProcessorSummary/Count eq 2 or ProcessorSummary/Count eq 4",
43         R"((unquoted_string("ProcessorSummary/Count") Equals int(2)) or (unquoted_string("ProcessorSummary/Count") Equals int(4)))");
44     parse("not ProcessorSummary/Count eq 2",
45           "not(unquoted_string(\"ProcessorSummary/Count\") Equals int(2))");
46     parse("not ProcessorSummary/Count eq -2",
47           "not(unquoted_string(\"ProcessorSummary/Count\") Equals int(-2))");
48     parse("Status/State eq 'Enabled')",
49           R"(unquoted_string("Status/State") Equals quoted_string("Enabled"))");
50     parse(
51         "ProcessorSummary/Count eq 2 and MemorySummary/TotalSystemMemoryGiB eq 64",
52         R"((unquoted_string("ProcessorSummary/Count") Equals int(2)) and (unquoted_string("MemorySummary/TotalSystemMemoryGiB") Equals int(64)))");
53     parse(
54         "Status/State eq 'Enabled' and Status/Health eq 'OK' or SystemType eq 'Physical'",
55         R"((unquoted_string("Status/State") Equals quoted_string("Enabled")) and ((unquoted_string("Status/Health") Equals quoted_string("OK")) or (unquoted_string("SystemType") Equals quoted_string("Physical"))))");
56     parse(
57         "(Status/State eq 'Enabled' and Status/Health eq 'OK') or SystemType eq 'Physical'",
58         R"(((unquoted_string("Status/State") Equals quoted_string("Enabled")) and (unquoted_string("Status/Health") Equals quoted_string("OK"))) or (unquoted_string("SystemType") Equals quoted_string("Physical")))");
59 }
60 
TEST(FilterParser,BasicOperations)61 TEST(FilterParser, BasicOperations)
62 {
63     // Negation
64     EXPECT_TRUE(parseFilter("not(ProcessorSummary/Count eq 2)"));
65 
66     // Negative numbers
67     EXPECT_TRUE(parseFilter("not(ProcessorSummary/Count eq -2)"));
68 
69     // Empty strings
70     EXPECT_TRUE(parseFilter("(foo eq '')"));
71 
72     // Identity
73     EXPECT_TRUE(parseFilter("1 eq 1"));
74     EXPECT_TRUE(parseFilter("'foo' eq 'foo'"));
75 
76     // Inverted params
77     EXPECT_TRUE(parseFilter("2 eq ProcessorSummary/Count"));
78     EXPECT_TRUE(parseFilter("'OK' eq Status/Health"));
79 
80     // Floating point
81     EXPECT_TRUE(parseFilter("Reading eq 4.0"));
82     EXPECT_TRUE(parseFilter("Reading eq 1e20"));
83     EXPECT_TRUE(parseFilter("Reading eq 1.575E1"));
84     EXPECT_TRUE(parseFilter("Reading eq -2.5E-3"));
85     EXPECT_TRUE(parseFilter("Reading eq 25E-4"));
86 
87     // numeric operators
88     EXPECT_TRUE(parseFilter("ProcessorSummary/Count eq 2"));
89     EXPECT_TRUE(parseFilter("ProcessorSummary/Count ne 2"));
90     EXPECT_TRUE(parseFilter("ProcessorSummary/Count gt 2"));
91     EXPECT_TRUE(parseFilter("ProcessorSummary/Count ge 2"));
92     EXPECT_TRUE(parseFilter("ProcessorSummary/Count lt 2"));
93     EXPECT_TRUE(parseFilter("ProcessorSummary/Count le 2"));
94 
95     // String comparison
96     EXPECT_TRUE(parseFilter("ProcessorSummary/Count eq 'foo'"));
97     EXPECT_TRUE(parseFilter("ProcessorSummary/Count ne 'foo'"));
98 
99     // Future, datetime values are strings and need to be compared
100     // Make sure they parse
101     EXPECT_TRUE(parseFilter("ProcessorSummary/Count lt 'Physical'"));
102     EXPECT_TRUE(parseFilter("ProcessorSummary/Count le 'Physical'"));
103     EXPECT_TRUE(parseFilter("ProcessorSummary/Count gt 'Physical'"));
104     EXPECT_TRUE(parseFilter("ProcessorSummary/Count ge 'Physical'"));
105     EXPECT_TRUE(parseFilter("'Physical' lt ProcessorSummary/Count"));
106     EXPECT_TRUE(parseFilter("'Physical' le ProcessorSummary/Count"));
107     EXPECT_TRUE(parseFilter("'Physical' gt ProcessorSummary/Count"));
108     EXPECT_TRUE(parseFilter("'Physical' ge ProcessorSummary/Count"));
109 }
110 
TEST(FilterParser,Spaces)111 TEST(FilterParser, Spaces)
112 {
113     // Strings with spaces
114     parse("foo eq ' '", R"(unquoted_string("foo") Equals quoted_string(" "))");
115 
116     // Lots of spaces between args
117     parse("foo       eq       ''",
118           R"(unquoted_string("foo") Equals quoted_string(""))");
119 
120     // Lots of spaces between parens
121     parse("(      foo eq ''      )",
122           R"(unquoted_string("foo") Equals quoted_string(""))");
123 
124     parse("not           foo eq ''",
125           R"(not(unquoted_string("foo") Equals quoted_string("")))");
126 }
127 
TEST(FilterParser,Failures)128 TEST(FilterParser, Failures)
129 {
130     // Invalid expressions
131     EXPECT_FALSE(parseFilter("("));
132     EXPECT_FALSE(parseFilter(")"));
133     EXPECT_FALSE(parseFilter("()"));
134     EXPECT_FALSE(parseFilter(""));
135     EXPECT_FALSE(parseFilter(" "));
136     EXPECT_FALSE(parseFilter("ProcessorSummary/Count eq"));
137     EXPECT_FALSE(parseFilter("eq ProcessorSummary/Count"));
138     EXPECT_FALSE(parseFilter("not(ProcessorSummary/Count)"));
139 }
140 } // namespace redfish
141