Add tests for CypherMainVisitor
Summary: Add tests for CypherMainVisitor Initialise members to nullptrs in ast.hpp data structures Preserver users identifier names Reviewers: teon.banek Reviewed By: teon.banek Differential Revision: https://phabricator.memgraph.io/D138
This commit is contained in:
@@ -47,8 +47,8 @@ class PropertyLookup : public Expression {
|
||||
visitor.PostVisit(*this);
|
||||
}
|
||||
|
||||
Expression *expression_;
|
||||
GraphDb::Property property_;
|
||||
Expression *expression_ = nullptr;
|
||||
GraphDb::Property property_ = nullptr;
|
||||
// TODO potential problem: property lookups are allowed on both map literals
|
||||
// and records, but map literals have strings as keys and records have
|
||||
// GraphDb::Property
|
||||
@@ -72,7 +72,7 @@ class NamedExpression : public Tree {
|
||||
}
|
||||
|
||||
std::string name_;
|
||||
Expression* expression_;
|
||||
Expression* expression_ = nullptr;
|
||||
|
||||
protected:
|
||||
NamedExpression(int uid) : Tree(uid) {}
|
||||
@@ -95,7 +95,7 @@ class NodeAtom : public PatternAtom {
|
||||
visitor.PostVisit(*this);
|
||||
}
|
||||
|
||||
Identifier* identifier_;
|
||||
Identifier* identifier_ = nullptr;
|
||||
std::vector<GraphDb::Label> labels_;
|
||||
std::map<GraphDb::Property, Expression*> properties_;
|
||||
|
||||
@@ -103,7 +103,6 @@ class NodeAtom : public PatternAtom {
|
||||
NodeAtom(int uid) : PatternAtom(uid) {}
|
||||
NodeAtom(int uid, Identifier *identifier) :
|
||||
PatternAtom(uid), identifier_(identifier) {}
|
||||
|
||||
};
|
||||
|
||||
class EdgeAtom : public PatternAtom {
|
||||
@@ -117,8 +116,9 @@ class EdgeAtom : public PatternAtom {
|
||||
visitor.PostVisit(*this);
|
||||
}
|
||||
|
||||
Direction direction = Direction::BOTH;
|
||||
Identifier* identifier_;
|
||||
Direction direction_ = Direction::BOTH;
|
||||
Identifier* identifier_ = nullptr;
|
||||
std::vector<GraphDb::EdgeType> types_;
|
||||
|
||||
protected:
|
||||
EdgeAtom(int uid) : PatternAtom(uid) {}
|
||||
@@ -140,7 +140,7 @@ class Pattern : public Tree {
|
||||
}
|
||||
visitor.PostVisit(*this);
|
||||
}
|
||||
Identifier* identifier_;
|
||||
Identifier* identifier_ = nullptr;
|
||||
std::vector<PatternAtom*> atoms_;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -39,18 +39,36 @@ namespace {
|
||||
//}
|
||||
}
|
||||
|
||||
const std::string CypherMainVisitor::kAnonPrefix = "anon";
|
||||
|
||||
antlrcpp::Any
|
||||
CypherMainVisitor::visitSingleQuery(CypherParser::SingleQueryContext *ctx) {
|
||||
query_ = storage_.query();
|
||||
for (auto *child : ctx->clause()) {
|
||||
query_->clauses_.push_back(child->accept(this));
|
||||
}
|
||||
// Construct unique names for anonymous identifiers;
|
||||
int id = 1;
|
||||
for (auto **identifier : anonymous_identifiers) {
|
||||
while (true) {
|
||||
std::string id_name = kAnonPrefix + std::to_string(id++);
|
||||
if (users_identifiers.find(id_name) == users_identifiers.end()) {
|
||||
*identifier = storage_.Create<Identifier>(id_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return query_;
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitClause(CypherParser::ClauseContext *ctx) {
|
||||
if (!ctx->cypherReturn() && !ctx->cypherMatch()) {
|
||||
throw std::exception();
|
||||
if (ctx->cypherReturn()) {
|
||||
return (Clause *)ctx->cypherReturn()->accept(this).as<Return *>();
|
||||
}
|
||||
if (ctx->cypherMatch()) {
|
||||
return (Clause *)ctx->cypherMatch()->accept(this).as<Match *>();
|
||||
}
|
||||
throw std::exception();
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
@@ -110,21 +128,15 @@ antlrcpp::Any
|
||||
CypherMainVisitor::visitNodePattern(CypherParser::NodePatternContext *ctx) {
|
||||
auto *node = storage_.Create<NodeAtom>();
|
||||
if (ctx->variable()) {
|
||||
// TODO: user's identifiers should be unchanged, but we must be sure that
|
||||
// ours identifier is not in a clash with user's.
|
||||
std::string variable = ctx->variable()->accept(this);
|
||||
node->identifier_ =
|
||||
storage_.Create<Identifier>(kUserIdentPrefix + variable);
|
||||
node->identifier_ = storage_.Create<Identifier>(variable);
|
||||
users_identifiers.insert(variable);
|
||||
} else {
|
||||
node->identifier_ = storage_.Create<Identifier>(
|
||||
kAnonIdentPrefix + std::to_string(next_ident_id_++));
|
||||
anonymous_identifiers.push_back(&node->identifier_);
|
||||
}
|
||||
if (ctx->nodeLabels()) {
|
||||
std::vector<std::string> labels = ctx->nodeLabels()->accept(this);
|
||||
for (const auto &label : labels) {
|
||||
// TODO: Labels should be garbage collected.
|
||||
node->labels_.push_back(ctx_.db_accessor_.label(label));
|
||||
}
|
||||
node->labels_ =
|
||||
ctx->nodeLabels()->accept(this).as<std::vector<GraphDb::Label>>();
|
||||
}
|
||||
if (ctx->properties()) {
|
||||
throw std::exception();
|
||||
@@ -138,9 +150,9 @@ CypherMainVisitor::visitNodePattern(CypherParser::NodePatternContext *ctx) {
|
||||
|
||||
antlrcpp::Any
|
||||
CypherMainVisitor::visitNodeLabels(CypherParser::NodeLabelsContext *ctx) {
|
||||
std::vector<std::string> labels;
|
||||
std::vector<GraphDb::Label> labels;
|
||||
for (auto *node_label : ctx->nodeLabel()) {
|
||||
labels.push_back(node_label->accept(this));
|
||||
labels.push_back(ctx_.db_accessor_.label(node_label->accept(this)));
|
||||
}
|
||||
return labels;
|
||||
}
|
||||
@@ -193,13 +205,11 @@ antlrcpp::Any
|
||||
CypherMainVisitor::visitPatternPart(CypherParser::PatternPartContext *ctx) {
|
||||
Pattern *pattern = ctx->anonymousPatternPart()->accept(this);
|
||||
if (ctx->variable()) {
|
||||
// TODO: don't change user's identifier name.
|
||||
std::string variable = ctx->variable()->accept(this);
|
||||
pattern->identifier_ =
|
||||
storage_.Create<Identifier>(kUserIdentPrefix + variable);
|
||||
pattern->identifier_ = storage_.Create<Identifier>(variable);
|
||||
users_identifiers.insert(variable);
|
||||
} else {
|
||||
pattern->identifier_ = storage_.Create<Identifier>(
|
||||
kAnonIdentPrefix + std::to_string(next_ident_id_++));
|
||||
anonymous_identifiers.push_back(&pattern->identifier_);
|
||||
}
|
||||
return pattern;
|
||||
}
|
||||
@@ -210,7 +220,7 @@ antlrcpp::Any CypherMainVisitor::visitPatternElement(
|
||||
return ctx->patternElement()->accept(this);
|
||||
}
|
||||
auto pattern = storage_.Create<Pattern>();
|
||||
pattern->atoms_.push_back(ctx->nodePattern()->accept(this));
|
||||
pattern->atoms_.push_back(ctx->nodePattern()->accept(this).as<NodeAtom *>());
|
||||
for (auto *pattern_element_chain : ctx->patternElementChain()) {
|
||||
std::pair<PatternAtom *, PatternAtom *> element =
|
||||
pattern_element_chain->accept(this);
|
||||
@@ -223,8 +233,8 @@ antlrcpp::Any CypherMainVisitor::visitPatternElement(
|
||||
antlrcpp::Any CypherMainVisitor::visitPatternElementChain(
|
||||
CypherParser::PatternElementChainContext *ctx) {
|
||||
return std::pair<PatternAtom *, PatternAtom *>(
|
||||
ctx->relationshipPattern()->accept(this),
|
||||
ctx->nodePattern()->accept(this));
|
||||
ctx->relationshipPattern()->accept(this).as<EdgeAtom *>(),
|
||||
ctx->nodePattern()->accept(this).as<NodeAtom *>());
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitRelationshipPattern(
|
||||
@@ -234,12 +244,14 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipPattern(
|
||||
if (ctx->relationshipDetail()->variable()) {
|
||||
std::string variable =
|
||||
ctx->relationshipDetail()->variable()->accept(this);
|
||||
// TODO: Don't change user's identifier name.
|
||||
edge->identifier_ =
|
||||
storage_.Create<Identifier>(kUserIdentPrefix + variable);
|
||||
edge->identifier_ = storage_.Create<Identifier>(variable);
|
||||
users_identifiers.insert(variable);
|
||||
}
|
||||
if (ctx->relationshipDetail()->relationshipTypes()) {
|
||||
throw std::exception();
|
||||
edge->types_ = ctx->relationshipDetail()
|
||||
->relationshipTypes()
|
||||
->accept(this)
|
||||
.as<std::vector<GraphDb::EdgeType>>();
|
||||
}
|
||||
if (ctx->relationshipDetail()->properties()) {
|
||||
throw std::exception();
|
||||
@@ -256,18 +268,17 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipPattern(
|
||||
// relationship.lower_bound = range.first;
|
||||
// relationship.upper_bound = range.second;
|
||||
if (!edge->identifier_) {
|
||||
edge->identifier_ = storage_.Create<Identifier>(
|
||||
kAnonIdentPrefix + std::to_string(next_ident_id_++));
|
||||
anonymous_identifiers.push_back(&edge->identifier_);
|
||||
}
|
||||
|
||||
if (ctx->leftArrowHead() && !ctx->rightArrowHead()) {
|
||||
edge->direction = EdgeAtom::Direction::LEFT;
|
||||
edge->direction_ = EdgeAtom::Direction::LEFT;
|
||||
} else if (!ctx->leftArrowHead() && ctx->rightArrowHead()) {
|
||||
edge->direction = EdgeAtom::Direction::RIGHT;
|
||||
edge->direction_ = EdgeAtom::Direction::RIGHT;
|
||||
} else {
|
||||
// <-[]-> and -[]- is the same thing as far as we understand openCypher
|
||||
// grammar.
|
||||
edge->direction = EdgeAtom::Direction::BOTH;
|
||||
edge->direction_ = EdgeAtom::Direction::BOTH;
|
||||
}
|
||||
return edge;
|
||||
}
|
||||
@@ -280,14 +291,11 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipDetail(
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitRelationshipTypes(
|
||||
CypherParser::RelationshipTypesContext *ctx) {
|
||||
throw std::exception();
|
||||
(void)ctx;
|
||||
return 0;
|
||||
// std::vector<std::string> types;
|
||||
// for (auto *label : ctx->relTypeName()) {
|
||||
// types.push_back(label->accept(this));
|
||||
// }
|
||||
// return types;
|
||||
std::vector<GraphDb::EdgeType> types;
|
||||
for (auto *edge_type : ctx->relTypeName()) {
|
||||
types.push_back(ctx_.db_accessor_.edge_type(edge_type->accept(this)));
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
antlrcpp::Any
|
||||
@@ -546,7 +554,8 @@ antlrcpp::Any CypherMainVisitor::visitAtom(CypherParser::AtomContext *ctx) {
|
||||
return ctx->parenthesizedExpression()->accept(this);
|
||||
} else if (ctx->variable()) {
|
||||
std::string variable = ctx->variable()->accept(this);
|
||||
return storage_.Create<Identifier>(kUserIdentPrefix + variable);
|
||||
users_identifiers.insert(variable);
|
||||
return storage_.Create<Identifier>(variable);
|
||||
}
|
||||
// TODO: Implement this. We don't support comprehensions, functions,
|
||||
// filtering... at the moment.
|
||||
|
||||
@@ -290,14 +290,16 @@ private:
|
||||
|
||||
public:
|
||||
Query *query() { return query_; }
|
||||
const static std::string kAnonPrefix;
|
||||
|
||||
private:
|
||||
Context &ctx_;
|
||||
int next_ident_id_;
|
||||
const std::string kUserIdentPrefix = "u_";
|
||||
const std::string kAnonIdentPrefix = "a_";
|
||||
// Set of identifiers from queries.
|
||||
std::unordered_set<std::string> users_identifiers;
|
||||
// Identifiers that user didn't name.
|
||||
std::vector<Identifier **> anonymous_identifiers;
|
||||
AstTreeStorage storage_;
|
||||
Query *query_;
|
||||
Query *query_ = nullptr;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
NodeAtom* node_atom_;
|
||||
NodeAtom* node_atom_ = nullptr;
|
||||
};
|
||||
|
||||
class ScanAll : public LogicalOperator {
|
||||
@@ -99,7 +99,7 @@ class ScanAll : public LogicalOperator {
|
||||
}
|
||||
|
||||
private:
|
||||
NodeAtom *node_atom_;
|
||||
NodeAtom *node_atom_ = nullptr;
|
||||
};
|
||||
|
||||
class NodeFilter : public LogicalOperator {
|
||||
|
||||
@@ -5,182 +5,116 @@
|
||||
#include <vector>
|
||||
|
||||
#include "antlr4-runtime.h"
|
||||
#include "dbms/dbms.hpp"
|
||||
#include "gmock/gmock.h"
|
||||
#include "query/context.hpp"
|
||||
#include "query/frontend/ast/cypher_main_visitor.hpp"
|
||||
#include "query/frontend/opencypher/parser.hpp"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace ::testing;
|
||||
namespace {
|
||||
|
||||
using namespace query;
|
||||
using namespace query::frontend;
|
||||
using testing::UnorderedElementsAre;
|
||||
|
||||
class AstGenerator {
|
||||
public:
|
||||
AstGenerator(const std::string &query)
|
||||
: dbms_(), db_accessor_(dbms_.active()),
|
||||
context_(Config{}, *db_accessor_), query_string_(query), parser_(query),
|
||||
visitor_(context_), query_([&]() {
|
||||
visitor_.visit(parser_.tree());
|
||||
return visitor_.query();
|
||||
}()) {}
|
||||
|
||||
Dbms dbms_;
|
||||
std::unique_ptr<GraphDbAccessor> db_accessor_;
|
||||
Context context_;
|
||||
std::string query_string_;
|
||||
::frontend::opencypher::Parser parser_;
|
||||
CypherMainVisitor visitor_;
|
||||
Query *query_;
|
||||
};
|
||||
|
||||
TEST(CompilerStructuresTest, SyntaxException) {
|
||||
ASSERT_THROW(AstGenerator("CREATE ()-[*1...2]-()"), std::exception);
|
||||
}
|
||||
|
||||
TEST(CompilerStructuresTest, NodePattern) {
|
||||
AstGenerator ast_generator("MATCH (:label1:label2:label3)");
|
||||
auto *query = ast_generator.query_;
|
||||
ASSERT_EQ(query->clauses_.size(), 1U);
|
||||
auto *match = dynamic_cast<Match *>(query->clauses_[0]);
|
||||
ASSERT_TRUE(match);
|
||||
ASSERT_EQ(match->patterns_.size(), 1U);
|
||||
ASSERT_TRUE(match->patterns_[0]);
|
||||
ASSERT_EQ(match->patterns_[0]->atoms_.size(), 1U);
|
||||
auto node = dynamic_cast<NodeAtom *>(match->patterns_[0]->atoms_[0]);
|
||||
ASSERT_TRUE(node);
|
||||
ASSERT_TRUE(node->identifier_);
|
||||
ASSERT_EQ(node->identifier_->name_,
|
||||
CypherMainVisitor::kAnonPrefix + std::to_string(1));
|
||||
ASSERT_THAT(node->labels_, UnorderedElementsAre(
|
||||
ast_generator.db_accessor_->label("label1"),
|
||||
ast_generator.db_accessor_->label("label2"),
|
||||
ast_generator.db_accessor_->label("label3")));
|
||||
// TODO: add test for properties.
|
||||
}
|
||||
|
||||
TEST(CompilerStructuresTest, NodePatternIdentifier) {
|
||||
AstGenerator ast_generator("MATCH (var)");
|
||||
auto *query = ast_generator.query_;
|
||||
auto *match = dynamic_cast<Match *>(query->clauses_[0]);
|
||||
auto node = dynamic_cast<NodeAtom *>(match->patterns_[0]->atoms_[0]);
|
||||
ASSERT_TRUE(node->identifier_);
|
||||
ASSERT_EQ(node->identifier_->name_, "var");
|
||||
ASSERT_THAT(node->labels_, UnorderedElementsAre());
|
||||
// TODO: add test for properties.
|
||||
}
|
||||
|
||||
TEST(CompilerStructuresTest, RelationshipPatternNoDetails) {
|
||||
AstGenerator ast_generator("MATCH ()--()");
|
||||
auto *query = ast_generator.query_;
|
||||
auto *match = dynamic_cast<Match *>(query->clauses_[0]);
|
||||
ASSERT_EQ(match->patterns_.size(), 1U);
|
||||
ASSERT_TRUE(match->patterns_[0]);
|
||||
ASSERT_EQ(match->patterns_[0]->atoms_.size(), 3U);
|
||||
auto *node1 = dynamic_cast<NodeAtom *>(match->patterns_[0]->atoms_[0]);
|
||||
ASSERT_TRUE(node1);
|
||||
auto *edge = dynamic_cast<EdgeAtom *>(match->patterns_[0]->atoms_[1]);
|
||||
ASSERT_TRUE(edge);
|
||||
auto *node2 = dynamic_cast<NodeAtom *>(match->patterns_[0]->atoms_[2]);
|
||||
ASSERT_TRUE(node2);
|
||||
ASSERT_EQ(edge->direction_, EdgeAtom::Direction::BOTH);
|
||||
ASSERT_TRUE(edge->identifier_);
|
||||
ASSERT_THAT(edge->identifier_->name_,
|
||||
CypherMainVisitor::kAnonPrefix + std::to_string(2));
|
||||
}
|
||||
|
||||
TEST(CompilerStructuresTest, RelationshipPatternDetails) {
|
||||
AstGenerator ast_generator("MATCH ()<-[:type1|type2]-()");
|
||||
auto *query = ast_generator.query_;
|
||||
auto *match = dynamic_cast<Match *>(query->clauses_[0]);
|
||||
auto *edge = dynamic_cast<EdgeAtom *>(match->patterns_[0]->atoms_[1]);
|
||||
ASSERT_EQ(edge->direction_, EdgeAtom::Direction::LEFT);
|
||||
ASSERT_THAT(
|
||||
edge->types_,
|
||||
UnorderedElementsAre(ast_generator.db_accessor_->edge_type("type1"),
|
||||
ast_generator.db_accessor_->edge_type("type2")));
|
||||
// TODO: test properties
|
||||
}
|
||||
|
||||
TEST(CompilerStructuresTest, RelationshipPatternVariable) {
|
||||
AstGenerator ast_generator("MATCH ()-[var]->()");
|
||||
auto *query = ast_generator.query_;
|
||||
auto *match = dynamic_cast<Match *>(query->clauses_[0]);
|
||||
auto *edge = dynamic_cast<EdgeAtom *>(match->patterns_[0]->atoms_[1]);
|
||||
ASSERT_EQ(edge->direction_, EdgeAtom::Direction::RIGHT);
|
||||
ASSERT_TRUE(edge->identifier_);
|
||||
ASSERT_THAT(edge->identifier_->name_, "var");
|
||||
}
|
||||
|
||||
// namespace {
|
||||
//
|
||||
// using query::Context;
|
||||
// using namespace query::frontend;
|
||||
//
|
||||
// class ParserTables {
|
||||
// template <typename T>
|
||||
// auto FilterAnies(std::unordered_map<std::string, antlrcpp::Any> map) {
|
||||
// std::unordered_map<std::string, T> filtered;
|
||||
// for (auto x : map) {
|
||||
// if (x.second.is<T>()) {
|
||||
// filtered[x.first] = x.second.as<T>();
|
||||
// }
|
||||
// }
|
||||
// return filtered;
|
||||
// }
|
||||
//
|
||||
// public:
|
||||
// ParserTables(const std::string &query) {
|
||||
// frontend::opencypher::Parser parser(query);
|
||||
// auto *tree = parser.tree();
|
||||
// CypherMainVisitor visitor;
|
||||
// visitor.visit(tree);
|
||||
// identifiers_map_ = visitor.ids_map().back();
|
||||
// symbol_table_ = visitor.symbol_table();
|
||||
// pattern_parts_ = FilterAnies<PatternPart>(symbol_table_);
|
||||
// nodes_ = FilterAnies<Node>(symbol_table_);
|
||||
// relationships_ = FilterAnies<Relationship>(symbol_table_);
|
||||
// }
|
||||
//
|
||||
// std::unordered_map<std::string, std::string> identifiers_map_;
|
||||
// std::unordered_map<std::string, antlrcpp::Any> symbol_table_;
|
||||
// std::unordered_map<std::string, PatternPart> pattern_parts_;
|
||||
// std::unordered_map<std::string, Node> nodes_;
|
||||
// std::unordered_map<std::string, Relationship> relationships_;
|
||||
// };
|
||||
//
|
||||
// // TODO: Once expression evaluation is implemented, we should also test if
|
||||
// // property values are equal.
|
||||
// void CompareNodes(std::pair<std::string, Node> node_entry,
|
||||
// std::vector<std::string> labels,
|
||||
// std::vector<std::string> property_keys) {
|
||||
// auto node = node_entry.second;
|
||||
// ASSERT_EQ(node_entry.first, node.output_id);
|
||||
// ASSERT_THAT(node.labels,
|
||||
// UnorderedElementsAreArray(labels.begin(), labels.end()));
|
||||
// std::vector<std::string> node_property_keys;
|
||||
// for (auto x : node.properties) {
|
||||
// node_property_keys.push_back(x.first);
|
||||
// }
|
||||
// ASSERT_THAT(
|
||||
// node_property_keys,
|
||||
// UnorderedElementsAreArray(property_keys.begin(), property_keys.end()));
|
||||
// }
|
||||
//
|
||||
// // If has_range is false, lower and upper bound values are ignored.
|
||||
// // TODO: Once expression evaluation is implemented, we should also test if
|
||||
// // property values are equal.
|
||||
// void CompareRelationships(
|
||||
// std::pair<std::string, Relationship> relationship_entry,
|
||||
// Relationship::Direction direction, std::vector<std::string> types,
|
||||
// std::vector<std::string> property_keys, bool has_range,
|
||||
// int64_t lower_bound = 1LL, int64_t upper_bound = LLONG_MAX) {
|
||||
// auto relationship = relationship_entry.second;
|
||||
// ASSERT_EQ(relationship_entry.first, relationship.output_id);
|
||||
// ASSERT_EQ(relationship.direction, direction);
|
||||
// ASSERT_THAT(relationship.types,
|
||||
// UnorderedElementsAreArray(types.begin(), types.end()));
|
||||
// std::vector<std::string> relationship_property_keys;
|
||||
// for (auto x : relationship.properties) {
|
||||
// relationship_property_keys.push_back(x.first);
|
||||
// }
|
||||
// ASSERT_THAT(
|
||||
// relationship_property_keys,
|
||||
// UnorderedElementsAreArray(property_keys.begin(), property_keys.end()));
|
||||
// ASSERT_EQ(relationship.has_range, has_range);
|
||||
// if (!has_range)
|
||||
// return;
|
||||
// ASSERT_EQ(relationship.lower_bound, lower_bound);
|
||||
// ASSERT_EQ(relationship.upper_bound, upper_bound);
|
||||
// }
|
||||
//
|
||||
// // SyntaxException on incorrect syntax.
|
||||
// TEST(CompilerStructuresTest, SyntaxException) {
|
||||
// ASSERT_THROW(ParserTables("CREATE ()-[*1...2]-()"),
|
||||
// frontend::opencypher::SyntaxException);
|
||||
// }
|
||||
//
|
||||
// // Empty node.
|
||||
// TEST(CompilerStructuresTest, NodePatternEmpty) {
|
||||
// ParserTables parser("CREATE ()");
|
||||
// ASSERT_EQ(parser.identifiers_map_.size(), 0U);
|
||||
// ASSERT_EQ(parser.nodes_.size(), 1U);
|
||||
// CompareNodes(*parser.nodes_.begin(), {}, {});
|
||||
// }
|
||||
//
|
||||
// // Node with variable.
|
||||
// TEST(CompilerStructuresTest, NodePatternVariable) {
|
||||
// ParserTables parser("CREATE (var)");
|
||||
// ASSERT_EQ(parser.identifiers_map_.size(), 1U);
|
||||
// ASSERT_NE(parser.identifiers_map_.find("var"), parser.identifiers_map_.end());
|
||||
// ASSERT_EQ(parser.nodes_.size(), 1U);
|
||||
// auto output_identifier = parser.identifiers_map_["var"];
|
||||
// ASSERT_NE(parser.nodes_.find(output_identifier), parser.nodes_.end());
|
||||
// CompareNodes(*parser.nodes_.begin(), {}, {});
|
||||
// }
|
||||
//
|
||||
// // Node with labels.
|
||||
// TEST(CompilerStructuresTest, NodePatternLabels) {
|
||||
// ParserTables parser("CREATE (:label1:label2:label3)");
|
||||
// ASSERT_EQ(parser.identifiers_map_.size(), 0U);
|
||||
// ASSERT_EQ(parser.nodes_.size(), 1U);
|
||||
// CompareNodes(*parser.nodes_.begin(), {"label1", "label2", "label3"}, {});
|
||||
// }
|
||||
//
|
||||
// // Node with properties.
|
||||
// TEST(CompilerStructuresTest, NodePatternProperties) {
|
||||
// ParserTables parser("CREATE ({age: 5, name: \"John\", surname: \"Smith\"})");
|
||||
// ASSERT_EQ(parser.identifiers_map_.size(), 0U);
|
||||
// ASSERT_EQ(parser.nodes_.size(), 1U);
|
||||
// CompareNodes(*parser.nodes_.begin(), {}, {"age", "name", "surname"});
|
||||
// }
|
||||
//
|
||||
// // Relationship without relationship details.
|
||||
// TEST(CompilerStructuresTest, RelationshipPatternNoDetails) {
|
||||
// ParserTables parser("CREATE ()--()");
|
||||
// ASSERT_EQ(parser.identifiers_map_.size(), 0U);
|
||||
// ASSERT_EQ(parser.relationships_.size(), 1U);
|
||||
// CompareRelationships(*parser.relationships_.begin(),
|
||||
// Relationship::Direction::BOTH, {}, {}, false);
|
||||
// }
|
||||
//
|
||||
// // Relationship with empty relationship details.
|
||||
// TEST(CompilerStructuresTest, RelationshipPatternEmptyDetails) {
|
||||
// ParserTables parser("CREATE ()-[]-()");
|
||||
// ASSERT_EQ(parser.identifiers_map_.size(), 0U);
|
||||
// ASSERT_EQ(parser.relationships_.size(), 1U);
|
||||
// CompareRelationships(*parser.relationships_.begin(),
|
||||
// Relationship::Direction::BOTH, {}, {}, false);
|
||||
// }
|
||||
//
|
||||
// // Relationship with left direction.
|
||||
// TEST(CompilerStructuresTest, RelationshipPatternLeftDirection) {
|
||||
// ParserTables parser("CREATE ()<--()");
|
||||
// ASSERT_EQ(parser.identifiers_map_.size(), 0U);
|
||||
// ASSERT_EQ(parser.relationships_.size(), 1U);
|
||||
// CompareRelationships(*parser.relationships_.begin(),
|
||||
// Relationship::Direction::LEFT, {}, {}, false);
|
||||
// }
|
||||
//
|
||||
// // Relationship with right direction.
|
||||
// TEST(CompilerStructuresTest, RelationshipPatternRightDirection) {
|
||||
// ParserTables parser("CREATE ()-[]->()");
|
||||
// ASSERT_EQ(parser.identifiers_map_.size(), 0U);
|
||||
// ASSERT_EQ(parser.relationships_.size(), 1U);
|
||||
// CompareRelationships(*parser.relationships_.begin(),
|
||||
// Relationship::Direction::RIGHT, {}, {}, false);
|
||||
// }
|
||||
//
|
||||
// // Relationship with both directions.
|
||||
// TEST(CompilerStructuresTest, RelationshipPatternBothDirection) {
|
||||
// ParserTables parser("CREATE ()<-[]->()");
|
||||
// ASSERT_EQ(parser.identifiers_map_.size(), 0U);
|
||||
// ASSERT_EQ(parser.relationships_.size(), 1U);
|
||||
// CompareRelationships(*parser.relationships_.begin(),
|
||||
// Relationship::Direction::BOTH, {}, {}, false);
|
||||
// }
|
||||
//
|
||||
// // Relationship with unbounded variable range.
|
||||
// TEST(CompilerStructuresTest, RelationshipPatternUnbounded) {
|
||||
// ParserTables parser("CREATE ()-[*]-()");
|
||||
@@ -190,7 +124,7 @@ using namespace ::testing;
|
||||
// Relationship::Direction::BOTH, {}, {}, true, 1,
|
||||
// LLONG_MAX);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // Relationship with lower bounded variable range.
|
||||
// TEST(CompilerStructuresTest, RelationshipPatternLowerBounded) {
|
||||
// ParserTables parser("CREATE ()-[*5..]-()");
|
||||
@@ -200,7 +134,7 @@ using namespace ::testing;
|
||||
// Relationship::Direction::BOTH, {}, {}, true, 5,
|
||||
// LLONG_MAX);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // Relationship with upper bounded variable range.
|
||||
// TEST(CompilerStructuresTest, RelationshipPatternUpperBounded) {
|
||||
// ParserTables parser("CREATE ()-[*..10]-()");
|
||||
@@ -209,7 +143,7 @@ using namespace ::testing;
|
||||
// CompareRelationships(*parser.relationships_.begin(),
|
||||
// Relationship::Direction::BOTH, {}, {}, true, 1, 10);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // Relationship with lower and upper bounded variable range.
|
||||
// TEST(CompilerStructuresTest, RelationshipPatternLowerUpperBounded) {
|
||||
// ParserTables parser("CREATE ()-[*5..10]-()");
|
||||
@@ -218,7 +152,7 @@ using namespace ::testing;
|
||||
// CompareRelationships(*parser.relationships_.begin(),
|
||||
// Relationship::Direction::BOTH, {}, {}, true, 5, 10);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // Relationship with fixed number of edges.
|
||||
// TEST(CompilerStructuresTest, RelationshipPatternFixedRange) {
|
||||
// ParserTables parser("CREATE ()-[*10]-()");
|
||||
@@ -227,48 +161,15 @@ using namespace ::testing;
|
||||
// CompareRelationships(*parser.relationships_.begin(),
|
||||
// Relationship::Direction::BOTH, {}, {}, true, 10, 10);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // Relationship with invalid bound (larger than long long).
|
||||
// TEST(CompilerStructuresTest, RelationshipPatternInvalidBound) {
|
||||
// ASSERT_THROW(
|
||||
// ParserTables parser("CREATE ()-[*100000000000000000000000000]-()"),
|
||||
// SemanticException);
|
||||
// }
|
||||
//
|
||||
// // Relationship with variable
|
||||
// TEST(CompilerStructuresTest, RelationshipPatternVariable) {
|
||||
// ParserTables parser("CREATE ()-[var]-()");
|
||||
// ASSERT_EQ(parser.identifiers_map_.size(), 1U);
|
||||
// ASSERT_NE(parser.identifiers_map_.find("var"), parser.identifiers_map_.end());
|
||||
// ASSERT_EQ(parser.relationships_.size(), 1U);
|
||||
// auto output_identifier = parser.identifiers_map_["var"];
|
||||
// ASSERT_NE(parser.relationships_.find(output_identifier),
|
||||
// parser.relationships_.end());
|
||||
// CompareRelationships(*parser.relationships_.begin(),
|
||||
// Relationship::Direction::BOTH, {}, {}, false);
|
||||
// }
|
||||
//
|
||||
// // Relationship with labels.
|
||||
// TEST(CompilerStructuresTest, RelationshipPatternLabels) {
|
||||
// ParserTables parser("CREATE ()-[:label1|label2|:label3]-()");
|
||||
// ASSERT_EQ(parser.identifiers_map_.size(), 0U);
|
||||
// ASSERT_EQ(parser.relationships_.size(), 1U);
|
||||
// CompareRelationships(*parser.relationships_.begin(),
|
||||
// Relationship::Direction::BOTH,
|
||||
// {"label1", "label2", "label3"}, {}, false);
|
||||
// }
|
||||
//
|
||||
// // Relationship with properties.
|
||||
// TEST(CompilerStructuresTest, RelationshipPatternProperties) {
|
||||
// ParserTables parser(
|
||||
// "CREATE ()-[{age: 5, name: \"John\", surname: \"Smith\"}]-()");
|
||||
// ASSERT_EQ(parser.identifiers_map_.size(), 0U);
|
||||
// ASSERT_EQ(parser.relationships_.size(), 1U);
|
||||
// CompareRelationships(*parser.relationships_.begin(),
|
||||
// Relationship::Direction::BOTH, {},
|
||||
// {"age", "name", "surname"}, false);
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
// // PatternPart.
|
||||
// TEST(CompilerStructuresTest, PatternPart) {
|
||||
// ParserTables parser("CREATE ()--()");
|
||||
@@ -279,7 +180,7 @@ using namespace ::testing;
|
||||
// ASSERT_EQ(parser.pattern_parts_.begin()->second.nodes.size(), 2U);
|
||||
// ASSERT_EQ(parser.pattern_parts_.begin()->second.relationships.size(), 1U);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // PatternPart in braces.
|
||||
// TEST(CompilerStructuresTest, PatternPartBraces) {
|
||||
// ParserTables parser("CREATE ((()--()))");
|
||||
@@ -290,7 +191,7 @@ using namespace ::testing;
|
||||
// ASSERT_EQ(parser.pattern_parts_.begin()->second.nodes.size(), 2U);
|
||||
// ASSERT_EQ(parser.pattern_parts_.begin()->second.relationships.size(), 1U);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // PatternPart with variable.
|
||||
// TEST(CompilerStructuresTest, PatternPartVariable) {
|
||||
// ParserTables parser("CREATE var=()--()");
|
||||
@@ -300,63 +201,16 @@ using namespace ::testing;
|
||||
// ASSERT_EQ(parser.nodes_.size(), 2U);
|
||||
// ASSERT_EQ(parser.pattern_parts_.begin()->second.nodes.size(), 2U);
|
||||
// ASSERT_EQ(parser.pattern_parts_.begin()->second.relationships.size(), 1U);
|
||||
// ASSERT_NE(parser.identifiers_map_.find("var"), parser.identifiers_map_.end());
|
||||
// ASSERT_NE(parser.identifiers_map_.find("var"),
|
||||
// parser.identifiers_map_.end());
|
||||
// auto output_identifier = parser.identifiers_map_["var"];
|
||||
// ASSERT_NE(parser.pattern_parts_.find(output_identifier),
|
||||
// parser.pattern_parts_.end());
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // Multiple nodes with same variable and properties.
|
||||
// TEST(CompilerStructuresTest, MultipleNodesWithVariableAndProperties) {
|
||||
// ASSERT_THROW(ParserTables parser("CREATE (a {b: 5})-[]-(a {c: 5})"),
|
||||
// SemanticException);
|
||||
// }
|
||||
//
|
||||
// // Multiple nodes with same variable name.
|
||||
// TEST(CompilerStructuresTest, MultipleNodesWithVariable) {
|
||||
// ParserTables parser("CREATE (a {b: 5, c: 5})-[]-(a)");
|
||||
// ASSERT_EQ(parser.identifiers_map_.size(), 1U);
|
||||
// ASSERT_EQ(parser.pattern_parts_.size(), 1U);
|
||||
// ASSERT_EQ(parser.relationships_.size(), 1U);
|
||||
// ASSERT_EQ(parser.nodes_.size(), 1U);
|
||||
// auto pattern_part = parser.pattern_parts_.begin()->second;
|
||||
// ASSERT_EQ(pattern_part.nodes.size(), 2U);
|
||||
// ASSERT_EQ(pattern_part.relationships.size(), 1U);
|
||||
// ASSERT_EQ(pattern_part.nodes[0], pattern_part.nodes[1]);
|
||||
// }
|
||||
//
|
||||
// // Multiple relationships with same variable name and properties.
|
||||
// TEST(CompilerStructuresTest, MultipleRelationshipsWithVariableAndProperties) {
|
||||
// ASSERT_THROW(ParserTables parser("CREATE ()-[e {a: 5}]-()-[e {c: 5}]-()"),
|
||||
// SemanticException);
|
||||
// }
|
||||
//
|
||||
// // Multiple relationships with same variable name.
|
||||
// TEST(CompilerStructuresTest, MultipleRelationshipsWithVariable) {
|
||||
// ParserTables parser("CREATE ()-[a {a: 5}]-()-[a]-()");
|
||||
// ASSERT_EQ(parser.identifiers_map_.size(), 1U);
|
||||
// ASSERT_EQ(parser.pattern_parts_.size(), 1U);
|
||||
// ASSERT_EQ(parser.relationships_.size(), 1U);
|
||||
// ASSERT_EQ(parser.nodes_.size(), 3U);
|
||||
// auto pattern_part = parser.pattern_parts_.begin()->second;
|
||||
// ASSERT_EQ(pattern_part.nodes.size(), 3U);
|
||||
// ASSERT_EQ(pattern_part.relationships.size(), 2U);
|
||||
// ASSERT_NE(pattern_part.nodes[0], pattern_part.nodes[1]);
|
||||
// ASSERT_NE(pattern_part.nodes[1], pattern_part.nodes[2]);
|
||||
// ASSERT_NE(pattern_part.nodes[0], pattern_part.nodes[2]);
|
||||
// ASSERT_EQ(pattern_part.relationships[0], pattern_part.relationships[1]);
|
||||
// }
|
||||
//
|
||||
// // Different structures (nodes, realtionships, patterns) with same variable
|
||||
// // name.
|
||||
// TEST(CompilerStructuresTest, DifferentTypesWithVariable) {
|
||||
// ASSERT_THROW(ParserTables parser("CREATE a=(a)"), SemanticException);
|
||||
// ASSERT_THROW(ParserTables parser("CREATE (a)-[a]-()"), SemanticException);
|
||||
// ASSERT_THROW(ParserTables parser("CREATE a=()-[a]-()"), SemanticException);
|
||||
// }
|
||||
// }
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user