summaryrefslogtreecommitdiff
path: root/src/mongo/db/pipeline/expression_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/pipeline/expression_test.cpp')
-rw-r--r--src/mongo/db/pipeline/expression_test.cpp91
1 files changed, 91 insertions, 0 deletions
diff --git a/src/mongo/db/pipeline/expression_test.cpp b/src/mongo/db/pipeline/expression_test.cpp
index 8acf746a696..b6a6b75d966 100644
--- a/src/mongo/db/pipeline/expression_test.cpp
+++ b/src/mongo/db/pipeline/expression_test.cpp
@@ -2180,6 +2180,97 @@ 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) {
+ VariablesIdGenerator idGenerator;
+ VariablesParseState vps(&idGenerator);
+
+ intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+
+ 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. */