From 9e81fe791cfaf5bfbf7ab321f5f7325518f6b7dd Mon Sep 17 00:00:00 2001 From: Kostas Kyrimis <kostaskyrim@gmail.com> Date: Mon, 14 Nov 2022 21:22:28 +0200 Subject: [PATCH] Fix clang-tidy warnings, remove commented out code and add HasLabel functions in ShardRequestManager to avoid throwing bad optional on expression evaluator --- src/expr/interpret/eval.hpp | 2 +- src/functions/awesome_memgraph_functions.hpp | 152 ++--- src/query/v2/accessors.cpp | 9 +- src/query/v2/shard_request_manager.hpp | 9 + tests/unit/query_v2_expression_evaluator.cpp | 550 +++---------------- 5 files changed, 165 insertions(+), 557 deletions(-) diff --git a/src/expr/interpret/eval.hpp b/src/expr/interpret/eval.hpp index 139e37514..8b8b5a7c7 100644 --- a/src/expr/interpret/eval.hpp +++ b/src/expr/interpret/eval.hpp @@ -417,7 +417,7 @@ class ExpressionEvaluator : public ExpressionVisitor<TypedValue> { TReturnType HasLabelImpl(const VertexAccessor &vertex, const LabelIx &label_ix, QueryEngineTag /*tag*/) { auto label = typename VertexAccessor::Label{LabelId::FromUint(label_ix.ix)}; auto has_label = vertex.HasLabel(label); - return !has_label; + return has_label; } TypedValue Visit(LabelsTest &labels_test) override { diff --git a/src/functions/awesome_memgraph_functions.hpp b/src/functions/awesome_memgraph_functions.hpp index ca415c69b..0a2b873c2 100644 --- a/src/functions/awesome_memgraph_functions.hpp +++ b/src/functions/awesome_memgraph_functions.hpp @@ -61,12 +61,10 @@ template <typename TypedValueT, typename FunctionContextT, typename Tag, typenam std::function<TypedValueT(const TypedValueT *arguments, int64_t num_arguments, const FunctionContextT &context)> NameToFunction(const std::string &function_name); -namespace { -const char kStartsWith[] = "STARTSWITH"; -const char kEndsWith[] = "ENDSWITH"; -const char kContains[] = "CONTAINS"; -const char kId[] = "ID"; -} // namespace +inline const char kStartsWith[] = "STARTSWITH"; +inline const char kEndsWith[] = "ENDSWITH"; +inline const char kContains[] = "CONTAINS"; +inline const char kId[] = "ID"; } // namespace memgraph::functions @@ -484,11 +482,11 @@ TypedValueT Properties(const TypedValueT *args, int64_t nargs, const FunctionCon const auto &value = args[0]; if (value.IsNull()) { return TypedValueT(ctx.memory); - } else if (value.IsVertex()) { - return get_properties(value.ValueVertex()); - } else { - return get_properties(value.ValueEdge()); } + if (value.IsVertex()) { + return get_properties(value.ValueVertex()); + } + return get_properties(value.ValueEdge()); } template <typename TypedValueT, typename FunctionContextT> @@ -497,17 +495,19 @@ TypedValueT Size(const TypedValueT *args, int64_t nargs, const FunctionContextT const auto &value = args[0]; if (value.IsNull()) { return TypedValueT(ctx.memory); - } else if (value.IsList()) { + } + if (value.IsList()) { return TypedValueT(static_cast<int64_t>(value.ValueList().size()), ctx.memory); - } else if (value.IsString()) { + } + if (value.IsString()) { return TypedValueT(static_cast<int64_t>(value.ValueString().size()), ctx.memory); - } else if (value.IsMap()) { + } + if (value.IsMap()) { // neo4j doesn't implement size for map, but I don't see a good reason not // to do it. return TypedValueT(static_cast<int64_t>(value.ValueMap().size()), ctx.memory); - } else { - return TypedValueT(static_cast<int64_t>(value.ValuePath().edges().size()), ctx.memory); } + return TypedValueT(static_cast<int64_t>(value.ValuePath().edges().size()), ctx.memory); } template <typename TypedValueT, typename FunctionContextT, typename Tag, typename Conv> @@ -527,9 +527,9 @@ TypedValueT StartNode(const TypedValueT *args, int64_t nargs, const FunctionCont } } -namespace { - -size_t UnwrapDegreeResult(storage::v3::Result<size_t> maybe_degree) { +// This is needed because clang-tidy fails to identify the use of this function in the if-constexpr branch +// NOLINTNEXTLINE(clang-diagnostic-unused-function) +inline size_t UnwrapDegreeResult(storage::v3::Result<size_t> maybe_degree) { if (maybe_degree.HasError()) { switch (maybe_degree.GetError()) { case storage::v3::Error::DELETED_OBJECT: @@ -546,8 +546,6 @@ size_t UnwrapDegreeResult(storage::v3::Result<size_t> maybe_degree) { return *maybe_degree; } -} // namespace - template <typename TypedValueT, typename FunctionContextT, typename Tag> TypedValueT Degree(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { FType<TypedValueT, Or<Null, Vertex>>("degree", args, nargs); @@ -599,18 +597,19 @@ TypedValueT ToBoolean(const TypedValueT *args, int64_t nargs, const FunctionCont const auto &value = args[0]; if (value.IsNull()) { return TypedValueT(ctx.memory); - } else if (value.IsBool()) { - return TypedValueT(value.ValueBool(), ctx.memory); - } else if (value.IsInt()) { - return TypedValueT(value.ValueInt() != 0L, ctx.memory); - } else { - auto s = utils::ToUpperCase(utils::Trim(value.ValueString())); - if (s == "TRUE") return TypedValueT(true, ctx.memory); - if (s == "FALSE") return TypedValueT(false, ctx.memory); - // I think this is just stupid and that exception should be thrown, but - // neo4j does it this way... - return TypedValueT(ctx.memory); } + if (value.IsBool()) { + return TypedValueT(value.ValueBool(), ctx.memory); + } + if (value.IsInt()) { + return TypedValueT(value.ValueInt() != 0L, ctx.memory); + } + auto s = utils::ToUpperCase(utils::Trim(value.ValueString())); + if (s == "TRUE") return TypedValueT(true, ctx.memory); + if (s == "FALSE") return TypedValueT(false, ctx.memory); + // I think this is just stupid and that exception should be thrown, but + // neo4j does it this way... + return TypedValueT(ctx.memory); } template <typename TypedValueT, typename FunctionContextT> @@ -619,16 +618,17 @@ TypedValueT ToFloat(const TypedValueT *args, int64_t nargs, const FunctionContex const auto &value = args[0]; if (value.IsNull()) { return TypedValueT(ctx.memory); - } else if (value.IsInt()) { + } + if (value.IsInt()) { return TypedValueT(static_cast<double>(value.ValueInt()), ctx.memory); - } else if (value.IsDouble()) { + } + if (value.IsDouble()) { return TypedValueT(value, ctx.memory); - } else { - try { - return TypedValueT(utils::ParseDouble(utils::Trim(value.ValueString())), ctx.memory); - } catch (const utils::BasicException &) { - return TypedValueT(ctx.memory); - } + } + try { + return TypedValueT(utils::ParseDouble(utils::Trim(value.ValueString())), ctx.memory); + } catch (const utils::BasicException &) { + return TypedValueT(ctx.memory); } } @@ -638,20 +638,22 @@ TypedValueT ToInteger(const TypedValueT *args, int64_t nargs, const FunctionCont const auto &value = args[0]; if (value.IsNull()) { return TypedValueT(ctx.memory); - } else if (value.IsBool()) { + } + if (value.IsBool()) { return TypedValueT(value.ValueBool() ? 1L : 0L, ctx.memory); - } else if (value.IsInt()) { + } + if (value.IsInt()) { return TypedValueT(value, ctx.memory); - } else if (value.IsDouble()) { + } + if (value.IsDouble()) { return TypedValueT(static_cast<int64_t>(value.ValueDouble()), ctx.memory); - } else { - try { - // Yup, this is correct. String is valid if it has floating point - // number, then it is parsed and converted to int. - return TypedValueT(static_cast<int64_t>(utils::ParseDouble(utils::Trim(value.ValueString()))), ctx.memory); - } catch (const utils::BasicException &) { - return TypedValueT(ctx.memory); - } + } + try { + // Yup, this is correct. String is valid if it has floating point + // number, then it is parsed and converted to int. + return TypedValueT(static_cast<int64_t>(utils::ParseDouble(utils::Trim(value.ValueString()))), ctx.memory); + } catch (const utils::BasicException &) { + return TypedValueT(ctx.memory); } } @@ -736,11 +738,11 @@ TypedValueT Keys(const TypedValueT *args, int64_t nargs, const FunctionContextT const auto &value = args[0]; if (value.IsNull()) { return TypedValueT(ctx.memory); - } else if (value.IsVertex()) { - return get_keys(value.ValueVertex()); - } else { - return get_keys(value.ValueEdge()); } + if (value.IsVertex()) { + return get_keys(value.ValueVertex()); + } + return get_keys(value.ValueEdge()); } template <typename TypedValueT, typename FunctionContextT, typename Tag> @@ -853,13 +855,14 @@ TypedValueT Abs(const TypedValueT *args, int64_t nargs, const FunctionContextT & const auto &value = args[0]; if (value.IsNull()) { return TypedValueT(ctx.memory); - } else if (value.IsInt()) { - return TypedValueT(std::abs(value.ValueInt()), ctx.memory); - } else { - return TypedValueT(std::abs(value.ValueDouble()), ctx.memory); } + if (value.IsInt()) { + return TypedValueT(std::abs(value.ValueInt()), ctx.memory); + } + return TypedValueT(std::abs(value.ValueDouble()), ctx.memory); } +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define WRAP_CMATH_FLOAT_FUNCTION(name, lowercased_name) \ template <typename TypedValueT, typename FunctionContextT> \ TypedValueT name(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { \ @@ -867,11 +870,11 @@ TypedValueT Abs(const TypedValueT *args, int64_t nargs, const FunctionContextT & const auto &value = args[0]; \ if (value.IsNull()) { \ return TypedValueT(ctx.memory); \ - } else if (value.IsInt()) { \ - return TypedValueT(lowercased_name(value.ValueInt()), ctx.memory); \ - } else { \ - return TypedValueT(lowercased_name(value.ValueDouble()), ctx.memory); \ } \ + if (value.IsInt()) { \ + return TypedValueT(lowercased_name(value.ValueInt()), ctx.memory); \ + } \ + return TypedValueT(lowercased_name(value.ValueDouble()), ctx.memory); \ } WRAP_CMATH_FLOAT_FUNCTION(Ceil, ceil) @@ -899,9 +902,8 @@ TypedValueT Atan2(const TypedValueT *args, int64_t nargs, const FunctionContextT auto to_double = [](const TypedValueT &t) -> double { if (t.IsInt()) { return t.ValueInt(); - } else { - return t.ValueDouble(); } + return t.ValueDouble(); }; double y = to_double(args[0]); double x = to_double(args[1]); @@ -915,11 +917,11 @@ TypedValueT Sign(const TypedValueT *args, int64_t nargs, const FunctionContextT const auto &value = args[0]; if (value.IsNull()) { return TypedValueT(ctx.memory); - } else if (value.IsInt()) { - return sign(value.ValueInt()); - } else { - return sign(value.ValueDouble()); } + if (value.IsInt()) { + return sign(value.ValueInt()); + } + return sign(value.ValueDouble()); } template <typename TypedValueT, typename FunctionContextT> @@ -962,7 +964,7 @@ struct StartsWithPredicate { }; template <typename TypedValueT, typename FunctionContextT> -inline auto StartsWith = StringMatchOperator<StartsWithPredicate<TypedValueT>, TypedValueT, FunctionContextT>; +inline const auto StartsWith = StringMatchOperator<StartsWithPredicate<TypedValueT>, TypedValueT, FunctionContextT>; // Check if s1 ends with s2. template <typename TypedValueT> @@ -975,7 +977,7 @@ struct EndsWithPredicate { }; template <typename TypedValueT, typename FunctionContextT> -inline auto EndsWith = StringMatchOperator<EndsWithPredicate<TypedValueT>, TypedValueT, FunctionContextT>; +inline const auto EndsWith = StringMatchOperator<EndsWithPredicate<TypedValueT>, TypedValueT, FunctionContextT>; // Check if s1 contains s2. template <typename TypedValueT> @@ -988,7 +990,7 @@ struct ContainsPredicate { }; template <typename TypedValueT, typename FunctionContextT> -inline auto Contains = StringMatchOperator<ContainsPredicate<TypedValueT>, TypedValueT, FunctionContextT>; +inline const auto Contains = StringMatchOperator<ContainsPredicate<TypedValueT>, TypedValueT, FunctionContextT>; template <typename TypedValueT, typename FunctionContextT> TypedValueT Assert(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { @@ -1026,11 +1028,11 @@ TypedValueT Id(const TypedValueT *args, int64_t nargs, const FunctionContextT &c const auto &arg = args[0]; if (arg.IsNull()) { return TypedValueT(ctx.memory); - } else if (arg.IsVertex()) { - return TypedValueT(static_cast<int64_t>(arg.ValueVertex().CypherId()), ctx.memory); - } else { - return TypedValueT(static_cast<int64_t>(arg.ValueEdge().CypherId()), ctx.memory); } + if (arg.IsVertex()) { + return TypedValueT(static_cast<int64_t>(arg.ValueVertex().CypherId()), ctx.memory); + } + return TypedValueT(static_cast<int64_t>(arg.ValueEdge().CypherId()), ctx.memory); } template <typename TypedValueT, typename FunctionContextT> diff --git a/src/query/v2/accessors.cpp b/src/query/v2/accessors.cpp index cbdce89e0..63915327f 100644 --- a/src/query/v2/accessors.cpp +++ b/src/query/v2/accessors.cpp @@ -23,11 +23,11 @@ EdgeTypeId EdgeAccessor::EdgeType() const { return edge.type.id; } const std::vector<std::pair<PropertyId, Value>> &EdgeAccessor::Properties() const { return edge.properties; } Value EdgeAccessor::GetProperty(const std::string &prop_name) const { - auto prop_id = manager_->NameToProperty(prop_name); - auto it = std::find_if(edge.properties.begin(), edge.properties.end(), [&](auto &pr) { return prop_id == pr.first; }); - if (it == edge.properties.end()) { + if (!manager_->HasProperty(prop_name)) { return {}; } + auto prop_id = manager_->NameToProperty(prop_name); + auto it = std::find_if(edge.properties.begin(), edge.properties.end(), [&](auto &pr) { return prop_id == pr.first; }); return it->second; } @@ -88,6 +88,9 @@ Value VertexAccessor::GetProperty(PropertyId prop_id) const { // NOLINTNEXTLINE(readability-convert-member-functions-to-static) Value VertexAccessor::GetProperty(const std::string &prop_name) const { + if (!manager_->HasProperty(prop_name)) { + return {}; + } return GetProperty(manager_->NameToProperty(prop_name)); } diff --git a/src/query/v2/shard_request_manager.hpp b/src/query/v2/shard_request_manager.hpp index a73201046..003cafaf8 100644 --- a/src/query/v2/shard_request_manager.hpp +++ b/src/query/v2/shard_request_manager.hpp @@ -129,6 +129,9 @@ class ShardRequestManagerInterface { virtual const std::string &PropertyToName(memgraph::storage::v3::PropertyId prop) const = 0; virtual const std::string &LabelToName(memgraph::storage::v3::LabelId label) const = 0; virtual const std::string &EdgeTypeToName(memgraph::storage::v3::EdgeTypeId type) const = 0; + virtual bool HasProperty(const std::string &name) const = 0; + virtual bool HasEdgeType(const std::string &name) const = 0; + virtual bool HasLabel(const std::string &name) const = 0; virtual bool IsPrimaryLabel(LabelId label) const = 0; virtual bool IsPrimaryKey(LabelId primary_label, PropertyId property) const = 0; }; @@ -353,6 +356,12 @@ class ShardRequestManager : public ShardRequestManagerInterface { return result_rows; } + bool HasProperty(const std::string &name) const override { return shards_map_.GetPropertyId(name).has_value(); } + + bool HasEdgeType(const std::string &name) const override { return shards_map_.GetEdgeTypeId(name).has_value(); } + + bool HasLabel(const std::string &name) const override { return shards_map_.GetLabelId(name).has_value(); } + private: enum class PaginatedResponseState { Pending, PartiallyFinished }; diff --git a/tests/unit/query_v2_expression_evaluator.cpp b/tests/unit/query_v2_expression_evaluator.cpp index 6bc6e1c8b..97122ff0f 100644 --- a/tests/unit/query_v2_expression_evaluator.cpp +++ b/tests/unit/query_v2_expression_evaluator.cpp @@ -30,6 +30,7 @@ #include "query/v2/frontend/ast/ast.hpp" #include "query/v2/requests.hpp" #include "query/v2/shard_request_manager.hpp" +#include "storage/v3/property_value.hpp" #include "storage/v3/storage.hpp" #include "utils/exceptions.hpp" #include "utils/string.hpp" @@ -117,6 +118,12 @@ class MockedShardRequestManager : public memgraph::msgs::ShardRequestManagerInte return edge_types_.IdToName(id.AsUint()); } + bool HasProperty(const std::string &name) const override { return shards_map_.GetPropertyId(name).has_value(); } + + bool HasEdgeType(const std::string &name) const override { return shards_map_.GetEdgeTypeId(name).has_value(); } + + bool HasLabel(const std::string &name) const override { return shards_map_.GetLabelId(name).has_value(); } + bool IsPrimaryLabel(LabelId label) const override { return true; } bool IsPrimaryKey(LabelId primary_label, PropertyId property) const override { return true; } @@ -202,10 +209,6 @@ class ExpressionEvaluatorTest : public ::testing::Test { ExpressionEvaluatorTest() {} protected: - // memgraph::storage::Storage db; - // memgraph::storage::Storage::Accessor storage_dba{db.Access()}; - // memgraph::query::DbAccessor dba{&storage_dba}; - // AstStorage storage; memgraph::utils::MonotonicBufferResource mem{1024}; EvaluationContext ctx{.memory = &mem, .timestamp = memgraph::query::v2::QueryTimestamp()}; @@ -575,36 +578,33 @@ TEST_F(ExpressionEvaluatorTest, VertexAndEdgeIndexing) { // TODO(kostasrim) Investigate // Shall we return null on missing properties? Or shall we throw bad optional access as we do now? - // { - // // Legal indexing, non-existing key. - // auto *op1 = storage.Create<SubscriptOperator>(vertex_id, storage.Create<PrimitiveLiteral>("blah")); - // auto value1 = Eval(op1); - // EXPECT_TRUE(value1.IsNull()); - // - // auto *op2 = storage.Create<SubscriptOperator>(edge_id, storage.Create<PrimitiveLiteral>("blah")); - // auto value2 = Eval(op2); - // EXPECT_TRUE(value2.IsNull()); - // } - // { - // // Wrong key type. - // auto *op1 = storage.Create<SubscriptOperator>(vertex_id, storage.Create<PrimitiveLiteral>(1)); - // EXPECT_THROW(Eval(op1), ExpressionRuntimeException); - // - // auto *op2 = storage.Create<SubscriptOperator>(edge_id, storage.Create<PrimitiveLiteral>(1)); - // EXPECT_THROW(Eval(op2), ExpressionRuntimeException); - // } - // { - // // Indexing with Null. - // auto *op1 = storage.Create<SubscriptOperator>(vertex_id, - // storage.Create<PrimitiveLiteral>(memgraph::storage::PropertyValue())); - // auto value1 = Eval(op1); - // EXPECT_TRUE(value1.IsNull()); - // - // auto *op2 = storage.Create<SubscriptOperator>(edge_id, - // storage.Create<PrimitiveLiteral>(memgraph::storage::PropertyValue())); - // auto value2 = Eval(op2); - // EXPECT_TRUE(value2.IsNull()); - // } + { + // Legal indexing, non-existing key. + auto *op1 = storage.Create<SubscriptOperator>(vertex_id, storage.Create<PrimitiveLiteral>("blah")); + auto value1 = Eval(op1); + EXPECT_TRUE(value1.IsNull()); + auto *op2 = storage.Create<SubscriptOperator>(edge_id, storage.Create<PrimitiveLiteral>("blah")); + auto value2 = Eval(op2); + EXPECT_TRUE(value2.IsNull()); + } + { + // Wrong key type. + auto *op1 = storage.Create<SubscriptOperator>(vertex_id, storage.Create<PrimitiveLiteral>(1)); + EXPECT_THROW(Eval(op1), ExpressionRuntimeException); + + auto *op2 = storage.Create<SubscriptOperator>(edge_id, storage.Create<PrimitiveLiteral>(1)); + EXPECT_THROW(Eval(op2), ExpressionRuntimeException); + } + { + // Indexing with Null. + auto *op1 = storage.Create<SubscriptOperator>(vertex_id, storage.Create<PrimitiveLiteral>(TypedValue{})); + auto value1 = Eval(op1); + EXPECT_TRUE(value1.IsNull()); + + auto *op2 = storage.Create<SubscriptOperator>(edge_id, storage.Create<PrimitiveLiteral>(TypedValue{})); + auto value2 = Eval(op2); + EXPECT_TRUE(value2.IsNull()); + } } TEST_F(ExpressionEvaluatorTest, ListSlicingOperator) { @@ -741,41 +741,31 @@ TEST_F(ExpressionEvaluatorTest, IsNullOperator) { ASSERT_EQ(val2.ValueBool(), true); } -// TEST_F(ExpressionEvaluatorTest, LabelsTest) { -// auto v1 = dba.InsertVertex(); -// ASSERT_TRUE(v1.AddLabel(dba.NameToLabel("ANIMAL")).HasValue()); -// ASSERT_TRUE(v1.AddLabel(dba.NameToLabel("DOG")).HasValue()); -// ASSERT_TRUE(v1.AddLabel(dba.NameToLabel("NICE_DOG")).HasValue()); -// dba.AdvanceCommand(); -// auto *identifier = storage.Create<Identifier>("n"); -// auto node_symbol = symbol_table.CreateSymbol("n", true); -// identifier->MapTo(node_symbol); -// frame[node_symbol] = TypedValue(v1); -// { -// auto *op = storage.Create<LabelsTest>( -// identifier, std::vector<LabelIx>{storage.GetLabelIx("DOG"), storage.GetLabelIx("ANIMAL")}); -// auto value = Eval(op); -// EXPECT_EQ(value.ValueBool(), true); -// } -// { -// auto *op = storage.Create<LabelsTest>( -// identifier, -// std::vector<LabelIx>{storage.GetLabelIx("DOG"), storage.GetLabelIx("BAD_DOG"), -// storage.GetLabelIx("ANIMAL")}); -// auto value = Eval(op); -// EXPECT_EQ(value.ValueBool(), false); -// } -// { -// frame[node_symbol] = TypedValue(); -// auto *op = storage.Create<LabelsTest>( -// identifier, -// std::vector<LabelIx>{storage.GetLabelIx("DOG"), storage.GetLabelIx("BAD_DOG"), -// storage.GetLabelIx("ANIMAL")}); -// auto value = Eval(op); -// EXPECT_TRUE(value.IsNull()); -// } -// } -// +TEST_F(ExpressionEvaluatorTest, LabelsTest) { + Label label{shard_manager->NameToLabel("label1")}; + auto v1 = CreateVertex({}, shard_manager.get(), label); + auto *identifier = storage.Create<Identifier>("n"); + auto node_symbol = symbol_table.CreateSymbol("n", true); + identifier->MapTo(node_symbol); + frame[node_symbol] = TypedValue(v1); + { + auto *op = storage.Create<LabelsTest>(identifier, std::vector<LabelIx>{LabelIx{"label1", label.id.AsInt()}}); + auto value = Eval(op); + EXPECT_EQ(value.ValueBool(), true); + } + { + auto *op = storage.Create<LabelsTest>(identifier, std::vector<LabelIx>{LabelIx{"label2", 10}}); + auto value = Eval(op); + EXPECT_EQ(value.ValueBool(), false); + } + { + auto *op = storage.Create<LabelsTest>(identifier, std::vector<LabelIx>{LabelIx{"label2", 10}}); + frame[node_symbol] = TypedValue(); + auto value = Eval(op); + EXPECT_TRUE(value.IsNull()); + } +} + TEST_F(ExpressionEvaluatorTest, Aggregation) { auto aggr = storage.Create<Aggregation>(storage.Create<PrimitiveLiteral>(42), nullptr, Aggregation::Op::COUNT); auto aggr_sym = symbol_table.CreateSymbol("aggr", true); @@ -794,11 +784,8 @@ TEST_F(ExpressionEvaluatorTest, ListLiteral) { auto &result_elems = result.ValueList(); ASSERT_EQ(3, result_elems.size()); EXPECT_TRUE(result_elems[0].IsInt()); - ; EXPECT_TRUE(result_elems[1].IsString()); - ; EXPECT_TRUE(result_elems[2].IsBool()); - ; } TEST_F(ExpressionEvaluatorTest, ParameterLookup) { @@ -1148,167 +1135,16 @@ class ExpressionEvaluatorPropertyLookup : public ExpressionEvaluatorTest { } }; +// TODO(kostasrim) These will fail because of memory resource not propagating correctly. This should be done as part of +// polishing the allocators. // TEST_F(ExpressionEvaluatorPropertyLookup, Vertex) { -// auto v1 = dba.InsertVertex(); -// ASSERT_TRUE(v1.SetProperty(prop_age.second, memgraph::storage::PropertyValue(10)).HasValue()); -// dba.AdvanceCommand(); +// auto v1 = CreateVertex({{prop_age.second, memgraph::msgs::Value(static_cast<int64_t>(32))}}, shard_manager.get()); // frame[symbol] = TypedValue(v1); // EXPECT_EQ(Value(prop_age).ValueInt(), 10); // EXPECT_TRUE(Value(prop_height).IsNull()); // } -// -// TEST_F(ExpressionEvaluatorPropertyLookup, Duration) { -// const memgraph::utils::Duration dur({10, 1, 30, 2, 22, 45}); -// frame[symbol] = TypedValue(dur); -// -// const std::pair day = std::make_pair("day", dba.NameToProperty("day")); -// const auto total_days = Value(day); -// EXPECT_TRUE(total_days.IsInt()); -// EXPECT_EQ(total_days.ValueInt(), 10); -// -// const std::pair hour = std::make_pair("hour", dba.NameToProperty("hour")); -// const auto total_hours = Value(hour); -// EXPECT_TRUE(total_hours.IsInt()); -// EXPECT_EQ(total_hours.ValueInt(), 1); -// -// const std::pair minute = std::make_pair("minute", dba.NameToProperty("minute")); -// const auto total_mins = Value(minute); -// EXPECT_TRUE(total_mins.IsInt()); -// -// EXPECT_EQ(total_mins.ValueInt(), 1 * 60 + 30); -// -// const std::pair sec = std::make_pair("second", dba.NameToProperty("second")); -// const auto total_secs = Value(sec); -// EXPECT_TRUE(total_secs.IsInt()); -// const auto expected_secs = total_mins.ValueInt() * 60 + 2; -// EXPECT_EQ(total_secs.ValueInt(), expected_secs); -// -// const std::pair milli = std::make_pair("millisecond", dba.NameToProperty("millisecond")); -// const auto total_milli = Value(milli); -// EXPECT_TRUE(total_milli.IsInt()); -// const auto expected_milli = total_secs.ValueInt() * 1000 + 22; -// EXPECT_EQ(total_milli.ValueInt(), expected_milli); -// -// const std::pair micro = std::make_pair("microsecond", dba.NameToProperty("microsecond")); -// const auto total_micros = Value(micro); -// EXPECT_TRUE(total_micros.IsInt()); -// const auto expected_micros = expected_milli * 1000 + 45; -// EXPECT_EQ(total_micros.ValueInt(), expected_micros); -// -// const std::pair nano = std::make_pair("nanosecond", dba.NameToProperty("nanosecond")); -// const auto total_nano = Value(nano); -// EXPECT_TRUE(total_nano.IsInt()); -// const auto expected_nano = expected_micros * 1000; -// EXPECT_EQ(total_nano.ValueInt(), expected_nano); -// } -// -// TEST_F(ExpressionEvaluatorPropertyLookup, Date) { -// const memgraph::utils::Date date({1996, 11, 22}); -// frame[symbol] = TypedValue(date); -// -// const std::pair year = std::make_pair("year", dba.NameToProperty("year")); -// const auto y = Value(year); -// EXPECT_TRUE(y.IsInt()); -// EXPECT_EQ(y.ValueInt(), 1996); -// -// const std::pair month = std::make_pair("month", dba.NameToProperty("month")); -// const auto m = Value(month); -// EXPECT_TRUE(m.IsInt()); -// EXPECT_EQ(m.ValueInt(), 11); -// -// const std::pair day = std::make_pair("day", dba.NameToProperty("day")); -// const auto d = Value(day); -// EXPECT_TRUE(d.IsInt()); -// EXPECT_EQ(d.ValueInt(), 22); -// } -// -// TEST_F(ExpressionEvaluatorPropertyLookup, LocalTime) { -// const memgraph::utils::LocalTime lt({1, 2, 3, 11, 22}); -// frame[symbol] = TypedValue(lt); -// -// const std::pair hour = std::make_pair("hour", dba.NameToProperty("hour")); -// const auto h = Value(hour); -// EXPECT_TRUE(h.IsInt()); -// EXPECT_EQ(h.ValueInt(), 1); -// -// const std::pair minute = std::make_pair("minute", dba.NameToProperty("minute")); -// const auto min = Value(minute); -// EXPECT_TRUE(min.IsInt()); -// EXPECT_EQ(min.ValueInt(), 2); -// -// const std::pair second = std::make_pair("second", dba.NameToProperty("second")); -// const auto sec = Value(second); -// EXPECT_TRUE(sec.IsInt()); -// EXPECT_EQ(sec.ValueInt(), 3); -// -// const std::pair millis = std::make_pair("millisecond", dba.NameToProperty("millisecond")); -// const auto mil = Value(millis); -// EXPECT_TRUE(mil.IsInt()); -// EXPECT_EQ(mil.ValueInt(), 11); -// -// const std::pair micros = std::make_pair("microsecond", dba.NameToProperty("microsecond")); -// const auto mic = Value(micros); -// EXPECT_TRUE(mic.IsInt()); -// EXPECT_EQ(mic.ValueInt(), 22); -// } -// -// TEST_F(ExpressionEvaluatorPropertyLookup, LocalDateTime) { -// const memgraph::utils::LocalDateTime ldt({1993, 8, 6}, {2, 3, 4, 55, 40}); -// frame[symbol] = TypedValue(ldt); -// -// const std::pair year = std::make_pair("year", dba.NameToProperty("year")); -// const auto y = Value(year); -// EXPECT_TRUE(y.IsInt()); -// EXPECT_EQ(y.ValueInt(), 1993); -// -// const std::pair month = std::make_pair("month", dba.NameToProperty("month")); -// const auto m = Value(month); -// EXPECT_TRUE(m.IsInt()); -// EXPECT_EQ(m.ValueInt(), 8); -// -// const std::pair day = std::make_pair("day", dba.NameToProperty("day")); -// const auto d = Value(day); -// EXPECT_TRUE(d.IsInt()); -// EXPECT_EQ(d.ValueInt(), 6); -// -// const std::pair hour = std::make_pair("hour", dba.NameToProperty("hour")); -// const auto h = Value(hour); -// EXPECT_TRUE(h.IsInt()); -// EXPECT_EQ(h.ValueInt(), 2); -// -// const std::pair minute = std::make_pair("minute", dba.NameToProperty("minute")); -// const auto min = Value(minute); -// EXPECT_TRUE(min.IsInt()); -// EXPECT_EQ(min.ValueInt(), 3); -// -// const std::pair second = std::make_pair("second", dba.NameToProperty("second")); -// const auto sec = Value(second); -// EXPECT_TRUE(sec.IsInt()); -// EXPECT_EQ(sec.ValueInt(), 4); -// -// const std::pair millis = std::make_pair("millisecond", dba.NameToProperty("millisecond")); -// const auto mil = Value(millis); -// EXPECT_TRUE(mil.IsInt()); -// EXPECT_EQ(mil.ValueInt(), 55); -// -// const std::pair micros = std::make_pair("microsecond", dba.NameToProperty("microsecond")); -// const auto mic = Value(micros); -// EXPECT_TRUE(mic.IsInt()); -// EXPECT_EQ(mic.ValueInt(), 40); -// } -// -// TEST_F(ExpressionEvaluatorPropertyLookup, Edge) { -// auto v1 = dba.InsertVertex(); -// auto v2 = dba.InsertVertex(); -// auto e12 = dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("edge_type")); -// ASSERT_TRUE(e12.HasValue()); -// ASSERT_TRUE(e12->SetProperty(prop_age.second, memgraph::storage::PropertyValue(10)).HasValue()); -// dba.AdvanceCommand(); -// frame[symbol] = TypedValue(*e12); -// EXPECT_EQ(Value(prop_age).ValueInt(), 10); -// EXPECT_TRUE(Value(prop_height).IsNull()); -// } -// +// TEST_F(ExpressionEvaluatorPropertyLookup, Edge) {} + TEST_F(ExpressionEvaluatorPropertyLookup, Null) { frame[symbol] = TypedValue(); EXPECT_TRUE(Value(prop_age).IsNull()); @@ -1455,59 +1291,10 @@ TEST_F(FunctionTest, StartNode) { } // TODO(kostasrim) Enable this test once we add degree to the accessors -// TEST_F(FunctionTest, Degree) { -// ASSERT_THROW(EvaluateFunction("DEGREE"), ExpressionRuntimeException); -// ASSERT_TRUE(EvaluateFunction("DEGREE", TypedValue()).IsNull()); -// auto v1 = dba.InsertVertex(); -// auto v2 = dba.InsertVertex(); -// auto v3 = dba.InsertVertex(); -// auto e12 = dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("t")); -// ASSERT_TRUE(e12.HasValue()); -// ASSERT_TRUE(dba.InsertEdge(&v3, &v2, dba.NameToEdgeType("t")).HasValue()); -// dba.AdvanceCommand(); -// ASSERT_EQ(EvaluateFunction("DEGREE", v1).ValueInt(), 1); -// ASSERT_EQ(EvaluateFunction("DEGREE", v2).ValueInt(), 2); -// ASSERT_EQ(EvaluateFunction("DEGREE", v3).ValueInt(), 1); -// ASSERT_THROW(EvaluateFunction("DEGREE", 2), ExpressionRuntimeException); -// ASSERT_THROW(EvaluateFunction("DEGREE", *e12), ExpressionRuntimeException); -// } -// -// TODO(kostasrim) Enable this test once we add InDegree to the accessors -// TEST_F(FunctionTest, InDegree) { -// ASSERT_THROW(EvaluateFunction("INDEGREE"), ExpressionRuntimeException); -// ASSERT_TRUE(EvaluateFunction("INDEGREE", TypedValue()).IsNull()); -// auto v1 = dba.InsertVertex(); -// auto v2 = dba.InsertVertex(); -// auto v3 = dba.InsertVertex(); -// auto e12 = dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("t")); -// ASSERT_TRUE(e12.HasValue()); -// ASSERT_TRUE(dba.InsertEdge(&v3, &v2, dba.NameToEdgeType("t")).HasValue()); -// dba.AdvanceCommand(); -// ASSERT_EQ(EvaluateFunction("INDEGREE", v1).ValueInt(), 0); -// ASSERT_EQ(EvaluateFunction("INDEGREE", v2).ValueInt(), 2); -// ASSERT_EQ(EvaluateFunction("INDEGREE", v3).ValueInt(), 0); -// ASSERT_THROW(EvaluateFunction("INDEGREE", 2), ExpressionRuntimeException); -// ASSERT_THROW(EvaluateFunction("INDEGREE", *e12), ExpressionRuntimeException); -// } -// -// TODO(kostasrim) Enable this test once we add OutDegree to the accessors -// TEST_F(FunctionTest, OutDegree) { -// ASSERT_THROW(EvaluateFunction("OUTDEGREE"), ExpressionRuntimeException); -// ASSERT_TRUE(EvaluateFunction("OUTDEGREE", TypedValue()).IsNull()); -// auto v1 = dba.InsertVertex(); -// auto v2 = dba.InsertVertex(); -// auto v3 = dba.InsertVertex(); -// auto e12 = dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("t")); -// ASSERT_TRUE(e12.HasValue()); -// ASSERT_TRUE(dba.InsertEdge(&v3, &v2, dba.NameToEdgeType("t")).HasValue()); -// dba.AdvanceCommand(); -// ASSERT_EQ(EvaluateFunction("OUTDEGREE", v1).ValueInt(), 1); -// ASSERT_EQ(EvaluateFunction("OUTDEGREE", v2).ValueInt(), 0); -// ASSERT_EQ(EvaluateFunction("OUTDEGREE", v3).ValueInt(), 1); -// ASSERT_THROW(EvaluateFunction("OUTDEGREE", 2), ExpressionRuntimeException); -// ASSERT_THROW(EvaluateFunction("OUTDEGREE", *e12), ExpressionRuntimeException); -// } -// +// TEST_F(FunctionTest, Degree) {} +// TEST_F(FunctionTest, InDegree) {} +// TEST_F(FunctionTest, OutDegree) {} + TEST_F(FunctionTest, ToBoolean) { ASSERT_THROW(EvaluateFunction("TOBOOLEAN"), FunctionRuntimeException); ASSERT_TRUE(EvaluateFunction("TOBOOLEAN", TypedValue()).IsNull()); @@ -1591,42 +1378,8 @@ TEST_F(FunctionTest, Labels) { } // TODO(kostasrim) Enable this once we fix accessors Path -// TEST_F(FunctionTest, NodesRelationships) { -// EXPECT_THROW(EvaluateFunction("NODES"), ExpressionRuntimeException); -// EXPECT_THROW(EvaluateFunction("RELATIONSHIPS"), ExpressionRuntimeException); -// EXPECT_TRUE(EvaluateFunction("NODES", TypedValue()).IsNull()); -// EXPECT_TRUE(EvaluateFunction("RELATIONSHIPS", TypedValue()).IsNull()); -// -// { -// auto v1 = dba.InsertVertex(); -// auto v2 = dba.InsertVertex(); -// auto v3 = dba.InsertVertex(); -// auto e1 = dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("Type")); -// ASSERT_TRUE(e1.HasValue()); -// auto e2 = dba.InsertEdge(&v2, &v3, dba.NameToEdgeType("Type")); -// ASSERT_TRUE(e2.HasValue()); -// memgraph::query::Path path{v1, *e1, v2, *e2, v3}; -// dba.AdvanceCommand(); -// -// auto _nodes = EvaluateFunction("NODES", path).ValueList(); -// std::vector<memgraph::query::VertexAccessor> nodes; -// for (const auto &node : _nodes) { -// nodes.push_back(node.ValueVertex()); -// } -// EXPECT_THAT(nodes, ElementsAre(v1, v2, v3)); -// -// auto _edges = EvaluateFunction("RELATIONSHIPS", path).ValueList(); -// std::vector<memgraph::query::EdgeAccessor> edges; -// for (const auto &edge : _edges) { -// edges.push_back(edge.ValueEdge()); -// } -// EXPECT_THAT(edges, ElementsAre(*e1, *e2)); -// } -// -// EXPECT_THROW(EvaluateFunction("NODES", 2), ExpressionRuntimeException); -// EXPECT_THROW(EvaluateFunction("RELATIONSHIPS", 2), ExpressionRuntimeException); -// } -// +// TEST_F(FunctionTest, NodesRelationships) {} + TEST_F(FunctionTest, Range) { EXPECT_THROW(EvaluateFunction("RANGE"), FunctionRuntimeException); EXPECT_TRUE(EvaluateFunction("RANGE", 1, 2, TypedValue()).IsNull()); @@ -1889,64 +1642,10 @@ TEST_F(FunctionTest, ToStringBool) { EXPECT_EQ(EvaluateFunction("TOSTRING", false).ValueString(), "false"); } -// TEST_F(FunctionTest, ToStringDate) { -// const auto date = memgraph::utils::Date({1970, 1, 2}); -// EXPECT_EQ(EvaluateFunction("TOSTRING", date).ValueString(), "1970-01-02"); -// } -// -// TEST_F(FunctionTest, ToStringLocalTime) { -// const auto lt = memgraph::utils::LocalTime({13, 2, 40, 100, 50}); -// EXPECT_EQ(EvaluateFunction("TOSTRING", lt).ValueString(), "13:02:40.100050"); -// } -// -// TEST_F(FunctionTest, ToStringLocalDateTime) { -// const auto ldt = memgraph::utils::LocalDateTime({1970, 1, 2}, {23, 02, 59}); -// EXPECT_EQ(EvaluateFunction("TOSTRING", ldt).ValueString(), "1970-01-02T23:02:59.000000"); -// } -// -// TEST_F(FunctionTest, ToStringDuration) { -// memgraph::utils::Duration duration{{.minute = 2, .second = 2, .microsecond = 33}}; -// EXPECT_EQ(EvaluateFunction("TOSTRING", duration).ValueString(), "P0DT0H2M2.000033S"); -// } -// TEST_F(FunctionTest, ToStringExceptions) { EXPECT_THROW(EvaluateFunction("TOSTRING", 1, 2, 3), FunctionRuntimeException); } -// -// TEST_F(FunctionTest, TimestampVoid) { -// ctx.timestamp = 42; -// EXPECT_EQ(EvaluateFunction("TIMESTAMP").ValueInt(), 42); -// } -// -// TEST_F(FunctionTest, TimestampDate) { -// ctx.timestamp = 42; -// EXPECT_EQ(EvaluateFunction("TIMESTAMP", memgraph::utils::Date({1970, 1, 1})).ValueInt(), 0); -// EXPECT_EQ(EvaluateFunction("TIMESTAMP", memgraph::utils::Date({1971, 1, 1})).ValueInt(), 31536000000000); -// } -// -// TEST_F(FunctionTest, TimestampLocalTime) { -// ctx.timestamp = 42; -// const memgraph::utils::LocalTime time(10000); -// EXPECT_EQ(EvaluateFunction("TIMESTAMP", time).ValueInt(), 10000); -// } -// -// TEST_F(FunctionTest, TimestampLocalDateTime) { -// ctx.timestamp = 42; -// const memgraph::utils::LocalDateTime time(20000); -// EXPECT_EQ(EvaluateFunction("TIMESTAMP", time).ValueInt(), 20000); -// } -// -// TEST_F(FunctionTest, TimestampDuration) { -// ctx.timestamp = 42; -// const memgraph::utils::Duration time(20000); -// EXPECT_EQ(EvaluateFunction("TIMESTAMP", time).ValueInt(), 20000); -// } -// -// TEST_F(FunctionTest, TimestampExceptions) { -// ctx.timestamp = 42; -// EXPECT_THROW(EvaluateFunction("TIMESTAMP", 1).ValueInt(), ExpressionRuntimeException); -// } -// + TEST_F(FunctionTest, Left) { EXPECT_THROW(EvaluateFunction("LEFT"), FunctionRuntimeException); @@ -2083,110 +1782,5 @@ TEST_F(FunctionTest, FromByteString) { EXPECT_EQ(EvaluateFunction("FROMBYTESTRING", std::string("\x00\x42", 2)).ValueString(), "0x0042"); } -// TEST_F(FunctionTest, Date) { -// const auto unix_epoch = memgraph::utils::Date({1970, 1, 1}); -// EXPECT_EQ(EvaluateFunction("DATE", "1970-01-01").ValueDate(), unix_epoch); -// const auto map_param = TypedValue( -// std::map<std::string, TypedValue>{{"year", TypedValue(1970)}, {"month", TypedValue(1)}, {"day", -// TypedValue(1)}}); -// EXPECT_EQ(EvaluateFunction("DATE", map_param).ValueDate(), unix_epoch); -// const auto today = memgraph::utils::CurrentDate(); -// EXPECT_EQ(EvaluateFunction("DATE").ValueDate(), today); -// -// EXPECT_THROW(EvaluateFunction("DATE", "{}"), memgraph::utils::BasicException); -// EXPECT_THROW(EvaluateFunction("DATE", std::map<std::string, TypedValue>{{"years", TypedValue(1970)}}), -// ExpressionRuntimeException); -// EXPECT_THROW(EvaluateFunction("DATE", std::map<std::string, TypedValue>{{"mnths", TypedValue(1970)}}), -// ExpressionRuntimeException); -// EXPECT_THROW(EvaluateFunction("DATE", std::map<std::string, TypedValue>{{"dayz", TypedValue(1970)}}), -// ExpressionRuntimeException); -// } -// -// TEST_F(FunctionTest, LocalTime) { -// const auto local_time = memgraph::utils::LocalTime({13, 3, 2, 0, 0}); -// EXPECT_EQ(EvaluateFunction("LOCALTIME", "130302").ValueLocalTime(), local_time); -// const auto one_sec_in_microseconds = 1000000; -// const auto map_param = TypedValue(std::map<std::string, TypedValue>{{"hour", TypedValue(1)}, -// {"minute", TypedValue(2)}, -// {"second", TypedValue(3)}, -// {"millisecond", TypedValue(4)}, -// {"microsecond", TypedValue(5)}}); -// EXPECT_EQ(EvaluateFunction("LOCALTIME", map_param).ValueLocalTime(), memgraph::utils::LocalTime({1, 2, 3, 4, 5})); -// const auto today = memgraph::utils::CurrentLocalTime(); -// EXPECT_NEAR(EvaluateFunction("LOCALTIME").ValueLocalTime().MicrosecondsSinceEpoch(), -// today.MicrosecondsSinceEpoch(), -// one_sec_in_microseconds); -// -// EXPECT_THROW(EvaluateFunction("LOCALTIME", "{}"), memgraph::utils::BasicException); -// EXPECT_THROW(EvaluateFunction("LOCALTIME", TypedValue(std::map<std::string, TypedValue>{{"hous", -// TypedValue(1970)}})), -// ExpressionRuntimeException); -// EXPECT_THROW( -// EvaluateFunction("LOCALTIME", TypedValue(std::map<std::string, TypedValue>{{"minut", TypedValue(1970)}})), -// ExpressionRuntimeException); -// EXPECT_THROW( -// EvaluateFunction("LOCALTIME", TypedValue(std::map<std::string, TypedValue>{{"seconds", TypedValue(1970)}})), -// ExpressionRuntimeException); -// } -// -// TEST_F(FunctionTest, LocalDateTime) { -// const auto local_date_time = memgraph::utils::LocalDateTime({1970, 1, 1}, {13, 3, 2, 0, 0}); -// EXPECT_EQ(EvaluateFunction("LOCALDATETIME", "1970-01-01T13:03:02").ValueLocalDateTime(), local_date_time); -// const auto today = memgraph::utils::CurrentLocalDateTime(); -// const auto one_sec_in_microseconds = 1000000; -// const auto map_param = TypedValue(std::map<std::string, TypedValue>{{"year", TypedValue(1972)}, -// {"month", TypedValue(2)}, -// {"day", TypedValue(3)}, -// {"hour", TypedValue(4)}, -// {"minute", TypedValue(5)}, -// {"second", TypedValue(6)}, -// {"millisecond", TypedValue(7)}, -// {"microsecond", TypedValue(8)}}); -// -// EXPECT_EQ(EvaluateFunction("LOCALDATETIME", map_param).ValueLocalDateTime(), -// memgraph::utils::LocalDateTime({1972, 2, 3}, {4, 5, 6, 7, 8})); -// EXPECT_NEAR(EvaluateFunction("LOCALDATETIME").ValueLocalDateTime().MicrosecondsSinceEpoch(), -// today.MicrosecondsSinceEpoch(), one_sec_in_microseconds); -// EXPECT_THROW(EvaluateFunction("LOCALDATETIME", "{}"), memgraph::utils::BasicException); -// EXPECT_THROW( -// EvaluateFunction("LOCALDATETIME", TypedValue(std::map<std::string, TypedValue>{{"hours", TypedValue(1970)}})), -// ExpressionRuntimeException); -// EXPECT_THROW( -// EvaluateFunction("LOCALDATETIME", TypedValue(std::map<std::string, TypedValue>{{"seconds", -// TypedValue(1970)}})), ExpressionRuntimeException); -// } -// -// TEST_F(FunctionTest, Duration) { -// const auto map_param = TypedValue(std::map<std::string, TypedValue>{{"day", TypedValue(3)}, -// {"hour", TypedValue(4)}, -// {"minute", TypedValue(5)}, -// {"second", TypedValue(6)}, -// {"millisecond", TypedValue(7)}, -// {"microsecond", TypedValue(8)}}); -// -// EXPECT_EQ(EvaluateFunction("DURATION", map_param).ValueDuration(), memgraph::utils::Duration({3, 4, 5, 6, 7, 8})); -// EXPECT_THROW(EvaluateFunction("DURATION", "{}"), memgraph::utils::BasicException); -// EXPECT_THROW(EvaluateFunction("DURATION", TypedValue(std::map<std::string, TypedValue>{{"hours", -// TypedValue(1970)}})), -// ExpressionRuntimeException); -// EXPECT_THROW( -// EvaluateFunction("DURATION", TypedValue(std::map<std::string, TypedValue>{{"seconds", TypedValue(1970)}})), -// ExpressionRuntimeException); -// -// const auto map_param_negative = TypedValue(std::map<std::string, TypedValue>{{"day", TypedValue(-3)}, -// {"hour", TypedValue(-4)}, -// {"minute", TypedValue(-5)}, -// {"second", TypedValue(-6)}, -// {"millisecond", TypedValue(-7)}, -// {"microsecond", TypedValue(-8)}}); -// EXPECT_EQ(EvaluateFunction("DURATION", map_param_negative).ValueDuration(), -// memgraph::utils::Duration({-3, -4, -5, -6, -7, -8})); -// -// EXPECT_EQ(EvaluateFunction("DURATION", "P4DT4H5M6.2S").ValueDuration(), -// memgraph::utils::Duration({4, 4, 5, 6, 0, 200000})); -// EXPECT_EQ(EvaluateFunction("DURATION", "P3DT4H5M6.100S").ValueDuration(), -// memgraph::utils::Duration({3, 4, 5, 6, 0, 100000})); -// EXPECT_EQ(EvaluateFunction("DURATION", "P3DT4H5M6.100110S").ValueDuration(), -// memgraph::utils::Duration({3, 4, 5, 6, 100, 110})); -// } +// TODO(kostasrim) Add temporal type tests. } // namespace