Coverage Report

Created: 2023-12-11 06:17

/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