diff options
Diffstat (limited to 'src/mongo/db/pipeline/expression_test.cpp')
| -rw-r--r-- | src/mongo/db/pipeline/expression_test.cpp | 70 |
1 files changed, 69 insertions, 1 deletions
diff --git a/src/mongo/db/pipeline/expression_test.cpp b/src/mongo/db/pipeline/expression_test.cpp index fd6f1c3490e..03fc4d3b663 100644 --- a/src/mongo/db/pipeline/expression_test.cpp +++ b/src/mongo/db/pipeline/expression_test.cpp @@ -1121,7 +1121,7 @@ TEST(ExpressionSwitch, ExpressionSwitchWithAllConstantFalsesAndNoDefaultErrors) ASSERT_THROWS_CODE(switchExp->optimize(), AssertionException, 40069); } -TEST(ExpressionSwitch, ExpressionSwitchWithZeroAsConstantFalsesAndNoDefaulErrors) { +TEST(ExpressionSwitch, ExpressionSwitchWithZeroAsConstantFalseAndNoDefaultErrors) { auto expCtx = ExpressionContextForTest{}; VariablesParseState vps = expCtx.variablesParseState; @@ -1233,6 +1233,62 @@ TEST(ExpressionSwitch, ExpressionSwitchWithNoConstantsShouldStayTheSame) { ASSERT_BSONOBJ_BINARY_EQ(switchQ, expressionToBson(optimizedStaySame)); } +// This test was designed to provide coverage for SERVER-70190, a bug in which optimizing a $switch +// expression could leave its children vector in a bad state. By walking the tree after optimizing +// we make sure that the expected children are found. +TEST(ExpressionSwitch, CaseEliminationShouldLeaveTreeInWalkableState) { + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; + + BSONObj switchQ = fromjson(R"( + {$switch: { + branches: [ + {case: false, then: {$const: 0}}, + {case: "$z", then: {$const: 1}}, + {case: "$y", then: {$const: 3}}, + {case: true, then: {$const: 4}}, + {case: "$a", then: {$const: 5}}, + {case: "$b", then: {$const: 6}}, + {case: "$c", then: {$const: 7}} + ], + default: {$const: 8} + }} + )"); + auto switchExp = ExpressionSwitch::parse(&expCtx, switchQ.firstElement(), vps); + auto optimizedExpr = switchExp->optimize(); + + BSONObj optimizedQ = fromjson(R"( + {$switch: { + branches: [ + {case: "$z", then: {$const: 1}}, + {case: "$y", then: {$const: 3}} + ], + default: {$const: 4} + }} + )"); + + ASSERT_BSONOBJ_BINARY_EQ(optimizedQ, expressionToBson(optimizedExpr)); + + // Make sure that the expression tree appears as expected when the children are traversed using + // a for-each loop. + int childNum = 0; + int numConstants = 0; + for (auto&& child : optimizedExpr->getChildren()) { + // Children 0 and 2 are field path expressions, whereas 1, 3, and 4 are constants. + auto constExpr = dynamic_cast<ExpressionConstant*>(child.get()); + if (constExpr) { + ASSERT_VALUE_EQ(constExpr->getValue(), Value{childNum}); + ++numConstants; + } else { + ASSERT(dynamic_cast<ExpressionFieldPath*>(child.get())); + } + ++childNum; + } + // We should have seen 5 children total, 3 of which are constants. + ASSERT_EQ(childNum, 5); + ASSERT_EQ(numConstants, 3); +} + TEST(ExpressionArray, ExpressionArrayShouldOptimizeSubExpressionToExpressionConstant) { auto expCtx = ExpressionContextForTest{}; VariablesParseState vps = expCtx.variablesParseState; @@ -3105,6 +3161,18 @@ TEST(ExpressionMetaTest, ExpressionMetaSearchScoreDetails) { Value val = expressionMeta->evaluate(doc.freeze(), &expCtx.variables); ASSERT_DOCUMENT_EQ(val.getDocument(), Document(details)); } + +TEST(ExpressionMetaTest, ExpressionMetaVectorSearchScore) { + auto expCtx = ExpressionContextForTest{}; + BSONObj expr = fromjson("{$meta: \"vectorSearchScore\"}"); + auto expressionMeta = + ExpressionMeta::parse(&expCtx, expr.firstElement(), expCtx.variablesParseState); + + MutableDocument doc; + doc.metadata().setVectorSearchScore(1.23); + Value val = expressionMeta->evaluate(doc.freeze(), &expCtx.variables); + ASSERT_EQ(val.getDouble(), 1.23); +} } // namespace expression_meta_test namespace ExpressionRegexTest { |
