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