diff --git a/src/common/expression/test/CMakeLists.txt b/src/common/expression/test/CMakeLists.txt index 20ba9d99f2a..577ce3f2f79 100644 --- a/src/common/expression/test/CMakeLists.txt +++ b/src/common/expression/test/CMakeLists.txt @@ -3,6 +3,50 @@ # This source code is licensed under Apache 2.0 License, # attached with Common Clause Condition 1.0, found in the LICENSES directory. +set(expression_test_common_libs + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ +) + nebula_add_library( expr_ctx_mock_obj OBJECT ExpressionContextMock.cpp @@ -24,9 +68,11 @@ nebula_add_test( $ $ $ + ${expression_test_common_libs} LIBRARIES gtest ${THRIFT_LIBRARIES} + ${PROXYGEN_LIBRARIES} ) nebula_add_executable( @@ -45,10 +91,12 @@ nebula_add_executable( $ $ $ + ${expression_test_common_libs} LIBRARIES follybenchmark boost_regex ${THRIFT_LIBRARIES} + ${PROXYGEN_LIBRARIES} ) nebula_add_executable( @@ -110,9 +158,11 @@ nebula_add_test( $ $ $ + ${expression_test_common_libs} LIBRARIES gtest ${THRIFT_LIBRARIES} + ${PROXYGEN_LIBRARIES} ) nebula_add_test( @@ -129,9 +179,11 @@ nebula_add_test( $ $ $ + ${expression_test_common_libs} LIBRARIES gtest ${THRIFT_LIBRARIES} + ${PROXYGEN_LIBRARIES} ) nebula_add_test( @@ -148,9 +200,11 @@ nebula_add_test( $ $ $ + ${expression_test_common_libs} LIBRARIES gtest ${THRIFT_LIBRARIES} + ${PROXYGEN_LIBRARIES} ) nebula_add_test( @@ -167,9 +221,11 @@ nebula_add_test( $ $ $ + ${expression_test_common_libs} LIBRARIES gtest ${THRIFT_LIBRARIES} + ${PROXYGEN_LIBRARIES} ) nebula_add_test( @@ -186,9 +242,11 @@ nebula_add_test( $ $ $ + ${expression_test_common_libs} LIBRARIES gtest ${THRIFT_LIBRARIES} + ${PROXYGEN_LIBRARIES} ) nebula_add_test( @@ -205,9 +263,11 @@ nebula_add_test( $ $ $ + ${expression_test_common_libs} LIBRARIES gtest ${THRIFT_LIBRARIES} + ${PROXYGEN_LIBRARIES} ) nebula_add_test( @@ -224,9 +284,11 @@ nebula_add_test( $ $ $ + ${expression_test_common_libs} LIBRARIES gtest ${THRIFT_LIBRARIES} + ${PROXYGEN_LIBRARIES} ) nebula_add_test( @@ -243,9 +305,11 @@ nebula_add_test( $ $ $ + ${expression_test_common_libs} LIBRARIES gtest ${THRIFT_LIBRARIES} + ${PROXYGEN_LIBRARIES} ) nebula_add_test( @@ -262,9 +326,11 @@ nebula_add_test( $ $ $ + ${expression_test_common_libs} LIBRARIES gtest ${THRIFT_LIBRARIES} + ${PROXYGEN_LIBRARIES} ) nebula_add_test( @@ -281,9 +347,11 @@ nebula_add_test( $ $ $ + ${expression_test_common_libs} LIBRARIES gtest ${THRIFT_LIBRARIES} + ${PROXYGEN_LIBRARIES} ) nebula_add_test( @@ -300,9 +368,11 @@ nebula_add_test( $ $ $ + ${expression_test_common_libs} LIBRARIES gtest ${THRIFT_LIBRARIES} + ${PROXYGEN_LIBRARIES} ) nebula_add_test( @@ -319,9 +389,11 @@ nebula_add_test( $ $ $ + ${expression_test_common_libs} LIBRARIES gtest ${THRIFT_LIBRARIES} + ${PROXYGEN_LIBRARIES} ) nebula_add_test( @@ -338,9 +410,11 @@ nebula_add_test( $ $ $ + ${expression_test_common_libs} LIBRARIES gtest ${THRIFT_LIBRARIES} + ${PROXYGEN_LIBRARIES} ) nebula_add_test( @@ -357,9 +431,11 @@ nebula_add_test( $ $ $ + ${expression_test_common_libs} LIBRARIES gtest ${THRIFT_LIBRARIES} + ${PROXYGEN_LIBRARIES} ) nebula_add_test( @@ -376,9 +452,11 @@ nebula_add_test( $ $ $ + ${expression_test_common_libs} LIBRARIES gtest ${THRIFT_LIBRARIES} + ${PROXYGEN_LIBRARIES} ) nebula_add_test( @@ -395,9 +473,11 @@ nebula_add_test( $ $ $ + ${expression_test_common_libs} LIBRARIES gtest ${THRIFT_LIBRARIES} + ${PROXYGEN_LIBRARIES} ) nebula_add_test( @@ -414,9 +494,11 @@ nebula_add_test( $ $ $ + ${expression_test_common_libs} LIBRARIES gtest ${THRIFT_LIBRARIES} + ${PROXYGEN_LIBRARIES} ) nebula_add_test( @@ -433,9 +515,11 @@ nebula_add_test( $ $ $ + ${expression_test_common_libs} LIBRARIES gtest ${THRIFT_LIBRARIES} + ${PROXYGEN_LIBRARIES} ) nebula_add_test( @@ -452,9 +536,11 @@ nebula_add_test( $ $ $ + ${expression_test_common_libs} LIBRARIES gtest ${THRIFT_LIBRARIES} + ${PROXYGEN_LIBRARIES} ) nebula_add_test( @@ -471,7 +557,9 @@ nebula_add_test( $ $ $ + ${expression_test_common_libs} LIBRARIES gtest ${THRIFT_LIBRARIES} + ${PROXYGEN_LIBRARIES} ) diff --git a/src/common/expression/test/FunctionCallExpressionTest.cpp b/src/common/expression/test/FunctionCallExpressionTest.cpp index 2f10c8ed350..63f6216f445 100644 --- a/src/common/expression/test/FunctionCallExpressionTest.cpp +++ b/src/common/expression/test/FunctionCallExpressionTest.cpp @@ -60,7 +60,7 @@ TEST_F(FunctionCallExpressionTest, FunctionCallTest) { path.src.vid = "1"; STEP("2", "edge", 0, 1); STEP("1", "edge", 0, -1); - TEST_FUNCTION(hasSameEdgeInPath, {path}, true); + TEST_PATH_FUNCTION(hasSameEdgeInPath, {path}, true); } { // hasSameEdgeInPath @@ -70,7 +70,7 @@ TEST_F(FunctionCallExpressionTest, FunctionCallTest) { STEP("2", "edge", 0, 1); STEP("1", "edge", 0, -1); STEP("2", "edge", 0, 1); - TEST_FUNCTION(hasSameEdgeInPath, {path}, true); + TEST_PATH_FUNCTION(hasSameEdgeInPath, {path}, true); } { // hasSameEdgeInPath @@ -80,7 +80,7 @@ TEST_F(FunctionCallExpressionTest, FunctionCallTest) { STEP("2", "edge", 0, 1); STEP("1", "edge", 0, 1); STEP("2", "edge", 0, 1); - TEST_FUNCTION(hasSameEdgeInPath, {path}, false); + TEST_PATH_FUNCTION(hasSameEdgeInPath, {path}, false); } { // hasSameEdgeInPath @@ -90,7 +90,7 @@ TEST_F(FunctionCallExpressionTest, FunctionCallTest) { STEP("2", "edge", 0, 1); STEP("1", "edge", 0, -1); STEP("2", "edge", 1, 1); - TEST_FUNCTION(hasSameEdgeInPath, {path}, false); + TEST_PATH_FUNCTION(hasSameEdgeInPath, {path}, false); } // Check function { diff --git a/src/common/expression/test/LogicalExpressionTest.cpp b/src/common/expression/test/LogicalExpressionTest.cpp index dd900642e20..4d87f99cbc7 100644 --- a/src/common/expression/test/LogicalExpressionTest.cpp +++ b/src/common/expression/test/LogicalExpressionTest.cpp @@ -94,21 +94,63 @@ TEST_F(LogicalExpressionTest, LogicalCalculation) { TEST_EXPR(true AND 2 / 0, Value::kNullDivByZero); TEST_EXPR(false AND 2 / 0, false); TEST_EXPR(2 / 0 AND 2 / 0, Value::kNullDivByZero); - TEST_EXPR(empty AND null AND 2 / 0 AND empty, Value::kNullDivByZero); + { + // empty AND null AND 2 / 0 AND empty + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(NullType::__NULL__)); + auto *operand3 = LogicalExpression::makeAnd(&pool, operand1, operand2); + auto *operand4 = ConstantExpression::make(&pool, Value(2)); + auto *operand5 = ConstantExpression::make(&pool, Value(0)); + auto *operand6 = ArithmeticExpression::makeDivision(&pool, operand4, operand5); + auto *operand7 = LogicalExpression::makeAnd(&pool, operand3, operand6); + auto *operand8 = ConstantExpression::make(&pool, Value()); + auto *expr = LogicalExpression::makeAnd(&pool, operand7, operand8); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kNullDivByZero.type()); + EXPECT_EQ(eval, Value::kNullDivByZero) << "check failed: " << expr->toString(); + } TEST_EXPR(2 / 0 OR true, Value::kNullDivByZero); TEST_EXPR(2 / 0 OR false, Value::kNullDivByZero); TEST_EXPR(true OR 2 / 0, true); TEST_EXPR(false OR 2 / 0, Value::kNullDivByZero); TEST_EXPR(2 / 0 OR 2 / 0, Value::kNullDivByZero); - TEST_EXPR(empty OR null OR 2 / 0 OR empty, Value::kNullDivByZero); + { + // empty OR null OR 2 / 0 OR empty + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(NullType::__NULL__)); + auto *operand3 = LogicalExpression::makeOr(&pool, operand1, operand2); + auto *operand4 = ConstantExpression::make(&pool, Value(2)); + auto *operand5 = ConstantExpression::make(&pool, Value(0)); + auto *operand6 = ArithmeticExpression::makeDivision(&pool, operand4, operand5); + auto *operand7 = LogicalExpression::makeOr(&pool, operand3, operand6); + auto *operand8 = ConstantExpression::make(&pool, Value()); + auto *expr = LogicalExpression::makeOr(&pool, operand7, operand8); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kNullDivByZero.type()); + EXPECT_EQ(eval, Value::kNullDivByZero) << "check failed: " << expr->toString(); + } TEST_EXPR(2 / 0 XOR true, Value::kNullDivByZero); TEST_EXPR(2 / 0 XOR false, Value::kNullDivByZero); TEST_EXPR(true XOR 2 / 0, Value::kNullDivByZero); TEST_EXPR(false XOR 2 / 0, Value::kNullDivByZero); TEST_EXPR(2 / 0 XOR 2 / 0, Value::kNullDivByZero); - TEST_EXPR(empty XOR 2 / 0 XOR null XOR empty, Value::kNullDivByZero); + { + // empty XOR 2 / 0 XOR null XOR empty + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(2)); + auto *operand3 = ConstantExpression::make(&pool, Value(0)); + auto *operand4 = ArithmeticExpression::makeDivision(&pool, operand2, operand3); + auto *operand5 = LogicalExpression::makeXor(&pool, operand1, operand4); + auto *operand6 = ConstantExpression::make(&pool, Value(NullType::__NULL__)); + auto *operand7 = LogicalExpression::makeXor(&pool, operand5, operand6); + auto *operand8 = ConstantExpression::make(&pool, Value()); + auto *expr = LogicalExpression::makeXor(&pool, operand7, operand8); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kNullDivByZero.type()); + EXPECT_EQ(eval, Value::kNullDivByZero) << "check failed: " << expr->toString(); + } // test normal null TEST_EXPR(null AND true, Value::kNullValue); @@ -116,62 +158,411 @@ TEST_F(LogicalExpressionTest, LogicalCalculation) { TEST_EXPR(true AND null, Value::kNullValue); TEST_EXPR(false AND null, false); TEST_EXPR(null AND null, Value::kNullValue); - TEST_EXPR(empty AND null AND empty, Value::kNullValue); + { + // empty AND null AND empty + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(NullType::__NULL__)); + auto *operand3 = LogicalExpression::makeAnd(&pool, operand1, operand2); + auto *operand4 = ConstantExpression::make(&pool, Value()); + auto *expr = LogicalExpression::makeAnd(&pool, operand3, operand4); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kNullValue.type()); + EXPECT_EQ(eval, Value::kNullValue) << "check failed: " << expr->toString(); + } TEST_EXPR(null OR true, true); TEST_EXPR(null OR false, Value::kNullValue); TEST_EXPR(true OR null, true); TEST_EXPR(false OR null, Value::kNullValue); TEST_EXPR(null OR null, Value::kNullValue); - TEST_EXPR(empty OR null OR empty, Value::kNullValue); + { + // empty OR null OR empty + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(NullType::__NULL__)); + auto *operand3 = LogicalExpression::makeOr(&pool, operand1, operand2); + auto *operand4 = ConstantExpression::make(&pool, Value()); + auto *expr = LogicalExpression::makeOr(&pool, operand3, operand4); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kNullValue.type()); + EXPECT_EQ(eval, Value::kNullValue) << "check failed: " << expr->toString(); + } TEST_EXPR(null XOR true, Value::kNullValue); TEST_EXPR(null XOR false, Value::kNullValue); TEST_EXPR(true XOR null, Value::kNullValue); TEST_EXPR(false XOR null, Value::kNullValue); TEST_EXPR(null XOR null, Value::kNullValue); - TEST_EXPR(empty XOR null XOR empty, Value::kNullValue); + { + // empty XOR null XOR empty + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(NullType::__NULL__)); + auto *operand3 = LogicalExpression::makeXor(&pool, operand1, operand2); + auto *operand4 = ConstantExpression::make(&pool, Value()); + auto *expr = LogicalExpression::makeXor(&pool, operand3, operand4); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kNullValue.type()); + EXPECT_EQ(eval, Value::kNullValue) << "check failed: " << expr->toString(); + } // test empty - TEST_EXPR(empty, Value::kEmpty); - TEST_EXPR(empty AND true, Value::kEmpty); - TEST_EXPR(empty AND false, false); - TEST_EXPR(true AND empty, Value::kEmpty); - TEST_EXPR(false AND empty, false); - TEST_EXPR(empty AND empty, Value::kEmpty); - TEST_EXPR(empty AND null, Value::kNullValue); - TEST_EXPR(null AND empty, Value::kNullValue); - TEST_EXPR(empty AND true AND empty, Value::kEmpty); - - TEST_EXPR(empty OR true, true); - TEST_EXPR(empty OR false, Value::kEmpty); - TEST_EXPR(true OR empty, true); - TEST_EXPR(false OR empty, Value::kEmpty); - TEST_EXPR(empty OR empty, Value::kEmpty); - TEST_EXPR(empty OR null, Value::kNullValue); - TEST_EXPR(null OR empty, Value::kNullValue); - TEST_EXPR(empty OR false OR empty, Value::kEmpty); - - TEST_EXPR(empty XOR true, Value::kEmpty); - TEST_EXPR(empty XOR false, Value::kEmpty); - TEST_EXPR(true XOR empty, Value::kEmpty); - TEST_EXPR(false XOR empty, Value::kEmpty); - TEST_EXPR(empty XOR empty, Value::kEmpty); - TEST_EXPR(empty XOR null, Value::kNullValue); - TEST_EXPR(null XOR empty, Value::kNullValue); - TEST_EXPR(true XOR empty XOR false, Value::kEmpty); - - TEST_EXPR(empty OR false AND true AND null XOR empty, Value::kEmpty); - TEST_EXPR(empty OR false AND true XOR empty OR true, true); + { + // empty + auto *expr = ConstantExpression::make(&pool, Value()); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kEmpty.type()); + EXPECT_EQ(eval, Value::kEmpty) << "check failed: " << expr->toString(); + } + { + // empty AND true + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(true)); + auto *expr = LogicalExpression::makeAnd(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kEmpty.type()); + EXPECT_EQ(eval, Value::kEmpty) << "check failed: " << expr->toString(); + } + { + // empty AND false + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(false)); + auto *expr = LogicalExpression::makeAnd(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value(false).type()); + EXPECT_EQ(eval, Value(false)) << "check failed: " << expr->toString(); + } + { + // true AND empty + auto *operand1 = ConstantExpression::make(&pool, Value(true)); + auto *operand2 = ConstantExpression::make(&pool, Value()); + auto *expr = LogicalExpression::makeAnd(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kEmpty.type()); + EXPECT_EQ(eval, Value::kEmpty) << "check failed: " << expr->toString(); + } + { + // false AND empty + auto *operand1 = ConstantExpression::make(&pool, Value(false)); + auto *operand2 = ConstantExpression::make(&pool, Value()); + auto *expr = LogicalExpression::makeAnd(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value(false).type()); + EXPECT_EQ(eval, Value(false)) << "check failed: " << expr->toString(); + } + { + // empty AND empty + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value()); + auto *expr = LogicalExpression::makeAnd(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kEmpty.type()); + EXPECT_EQ(eval, Value::kEmpty) << "check failed: " << expr->toString(); + } + { + // empty AND null + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(NullType::__NULL__)); + auto *expr = LogicalExpression::makeAnd(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kNullValue.type()); + EXPECT_EQ(eval, Value::kNullValue) << "check failed: " << expr->toString(); + } + { + // null AND empty + auto *operand1 = ConstantExpression::make(&pool, Value(NullType::__NULL__)); + auto *operand2 = ConstantExpression::make(&pool, Value()); + auto *expr = LogicalExpression::makeAnd(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kNullValue.type()); + EXPECT_EQ(eval, Value::kNullValue) << "check failed: " << expr->toString(); + } + { + // empty AND true AND empty + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(true)); + auto *operand3 = LogicalExpression::makeAnd(&pool, operand1, operand2); + auto *operand4 = ConstantExpression::make(&pool, Value()); + auto *expr = LogicalExpression::makeAnd(&pool, operand3, operand4); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kEmpty.type()); + EXPECT_EQ(eval, Value::kEmpty) << "check failed: " << expr->toString(); + } + + { + // empty OR true + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(true)); + auto *expr = LogicalExpression::makeOr(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value(true).type()); + EXPECT_EQ(eval, Value(true)) << "check failed: " << expr->toString(); + } + { + // empty OR false + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(false)); + auto *expr = LogicalExpression::makeOr(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kEmpty.type()); + EXPECT_EQ(eval, Value::kEmpty) << "check failed: " << expr->toString(); + } + { + // true OR empty + auto *operand1 = ConstantExpression::make(&pool, Value(true)); + auto *operand2 = ConstantExpression::make(&pool, Value()); + auto *expr = LogicalExpression::makeOr(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value(true).type()); + EXPECT_EQ(eval, Value(true)) << "check failed: " << expr->toString(); + } + { + // false OR empty + auto *operand1 = ConstantExpression::make(&pool, Value(false)); + auto *operand2 = ConstantExpression::make(&pool, Value()); + auto *expr = LogicalExpression::makeOr(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kEmpty.type()); + EXPECT_EQ(eval, Value::kEmpty) << "check failed: " << expr->toString(); + } + { + // empty OR empty + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value()); + auto *expr = LogicalExpression::makeOr(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kEmpty.type()); + EXPECT_EQ(eval, Value::kEmpty) << "check failed: " << expr->toString(); + } + { + // empty OR null + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(NullType::__NULL__)); + auto *expr = LogicalExpression::makeOr(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kNullValue.type()); + EXPECT_EQ(eval, Value::kNullValue) << "check failed: " << expr->toString(); + } + { + // null OR empty + auto *operand1 = ConstantExpression::make(&pool, Value(NullType::__NULL__)); + auto *operand2 = ConstantExpression::make(&pool, Value()); + auto *expr = LogicalExpression::makeOr(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kNullValue.type()); + EXPECT_EQ(eval, Value::kNullValue) << "check failed: " << expr->toString(); + } + { + // empty OR false OR empty + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(false)); + auto *operand3 = LogicalExpression::makeOr(&pool, operand1, operand2); + auto *operand4 = ConstantExpression::make(&pool, Value()); + auto *expr = LogicalExpression::makeOr(&pool, operand3, operand4); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kEmpty.type()); + EXPECT_EQ(eval, Value::kEmpty) << "check failed: " << expr->toString(); + } + + { + // empty XOR true + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(true)); + auto *expr = LogicalExpression::makeXor(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kEmpty.type()); + EXPECT_EQ(eval, Value::kEmpty) << "check failed: " << expr->toString(); + } + { + // empty XOR false + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(false)); + auto *expr = LogicalExpression::makeXor(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kEmpty.type()); + EXPECT_EQ(eval, Value::kEmpty) << "check failed: " << expr->toString(); + } + { + // true XOR empty + auto *operand1 = ConstantExpression::make(&pool, Value(true)); + auto *operand2 = ConstantExpression::make(&pool, Value()); + auto *expr = LogicalExpression::makeXor(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kEmpty.type()); + EXPECT_EQ(eval, Value::kEmpty) << "check failed: " << expr->toString(); + } + { + // false XOR empty + auto *operand1 = ConstantExpression::make(&pool, Value(false)); + auto *operand2 = ConstantExpression::make(&pool, Value()); + auto *expr = LogicalExpression::makeXor(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kEmpty.type()); + EXPECT_EQ(eval, Value::kEmpty) << "check failed: " << expr->toString(); + } + { + // empty XOR empty + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value()); + auto *expr = LogicalExpression::makeXor(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kEmpty.type()); + EXPECT_EQ(eval, Value::kEmpty) << "check failed: " << expr->toString(); + } + { + // empty XOR null + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(NullType::__NULL__)); + auto *expr = LogicalExpression::makeXor(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kNullValue.type()); + EXPECT_EQ(eval, Value::kNullValue) << "check failed: " << expr->toString(); + } + { + // null XOR empty + auto *operand1 = ConstantExpression::make(&pool, Value(NullType::__NULL__)); + auto *operand2 = ConstantExpression::make(&pool, Value()); + auto *expr = LogicalExpression::makeXor(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kNullValue.type()); + EXPECT_EQ(eval, Value::kNullValue) << "check failed: " << expr->toString(); + } + { + // true XOR empty XOR false + auto *operand1 = ConstantExpression::make(&pool, Value(true)); + auto *operand2 = ConstantExpression::make(&pool, Value()); + auto *operand3 = LogicalExpression::makeXor(&pool, operand1, operand2); + auto *operand4 = ConstantExpression::make(&pool, Value(false)); + auto *expr = LogicalExpression::makeXor(&pool, operand3, operand4); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kEmpty.type()); + EXPECT_EQ(eval, Value::kEmpty) << "check failed: " << expr->toString(); + } + + { + // empty OR false AND true AND null XOR empty + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(false)); + auto *operand3 = ConstantExpression::make(&pool, Value(true)); + auto *operand4 = LogicalExpression::makeAnd(&pool, operand2, operand3); + auto *operand5 = ConstantExpression::make(&pool, Value(NullType::__NULL__)); + auto *operand6 = LogicalExpression::makeAnd(&pool, operand4, operand5); + auto *operand7 = LogicalExpression::makeOr(&pool, operand1, operand6); + auto *operand8 = ConstantExpression::make(&pool, Value()); + auto *expr = LogicalExpression::makeXor(&pool, operand7, operand8); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kEmpty.type()); + EXPECT_EQ(eval, Value::kEmpty) << "check failed: " << expr->toString(); + } + { + // empty OR false AND true XOR empty OR true + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(false)); + auto *operand3 = ConstantExpression::make(&pool, Value(true)); + auto *operand4 = LogicalExpression::makeAnd(&pool, operand2, operand3); + auto *operand5 = LogicalExpression::makeOr(&pool, operand1, operand4); + auto *operand6 = ConstantExpression::make(&pool, Value()); + auto *operand7 = LogicalExpression::makeXor(&pool, operand5, operand6); + auto *operand8 = ConstantExpression::make(&pool, Value(true)); + auto *expr = LogicalExpression::makeOr(&pool, operand7, operand8); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value(true).type()); + EXPECT_EQ(eval, Value(true)) << "check failed: " << expr->toString(); + } // clang-format off - TEST_EXPR((empty OR false) AND true XOR empty XOR null AND 2 / 0, Value::kNullValue); + { + // (empty OR false) AND true XOR empty XOR null AND 2 / 0 + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(false)); + auto *operand3 = LogicalExpression::makeOr(&pool, operand1, operand2); + auto *operand4 = ConstantExpression::make(&pool, Value(true)); + auto *operand5 = LogicalExpression::makeAnd(&pool, operand3, operand4); + auto *operand6 = ConstantExpression::make(&pool, Value()); + auto *operand7 = LogicalExpression::makeXor(&pool, operand5, operand6); + auto *operand8 = ConstantExpression::make(&pool, Value(NullType::__NULL__)); + auto *operand9 = ConstantExpression::make(&pool, Value(2)); + auto *operand10 = ConstantExpression::make(&pool, Value(0)); + auto *operand11 = ArithmeticExpression::makeDivision(&pool, operand9, operand10); + auto *operand12 = LogicalExpression::makeAnd(&pool, operand8, operand11); + auto *expr = LogicalExpression::makeXor(&pool, operand7, operand12); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kNullValue.type()); + EXPECT_EQ(eval, Value::kNullValue) << "check failed: " << expr->toString(); + } + // clang-format on // empty OR false AND 2/0 - TEST_EXPR(empty OR false AND true XOR empty XOR null AND 2 / 0, Value::kEmpty); - TEST_EXPR(empty AND true XOR empty XOR null AND 2 / 0, Value::kNullValue); - TEST_EXPR(empty OR false AND true XOR empty OR null AND 2 / 0, Value::kNullDivByZero); - TEST_EXPR(empty OR false AND empty XOR empty OR null, Value::kNullValue); + { + // empty OR false AND true XOR empty XOR null AND 2 / 0 + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(false)); + auto *operand3 = ConstantExpression::make(&pool, Value(true)); + auto *operand4 = LogicalExpression::makeAnd(&pool, operand2, operand3); + auto *operand5 = LogicalExpression::makeOr(&pool, operand1, operand4); + auto *operand6 = ConstantExpression::make(&pool, Value()); + auto *operand7 = LogicalExpression::makeXor(&pool, operand5, operand6); + auto *operand8 = ConstantExpression::make(&pool, Value(NullType::__NULL__)); + auto *operand9 = ConstantExpression::make(&pool, Value(2)); + auto *operand10 = ConstantExpression::make(&pool, Value(0)); + auto *operand11 = ArithmeticExpression::makeDivision(&pool, operand9, operand10); + auto *operand12 = LogicalExpression::makeAnd(&pool, operand8, operand11); + auto *expr = LogicalExpression::makeXor(&pool, operand7, operand12); + auto eval = Expression::eval(expr, gExpCtxt); + // caution + EXPECT_EQ(eval.type(), Value::kNullDivByZero.type()); + EXPECT_EQ(eval, Value::kNullDivByZero) << "check failed: " << expr->toString(); + } + { + // empty AND true XOR empty XOR null AND 2 / 0 + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(true)); + auto *operand3 = LogicalExpression::makeAnd(&pool, operand1, operand2); + auto *operand4 = ConstantExpression::make(&pool, Value()); + auto *operand5 = LogicalExpression::makeXor(&pool, operand3, operand4); + auto *operand6 = ConstantExpression::make(&pool, Value(NullType::__NULL__)); + auto *operand7 = ConstantExpression::make(&pool, Value(2)); + auto *operand8 = ConstantExpression::make(&pool, Value(0)); + auto *operand9 = ArithmeticExpression::makeDivision(&pool, operand7, operand8); + auto *operand10 = LogicalExpression::makeAnd(&pool, operand6, operand9); + auto *expr = LogicalExpression::makeXor(&pool, operand5, operand10); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kNullValue.type()); + EXPECT_EQ(eval, Value::kNullValue) << "check failed: " << expr->toString(); + } + { + // empty OR false AND true XOR empty OR null AND 2 / 0 + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(false)); + auto *operand3 = ConstantExpression::make(&pool, Value(true)); + auto *operand4 = LogicalExpression::makeAnd(&pool, operand2, operand3); + auto *operand5 = LogicalExpression::makeOr(&pool, operand1, operand4); + auto *operand6 = ConstantExpression::make(&pool, Value()); + auto *operand7 = LogicalExpression::makeXor(&pool, operand5, operand6); + auto *operand8 = ConstantExpression::make(&pool, Value(NullType::__NULL__)); + auto *operand9 = ConstantExpression::make(&pool, Value(2)); + auto *operand10 = ConstantExpression::make(&pool, Value(0)); + auto *operand11 = ArithmeticExpression::makeDivision(&pool, operand9, operand10); + auto *operand12 = LogicalExpression::makeAnd(&pool, operand8, operand11); + auto *expr = LogicalExpression::makeOr(&pool, operand7, operand12); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kNullDivByZero.type()); + EXPECT_EQ(eval, Value::kNullDivByZero) << "check failed: " << expr->toString(); + } + { + // TEST_EXPR(empty OR false AND empty XOR empty OR null, Value::kNullValue); + // 7 OR null + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(false)); + auto *operand3 = ConstantExpression::make(&pool, Value()); + auto *operand4 = LogicalExpression::makeAnd(&pool, operand2, operand3); + auto *operand5 = LogicalExpression::makeOr(&pool, operand1, operand4); + auto *operand6 = ConstantExpression::make(&pool, Value()); + auto *operand7 = LogicalExpression::makeXor(&pool, operand5, operand6); + auto *operand8 = ConstantExpression::make(&pool, Value(NullType::__NULL__)); + auto *expr = LogicalExpression::makeOr(&pool, operand7, operand8); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kNullValue.type()); + EXPECT_EQ(eval, Value::kNullValue) << "check failed: " << expr->toString(); + } } } } // namespace nebula diff --git a/src/common/expression/test/RelationalExpressionTest.cpp b/src/common/expression/test/RelationalExpressionTest.cpp index 1ae134bc8ae..11bc892c463 100644 --- a/src/common/expression/test/RelationalExpressionTest.cpp +++ b/src/common/expression/test/RelationalExpressionTest.cpp @@ -96,15 +96,78 @@ TEST_F(ExpressionTest, LiteralConstantsRelational) { TEST_EXPR(1 <= 1, true); } { - TEST_EXPR(empty == empty, true); - TEST_EXPR(empty == null, Value::kNullValue); - TEST_EXPR(empty != null, Value::kNullValue); - TEST_EXPR(empty != 1, true); - TEST_EXPR(empty != true, true); - TEST_EXPR(empty > "1", Value::kEmpty); - TEST_EXPR(empty < 1, Value::kEmpty); - TEST_EXPR(empty >= 1.11, Value::kEmpty); - + // empty == empty + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value()); + auto *expr = RelationalExpression::makeEQ(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value(true).type()) << "type check failed: " << expr->toString(); + EXPECT_EQ(eval, Value(true)) << "check failed: " << expr->toString(); + } + { + // empty == null + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(NullType::__NULL__)); + auto *expr = RelationalExpression::makeEQ(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kNullValue.type()) << "type check failed: " << expr->toString(); + EXPECT_EQ(eval, Value::kNullValue) << "check failed: " << expr->toString(); + } + { + // empty != null + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(NullType::__NULL__)); + auto *expr = RelationalExpression::makeNE(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kNullValue.type()) << "type check failed: " << expr->toString(); + EXPECT_EQ(eval, Value::kNullValue) << "check failed: " << expr->toString(); + } + { + // empty != 1 + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(1)); + auto *expr = RelationalExpression::makeNE(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value(true).type()) << "type check failed: " << expr->toString(); + EXPECT_EQ(eval, Value(true)) << "check failed: " << expr->toString(); + } + { + // empty != true + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(true)); + auto *expr = RelationalExpression::makeNE(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value(true).type()) << "type check failed: " << expr->toString(); + EXPECT_EQ(eval, Value(true)) << "check failed: " << expr->toString(); + } + { + // empty > "1" + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value("1")); + auto *expr = RelationalExpression::makeGT(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kEmpty.type()) << "type check failed: " << expr->toString(); + EXPECT_EQ(eval, Value::kEmpty) << "check failed: " << expr->toString(); + } + { + // empty < 1 + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(1)); + auto *expr = RelationalExpression::makeLT(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kEmpty.type()) << "type check failed: " << expr->toString(); + EXPECT_EQ(eval, Value::kEmpty) << "check failed: " << expr->toString(); + } + { + // empty >= 1.11 + auto *operand1 = ConstantExpression::make(&pool, Value()); + auto *operand2 = ConstantExpression::make(&pool, Value(1.11)); + auto *expr = RelationalExpression::makeGE(&pool, operand1, operand2); + auto eval = Expression::eval(expr, gExpCtxt); + EXPECT_EQ(eval.type(), Value::kEmpty.type()) << "type check failed: " << expr->toString(); + EXPECT_EQ(eval, Value::kEmpty) << "check failed: " << expr->toString(); + } + { TEST_EXPR(null != 1, Value::kNullValue); TEST_EXPR(null != true, Value::kNullValue); TEST_EXPR(null > "1", Value::kNullValue); diff --git a/src/common/expression/test/TestBase.h b/src/common/expression/test/TestBase.h index 2ba5a6c629a..89fc2b3cb85 100644 --- a/src/common/expression/test/TestBase.h +++ b/src/common/expression/test/TestBase.h @@ -46,162 +46,86 @@ #include "common/expression/VariableExpression.h" #include "common/expression/VertexExpression.h" #include "common/expression/test/ExpressionContextMock.h" +#include "parser/GQLParser.h" nebula::ExpressionContextMock gExpCtxt; nebula::ObjectPool pool; namespace nebula { - -static void InsertSpace(std::string &str) { - for (unsigned int i = 0; i < str.size(); i++) { - if (str[i] == '(') { - str.insert(i + 1, 1, ' '); - } else if (str[i] == ')') { - str.insert(i, 1, ' '); - i += 1; - } else { - continue; - } - } -} - -static std::vector InfixToSuffix(const std::vector &expr) { - std::vector values; - std::stack operators; - std::unordered_map priority = {{"OR", 1}, - {"AND", 2}, - {"XOR", 3}, - {"==", 4}, - {"!=", 4}, - {">=", 5}, - {"<=", 5}, - {">", 5}, - {"<", 5}, - {"+", 6}, - {"-", 6}, - {"*", 7}, - {"/", 7}, - {"%", 7}, - {"!", 8}}; - - for (const auto &str : expr) { - if (priority.find(str) != priority.end() || str == "(") { - if (operators.empty() || str == "(") { - operators.push(str); - } else { - if (operators.top() == "(" || priority[str] > priority[operators.top()]) { - operators.push(str); - } else { - while (!operators.empty() && priority[str] <= priority[operators.top()]) { - values.push_back(operators.top()); - operators.pop(); - } - operators.push(str); - } - } - } else if (str == ")") { - while (!operators.empty() && operators.top() != "(") { - values.push_back(operators.top()); - operators.pop(); - } - operators.pop(); - } else { - values.push_back(str); - } - } - while (!operators.empty()) { - values.push_back(operators.top()); - operators.pop(); - } - return values; -} - class ExpressionTest : public ::testing::Test { public: void SetUp() override {} void TearDown() override {} protected: - static std::unordered_map boolen_; - // static std::unordered_map op_; - static std::unordered_map< - std::string, - std::function> - op_; - - protected: - Expression *ExpressionCalu(const std::vector &expr) { - std::vector relationOp = {">", ">=", "<", "<=", "==", "!="}; - std::vector logicalOp = {"AND", "OR", "XOR"}; - std::vector arithmeticOp = {"+", "-", "*", "/", "%"}; - - std::vector symbol = InfixToSuffix(expr); - if (symbol.size() == 1) { - // TEST_EXPR(true, true) - if (boolen_.find(symbol.front()) != boolen_.end()) { - return ConstantExpression::make(&pool, boolen_[symbol.front()]); - } else if (symbol.front().find('.') != std::string::npos) { - // TEST_EXPR(123.0, 123.0) - return ConstantExpression::make(&pool, ::atof(symbol.front().c_str())); - } - // TEST_EXPR(123, 123) - return ConstantExpression::make(&pool, ::atoi(symbol.front().c_str())); - } - - // calu suffix expression - std::stack value; - for (const auto &str : symbol) { - if (op_.find(str) == op_.end()) { - Expression *ep = nullptr; - if (boolen_.find(str) != boolen_.end()) { - ep = ConstantExpression::make(&pool, boolen_[str.c_str()]); - } else if (str.find('.') != std::string::npos) { - ep = ConstantExpression::make(&pool, ::atof(str.c_str())); - } else { - ep = ConstantExpression::make(&pool, ::atoi(str.c_str())); - } - value.push(ep); - } else { - Expression *result = nullptr; - Expression *rhs = value.top(); - value.pop(); - Expression *lhs = value.top(); - value.pop(); - if (std::find(arithmeticOp.begin(), arithmeticOp.end(), str) != arithmeticOp.end()) { - result = op_[str](&pool, lhs, rhs); - } else if (std::find(relationOp.begin(), relationOp.end(), str) != relationOp.end()) { - result = op_[str](&pool, lhs, rhs); - } else if (std::find(logicalOp.begin(), logicalOp.end(), str) != logicalOp.end()) { - result = op_[str](&pool, lhs, rhs); - } else { - return ConstantExpression::make(&pool, NullType::UNKNOWN_PROP); - } - value.push(result); - } - } - return value.top(); - } - void testExpr(const std::string &exprSymbol, Value expected) { - std::string expr(exprSymbol); - InsertSpace(expr); - std::vector splitString; - boost::split(splitString, expr, boost::is_any_of(" \t")); - Expression *ep = ExpressionCalu(splitString); + std::string query = "RETURN " + exprSymbol; + nebula::graph::QueryContext queryCtxt; + nebula::GQLParser gParser(&queryCtxt); + auto result = gParser.parse(query); + ASSERT_EQ(result.ok(), true); + auto *sequentialSentences = static_cast(result.value().get()); + ASSERT_NE(sequentialSentences, nullptr); + auto sentences = sequentialSentences->sentences(); + ASSERT_GT(sentences.size(), 0); + auto *yieldSentence = static_cast(sentences[0]); + ASSERT_NE(yieldSentence, nullptr); + ASSERT_NE(yieldSentence->yield(), nullptr); + ASSERT_NE(yieldSentence->yield()->yields(), nullptr); + ASSERT_NE(yieldSentence->yield()->yields()->back(), nullptr); + Expression *ep = yieldSentence->yield()->yields()->back()->expr(); auto eval = Expression::eval(ep, gExpCtxt); EXPECT_EQ(eval.type(), expected.type()) << "type check failed: " << ep->toString(); EXPECT_EQ(eval, expected) << "check failed: " << ep->toString(); } void testToString(const std::string &exprSymbol, const char *expected) { - std::string expr(exprSymbol); - InsertSpace(expr); - std::vector splitString; - boost::split(splitString, expr, boost::is_any_of(" \t")); - Expression *ep = ExpressionCalu(splitString); + std::string query = "RETURN " + exprSymbol; + nebula::graph::QueryContext queryCtxt; + nebula::GQLParser gParser(&queryCtxt); + auto result = gParser.parse(query); + ASSERT_EQ(result.ok(), true); + auto *sequentialSentences = static_cast(result.value().get()); + ASSERT_NE(sequentialSentences, nullptr); + auto sentences = sequentialSentences->sentences(); + ASSERT_GT(sentences.size(), 0); + auto *yieldSentence = static_cast(sentences[0]); + ASSERT_NE(yieldSentence, nullptr); + ASSERT_NE(yieldSentence->yield(), nullptr); + ASSERT_NE(yieldSentence->yield()->yields(), nullptr); + ASSERT_NE(yieldSentence->yield()->yields()->back(), nullptr); + Expression *ep = yieldSentence->yield()->yields()->back()->expr(); + ASSERT_NE(ep, nullptr); EXPECT_EQ(ep->toString(), expected); } void testFunction(const char *name, const std::vector &args, const Value &expected) { + std::string query = "RETURN " + std::string(name) + "("; + for (const auto &i : args) { + query += i.toString() + ","; + } + if (query.back() == ',') { + query.pop_back(); + } + query += ")"; + nebula::graph::QueryContext queryCtxt; + nebula::GQLParser gParser(&queryCtxt); + auto result = gParser.parse(query); + ASSERT_EQ(result.ok(), true); + auto *sequentialSentences = static_cast(result.value().get()); + ASSERT_NE(sequentialSentences, nullptr); + auto sentences = sequentialSentences->sentences(); + ASSERT_GT(sentences.size(), 0); + auto *yieldSentence = static_cast(sentences[0]); + ASSERT_NE(yieldSentence, nullptr); + ASSERT_NE(yieldSentence->yield(), nullptr); + ASSERT_NE(yieldSentence->yield()->yields(), nullptr); + ASSERT_NE(yieldSentence->yield()->yields()->back(), nullptr); + auto eval = Expression::eval(yieldSentence->yield()->yields()->back()->expr(), gExpCtxt); + // EXPECT_EQ(eval.type(), expected.type()); + EXPECT_EQ(eval, expected); + } + + void testPathFunction(const char *name, const std::vector &args, const Value &expected) { ArgumentList *argList = ArgumentList::make(&pool); for (const auto &i : args) { argList->addArgument(ConstantExpression::make(&pool, i)); @@ -212,6 +136,7 @@ class ExpressionTest : public ::testing::Test { EXPECT_EQ(eval, expected); } }; + // expr -- the expression can evaluate by nGQL parser may not evaluated by c++ // expected -- the expected value of expression must evaluated by c++ #define TEST_EXPR(expr, expected) \ @@ -224,6 +149,11 @@ class ExpressionTest : public ::testing::Test { testFunction(#expr, args, expected); \ } while (0) +#define TEST_PATH_FUNCTION(expr, args, expected) \ + do { \ + testPathFunction(#expr, args, expected); \ + } while (0) + #define TEST_TOSTRING(expr, expected) \ do { \ testToString(#expr, expected); \ @@ -239,64 +169,6 @@ class ExpressionTest : public ::testing::Test { path.steps.emplace_back(std::move(step)); \ } while (0) -// Functions used to construct corresponding expressions -using expressionGen = - std::function; - -expressionGen makeAddExpr{&ArithmeticExpression::makeAdd}; -expressionGen makeMinusExpr{&ArithmeticExpression::makeMinus}; -expressionGen makeMultiplyExpr{&ArithmeticExpression::makeMultiply}; -expressionGen makeDivisionExpr{&ArithmeticExpression::makeDivision}; -expressionGen makeModExpr{&ArithmeticExpression::makeMod}; -expressionGen makeOrExpr{ - static_cast( - &LogicalExpression::makeOr)}; -expressionGen makeAndExpr{ - static_cast( - &LogicalExpression::makeAnd)}; -expressionGen makeXorExpr{ - static_cast( - &LogicalExpression::makeXor)}; -expressionGen makeRelGT{ - static_cast( - &RelationalExpression::makeGT)}; -expressionGen makeRelLT{ - static_cast( - &RelationalExpression::makeLT)}; -expressionGen makeRelGE{ - static_cast( - &RelationalExpression::makeGE)}; -expressionGen makeRelLE{ - static_cast( - &RelationalExpression::makeLE)}; -expressionGen makeRelEQ{ - static_cast( - &RelationalExpression::makeEQ)}; -expressionGen makeRelNE{ - static_cast( - &RelationalExpression::makeNE)}; - -std::unordered_map ExpressionTest::op_ = {{"+", makeAddExpr}, - {"-", makeMinusExpr}, - {"*", makeMultiplyExpr}, - {"/", makeDivisionExpr}, - {"%", makeModExpr}, - {"OR", makeOrExpr}, - {"AND", makeAndExpr}, - {"XOR", makeXorExpr}, - {">", makeRelGT}, - {"<", makeRelLT}, - {">=", makeRelGE}, - {"<=", makeRelLE}, - {"==", makeRelEQ}, - {"!=", makeRelNE}}; - -std::unordered_map ExpressionTest::boolen_ = { - {"true", Value(true)}, - {"false", Value(false)}, - {"empty", Value()}, - {"null", Value(NullType::__NULL__)}}; - static std::unordered_map> args_ = { {"null", {}}, {"int", {4}}, @@ -314,6 +186,5 @@ static std::unordered_map> args_ = { {"neg_side", {"abcdefghijklmnopq", -2}}, {"pad", {"abcdefghijkl", 16, "123"}}, {"udf_is_in", {4, 1, 2, 8, 4, 3, 1, 0}}}; - } // namespace nebula #endif // COMMON_EXPRESSION_TEST_TESTBASE_H_