kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/cxx/verifier/assertions_to_souffle_test.cc (about) 1 /* 2 * Copyright 2021 The Kythe Authors. All rights reserved. 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 * http://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 "kythe/cxx/verifier/assertions_to_souffle.h" 18 19 #include <cstddef> 20 #include <string> 21 #include <vector> 22 23 #include "absl/log/check.h" 24 #include "absl/strings/string_view.h" 25 #include "absl/strings/strip.h" 26 #include "absl/types/span.h" 27 #include "gtest/gtest.h" 28 #include "kythe/cxx/verifier/assertion_ast.h" 29 #include "kythe/cxx/verifier/pretty_printer.h" 30 31 namespace kythe::verifier { 32 namespace { 33 34 /// \brief a test fixture that makes it easy to manipulate verifier ASTs. 35 class AstTest : public ::testing::Test { 36 protected: 37 AstTest() { p_.set_emit_prelude(false); } 38 39 /// \return an `Identifier` node with value `string`. 40 Identifier* Id(const std::string& string) { 41 auto symbol = symbol_table_.intern(string); 42 return new (&arena_) Identifier(yy::location{}, symbol); 43 } 44 45 /// \return an `AstNode` of the form App(`head`, Tuple(`values`)) 46 AstNode* Pred(AstNode* head, absl::Span<AstNode* const> values) { 47 size_t values_count = values.size(); 48 AstNode** body = (AstNode**)arena_.New(values_count * sizeof(AstNode*)); 49 size_t vn = 0; 50 for (AstNode* v : values) { 51 body[vn] = v; 52 ++vn; 53 } 54 AstNode* tuple = new (&arena_) Tuple(yy::location{}, values_count, body); 55 return new (&arena_) App(yy::location{}, head, tuple); 56 } 57 58 /// \return a `Range` at the given location. 59 Range* Range(size_t begin, size_t end, const std::string& path, 60 const std::string& root, const std::string& corpus) { 61 return new (&arena_) kythe::verifier::Range( 62 yy::location{}, begin, end, symbol_table_.intern(path), 63 symbol_table_.intern(root), symbol_table_.intern(corpus)); 64 } 65 66 /// \return a string representation of `node` 67 std::string Dump(AstNode* node) { 68 StringPrettyPrinter printer; 69 node->Dump(symbol_table_, &printer); 70 return printer.str(); 71 } 72 73 /// \return the generated program without boilerplate 74 absl::string_view MustGenerateProgram() { 75 std::vector<GoalGroup> groups; 76 SouffleErrorState error_state(&groups); 77 CHECK(p_.Lower(symbol_table_, groups, {}, error_state)); 78 auto code = p_.code(); 79 CHECK(absl::ConsumeSuffix(&code, ".\n")); 80 return code; 81 } 82 83 private: 84 Arena arena_; 85 SymbolTable symbol_table_; 86 SouffleProgram p_; 87 }; 88 89 TEST_F(AstTest, SelfTest) { 90 EXPECT_EQ("test", Dump(Id("test"))); 91 EXPECT_EQ("a()", Dump(Pred(Id("a"), {}))); 92 EXPECT_EQ("a(b, c)", Dump(Pred(Id("a"), {Id("b"), Id("c")}))); 93 EXPECT_EQ("Range(c,r,p,0,1)", Dump(Range(0, 1, "p", "r", "c"))); 94 } 95 96 TEST_F(AstTest, EmptyProgramTest) { EXPECT_EQ("", MustGenerateProgram()); } 97 98 TEST(ErrorStateTest, NoGroups) { 99 std::vector<GoalGroup> groups; 100 SouffleErrorState error_state(&groups); 101 EXPECT_FALSE(error_state.NextStep()); 102 } 103 104 TEST(ErrorStateTest, Empty) { 105 std::vector<GoalGroup> groups{{}}; 106 SouffleErrorState error_state(&groups); 107 EXPECT_FALSE(error_state.NextStep()); 108 } 109 110 TEST(ErrorStateTest, SimpleStep) { 111 std::vector<GoalGroup> groups{{.goals = {nullptr}}}; 112 SouffleErrorState error_state(&groups); 113 ASSERT_TRUE(error_state.NextStep()); 114 EXPECT_FALSE(error_state.IsDoingErrorRecovery()); 115 EXPECT_EQ(error_state.target_group(), 0); 116 EXPECT_EQ(error_state.target_goal(), 0); 117 EXPECT_EQ(error_state.GoalForGroup(0), 0); 118 EXPECT_FALSE(error_state.NextStep()); 119 } 120 121 TEST(ErrorStateTest, MultiStep) { 122 std::vector<GoalGroup> groups{{.goals = {nullptr, nullptr}}}; 123 SouffleErrorState error_state(&groups); 124 ASSERT_TRUE(error_state.NextStep()); 125 EXPECT_FALSE(error_state.IsDoingErrorRecovery()); 126 EXPECT_EQ(error_state.target_group(), 0); 127 EXPECT_EQ(error_state.target_goal(), 1); 128 EXPECT_EQ(error_state.GoalForGroup(0), 1); 129 ASSERT_TRUE(error_state.NextStep()); 130 EXPECT_TRUE(error_state.IsDoingErrorRecovery()); 131 EXPECT_EQ(error_state.target_group(), 0); 132 EXPECT_EQ(error_state.target_goal(), 0); 133 EXPECT_EQ(error_state.GoalForGroup(0), 0); 134 EXPECT_FALSE(error_state.NextStep()); 135 } 136 137 TEST(ErrorStateTest, MultiGroupSingleStep) { 138 std::vector<GoalGroup> groups{{.goals = {nullptr}}, {.goals = {nullptr}}}; 139 SouffleErrorState error_state(&groups); 140 ASSERT_TRUE(error_state.NextStep()); 141 EXPECT_EQ(error_state.target_group(), 1); 142 EXPECT_EQ(error_state.target_goal(), 0); 143 EXPECT_EQ(error_state.GoalForGroup(1), 0); 144 EXPECT_EQ(error_state.GoalForGroup(0), -1); 145 EXPECT_EQ(error_state.IsFinished(1), false); 146 EXPECT_EQ(error_state.IsFinished(0), false); 147 ASSERT_TRUE(error_state.NextStep()); 148 EXPECT_EQ(error_state.target_group(), 0); 149 EXPECT_EQ(error_state.target_goal(), 0); 150 EXPECT_EQ(error_state.GoalForGroup(0), 0); 151 EXPECT_EQ(error_state.IsFinished(1), true); 152 EXPECT_EQ(error_state.IsFinished(0), false); 153 EXPECT_FALSE(error_state.NextStep()); 154 } 155 156 TEST(ErrorStateTest, MultiGroupMultiStep) { 157 std::vector<GoalGroup> groups{{.goals = {nullptr, nullptr}}, 158 {.goals = {nullptr, nullptr}}}; 159 SouffleErrorState error_state(&groups); 160 ASSERT_TRUE(error_state.NextStep()); 161 EXPECT_EQ(error_state.target_group(), 1); 162 EXPECT_EQ(error_state.target_goal(), 1); 163 ASSERT_TRUE(error_state.NextStep()); 164 EXPECT_EQ(error_state.target_group(), 1); 165 EXPECT_EQ(error_state.target_goal(), 0); 166 ASSERT_TRUE(error_state.NextStep()); 167 EXPECT_EQ(error_state.target_group(), 0); 168 EXPECT_EQ(error_state.target_goal(), 1); 169 ASSERT_TRUE(error_state.NextStep()); 170 EXPECT_EQ(error_state.target_group(), 0); 171 EXPECT_EQ(error_state.target_goal(), 0); 172 EXPECT_FALSE(error_state.NextStep()); 173 } 174 175 TEST(ErrorStateTest, SkipEmptyGroups) { 176 std::vector<GoalGroup> groups{ 177 {}, {}, {.goals = {nullptr}}, {}, {}, {.goals = {nullptr}}, {}, {}}; 178 SouffleErrorState error_state(&groups); 179 ASSERT_TRUE(error_state.NextStep()); 180 EXPECT_EQ(error_state.target_group(), 5); 181 EXPECT_EQ(error_state.target_goal(), 0); 182 EXPECT_EQ(error_state.GoalForGroup(5), 0); 183 EXPECT_EQ(error_state.GoalForGroup(4), -1); 184 EXPECT_EQ(error_state.IsFinished(5), false); 185 EXPECT_EQ(error_state.IsFinished(6), true); 186 EXPECT_EQ(error_state.IsFinished(7), true); 187 ASSERT_TRUE(error_state.NextStep()); 188 EXPECT_EQ(error_state.target_group(), 2); 189 EXPECT_EQ(error_state.target_goal(), 0); 190 EXPECT_EQ(error_state.IsFinished(5), true); 191 EXPECT_EQ(error_state.IsFinished(2), false); 192 EXPECT_EQ(error_state.GoalForGroup(2), 0); 193 EXPECT_FALSE(error_state.NextStep()); 194 } 195 } // anonymous namespace 196 } // namespace kythe::verifier