/proc/self/cwd/src/ir/datalog/value_test.cc
Line | Count | Source (jump to first uncovered line) |
1 | | //----------------------------------------------------------------------------- |
2 | | // Copyright 2022 Google LLC |
3 | | // |
4 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | // you may not use this file except in compliance with the License. |
6 | | // You may obtain a copy of the License at |
7 | | // |
8 | | // https://www.apache.org/licenses/LICENSE-2.0 |
9 | | // |
10 | | // Unless required by applicable law or agreed to in writing, software |
11 | | // distributed under the License is distributed on an "AS IS" BASIS, |
12 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | // See the License for the specific language governing permissions and |
14 | | // limitations under the License. |
15 | | //---------------------------------------------------------------------------- |
16 | | |
17 | | #include "src/ir/datalog/value.h" |
18 | | |
19 | | #include <limits> |
20 | | |
21 | | #include "fuzztest/fuzztest.h" |
22 | | #include "absl/strings/numbers.h" |
23 | | #include "absl/strings/string_view.h" |
24 | | #include "src/common/testing/gtest.h" |
25 | | |
26 | | namespace raksha::ir::datalog { |
27 | | namespace { |
28 | | |
29 | | using fuzztest::Arbitrary; |
30 | | using testing::Combine; |
31 | | using testing::TestWithParam; |
32 | | using testing::ValuesIn; |
33 | | |
34 | | class FloatTest : public TestWithParam<double> {}; |
35 | | |
36 | 0 | TEST_P(FloatTest, FloatTest) { |
37 | 0 | double num = GetParam(); |
38 | 0 | Float float_value = Float(num); |
39 | 0 | std::string datalog_str = float_value.ToDatalogString(); |
40 | 0 | double parsed_float = 0; |
41 | 0 | bool conversion_succeeds = absl::SimpleAtod(datalog_str, &parsed_float); |
42 | 0 | ASSERT_TRUE(conversion_succeeds) << "Failed to convert " << datalog_str |
43 | 0 | << " into a float (from " << num << ")."; |
44 | 0 | ASSERT_EQ(parsed_float, num) << "Failed to convert " << datalog_str |
45 | 0 | << " into a float equal to " << num << "."; |
46 | 0 | } |
47 | | |
48 | | static double kSampleFloatValues[] = {0.0, 1.0, 2.0, -0.5, |
49 | | 45.1, 999e100, -999e100}; |
50 | | |
51 | | INSTANTIATE_TEST_SUITE_P(FloatTest, FloatTest, ValuesIn(kSampleFloatValues)); |
52 | | |
53 | | // TODO(https://github.com/google/fuzztest/issues/46) We currently have to wrap |
54 | | // our parameters in an additional layer of tuple because of some compatibility |
55 | | // issues in the fuzzing library. Once that is fixed, we can simplify this. |
56 | | constexpr std::tuple<int64_t> kSampleIntegerValues[] = { |
57 | | {0}, |
58 | | {-1}, |
59 | | {1}, |
60 | | {std::numeric_limits<int64_t>::max()}, |
61 | | {std::numeric_limits<int64_t>::min()}}; |
62 | | |
63 | 260 | void RoundTripNumberThroughDatalogString(int64_t num) { |
64 | 260 | Number number_value = Number(num); |
65 | 260 | std::string datalog_str = number_value.ToDatalogString(); |
66 | 260 | int64_t parsed_int = 0; |
67 | 260 | bool conversion_succeeds = absl::SimpleAtoi(datalog_str, &parsed_int); |
68 | 260 | ASSERT_TRUE(conversion_succeeds); |
69 | 260 | ASSERT_EQ(parsed_int, num); |
70 | 260 | } |
71 | | |
72 | | FUZZ_TEST(NumberTest, RoundTripNumberThroughDatalogString) |
73 | | .WithDomains(Arbitrary<int64_t>()) |
74 | | .WithSeeds(kSampleIntegerValues); |
75 | | |
76 | | constexpr std::tuple<absl::string_view> kSampleSymbols[] = { |
77 | | {""}, {"x"}, {"foo"}, {"hello_world"}}; |
78 | | |
79 | 169 | void RoundTripStringThroughDatalogString(absl::string_view symbol) { |
80 | 169 | Symbol symbol_value = Symbol(symbol); |
81 | 169 | std::string symbol_str = symbol_value.ToDatalogString(); |
82 | 169 | ASSERT_EQ(symbol_str, "\"" + std::string(symbol) + "\""); |
83 | 169 | } |
84 | | |
85 | | FUZZ_TEST(SymbolTest, RoundTripStringThroughDatalogString) |
86 | | .WithDomains(Arbitrary<absl::string_view>()) |
87 | | .WithSeeds(kSampleSymbols); |
88 | | |
89 | | using SimpleRecord = Record<Symbol, Number>; |
90 | | |
91 | 0 | TEST(SimpleRecordNilTest, SimpleRecordNilTest) { |
92 | 0 | ASSERT_EQ(Record<SimpleRecord>().ToDatalogString(), "nil"); |
93 | 0 | } |
94 | | |
95 | | class SimpleRecordTest |
96 | | : public TestWithParam< |
97 | | std::tuple<std::tuple<absl::string_view>, std::tuple<int64_t>>> {}; |
98 | | |
99 | 734 | void PerformSimpleRecordTest(absl::string_view symbol, int64_t number) { |
100 | 734 | SimpleRecord record_value = SimpleRecord(Symbol(symbol), Number(number)); |
101 | 734 | ASSERT_EQ(record_value.ToDatalogString(), |
102 | 734 | absl::StrFormat(R"(["%s", %d])", symbol, number)); |
103 | 734 | } |
104 | | |
105 | 0 | TEST_P(SimpleRecordTest, SimpleRecordTest) { |
106 | 0 | PerformSimpleRecordTest(std::get<0>(std::get<0>(GetParam())), |
107 | 0 | std::get<0>(std::get<1>(GetParam()))); |
108 | 0 | } |
109 | | |
110 | | INSTANTIATE_TEST_SUITE_P(SimpleRecordTest, SimpleRecordTest, |
111 | | Combine(ValuesIn(kSampleSymbols), |
112 | | ValuesIn(kSampleIntegerValues))); |
113 | | |
114 | | FUZZ_TEST(SimpleRecordTest, PerformSimpleRecordTest) |
115 | | .WithDomains(Arbitrary<absl::string_view>(), Arbitrary<int64_t>()); |
116 | | |
117 | | class NumList : public Record<Number, NumList> { |
118 | | public: |
119 | | using Record::Record; |
120 | | }; |
121 | | |
122 | | struct NumListAndExpectedDatalog { |
123 | | const NumList *num_list_ptr; |
124 | | absl::string_view expected_datalog; |
125 | | }; |
126 | | |
127 | | class NumListTest : public TestWithParam<NumListAndExpectedDatalog> {}; |
128 | | |
129 | 0 | TEST_P(NumListTest, NumListTest) { |
130 | 0 | const auto [num_list_ptr, expected_datalog] = GetParam(); |
131 | 0 | EXPECT_EQ(num_list_ptr->ToDatalogString(), expected_datalog); |
132 | 0 | } |
133 | | |
134 | | static const NumList kEmptyNumList; |
135 | | static const NumList kOneElementNumList = NumList(Number(5), NumList()); |
136 | | static const NumList kTwoElementNumList(Number(-30), |
137 | | NumList(Number(28), NumList())); |
138 | | |
139 | | static NumListAndExpectedDatalog kListAndExpectedDatalog[] = { |
140 | | {.num_list_ptr = &kEmptyNumList, .expected_datalog = "nil"}, |
141 | | {.num_list_ptr = &kOneElementNumList, .expected_datalog = "[5, nil]"}, |
142 | | {.num_list_ptr = &kTwoElementNumList, |
143 | | .expected_datalog = "[-30, [28, nil]]"}}; |
144 | | |
145 | | INSTANTIATE_TEST_SUITE_P(NumListTest, NumListTest, |
146 | | ValuesIn(kListAndExpectedDatalog)); |
147 | | |
148 | | using NumberSymbolPair = Record<Number, Symbol>; |
149 | | using NumberSymbolPairPair = Record<NumberSymbolPair, NumberSymbolPair>; |
150 | | |
151 | | class NumberSymbolPairPairTest |
152 | | : public TestWithParam< |
153 | | std::tuple<std::tuple<int64_t>, std::tuple<absl::string_view>, |
154 | | std::tuple<int64_t>, std::tuple<absl::string_view>>> {}; |
155 | | |
156 | | void CheckNumberSymbolPairPair(int64_t number1, absl::string_view symbol1, |
157 | 792 | int64_t number2, absl::string_view symbol2) { |
158 | 792 | NumberSymbolPair number_symbol_pair1 = |
159 | 792 | NumberSymbolPair(Number(number1), Symbol(symbol1)); |
160 | 792 | NumberSymbolPair number_symbol_pair2 = |
161 | 792 | NumberSymbolPair(Number(number2), Symbol(symbol2)); |
162 | 792 | NumberSymbolPairPair pair_pair(std::move(number_symbol_pair1), |
163 | 792 | std::move(number_symbol_pair2)); |
164 | 792 | EXPECT_EQ(pair_pair.ToDatalogString(), |
165 | 792 | absl::StrFormat(R"([[%d, "%s"], [%d, "%s"]])", number1, symbol1, |
166 | 792 | number2, symbol2)); |
167 | 792 | } |
168 | | |
169 | 0 | TEST_P(NumberSymbolPairPairTest, NumberSymbolPairPairTest) { |
170 | 0 | auto [num1, str1, num2, str2] = GetParam(); |
171 | 0 | CheckNumberSymbolPairPair(std::get<0>(num1), std::get<0>(str1), |
172 | 0 | std::get<0>(num2), std::get<0>(str2)); |
173 | 0 | } |
174 | | |
175 | | INSTANTIATE_TEST_SUITE_P(NumberSymbolPairPairTest, NumberSymbolPairPairTest, |
176 | | Combine(ValuesIn(kSampleIntegerValues), |
177 | | ValuesIn(kSampleSymbols), |
178 | | ValuesIn(kSampleIntegerValues), |
179 | | ValuesIn(kSampleSymbols))); |
180 | | |
181 | | FUZZ_TEST(NumberSymbolPairPairTest, CheckNumberSymbolPairPair) |
182 | | .WithDomains(Arbitrary<int64_t>(), Arbitrary<absl::string_view>(), |
183 | | Arbitrary<int64_t>(), Arbitrary<absl::string_view>()); |
184 | | |
185 | | static constexpr char kNullBranchName[] = "Null"; |
186 | | static constexpr char kNumberBranchName[] = "Number"; |
187 | | static constexpr char kAddBranchName[] = "Add"; |
188 | | |
189 | | class ArithmeticAdt : public Adt { |
190 | | using Adt::Adt; |
191 | | }; |
192 | | |
193 | | class NullBranch : public ArithmeticAdt { |
194 | | public: |
195 | 16 | NullBranch() : ArithmeticAdt(kNullBranchName) {} |
196 | | }; |
197 | | |
198 | | class NumberBranch : public ArithmeticAdt { |
199 | | public: |
200 | 48 | NumberBranch(Number number) : ArithmeticAdt(kNumberBranchName) { |
201 | 48 | arguments_.push_back(std::make_unique<Number>(number)); |
202 | 48 | } |
203 | | }; |
204 | | |
205 | | class AddBranch : public ArithmeticAdt { |
206 | | public: |
207 | | AddBranch(ArithmeticAdt lhs, ArithmeticAdt rhs) |
208 | 24 | : ArithmeticAdt(kAddBranchName) { |
209 | 24 | arguments_.push_back(std::make_unique<ArithmeticAdt>(std::move(lhs))); |
210 | 24 | arguments_.push_back(std::make_unique<ArithmeticAdt>(std::move(rhs))); |
211 | 24 | } |
212 | | }; |
213 | | |
214 | | struct AdtAndExpectedDatalog { |
215 | | const ArithmeticAdt *adt; |
216 | | absl::string_view expected_datalog; |
217 | | }; |
218 | | |
219 | | class AdtTest : public TestWithParam<AdtAndExpectedDatalog> {}; |
220 | | |
221 | 0 | TEST_P(AdtTest, AdtTest) { |
222 | 0 | auto &[adt, expected_datalog] = GetParam(); |
223 | 0 | EXPECT_EQ(adt->ToDatalogString(), expected_datalog); |
224 | 0 | } |
225 | | |
226 | | static const ArithmeticAdt kNull = ArithmeticAdt(NullBranch()); |
227 | | static const ArithmeticAdt kFive = ArithmeticAdt(NumberBranch(Number(5))); |
228 | | static const ArithmeticAdt kTwo = ArithmeticAdt(NumberBranch(Number(2))); |
229 | | static const ArithmeticAdt kFivePlusTwo = |
230 | | ArithmeticAdt(AddBranch(ArithmeticAdt(NumberBranch(Number(5))), |
231 | | ArithmeticAdt(NumberBranch(Number(2))))); |
232 | | static const ArithmeticAdt kFivePlusTwoPlusNull = ArithmeticAdt( |
233 | | AddBranch(ArithmeticAdt(NumberBranch(Number(5))), |
234 | | ArithmeticAdt(AddBranch(ArithmeticAdt(NumberBranch(Number(2))), |
235 | | ArithmeticAdt(NullBranch()))))); |
236 | | |
237 | | static const AdtAndExpectedDatalog kAdtAndExpectedDatalog[] = { |
238 | | {.adt = &kNull, .expected_datalog = "$Null()"}, |
239 | | {.adt = &kFive, .expected_datalog = "$Number(5)"}, |
240 | | {.adt = &kFivePlusTwo, .expected_datalog = "$Add($Number(5), $Number(2))"}, |
241 | | {.adt = &kFivePlusTwoPlusNull, |
242 | | .expected_datalog = "$Add($Number(5), $Add($Number(2), $Null()))"}}; |
243 | | |
244 | | INSTANTIATE_TEST_SUITE_P(AdtTest, AdtTest, ValuesIn(kAdtAndExpectedDatalog)); |
245 | | |
246 | | } // namespace |
247 | | } // namespace raksha::ir::datalog |