diff options
Diffstat (limited to 'src/mongo/db/pipeline/expression_test.cpp')
-rw-r--r-- | src/mongo/db/pipeline/expression_test.cpp | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/src/mongo/db/pipeline/expression_test.cpp b/src/mongo/db/pipeline/expression_test.cpp index 04233cbb806..48e011d37be 100644 --- a/src/mongo/db/pipeline/expression_test.cpp +++ b/src/mongo/db/pipeline/expression_test.cpp @@ -2221,6 +2221,95 @@ TEST(ExpressionFromAccumulators, StdDevSamp) { {{}, Value(BSONNULL)}}); } +TEST(ExpressionPowTest, LargeExponentValuesWithBaseOfZero) { + assertExpectedResults( + "$pow", + { + {{Value(0), Value(0)}, Value(1)}, + {{Value(0LL), Value(0LL)}, Value(1LL)}, + + {{Value(0), Value(10)}, Value(0)}, + {{Value(0), Value(10000)}, Value(0)}, + + {{Value(0LL), Value(10)}, Value(0LL)}, + + // $pow may sometimes use a loop to compute a^b, so it's important to check + // that the loop doesn't hang if a large exponent is provided. + {{Value(0LL), Value(std::numeric_limits<long long>::max())}, Value(0LL)}, + }); +} + +TEST(ExpressionPowTest, ThrowsWhenBaseZeroAndExpNegative) { + intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + VariablesParseState vps = expCtx->variablesParseState; + + const auto expr = Expression::parseExpression(expCtx, BSON("$pow" << BSON_ARRAY(0 << -5)), vps); + ASSERT_THROWS([&] { expr->evaluate(Document()); }(), AssertionException); + + const auto exprWithLong = + Expression::parseExpression(expCtx, BSON("$pow" << BSON_ARRAY(0LL << -5LL)), vps); + ASSERT_THROWS([&] { expr->evaluate(Document()); }(), AssertionException); +} + +TEST(ExpressionPowTest, LargeExponentValuesWithBaseOfOne) { + assertExpectedResults( + "$pow", + { + {{Value(1), Value(10)}, Value(1)}, + {{Value(1), Value(10LL)}, Value(1LL)}, + {{Value(1), Value(10000LL)}, Value(1LL)}, + + {{Value(1LL), Value(10LL)}, Value(1LL)}, + + // $pow may sometimes use a loop to compute a^b, so it's important to check + // that the loop doesn't hang if a large exponent is provided. + {{Value(1LL), Value(std::numeric_limits<long long>::max())}, Value(1LL)}, + {{Value(1LL), Value(std::numeric_limits<long long>::min())}, Value(1LL)}, + }); +} + +TEST(ExpressionPowTest, LargeExponentValuesWithBaseOfNegativeOne) { + assertExpectedResults("$pow", + { + {{Value(-1), Value(-1)}, Value(-1)}, + {{Value(-1), Value(-2)}, Value(1)}, + {{Value(-1), Value(-3)}, Value(-1)}, + + {{Value(-1LL), Value(0LL)}, Value(1LL)}, + {{Value(-1LL), Value(-1LL)}, Value(-1LL)}, + {{Value(-1LL), Value(-2LL)}, Value(1LL)}, + {{Value(-1LL), Value(-3LL)}, Value(-1LL)}, + {{Value(-1LL), Value(-4LL)}, Value(1LL)}, + {{Value(-1LL), Value(-5LL)}, Value(-1LL)}, + + {{Value(-1LL), Value(-61LL)}, Value(-1LL)}, + {{Value(-1LL), Value(61LL)}, Value(-1LL)}, + + {{Value(-1LL), Value(-62LL)}, Value(1LL)}, + {{Value(-1LL), Value(62LL)}, Value(1LL)}, + + {{Value(-1LL), Value(-101LL)}, Value(-1LL)}, + {{Value(-1LL), Value(-102LL)}, Value(1LL)}, + + // Use a value large enough that will make the test hang for a + // considerable amount of time if a loop is used to compute the + // answer. + {{Value(-1LL), Value(63234673905128LL)}, Value(1LL)}, + {{Value(-1LL), Value(-63234673905128LL)}, Value(1LL)}, + + {{Value(-1LL), Value(63234673905127LL)}, Value(-1LL)}, + {{Value(-1LL), Value(-63234673905127LL)}, Value(-1LL)}, + }); +} + +TEST(ExpressionPowTest, LargeBaseSmallPositiveExponent) { + assertExpectedResults("$pow", + { + {{Value(4294967296LL), Value(1LL)}, Value(4294967296LL)}, + {{Value(4294967296LL), Value(0)}, Value(1LL)}, + }); +} + namespace FieldPath { /** The provided field path does not pass validation. */ |