From f7d540829a1c576b7ab0eac33bb14cd34a49f707 Mon Sep 17 00:00:00 2001 From: Mislav Bradac Date: Tue, 13 Jun 2017 11:17:12 +0200 Subject: [PATCH] Add deep clone to Ast Summary: Prepare your aspergillums for blessing this magnificent diff. Reviewers: buda, teon.banek, florijan Reviewed By: teon.banek Subscribers: lion, pullbot Differential Revision: https://phabricator.memgraph.io/D458 --- CMakeLists.txt | 1 + src/query/frontend/ast/ast.cpp | 28 ++ src/query/frontend/ast/ast.hpp | 302 +++++++++++++++++++-- tests/unit/cypher_main_visitor.cpp | 407 ++++++++++++++++------------- 4 files changed, 530 insertions(+), 208 deletions(-) create mode 100644 src/query/frontend/ast/ast.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ecf5e8fec..056046953 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -354,6 +354,7 @@ set(memgraph_src_files ${src_dir}/query/stripped.cpp ${src_dir}/query/common.cpp ${src_dir}/query/console.cpp + ${src_dir}/query/frontend/ast/ast.cpp ${src_dir}/query/frontend/ast/cypher_main_visitor.cpp ${src_dir}/query/typed_value.cpp ${src_dir}/query/interpret/awesome_memgraph_functions.cpp diff --git a/src/query/frontend/ast/ast.cpp b/src/query/frontend/ast/ast.cpp new file mode 100644 index 000000000..52aa3783e --- /dev/null +++ b/src/query/frontend/ast/ast.cpp @@ -0,0 +1,28 @@ +#include "query/frontend/ast/ast.hpp" + +namespace query { + +AstTreeStorage::AstTreeStorage() { + storage_.emplace_back(new Query(next_uid_++)); +} + +Query *AstTreeStorage::query() const { + return dynamic_cast(storage_[0].get()); +} + +ReturnBody CloneReturnBody(AstTreeStorage &storage, const ReturnBody &body) { + ReturnBody new_body; + new_body.distinct = body.distinct; + new_body.all_identifiers = body.all_identifiers; + for (auto *named_expr : body.named_expressions) { + new_body.named_expressions.push_back(named_expr->Clone(storage)); + } + for (auto order : body.order_by) { + new_body.order_by.emplace_back(order.first, order.second->Clone(storage)); + } + new_body.skip = body.skip ? body.skip->Clone(storage) : nullptr; + new_body.limit = body.limit ? body.limit->Clone(storage) : nullptr; + return new_body; +} + +} // namespace query diff --git a/src/query/frontend/ast/ast.hpp b/src/query/frontend/ast/ast.hpp index ee16fa361..0cc579afe 100644 --- a/src/query/frontend/ast/ast.hpp +++ b/src/query/frontend/ast/ast.hpp @@ -12,7 +12,47 @@ namespace query { -class AstTreeStorage; +#define CLONE_BINARY_EXPRESSION \ + auto Clone(AstTreeStorage &storage) const->std::remove_const< \ + std::remove_pointer::type>::type * override { \ + return storage.Create< \ + std::remove_cv::type>::type>( \ + expression1_->Clone(storage), expression2_->Clone(storage)); \ + } +#define CLONE_UNARY_EXPRESSION \ + auto Clone(AstTreeStorage &storage) const->std::remove_const< \ + std::remove_pointer::type>::type * override { \ + return storage.Create< \ + std::remove_cv::type>::type>( \ + expression_->Clone(storage)); \ + } + +class Tree; + +// It would be better to call this AstTree, but we already have a class Tree, +// which could be renamed to Node or AstTreeNode, but we also have a class +// called NodeAtom... +class AstTreeStorage { + public: + AstTreeStorage(); + AstTreeStorage(const AstTreeStorage &) = delete; + AstTreeStorage &operator=(const AstTreeStorage &) = delete; + + template + T *Create(Args &&... args) { + // Never call create for a Query. Call query() instead. + static_assert(!std::is_same::value, "Call query() instead"); + T *p = new T(next_uid_++, std::forward(args)...); + storage_.emplace_back(p); + return p; + } + + Query *query() const; + + private: + int next_uid_ = 0; + std::vector> storage_; +}; class Tree : public ::utils::Visitable, ::utils::Visitable> { @@ -24,6 +64,8 @@ class Tree : public ::utils::Visitable, int uid() const { return uid_; } + virtual Tree *Clone(AstTreeStorage &storage) const = 0; + protected: Tree(int uid) : uid_(uid) {} @@ -34,6 +76,9 @@ class Tree : public ::utils::Visitable, class Expression : public Tree { friend class AstTreeStorage; + public: + Expression *Clone(AstTreeStorage &storage) const override = 0; + protected: Expression(int uid) : Tree(uid) {} }; @@ -45,6 +90,8 @@ class BinaryOperator : public Expression { Expression *expression1_ = nullptr; Expression *expression2_ = nullptr; + BinaryOperator *Clone(AstTreeStorage &storage) const override = 0; + protected: BinaryOperator(int uid) : Expression(uid) {} BinaryOperator(int uid, Expression *expression1, Expression *expression2) @@ -57,6 +104,8 @@ class UnaryOperator : public Expression { public: Expression *expression_ = nullptr; + UnaryOperator *Clone(AstTreeStorage &storage) const override = 0; + protected: UnaryOperator(int uid) : Expression(uid) {} UnaryOperator(int uid, Expression *expression) @@ -74,6 +123,7 @@ class OrOperator : public BinaryOperator { } return visitor.PostVisit(*this); } + CLONE_BINARY_EXPRESSION; protected: using BinaryOperator::BinaryOperator; @@ -90,6 +140,7 @@ class XorOperator : public BinaryOperator { } return visitor.PostVisit(*this); } + CLONE_BINARY_EXPRESSION; protected: using BinaryOperator::BinaryOperator; @@ -106,6 +157,7 @@ class AndOperator : public BinaryOperator { } return visitor.PostVisit(*this); } + CLONE_BINARY_EXPRESSION; protected: using BinaryOperator::BinaryOperator; @@ -126,6 +178,7 @@ class FilterAndOperator : public BinaryOperator { } return visitor.PostVisit(*this); } + CLONE_BINARY_EXPRESSION; protected: using BinaryOperator::BinaryOperator; @@ -142,6 +195,7 @@ class AdditionOperator : public BinaryOperator { } return visitor.PostVisit(*this); } + CLONE_BINARY_EXPRESSION; protected: using BinaryOperator::BinaryOperator; @@ -158,6 +212,7 @@ class SubtractionOperator : public BinaryOperator { } return visitor.PostVisit(*this); } + CLONE_BINARY_EXPRESSION; protected: using BinaryOperator::BinaryOperator; @@ -174,6 +229,7 @@ class MultiplicationOperator : public BinaryOperator { } return visitor.PostVisit(*this); } + CLONE_BINARY_EXPRESSION; protected: using BinaryOperator::BinaryOperator; @@ -190,6 +246,7 @@ class DivisionOperator : public BinaryOperator { } return visitor.PostVisit(*this); } + CLONE_BINARY_EXPRESSION; protected: using BinaryOperator::BinaryOperator; @@ -206,6 +263,7 @@ class ModOperator : public BinaryOperator { } return visitor.PostVisit(*this); } + CLONE_BINARY_EXPRESSION; protected: using BinaryOperator::BinaryOperator; @@ -222,6 +280,7 @@ class NotEqualOperator : public BinaryOperator { } return visitor.PostVisit(*this); } + CLONE_BINARY_EXPRESSION; protected: using BinaryOperator::BinaryOperator; @@ -238,6 +297,7 @@ class EqualOperator : public BinaryOperator { } return visitor.PostVisit(*this); } + CLONE_BINARY_EXPRESSION; protected: using BinaryOperator::BinaryOperator; @@ -254,6 +314,7 @@ class LessOperator : public BinaryOperator { } return visitor.PostVisit(*this); } + CLONE_BINARY_EXPRESSION; protected: using BinaryOperator::BinaryOperator; @@ -270,6 +331,7 @@ class GreaterOperator : public BinaryOperator { } return visitor.PostVisit(*this); } + CLONE_BINARY_EXPRESSION; protected: using BinaryOperator::BinaryOperator; @@ -286,6 +348,7 @@ class LessEqualOperator : public BinaryOperator { } return visitor.PostVisit(*this); } + CLONE_BINARY_EXPRESSION; protected: using BinaryOperator::BinaryOperator; @@ -302,6 +365,7 @@ class GreaterEqualOperator : public BinaryOperator { } return visitor.PostVisit(*this); } + CLONE_BINARY_EXPRESSION; protected: using BinaryOperator::BinaryOperator; @@ -318,6 +382,7 @@ class InListOperator : public BinaryOperator { } return visitor.PostVisit(*this); } + CLONE_BINARY_EXPRESSION; protected: using BinaryOperator::BinaryOperator; @@ -334,6 +399,7 @@ class ListIndexingOperator : public BinaryOperator { } return visitor.PostVisit(*this); } + CLONE_BINARY_EXPRESSION; protected: using BinaryOperator::BinaryOperator; @@ -357,6 +423,13 @@ class ListSlicingOperator : public Expression { return visitor.PostVisit(*this); } + ListSlicingOperator *Clone(AstTreeStorage &storage) const override { + return storage.Create( + list_->Clone(storage), + lower_bound_ ? lower_bound_->Clone(storage) : nullptr, + upper_bound_ ? upper_bound_->Clone(storage) : nullptr); + } + Expression *list_; Expression *lower_bound_; Expression *upper_bound_; @@ -381,6 +454,7 @@ class NotOperator : public UnaryOperator { } return visitor.PostVisit(*this); } + CLONE_UNARY_EXPRESSION; protected: using UnaryOperator::UnaryOperator; @@ -397,6 +471,7 @@ class UnaryPlusOperator : public UnaryOperator { } return visitor.PostVisit(*this); } + CLONE_UNARY_EXPRESSION; protected: using UnaryOperator::UnaryOperator; @@ -413,6 +488,7 @@ class UnaryMinusOperator : public UnaryOperator { } return visitor.PostVisit(*this); } + CLONE_UNARY_EXPRESSION; protected: using UnaryOperator::UnaryOperator; @@ -429,6 +505,7 @@ class IsNullOperator : public UnaryOperator { } return visitor.PostVisit(*this); } + CLONE_UNARY_EXPRESSION; protected: using UnaryOperator::UnaryOperator; @@ -437,6 +514,9 @@ class IsNullOperator : public UnaryOperator { class BaseLiteral : public Expression { friend class AstTreeStorage; + public: + BaseLiteral *Clone(AstTreeStorage &storage) const override = 0; + protected: BaseLiteral(int uid) : Expression(uid) {} }; @@ -447,6 +527,11 @@ class PrimitiveLiteral : public BaseLiteral { public: DEFVISITABLE(TreeVisitor); DEFVISITABLE(HierarchicalTreeVisitor); + + PrimitiveLiteral *Clone(AstTreeStorage &storage) const override { + return storage.Create(value_); + } + TypedValue value_; protected: @@ -459,7 +544,6 @@ class ListLiteral : public BaseLiteral { friend class AstTreeStorage; public: - const std::vector elements_; DEFVISITABLE(TreeVisitor); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { @@ -469,6 +553,16 @@ class ListLiteral : public BaseLiteral { return visitor.PostVisit(*this); } + ListLiteral *Clone(AstTreeStorage &storage) const override { + auto *list = storage.Create(); + for (auto *element : elements_) { + list->elements_.push_back(element->Clone(storage)); + } + return list; + } + + std::vector elements_; + protected: ListLiteral(int uid) : BaseLiteral(uid) {} ListLiteral(int uid, const std::vector &elements) @@ -481,6 +575,11 @@ class Identifier : public Expression { public: DEFVISITABLE(TreeVisitor); DEFVISITABLE(HierarchicalTreeVisitor); + + Identifier *Clone(AstTreeStorage &storage) const override { + return storage.Create(name_, user_declared_); + } + std::string name_; bool user_declared_ = true; @@ -502,6 +601,11 @@ class PropertyLookup : public Expression { return visitor.PostVisit(*this); } + PropertyLookup *Clone(AstTreeStorage &storage) const override { + return storage.Create(expression_->Clone(storage), + property_); + } + Expression *expression_ = nullptr; GraphDbTypes::Property property_ = nullptr; // TODO potential problem: property lookups are allowed on both map literals @@ -530,6 +634,10 @@ class LabelsTest : public Expression { return visitor.PostVisit(*this); } + LabelsTest *Clone(AstTreeStorage &storage) const override { + return storage.Create(expression_->Clone(storage), labels_); + } + Expression *expression_ = nullptr; std::vector labels_; @@ -551,6 +659,11 @@ class EdgeTypeTest : public Expression { return visitor.PostVisit(*this); } + EdgeTypeTest *Clone(AstTreeStorage &storage) const override { + return storage.Create(expression_->Clone(storage), + edge_types_); + } + Expression *expression_ = nullptr; std::vector edge_types_; @@ -577,6 +690,15 @@ class Function : public Expression { return visitor.PostVisit(*this); } + // TODO: Think if there are any problems if function_ is mutable. + Function *Clone(AstTreeStorage &storage) const override { + std::vector arguments; + for (auto *argument : arguments_) { + arguments.push_back(argument->Clone(storage)); + } + return storage.Create(function_, arguments); + } + std::function &, GraphDbAccessor &)> function_; std::vector arguments_; @@ -610,6 +732,12 @@ class Aggregation : public UnaryOperator { } return visitor.PostVisit(*this); } + + Aggregation *Clone(AstTreeStorage &storage) const override { + return storage.Create( + expression_ ? expression_->Clone(storage) : nullptr, op_); + } + Op op_; protected: @@ -633,6 +761,10 @@ class NamedExpression : public Tree { return visitor.PostVisit(*this); } + NamedExpression *Clone(AstTreeStorage &storage) const override { + return storage.Create(name_, expression_->Clone(storage)); + } + std::string name_; Expression *expression_ = nullptr; @@ -649,6 +781,8 @@ class PatternAtom : public Tree { public: Identifier *identifier_ = nullptr; + PatternAtom *Clone(AstTreeStorage &storage) const override = 0; + protected: PatternAtom(int uid) : Tree(uid) {} PatternAtom(int uid, Identifier *identifier) @@ -667,6 +801,15 @@ class NodeAtom : public PatternAtom { return visitor.PostVisit(*this); } + NodeAtom *Clone(AstTreeStorage &storage) const override { + auto *node_atom = storage.Create(identifier_->Clone(storage)); + node_atom->labels_ = labels_; + for (auto property : properties_) { + node_atom->properties_[property.first] = property.second->Clone(storage); + } + return node_atom; + } + std::vector labels_; // TODO: change to unordered_map std::map properties_; @@ -689,6 +832,16 @@ class EdgeAtom : public PatternAtom { return visitor.PostVisit(*this); } + EdgeAtom *Clone(AstTreeStorage &storage) const override { + auto *edge_atom = storage.Create(identifier_->Clone(storage)); + edge_atom->direction_ = direction_; + edge_atom->edge_types_ = edge_types_; + for (auto property : properties_) { + edge_atom->properties_[property.first] = property.second->Clone(storage); + } + return edge_atom; + } + Direction direction_ = Direction::BOTH; std::vector edge_types_; // TODO: change to unordered_map @@ -705,6 +858,8 @@ class Clause : public Tree { public: Clause(int uid) : Tree(uid) {} + + Clause *Clone(AstTreeStorage &storage) const override = 0; }; class Pattern : public Tree { @@ -720,6 +875,16 @@ class Pattern : public Tree { } return visitor.PostVisit(*this); } + + Pattern *Clone(AstTreeStorage &storage) const override { + auto *pattern = storage.Create(); + pattern->identifier_ = identifier_->Clone(storage); + for (auto *atom : atoms_) { + pattern->atoms_.push_back(atom->Clone(storage)); + } + return pattern; + } + Identifier *identifier_ = nullptr; std::vector atoms_; @@ -740,6 +905,16 @@ class Query : public Tree { } return visitor.PostVisit(*this); } + + // Creates deep copy of whole ast. + Query *Clone(AstTreeStorage &storage) const override { + auto *query = storage.query(); + for (auto *clause : clauses_) { + query->clauses_.push_back(clause->Clone(storage)); + } + return query; + } + std::vector clauses_; protected: @@ -751,7 +926,6 @@ class Create : public Clause { public: Create(int uid) : Clause(uid) {} - std::vector patterns_; DEFVISITABLE(TreeVisitor); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { @@ -761,6 +935,16 @@ class Create : public Clause { } return visitor.PostVisit(*this); } + + Create *Clone(AstTreeStorage &storage) const override { + auto *create = storage.Create(); + for (auto *pattern : patterns_) { + create->patterns_.push_back(pattern->Clone(storage)); + } + return create; + } + + std::vector patterns_; }; class Where : public Tree { @@ -774,6 +958,11 @@ class Where : public Tree { } return visitor.PostVisit(*this); } + + Where *Clone(AstTreeStorage &storage) const override { + return storage.Create(expression_->Clone(storage)); + } + Expression *expression_ = nullptr; protected: @@ -801,6 +990,16 @@ class Match : public Clause { } return visitor.PostVisit(*this); } + + Match *Clone(AstTreeStorage &storage) const override { + auto *match = storage.Create(optional_); + for (auto *pattern : patterns_) { + match->patterns_.push_back(pattern->Clone(storage)); + } + match->where_ = where_ ? where_->Clone(storage) : nullptr; + return match; + } + std::vector patterns_; Where *where_ = nullptr; bool optional_ = false; @@ -831,6 +1030,11 @@ struct ReturnBody { Expression *limit = nullptr; }; +// Deep copy ReturnBody. +// TODO: Think about turning ReturnBody to class and making this +// function class member. +ReturnBody CloneReturnBody(AstTreeStorage &storage, const ReturnBody &body); + class Return : public Clause { friend class AstTreeStorage; @@ -859,6 +1063,12 @@ class Return : public Clause { return visitor.PostVisit(*this); } + Return *Clone(AstTreeStorage &storage) const override { + auto *ret = storage.Create(); + ret->body_ = CloneReturnBody(storage, body_); + return ret; + } + ReturnBody body_; protected: @@ -894,6 +1104,13 @@ class With : public Clause { return visitor.PostVisit(*this); } + With *Clone(AstTreeStorage &storage) const override { + auto *with = storage.Create(); + with->body_ = CloneReturnBody(storage, body_); + with->where_ = where_ ? where_->Clone(storage) : nullptr; + return with; + } + ReturnBody body_; Where *where_ = nullptr; @@ -914,6 +1131,16 @@ class Delete : public Clause { } return visitor.PostVisit(*this); } + + Delete *Clone(AstTreeStorage &storage) const override { + auto *del = storage.Create(); + for (auto *expression : expressions_) { + del->expressions_.push_back(expression->Clone(storage)); + } + del->detach_ = detach_; + return del; + } + std::vector expressions_; bool detach_ = false; @@ -932,6 +1159,12 @@ class SetProperty : public Clause { } return visitor.PostVisit(*this); } + + SetProperty *Clone(AstTreeStorage &storage) const override { + return storage.Create(property_lookup_->Clone(storage), + expression_->Clone(storage)); + } + PropertyLookup *property_lookup_ = nullptr; Expression *expression_ = nullptr; @@ -954,6 +1187,12 @@ class SetProperties : public Clause { } return visitor.PostVisit(*this); } + + SetProperties *Clone(AstTreeStorage &storage) const override { + return storage.Create(identifier_->Clone(storage), + expression_->Clone(storage), update_); + } + Identifier *identifier_ = nullptr; Expression *expression_ = nullptr; bool update_ = false; @@ -979,6 +1218,11 @@ class SetLabels : public Clause { } return visitor.PostVisit(*this); } + + SetLabels *Clone(AstTreeStorage &storage) const override { + return storage.Create(identifier_->Clone(storage), labels_); + } + Identifier *identifier_ = nullptr; std::vector labels_; @@ -1000,6 +1244,11 @@ class RemoveProperty : public Clause { } return visitor.PostVisit(*this); } + + RemoveProperty *Clone(AstTreeStorage &storage) const override { + return storage.Create(property_lookup_->Clone(storage)); + } + PropertyLookup *property_lookup_ = nullptr; protected: @@ -1019,6 +1268,11 @@ class RemoveLabels : public Clause { } return visitor.PostVisit(*this); } + + RemoveLabels *Clone(AstTreeStorage &storage) const override { + return storage.Create(identifier_->Clone(storage), labels_); + } + Identifier *identifier_ = nullptr; std::vector labels_; @@ -1057,6 +1311,18 @@ class Merge : public Clause { return visitor.PostVisit(*this); } + Merge *Clone(AstTreeStorage &storage) const override { + auto *merge = storage.Create(); + merge->pattern_ = pattern_->Clone(storage); + for (auto *on_match : on_match_) { + merge->on_match_.push_back(on_match->Clone(storage)); + } + for (auto *on_create : on_create_) { + merge->on_create_.push_back(on_create->Clone(storage)); + } + return merge; + } + Pattern *pattern_ = nullptr; std::vector on_match_; std::vector on_create_; @@ -1077,6 +1343,10 @@ class Unwind : public Clause { return visitor.PostVisit(*this); } + Unwind *Clone(AstTreeStorage &storage) const override { + return storage.Create(named_expression_->Clone(storage)); + } + NamedExpression *const named_expression_ = nullptr; protected: @@ -1087,28 +1357,6 @@ class Unwind : public Clause { } }; -// It would be better to call this AstTree, but we already have a class Tree, -// which could be renamed to Node or AstTreeNode, but we also have a class -// called NodeAtom... -class AstTreeStorage { - public: - AstTreeStorage() { storage_.emplace_back(new Query(next_uid_++)); } - AstTreeStorage(const AstTreeStorage &) = delete; - AstTreeStorage &operator=(const AstTreeStorage &) = delete; - - template - T *Create(Args &&... args) { - // Never call create for a Query. Call query() instead. - static_assert(!std::is_same::value, "Call query() instead"); - T *p = new T(next_uid_++, std::forward(args)...); - storage_.emplace_back(p); - return p; - } - - Query *query() { return dynamic_cast(storage_[0].get()); } - - private: - int next_uid_ = 0; - std::vector> storage_; -}; +#undef CLONE_BINARY_EXPRESSION +#undef CLONE_UNARY_EXPRESSION } diff --git a/tests/unit/cypher_main_visitor.cpp b/tests/unit/cypher_main_visitor.cpp index e4bd629ae..08b2dfdd6 100644 --- a/tests/unit/cypher_main_visitor.cpp +++ b/tests/unit/cypher_main_visitor.cpp @@ -23,6 +23,7 @@ using testing::Pair; using testing::ElementsAre; using testing::UnorderedElementsAre; +// This generator uses ast constructed by parsing the query. class AstGenerator { public: AstGenerator(const std::string &query) @@ -46,16 +47,60 @@ class AstGenerator { Query *query_; }; -TEST(CypherMainVisitorTest, SyntaxException) { - ASSERT_THROW(AstGenerator("CREATE ()-[*1...2]-()"), SyntaxException); +// This clones ast, but uses original one. This done just to ensure that cloning +// doesn't change original. +class OriginalAfterCloningAstGenerator : public AstGenerator { + public: + OriginalAfterCloningAstGenerator(const std::string &query) + : AstGenerator(query) { + AstTreeStorage storage; + visitor_.query()->Clone(storage); + } +}; + +// This generator clones parsed ast and uses that one. +// Original ast is cleared after cloning to ensure that cloned ast doesn't reuse +// any data from original ast. +class ClonedAstGenerator { + public: + ClonedAstGenerator(const std::string &query) + : dbms_(), + db_accessor_(dbms_.active()), + context_(Config{}, *db_accessor_), + query_string_(query), + query_([&]() { + ::frontend::opencypher::Parser parser(query); + CypherMainVisitor visitor(context_); + visitor.visit(parser.tree()); + return visitor.query()->Clone(storage); + }()) {} + + Dbms dbms_; + std::unique_ptr db_accessor_; + Context context_; + std::string query_string_; + AstTreeStorage storage; + Query *query_; +}; + +template +class CypherMainVisitorTest : public ::testing::Test {}; + +typedef ::testing::Types + AstGeneratorTypes; +TYPED_TEST_CASE(CypherMainVisitorTest, AstGeneratorTypes); + +TYPED_TEST(CypherMainVisitorTest, SyntaxException) { + ASSERT_THROW(TypeParam("CREATE ()-[*1...2]-()"), SyntaxException); } -TEST(CypherMainVisitorTest, SyntaxExceptionOnTrailingText) { - ASSERT_THROW(AstGenerator("RETURN 2 + 2 mirko"), SyntaxException); +TYPED_TEST(CypherMainVisitorTest, SyntaxExceptionOnTrailingText) { + ASSERT_THROW(TypeParam("RETURN 2 + 2 mirko"), SyntaxException); } -TEST(CypherMainVisitorTest, PropertyLookup) { - AstGenerator ast_generator("RETURN n.x"); +TYPED_TEST(CypherMainVisitorTest, PropertyLookup) { + TypeParam ast_generator("RETURN n.x"); auto *query = ast_generator.query_; ASSERT_EQ(query->clauses_.size(), 1U); auto *return_clause = dynamic_cast(query->clauses_[0]); @@ -69,8 +114,8 @@ TEST(CypherMainVisitorTest, PropertyLookup) { ast_generator.db_accessor_->property("x")); } -TEST(CypherMainVisitorTest, LabelsTest) { - AstGenerator ast_generator("RETURN n:x:y"); +TYPED_TEST(CypherMainVisitorTest, LabelsTest) { + TypeParam ast_generator("RETURN n:x:y"); auto *query = ast_generator.query_; ASSERT_EQ(query->clauses_.size(), 1U); auto *return_clause = dynamic_cast(query->clauses_[0]); @@ -85,8 +130,8 @@ TEST(CypherMainVisitorTest, LabelsTest) { ast_generator.db_accessor_->label("y"))); } -TEST(CypherMainVisitorTest, EscapedLabel) { - AstGenerator ast_generator("RETURN n:`l-$\"'ab``e````l`"); +TYPED_TEST(CypherMainVisitorTest, EscapedLabel) { + TypeParam ast_generator("RETURN n:`l-$\"'ab``e````l`"); auto *query = ast_generator.query_; ASSERT_EQ(query->clauses_.size(), 1U); auto *return_clause = dynamic_cast(query->clauses_[0]); @@ -98,8 +143,8 @@ TEST(CypherMainVisitorTest, EscapedLabel) { ElementsAre(ast_generator.db_accessor_->label("l-$\"'ab`e``l"))); } -TEST(CypherMainVisitorTest, ReturnNoDistinctNoBagSemantics) { - AstGenerator ast_generator("RETURN x"); +TYPED_TEST(CypherMainVisitorTest, ReturnNoDistinctNoBagSemantics) { + TypeParam ast_generator("RETURN x"); auto *query = ast_generator.query_; ASSERT_EQ(query->clauses_.size(), 1U); auto *return_clause = dynamic_cast(query->clauses_[0]); @@ -111,16 +156,16 @@ TEST(CypherMainVisitorTest, ReturnNoDistinctNoBagSemantics) { ASSERT_FALSE(return_clause->body_.distinct); } -TEST(CypherMainVisitorTest, ReturnDistinct) { - AstGenerator ast_generator("RETURN DISTINCT x"); +TYPED_TEST(CypherMainVisitorTest, ReturnDistinct) { + TypeParam ast_generator("RETURN DISTINCT x"); auto *query = ast_generator.query_; ASSERT_EQ(query->clauses_.size(), 1U); auto *return_clause = dynamic_cast(query->clauses_[0]); ASSERT_TRUE(return_clause->body_.distinct); } -TEST(CypherMainVisitorTest, ReturnLimit) { - AstGenerator ast_generator("RETURN x LIMIT 5"); +TYPED_TEST(CypherMainVisitorTest, ReturnLimit) { + TypeParam ast_generator("RETURN x LIMIT 5"); auto *query = ast_generator.query_; ASSERT_EQ(query->clauses_.size(), 1U); auto *return_clause = dynamic_cast(query->clauses_[0]); @@ -130,8 +175,8 @@ TEST(CypherMainVisitorTest, ReturnLimit) { ASSERT_EQ(literal->value_.Value(), 5); } -TEST(CypherMainVisitorTest, ReturnSkip) { - AstGenerator ast_generator("RETURN x SKIP 5"); +TYPED_TEST(CypherMainVisitorTest, ReturnSkip) { + TypeParam ast_generator("RETURN x SKIP 5"); auto *query = ast_generator.query_; ASSERT_EQ(query->clauses_.size(), 1U); auto *return_clause = dynamic_cast(query->clauses_[0]); @@ -141,8 +186,8 @@ TEST(CypherMainVisitorTest, ReturnSkip) { ASSERT_EQ(literal->value_.Value(), 5); } -TEST(CypherMainVisitorTest, ReturnOrderBy) { - AstGenerator ast_generator("RETURN x, y, z ORDER BY z ASC, x, y DESC"); +TYPED_TEST(CypherMainVisitorTest, ReturnOrderBy) { + TypeParam ast_generator("RETURN x, y, z ORDER BY z ASC, x, y DESC"); auto *query = ast_generator.query_; ASSERT_EQ(query->clauses_.size(), 1U); auto *return_clause = dynamic_cast(query->clauses_[0]); @@ -157,8 +202,8 @@ TEST(CypherMainVisitorTest, ReturnOrderBy) { Pair(Ordering::DESC, "y"))); } -TEST(CypherMainVisitorTest, ReturnNamedIdentifier) { - AstGenerator ast_generator("RETURN var AS var5"); +TYPED_TEST(CypherMainVisitorTest, ReturnNamedIdentifier) { + TypeParam ast_generator("RETURN var AS var5"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); ASSERT_FALSE(return_clause->body_.all_identifiers); @@ -168,16 +213,16 @@ TEST(CypherMainVisitorTest, ReturnNamedIdentifier) { ASSERT_EQ(identifier->name_, "var"); } -TEST(CypherMainVisitorTest, ReturnAsterisk) { - AstGenerator ast_generator("RETURN *"); +TYPED_TEST(CypherMainVisitorTest, ReturnAsterisk) { + TypeParam ast_generator("RETURN *"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); ASSERT_TRUE(return_clause->body_.all_identifiers); ASSERT_EQ(return_clause->body_.named_expressions.size(), 0U); } -TEST(CypherMainVisitorTest, IntegerLiteral) { - AstGenerator ast_generator("RETURN 42"); +TYPED_TEST(CypherMainVisitorTest, IntegerLiteral) { + TypeParam ast_generator("RETURN 42"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *literal = dynamic_cast( @@ -186,13 +231,13 @@ TEST(CypherMainVisitorTest, IntegerLiteral) { ASSERT_EQ(literal->value_.Value(), 42); } -TEST(CypherMainVisitorTest, IntegerLiteralTooLarge) { - ASSERT_THROW(AstGenerator("RETURN 10000000000000000000000000"), +TYPED_TEST(CypherMainVisitorTest, IntegerLiteralTooLarge) { + ASSERT_THROW(TypeParam("RETURN 10000000000000000000000000"), SemanticException); } -TEST(CypherMainVisitorTest, BooleanLiteralTrue) { - AstGenerator ast_generator("RETURN TrUe"); +TYPED_TEST(CypherMainVisitorTest, BooleanLiteralTrue) { + TypeParam ast_generator("RETURN TrUe"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *literal = dynamic_cast( @@ -201,8 +246,8 @@ TEST(CypherMainVisitorTest, BooleanLiteralTrue) { ASSERT_EQ(literal->value_.Value(), true); } -TEST(CypherMainVisitorTest, BooleanLiteralFalse) { - AstGenerator ast_generator("RETURN faLSE"); +TYPED_TEST(CypherMainVisitorTest, BooleanLiteralFalse) { + TypeParam ast_generator("RETURN faLSE"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *literal = dynamic_cast( @@ -211,8 +256,8 @@ TEST(CypherMainVisitorTest, BooleanLiteralFalse) { ASSERT_EQ(literal->value_.Value(), false); } -TEST(CypherMainVisitorTest, NullLiteral) { - AstGenerator ast_generator("RETURN nULl"); +TYPED_TEST(CypherMainVisitorTest, NullLiteral) { + TypeParam ast_generator("RETURN nULl"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *literal = dynamic_cast( @@ -221,8 +266,8 @@ TEST(CypherMainVisitorTest, NullLiteral) { ASSERT_EQ(literal->value_.type(), TypedValue::Type::Null); } -TEST(CypherMainVisitorTest, ParenthesizedExpression) { - AstGenerator ast_generator("RETURN (2)"); +TYPED_TEST(CypherMainVisitorTest, ParenthesizedExpression) { + TypeParam ast_generator("RETURN (2)"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *literal = dynamic_cast( @@ -231,8 +276,8 @@ TEST(CypherMainVisitorTest, ParenthesizedExpression) { ASSERT_EQ(literal->value_.Value(), 2); } -TEST(CypherMainVisitorTest, OrOperator) { - AstGenerator ast_generator("RETURN true Or false oR n"); +TYPED_TEST(CypherMainVisitorTest, OrOperator) { + TypeParam ast_generator("RETURN true Or false oR n"); auto *query = ast_generator.query_; ASSERT_EQ(query->clauses_.size(), 1U); auto *return_clause = dynamic_cast(query->clauses_[0]); @@ -252,8 +297,8 @@ TEST(CypherMainVisitorTest, OrOperator) { ASSERT_EQ(operand3->name_, "n"); } -TEST(CypherMainVisitorTest, XorOperator) { - AstGenerator ast_generator("RETURN true xOr false"); +TYPED_TEST(CypherMainVisitorTest, XorOperator) { + TypeParam ast_generator("RETURN true xOr false"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *xor_operator = dynamic_cast( @@ -266,8 +311,8 @@ TEST(CypherMainVisitorTest, XorOperator) { ASSERT_EQ(operand2->value_.Value(), false); } -TEST(CypherMainVisitorTest, AndOperator) { - AstGenerator ast_generator("RETURN true and false"); +TYPED_TEST(CypherMainVisitorTest, AndOperator) { + TypeParam ast_generator("RETURN true and false"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *and_operator = dynamic_cast( @@ -280,8 +325,8 @@ TEST(CypherMainVisitorTest, AndOperator) { ASSERT_EQ(operand2->value_.Value(), false); } -TEST(CypherMainVisitorTest, AdditionSubtractionOperators) { - AstGenerator ast_generator("RETURN 1 - 2 + 3"); +TYPED_TEST(CypherMainVisitorTest, AdditionSubtractionOperators) { + TypeParam ast_generator("RETURN 1 - 2 + 3"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *addition_operator = dynamic_cast( @@ -304,8 +349,8 @@ TEST(CypherMainVisitorTest, AdditionSubtractionOperators) { ASSERT_EQ(operand3->value_.Value(), 3); } -TEST(CypherMainVisitorTest, MulitplicationOperator) { - AstGenerator ast_generator("RETURN 2 * 3"); +TYPED_TEST(CypherMainVisitorTest, MulitplicationOperator) { + TypeParam ast_generator("RETURN 2 * 3"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *mult_operator = dynamic_cast( @@ -320,8 +365,8 @@ TEST(CypherMainVisitorTest, MulitplicationOperator) { ASSERT_EQ(operand2->value_.Value(), 3); } -TEST(CypherMainVisitorTest, DivisionOperator) { - AstGenerator ast_generator("RETURN 2 / 3"); +TYPED_TEST(CypherMainVisitorTest, DivisionOperator) { + TypeParam ast_generator("RETURN 2 / 3"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *div_operator = dynamic_cast( @@ -334,8 +379,8 @@ TEST(CypherMainVisitorTest, DivisionOperator) { ASSERT_EQ(operand2->value_.Value(), 3); } -TEST(CypherMainVisitorTest, ModOperator) { - AstGenerator ast_generator("RETURN 2 % 3"); +TYPED_TEST(CypherMainVisitorTest, ModOperator) { + TypeParam ast_generator("RETURN 2 % 3"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *mod_operator = dynamic_cast( @@ -363,8 +408,8 @@ TEST(CypherMainVisitorTest, ModOperator) { ASSERT_EQ(operand2->value_.Value(), VALUE2); \ } while (0) -TEST(CypherMainVisitorTest, ComparisonOperators) { - AstGenerator ast_generator("RETURN 2 = 3 != 4 <> 5 < 6 > 7 <= 8 >= 9"); +TYPED_TEST(CypherMainVisitorTest, ComparisonOperators) { + TypeParam ast_generator("RETURN 2 = 3 != 4 <> 5 < 6 > 7 <= 8 >= 9"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); Expression *_operator = @@ -385,8 +430,8 @@ TEST(CypherMainVisitorTest, ComparisonOperators) { #undef CHECK_COMPARISON -TEST(CypherMainVisitorTest, ListIndexingOperator) { - AstGenerator ast_generator("RETURN [1,2,3] [ 2 ]"); +TYPED_TEST(CypherMainVisitorTest, ListIndexingOperator) { + TypeParam ast_generator("RETURN [1,2,3] [ 2 ]"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *list_index_op = dynamic_cast( @@ -398,12 +443,12 @@ TEST(CypherMainVisitorTest, ListIndexingOperator) { ASSERT_EQ(index->value_.Value(), 2); } -TEST(CypherMainVisitorTest, ListSlicingOperatorNoBounds) { - ASSERT_THROW(AstGenerator("RETURN [1,2,3] [ .. ]"), SemanticException); +TYPED_TEST(CypherMainVisitorTest, ListSlicingOperatorNoBounds) { + ASSERT_THROW(TypeParam("RETURN [1,2,3] [ .. ]"), SemanticException); } -TEST(CypherMainVisitorTest, ListSlicingOperator) { - AstGenerator ast_generator("RETURN [1,2,3] [ .. 2 ]"); +TYPED_TEST(CypherMainVisitorTest, ListSlicingOperator) { + TypeParam ast_generator("RETURN [1,2,3] [ .. 2 ]"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *list_slicing_op = dynamic_cast( @@ -417,8 +462,8 @@ TEST(CypherMainVisitorTest, ListSlicingOperator) { EXPECT_EQ(upper_bound->value_.Value(), 2); } -TEST(CypherMainVisitorTest, InListOperator) { - AstGenerator ast_generator("RETURN 5 IN [1,2]"); +TYPED_TEST(CypherMainVisitorTest, InListOperator) { + TypeParam ast_generator("RETURN 5 IN [1,2]"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *in_list_operator = dynamic_cast( @@ -432,8 +477,8 @@ TEST(CypherMainVisitorTest, InListOperator) { ASSERT_TRUE(list); } -TEST(CypherMainVisitorTest, InWithListIndexing) { - AstGenerator ast_generator("RETURN 1 IN [[1,2]][0]"); +TYPED_TEST(CypherMainVisitorTest, InWithListIndexing) { + TypeParam ast_generator("RETURN 1 IN [[1,2]][0]"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *in_list_operator = dynamic_cast( @@ -443,16 +488,18 @@ TEST(CypherMainVisitorTest, InWithListIndexing) { dynamic_cast(in_list_operator->expression1_); ASSERT_TRUE(literal); EXPECT_EQ(literal->value_.Value(), 1); - auto *list_indexing = dynamic_cast(in_list_operator->expression2_); + auto *list_indexing = + dynamic_cast(in_list_operator->expression2_); ASSERT_TRUE(list_indexing); auto *list = dynamic_cast(list_indexing->expression1_); EXPECT_TRUE(list); - auto *list_index = dynamic_cast(list_indexing->expression2_); + auto *list_index = + dynamic_cast(list_indexing->expression2_); EXPECT_TRUE(list_index); } -TEST(CypherMainVisitorTest, IsNull) { - AstGenerator ast_generator("RETURN 2 iS NulL"); +TYPED_TEST(CypherMainVisitorTest, IsNull) { + TypeParam ast_generator("RETURN 2 iS NulL"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *is_type_operator = dynamic_cast( @@ -463,8 +510,8 @@ TEST(CypherMainVisitorTest, IsNull) { ASSERT_EQ(operand1->value_.Value(), 2); } -TEST(CypherMainVisitorTest, IsNotNull) { - AstGenerator ast_generator("RETURN 2 iS nOT NulL"); +TYPED_TEST(CypherMainVisitorTest, IsNotNull) { + TypeParam ast_generator("RETURN 2 iS nOT NulL"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *not_operator = dynamic_cast( @@ -477,8 +524,8 @@ TEST(CypherMainVisitorTest, IsNotNull) { ASSERT_EQ(operand1->value_.Value(), 2); } -TEST(CypherMainVisitorTest, NotOperator) { - AstGenerator ast_generator("RETURN not true"); +TYPED_TEST(CypherMainVisitorTest, NotOperator) { + TypeParam ast_generator("RETURN not true"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *not_operator = dynamic_cast( @@ -488,8 +535,8 @@ TEST(CypherMainVisitorTest, NotOperator) { ASSERT_EQ(operand->value_.Value(), true); } -TEST(CypherMainVisitorTest, UnaryMinusPlusOperators) { - AstGenerator ast_generator("RETURN -+5"); +TYPED_TEST(CypherMainVisitorTest, UnaryMinusPlusOperators) { + TypeParam ast_generator("RETURN -+5"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *unary_minus_operator = dynamic_cast( @@ -504,8 +551,8 @@ TEST(CypherMainVisitorTest, UnaryMinusPlusOperators) { ASSERT_EQ(operand->value_.Value(), 5); } -TEST(CypherMainVisitorTest, Aggregation) { - AstGenerator ast_generator( +TYPED_TEST(CypherMainVisitorTest, Aggregation) { + TypeParam ast_generator( "RETURN COUNT(a), MIN(b), MAX(c), SUM(d), AVG(e), COLLECT(f), COUNT(*)"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); @@ -530,15 +577,15 @@ TEST(CypherMainVisitorTest, Aggregation) { ASSERT_FALSE(aggregation->expression_); } -TEST(CypherMainVisitorTest, UndefinedFunction) { - ASSERT_THROW(AstGenerator("RETURN " - "IHopeWeWillNeverHaveAwesomeMemgraphProcedureWithS" - "uchALongAndAwesomeNameSinceThisTestWouldFail(1)"), +TYPED_TEST(CypherMainVisitorTest, UndefinedFunction) { + ASSERT_THROW(TypeParam("RETURN " + "IHopeWeWillNeverHaveAwesomeMemgraphProcedureWithS" + "uchALongAndAwesomeNameSinceThisTestWouldFail(1)"), SemanticException); } -TEST(CypherMainVisitorTest, Function) { - AstGenerator ast_generator("RETURN abs(n, 2)"); +TYPED_TEST(CypherMainVisitorTest, Function) { + TypeParam ast_generator("RETURN abs(n, 2)"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); ASSERT_EQ(return_clause->body_.named_expressions.size(), 1); @@ -548,8 +595,8 @@ TEST(CypherMainVisitorTest, Function) { ASSERT_TRUE(function->function_); } -TEST(CypherMainVisitorTest, StringLiteralDoubleQuotes) { - AstGenerator ast_generator("RETURN \"mi'rko\""); +TYPED_TEST(CypherMainVisitorTest, StringLiteralDoubleQuotes) { + TypeParam ast_generator("RETURN \"mi'rko\""); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *literal = dynamic_cast( @@ -558,8 +605,8 @@ TEST(CypherMainVisitorTest, StringLiteralDoubleQuotes) { ASSERT_EQ(literal->value_.Value(), "mi'rko"); } -TEST(CypherMainVisitorTest, StringLiteralSingleQuotes) { - AstGenerator ast_generator("RETURN 'mi\"rko'"); +TYPED_TEST(CypherMainVisitorTest, StringLiteralSingleQuotes) { + TypeParam ast_generator("RETURN 'mi\"rko'"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *literal = dynamic_cast( @@ -568,9 +615,8 @@ TEST(CypherMainVisitorTest, StringLiteralSingleQuotes) { ASSERT_EQ(literal->value_.Value(), "mi\"rko"); } -TEST(CypherMainVisitorTest, StringLiteralEscapedChars) { - AstGenerator ast_generator( - "RETURN '\\\\\\'\\\"\\b\\B\\f\\F\\n\\N\\r\\R\\t\\T'"); +TYPED_TEST(CypherMainVisitorTest, StringLiteralEscapedChars) { + TypeParam ast_generator("RETURN '\\\\\\'\\\"\\b\\B\\f\\F\\n\\N\\r\\R\\t\\T'"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *literal = dynamic_cast( @@ -579,8 +625,8 @@ TEST(CypherMainVisitorTest, StringLiteralEscapedChars) { ASSERT_EQ(literal->value_.Value(), "\\'\"\b\b\f\f\n\n\r\r\t\t"); } -TEST(CypherMainVisitorTest, StringLiteralEscapedUtf16) { - AstGenerator ast_generator("RETURN '\\u221daaa\\U221daaa'"); +TYPED_TEST(CypherMainVisitorTest, StringLiteralEscapedUtf16) { + TypeParam ast_generator("RETURN '\\u221daaa\\U221daaa'"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *literal = dynamic_cast( @@ -589,8 +635,8 @@ TEST(CypherMainVisitorTest, StringLiteralEscapedUtf16) { ASSERT_EQ(literal->value_.Value(), u8"\u221daaa\u221daaa"); } -TEST(CypherMainVisitorTest, StringLiteralEscapedUtf32) { - AstGenerator ast_generator("RETURN '\\u0001F600aaaa\\U0001F600aaaaaaaa'"); +TYPED_TEST(CypherMainVisitorTest, StringLiteralEscapedUtf32) { + TypeParam ast_generator("RETURN '\\u0001F600aaaa\\U0001F600aaaaaaaa'"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *literal = dynamic_cast( @@ -600,8 +646,8 @@ TEST(CypherMainVisitorTest, StringLiteralEscapedUtf32) { u8"\U0001F600aaaa\U0001F600aaaaaaaa"); } -TEST(CypherMainVisitorTest, DoubleLiteral) { - AstGenerator ast_generator("RETURN 3.5"); +TYPED_TEST(CypherMainVisitorTest, DoubleLiteral) { + TypeParam ast_generator("RETURN 3.5"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *literal = dynamic_cast( @@ -610,8 +656,8 @@ TEST(CypherMainVisitorTest, DoubleLiteral) { ASSERT_EQ(literal->value_.Value(), 3.5); } -TEST(CypherMainVisitorTest, DoubleLiteralExponent) { - AstGenerator ast_generator("RETURN 5e-1"); +TYPED_TEST(CypherMainVisitorTest, DoubleLiteralExponent) { + TypeParam ast_generator("RETURN 5e-1"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *literal = dynamic_cast( @@ -620,8 +666,8 @@ TEST(CypherMainVisitorTest, DoubleLiteralExponent) { ASSERT_EQ(literal->value_.Value(), 0.5); } -TEST(CypherMainVisitorTest, ListLiteral) { - AstGenerator ast_generator("RETURN [3, [], 'johhny']"); +TYPED_TEST(CypherMainVisitorTest, ListLiteral) { + TypeParam ast_generator("RETURN [3, [], 'johhny']"); auto *query = ast_generator.query_; auto *return_clause = dynamic_cast(query->clauses_[0]); auto *list_literal = dynamic_cast( @@ -639,8 +685,8 @@ TEST(CypherMainVisitorTest, ListLiteral) { EXPECT_EQ(elem_2->value_.type(), TypedValue::Type::String); } -TEST(CypherMainVisitorTest, NodePattern) { - AstGenerator ast_generator( +TYPED_TEST(CypherMainVisitorTest, NodePattern) { + TypeParam ast_generator( "MATCH (:label1:label2:label3 {a : 5, b : 10}) RETURN 1"); auto *query = ast_generator.query_; ASSERT_EQ(query->clauses_.size(), 2U); @@ -674,12 +720,12 @@ TEST(CypherMainVisitorTest, NodePattern) { Pair(ast_generator.db_accessor_->property("b"), 10))); } -TEST(CypherMainVisitorTest, PropertyMapSameKeyAppearsTwice) { - EXPECT_THROW(AstGenerator("MATCH ({a : 1, a : 2})"), SemanticException); +TYPED_TEST(CypherMainVisitorTest, PropertyMapSameKeyAppearsTwice) { + EXPECT_THROW(TypeParam("MATCH ({a : 1, a : 2})"), SemanticException); } -TEST(CypherMainVisitorTest, NodePatternIdentifier) { - AstGenerator ast_generator("MATCH (var) RETURN 1"); +TYPED_TEST(CypherMainVisitorTest, NodePatternIdentifier) { + TypeParam ast_generator("MATCH (var) RETURN 1"); auto *query = ast_generator.query_; auto *match = dynamic_cast(query->clauses_[0]); ASSERT_TRUE(match); @@ -694,8 +740,8 @@ TEST(CypherMainVisitorTest, NodePatternIdentifier) { EXPECT_THAT(node->properties_, UnorderedElementsAre()); } -TEST(CypherMainVisitorTest, RelationshipPatternNoDetails) { - AstGenerator ast_generator("MATCH ()--() RETURN 1"); +TYPED_TEST(CypherMainVisitorTest, RelationshipPatternNoDetails) { + TypeParam ast_generator("MATCH ()--() RETURN 1"); auto *query = ast_generator.query_; auto *match = dynamic_cast(query->clauses_[0]); ASSERT_TRUE(match); @@ -718,8 +764,8 @@ TEST(CypherMainVisitorTest, RelationshipPatternNoDetails) { } // PatternPart in braces. -TEST(CypherMainVisitorTest, PatternPartBraces) { - AstGenerator ast_generator("MATCH ((()--())) RETURN 1"); +TYPED_TEST(CypherMainVisitorTest, PatternPartBraces) { + TypeParam ast_generator("MATCH ((()--())) RETURN 1"); auto *query = ast_generator.query_; auto *match = dynamic_cast(query->clauses_[0]); ASSERT_TRUE(match); @@ -740,8 +786,8 @@ TEST(CypherMainVisitorTest, PatternPartBraces) { EXPECT_FALSE(edge->identifier_->user_declared_); } -TEST(CypherMainVisitorTest, RelationshipPatternDetails) { - AstGenerator ast_generator( +TYPED_TEST(CypherMainVisitorTest, RelationshipPatternDetails) { + TypeParam ast_generator( "MATCH ()<-[:type1|type2 {a : 5, b : 10}]-() RETURN 1"); auto *query = ast_generator.query_; auto *match = dynamic_cast(query->clauses_[0]); @@ -768,8 +814,8 @@ TEST(CypherMainVisitorTest, RelationshipPatternDetails) { Pair(ast_generator.db_accessor_->property("b"), 10))); } -TEST(CypherMainVisitorTest, RelationshipPatternVariable) { - AstGenerator ast_generator("MATCH ()-[var]->() RETURN 1"); +TYPED_TEST(CypherMainVisitorTest, RelationshipPatternVariable) { + TypeParam ast_generator("MATCH ()-[var]->() RETURN 1"); auto *query = ast_generator.query_; auto *match = dynamic_cast(query->clauses_[0]); ASSERT_TRUE(match); @@ -784,7 +830,7 @@ TEST(CypherMainVisitorTest, RelationshipPatternVariable) { } // // Relationship with unbounded variable range. -// TEST(CypherMainVisitorTest, RelationshipPatternUnbounded) { +// TYPED_TEST(CypherMainVisitorTest, RelationshipPatternUnbounded) { // ParserTables parser("CREATE ()-[*]-()"); // ASSERT_EQ(parser.identifiers_map_.size(), 0U); // ASSERT_EQ(parser.relationships_.size(), 1U); @@ -794,7 +840,7 @@ TEST(CypherMainVisitorTest, RelationshipPatternVariable) { // } // // // Relationship with lower bounded variable range. -// TEST(CypherMainVisitorTest, RelationshipPatternLowerBounded) { +// TYPED_TEST(CypherMainVisitorTest, RelationshipPatternLowerBounded) { // ParserTables parser("CREATE ()-[*5..]-()"); // ASSERT_EQ(parser.identifiers_map_.size(), 0U); // ASSERT_EQ(parser.relationships_.size(), 1U); @@ -804,7 +850,7 @@ TEST(CypherMainVisitorTest, RelationshipPatternVariable) { // } // // // Relationship with upper bounded variable range. -// TEST(CypherMainVisitorTest, RelationshipPatternUpperBounded) { +// TYPED_TEST(CypherMainVisitorTest, RelationshipPatternUpperBounded) { // ParserTables parser("CREATE ()-[*..10]-()"); // ASSERT_EQ(parser.identifiers_map_.size(), 0U); // ASSERT_EQ(parser.relationships_.size(), 1U); @@ -813,7 +859,7 @@ TEST(CypherMainVisitorTest, RelationshipPatternVariable) { // } // // // Relationship with lower and upper bounded variable range. -// TEST(CypherMainVisitorTest, RelationshipPatternLowerUpperBounded) { +// TYPED_TEST(CypherMainVisitorTest, RelationshipPatternLowerUpperBounded) { // ParserTables parser("CREATE ()-[*5..10]-()"); // ASSERT_EQ(parser.identifiers_map_.size(), 0U); // ASSERT_EQ(parser.relationships_.size(), 1U); @@ -822,7 +868,7 @@ TEST(CypherMainVisitorTest, RelationshipPatternVariable) { // } // // // Relationship with fixed number of edges. -// TEST(CypherMainVisitorTest, RelationshipPatternFixedRange) { +// TYPED_TEST(CypherMainVisitorTest, RelationshipPatternFixedRange) { // ParserTables parser("CREATE ()-[*10]-()"); // ASSERT_EQ(parser.identifiers_map_.size(), 0U); // ASSERT_EQ(parser.relationships_.size(), 1U); @@ -832,7 +878,7 @@ TEST(CypherMainVisitorTest, RelationshipPatternVariable) { // // // // PatternPart with variable. -// TEST(CypherMainVisitorTest, PatternPartVariable) { +// TYPED_TEST(CypherMainVisitorTest, PatternPartVariable) { // ParserTables parser("CREATE var=()--()"); // ASSERT_EQ(parser.identifiers_map_.size(), 1U); // ASSERT_EQ(parser.pattern_parts_.size(), 1U); @@ -847,8 +893,8 @@ TEST(CypherMainVisitorTest, RelationshipPatternVariable) { // parser.pattern_parts_.end()); // } -TEST(CypherMainVisitorTest, ReturnUnanemdIdentifier) { - AstGenerator ast_generator("RETURN var"); +TYPED_TEST(CypherMainVisitorTest, ReturnUnanemdIdentifier) { + TypeParam ast_generator("RETURN var"); auto *query = ast_generator.query_; ASSERT_EQ(query->clauses_.size(), 1U); auto *return_clause = dynamic_cast(query->clauses_[0]); @@ -863,8 +909,8 @@ TEST(CypherMainVisitorTest, ReturnUnanemdIdentifier) { ASSERT_TRUE(identifier->user_declared_); } -TEST(CypherMainVisitorTest, Create) { - AstGenerator ast_generator("CREATE (n)"); +TYPED_TEST(CypherMainVisitorTest, Create) { + TypeParam ast_generator("CREATE (n)"); auto *query = ast_generator.query_; ASSERT_EQ(query->clauses_.size(), 1U); auto *create = dynamic_cast(query->clauses_[0]); @@ -878,8 +924,8 @@ TEST(CypherMainVisitorTest, Create) { ASSERT_EQ(node->identifier_->name_, "n"); } -TEST(CypherMainVisitorTest, Delete) { - AstGenerator ast_generator("DELETE n, m"); +TYPED_TEST(CypherMainVisitorTest, Delete) { + TypeParam ast_generator("DELETE n, m"); auto *query = ast_generator.query_; ASSERT_EQ(query->clauses_.size(), 1U); auto *del = dynamic_cast(query->clauses_[0]); @@ -894,8 +940,8 @@ TEST(CypherMainVisitorTest, Delete) { ASSERT_EQ(identifier2->name_, "m"); } -TEST(CypherMainVisitorTest, DeleteDetach) { - AstGenerator ast_generator("DETACH DELETE n"); +TYPED_TEST(CypherMainVisitorTest, DeleteDetach) { + TypeParam ast_generator("DETACH DELETE n"); auto *query = ast_generator.query_; ASSERT_EQ(query->clauses_.size(), 1U); auto *del = dynamic_cast(query->clauses_[0]); @@ -907,8 +953,8 @@ TEST(CypherMainVisitorTest, DeleteDetach) { ASSERT_EQ(identifier1->name_, "n"); } -TEST(CypherMainVisitorTest, OptionalMatchWhere) { - AstGenerator ast_generator("OPTIONAL MATCH (n) WHERE m RETURN 1"); +TYPED_TEST(CypherMainVisitorTest, OptionalMatchWhere) { + TypeParam ast_generator("OPTIONAL MATCH (n) WHERE m RETURN 1"); auto *query = ast_generator.query_; ASSERT_EQ(query->clauses_.size(), 2U); auto *match = dynamic_cast(query->clauses_[0]); @@ -920,8 +966,8 @@ TEST(CypherMainVisitorTest, OptionalMatchWhere) { ASSERT_EQ(identifier->name_, "m"); } -TEST(CypherMainVisitorTest, Set) { - AstGenerator ast_generator("SET a.x = b, c = d, e += f, g : h : i "); +TYPED_TEST(CypherMainVisitorTest, Set) { + TypeParam ast_generator("SET a.x = b, c = d, e += f, g : h : i "); auto *query = ast_generator.query_; ASSERT_EQ(query->clauses_.size(), 4U); @@ -974,8 +1020,8 @@ TEST(CypherMainVisitorTest, Set) { } } -TEST(CypherMainVisitorTest, Remove) { - AstGenerator ast_generator("REMOVE a.x, g : h : i"); +TYPED_TEST(CypherMainVisitorTest, Remove) { + TypeParam ast_generator("REMOVE a.x, g : h : i"); auto *query = ast_generator.query_; ASSERT_EQ(query->clauses_.size(), 2U); @@ -1001,8 +1047,8 @@ TEST(CypherMainVisitorTest, Remove) { } } -TEST(CypherMainVisitorTest, With) { - AstGenerator ast_generator("WITH n AS m RETURN 1"); +TYPED_TEST(CypherMainVisitorTest, With) { + TypeParam ast_generator("WITH n AS m RETURN 1"); auto *query = ast_generator.query_; ASSERT_EQ(query->clauses_.size(), 2U); auto *with = dynamic_cast(query->clauses_[0]); @@ -1019,12 +1065,12 @@ TEST(CypherMainVisitorTest, With) { ASSERT_EQ(identifier->name_, "n"); } -TEST(CypherMainVisitorTest, WithNonAliasedExpression) { - ASSERT_THROW(AstGenerator("WITH n.x RETURN 1"), SemanticException); +TYPED_TEST(CypherMainVisitorTest, WithNonAliasedExpression) { + ASSERT_THROW(TypeParam("WITH n.x RETURN 1"), SemanticException); } -TEST(CypherMainVisitorTest, WithNonAliasedVariable) { - AstGenerator ast_generator("WITH n RETURN 1"); +TYPED_TEST(CypherMainVisitorTest, WithNonAliasedVariable) { + TypeParam ast_generator("WITH n RETURN 1"); auto *query = ast_generator.query_; ASSERT_EQ(query->clauses_.size(), 2U); auto *with = dynamic_cast(query->clauses_[0]); @@ -1036,8 +1082,8 @@ TEST(CypherMainVisitorTest, WithNonAliasedVariable) { ASSERT_EQ(identifier->name_, "n"); } -TEST(CypherMainVisitorTest, WithDistinct) { - AstGenerator ast_generator("WITH DISTINCT n AS m RETURN 1"); +TYPED_TEST(CypherMainVisitorTest, WithDistinct) { + TypeParam ast_generator("WITH DISTINCT n AS m RETURN 1"); auto *query = ast_generator.query_; ASSERT_EQ(query->clauses_.size(), 2U); auto *with = dynamic_cast(query->clauses_[0]); @@ -1050,8 +1096,8 @@ TEST(CypherMainVisitorTest, WithDistinct) { ASSERT_EQ(identifier->name_, "n"); } -TEST(CypherMainVisitorTest, WithBag) { - AstGenerator ast_generator("WITH n as m ORDER BY m SKIP 1 LIMIT 2 RETURN 1"); +TYPED_TEST(CypherMainVisitorTest, WithBag) { + TypeParam ast_generator("WITH n as m ORDER BY m SKIP 1 LIMIT 2 RETURN 1"); auto *query = ast_generator.query_; ASSERT_EQ(query->clauses_.size(), 2U); auto *with = dynamic_cast(query->clauses_[0]); @@ -1064,8 +1110,8 @@ TEST(CypherMainVisitorTest, WithBag) { ASSERT_TRUE(with->body_.skip); } -TEST(CypherMainVisitorTest, WithWhere) { - AstGenerator ast_generator("WITH n AS m WHERE k RETURN 1"); +TYPED_TEST(CypherMainVisitorTest, WithWhere) { + TypeParam ast_generator("WITH n AS m WHERE k RETURN 1"); auto *query = ast_generator.query_; ASSERT_EQ(query->clauses_.size(), 2U); auto *with = dynamic_cast(query->clauses_[0]); @@ -1081,53 +1127,52 @@ TEST(CypherMainVisitorTest, WithWhere) { ASSERT_EQ(identifier2->name_, "n"); } -TEST(CypherMainVisitorTest, ClausesOrdering) { +TYPED_TEST(CypherMainVisitorTest, ClausesOrdering) { // Obviously some of the ridiculous combinations don't fail here, but they // will fail in semantic analysis or they make perfect sense as a part of // bigger query. - AstGenerator("RETURN 1"); - ASSERT_THROW(AstGenerator("RETURN 1 RETURN 1"), SemanticException); - ASSERT_THROW(AstGenerator("RETURN 1 MATCH (n) RETURN n"), SemanticException); - ASSERT_THROW(AstGenerator("RETURN 1 DELETE n"), SemanticException); - ASSERT_THROW(AstGenerator("RETURN 1 MERGE (n)"), SemanticException); - ASSERT_THROW(AstGenerator("RETURN 1 WITH n AS m RETURN 1"), - SemanticException); - ASSERT_THROW(AstGenerator("RETURN 1 AS n UNWIND n AS x RETURN x"), + TypeParam("RETURN 1"); + ASSERT_THROW(TypeParam("RETURN 1 RETURN 1"), SemanticException); + ASSERT_THROW(TypeParam("RETURN 1 MATCH (n) RETURN n"), SemanticException); + ASSERT_THROW(TypeParam("RETURN 1 DELETE n"), SemanticException); + ASSERT_THROW(TypeParam("RETURN 1 MERGE (n)"), SemanticException); + ASSERT_THROW(TypeParam("RETURN 1 WITH n AS m RETURN 1"), SemanticException); + ASSERT_THROW(TypeParam("RETURN 1 AS n UNWIND n AS x RETURN x"), SemanticException); - ASSERT_THROW(AstGenerator("OPTIONAL MATCH (n) MATCH (m) RETURN n, m"), + ASSERT_THROW(TypeParam("OPTIONAL MATCH (n) MATCH (m) RETURN n, m"), SemanticException); - AstGenerator("OPTIONAL MATCH (n) WITH n MATCH (m) RETURN n, m"); - AstGenerator("OPTIONAL MATCH (n) OPTIONAL MATCH (m) RETURN n, m"); - AstGenerator("MATCH (n) OPTIONAL MATCH (m) RETURN n, m"); + TypeParam("OPTIONAL MATCH (n) WITH n MATCH (m) RETURN n, m"); + TypeParam("OPTIONAL MATCH (n) OPTIONAL MATCH (m) RETURN n, m"); + TypeParam("MATCH (n) OPTIONAL MATCH (m) RETURN n, m"); - AstGenerator("CREATE (n)"); - ASSERT_THROW(AstGenerator("SET n:x MATCH (n) RETURN n"), SemanticException); - AstGenerator("REMOVE n.x SET n.x = 1"); - AstGenerator("REMOVE n:L RETURN n"); - AstGenerator("SET n.x = 1 WITH n AS m RETURN m"); + TypeParam("CREATE (n)"); + ASSERT_THROW(TypeParam("SET n:x MATCH (n) RETURN n"), SemanticException); + TypeParam("REMOVE n.x SET n.x = 1"); + TypeParam("REMOVE n:L RETURN n"); + TypeParam("SET n.x = 1 WITH n AS m RETURN m"); - ASSERT_THROW(AstGenerator("MATCH (n)"), SemanticException); - AstGenerator("MATCH (n) MATCH (n) RETURN n"); - AstGenerator("MATCH (n) SET n = m"); - AstGenerator("MATCH (n) RETURN n"); - AstGenerator("MATCH (n) WITH n AS m RETURN m"); + ASSERT_THROW(TypeParam("MATCH (n)"), SemanticException); + TypeParam("MATCH (n) MATCH (n) RETURN n"); + TypeParam("MATCH (n) SET n = m"); + TypeParam("MATCH (n) RETURN n"); + TypeParam("MATCH (n) WITH n AS m RETURN m"); - ASSERT_THROW(AstGenerator("WITH 1 AS n"), SemanticException); - AstGenerator("WITH 1 AS n WITH n AS m RETURN m"); - AstGenerator("WITH 1 AS n RETURN n"); - AstGenerator("WITH 1 AS n SET n += m"); - AstGenerator("WITH 1 AS n MATCH (n) RETURN n"); + ASSERT_THROW(TypeParam("WITH 1 AS n"), SemanticException); + TypeParam("WITH 1 AS n WITH n AS m RETURN m"); + TypeParam("WITH 1 AS n RETURN n"); + TypeParam("WITH 1 AS n SET n += m"); + TypeParam("WITH 1 AS n MATCH (n) RETURN n"); - ASSERT_THROW(AstGenerator("UNWIND [1,2,3] AS x"), SemanticException); - ASSERT_THROW(AstGenerator("CREATE (n) UNWIND [1,2,3] AS x RETURN x"), + ASSERT_THROW(TypeParam("UNWIND [1,2,3] AS x"), SemanticException); + ASSERT_THROW(TypeParam("CREATE (n) UNWIND [1,2,3] AS x RETURN x"), SemanticException); - AstGenerator("UNWIND [1,2,3] AS x CREATE (n) RETURN x"); - AstGenerator("CREATE (n) WITH n UNWIND [1,2,3] AS x RETURN x"); + TypeParam("UNWIND [1,2,3] AS x CREATE (n) RETURN x"); + TypeParam("CREATE (n) WITH n UNWIND [1,2,3] AS x RETURN x"); } -TEST(CypherMainVisitorTest, Merge) { - AstGenerator ast_generator( +TYPED_TEST(CypherMainVisitorTest, Merge) { + TypeParam ast_generator( "MERGE (a) -[:r]- (b) ON MATCH SET a.x = b.x " "ON CREATE SET b :label ON MATCH SET b = a"); auto *query = ast_generator.query_; @@ -1142,8 +1187,8 @@ TEST(CypherMainVisitorTest, Merge) { EXPECT_TRUE(dynamic_cast(merge->on_create_[0])); } -TEST(CypherMainVisitorTest, Unwind) { - AstGenerator ast_generator("UNWIND [1,2,3] AS elem RETURN elem"); +TYPED_TEST(CypherMainVisitorTest, Unwind) { + TypeParam ast_generator("UNWIND [1,2,3] AS elem RETURN elem"); auto *query = ast_generator.query_; ASSERT_EQ(query->clauses_.size(), 2U); auto *unwind = dynamic_cast(query->clauses_[0]); @@ -1157,7 +1202,7 @@ TEST(CypherMainVisitorTest, Unwind) { ASSERT_TRUE(dynamic_cast(expr)); } -TEST(CypherMainVisitorTest, UnwindWithoutAsError) { - EXPECT_THROW(AstGenerator("UNWIND [1,2,3] RETURN 42"), SyntaxException); +TYPED_TEST(CypherMainVisitorTest, UnwindWithoutAsError) { + EXPECT_THROW(TypeParam("UNWIND [1,2,3] RETURN 42"), SyntaxException); } }