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