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:
Mislav Bradac
2017-03-17 10:43:18 +01:00
parent 0db7883670
commit dd56acf375
5 changed files with 181 additions and 316 deletions

View File

@@ -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:

View File

@@ -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.

View File

@@ -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;
};
}
}

View File

@@ -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 {

View File

@@ -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();
}