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