summaryrefslogtreecommitdiff
path: root/src/mongo/db/pipeline/expression_test.cpp
diff options
context:
space:
mode:
authorPatrick Meredith <pmeredit@gmail.com>2018-10-22 17:01:46 -0400
committerCharlie Swanson <charlie.swanson@mongodb.com>2019-02-14 17:54:56 -0500
commit814b1f8237db9ecb27dd0ffa96f11edd58bac73e (patch)
tree4e13cadda4f9dc3ea4f4d7156476f31c77ba9726 /src/mongo/db/pipeline/expression_test.cpp
parentf1da8170c1c568762b29e44910afbcc6f01a644f (diff)
downloadmongo-814b1f8237db9ecb27dd0ffa96f11edd58bac73e.tar.gz
SERVER-15926: Implement $round function and allow a precision argument for $trunc
Closes #1297 Signed-off-by: Charlie Swanson <charlie.swanson@mongodb.com>
Diffstat (limited to 'src/mongo/db/pipeline/expression_test.cpp')
-rw-r--r--src/mongo/db/pipeline/expression_test.cpp336
1 files changed, 299 insertions, 37 deletions
diff --git a/src/mongo/db/pipeline/expression_test.cpp b/src/mongo/db/pipeline/expression_test.cpp
index fc281669707..cddeedef7b9 100644
--- a/src/mongo/db/pipeline/expression_test.cpp
+++ b/src/mongo/db/pipeline/expression_test.cpp
@@ -182,6 +182,18 @@ public:
intrusive_ptr<ExpressionNary> _expr;
};
+class ExpressionNaryTestTwoArg : public ExpressionBaseTest {
+public:
+ virtual void assertEvaluates(Value input1, Value input2, Value output) {
+ addOperand(_expr, input1);
+ addOperand(_expr, input2);
+ ASSERT_VALUE_EQ(output, _expr->evaluate(Document()));
+ ASSERT_EQUALS(output.getType(), _expr->evaluate(Document()).getType());
+ }
+
+ intrusive_ptr<ExpressionNary> _expr;
+};
+
/* ------------------------- NaryExpression -------------------------- */
/** A dummy child of ExpressionNary used for testing. */
@@ -929,63 +941,313 @@ TEST(ExpressionReverseArrayTest, ReturnsNullWithNullishInput) {
{{{Value(BSONNULL)}, Value(BSONNULL)}, {{Value(BSONUndefined)}, Value(BSONNULL)}});
}
-/* ------------------------- ExpressionTrunc -------------------------- */
+/* ------------------------- ExpressionRound -------------------------- */
-class ExpressionTruncTest : public ExpressionNaryTestOneArg {
+class ExpressionRoundOneArgTest : public ExpressionNaryTestOneArg {
public:
- virtual void assertEvaluates(Value input, Value output) override {
+ void assertEval(ImplicitValue input, ImplicitValue output) {
intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
- _expr = new ExpressionTrunc(expCtx);
+ _expr = new ExpressionRound(expCtx);
ExpressionNaryTestOneArg::assertEvaluates(input, output);
}
};
-TEST_F(ExpressionTruncTest, IntArg) {
- assertEvaluates(Value(0), Value(0));
- assertEvaluates(Value(numeric_limits<int>::min()), Value(numeric_limits<int>::min()));
- assertEvaluates(Value(numeric_limits<int>::max()), Value(numeric_limits<int>::max()));
+class ExpressionRoundTwoArgTest : public ExpressionNaryTestTwoArg {
+public:
+ void assertEval(ImplicitValue input1, ImplicitValue input2, ImplicitValue output) {
+ intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ _expr = new ExpressionRound(expCtx);
+ ExpressionNaryTestTwoArg::assertEvaluates(input1, input2, output);
+ }
+};
+
+TEST_F(ExpressionRoundOneArgTest, IntArg1) {
+ assertEval(0, 0);
+ assertEval(numeric_limits<int>::min(), numeric_limits<int>::min());
+ assertEval(numeric_limits<int>::max(), numeric_limits<int>::max());
}
-TEST_F(ExpressionTruncTest, LongArg) {
- assertEvaluates(Value(0LL), Value(0LL));
- assertEvaluates(Value(numeric_limits<long long>::min()),
- Value(numeric_limits<long long>::min()));
- assertEvaluates(Value(numeric_limits<long long>::max()),
- Value(numeric_limits<long long>::max()));
+TEST_F(ExpressionRoundTwoArgTest, IntArg2) {
+ assertEval(0, 0, 0);
+ assertEval(2, -1, 0);
+ assertEval(29, -1, 30);
+ assertEval(numeric_limits<int>::min(), 10, numeric_limits<int>::min());
+ assertEval(numeric_limits<int>::max(), 42, numeric_limits<int>::max());
}
-TEST_F(ExpressionTruncTest, DoubleArg) {
- assertEvaluates(Value(2.0), Value(2.0));
- assertEvaluates(Value(-2.0), Value(-2.0));
- assertEvaluates(Value(0.9), Value(0.0));
- assertEvaluates(Value(0.1), Value(0.0));
- assertEvaluates(Value(-1.2), Value(-1.0));
- assertEvaluates(Value(-1.7), Value(-1.0));
+TEST_F(ExpressionRoundOneArgTest, LongArg1) {
+ assertEval(0LL, 0LL);
+ assertEval(numeric_limits<long long>::min(), numeric_limits<long long>::min());
+ assertEval(numeric_limits<long long>::max(), numeric_limits<long long>::max());
+}
+
+TEST_F(ExpressionRoundTwoArgTest, LongArg2) {
+ assertEval(0LL, 0LL, 0LL);
+ assertEval(2LL, -1LL, 0LL);
+ assertEval(29LL, -1LL, 30LL);
+ assertEval(numeric_limits<long long>::min(), 10LL, numeric_limits<long long>::min());
+ assertEval(numeric_limits<long long>::max(), 42LL, numeric_limits<long long>::max());
+}
+
+TEST_F(ExpressionRoundOneArgTest, DoubleArg1) {
+ assertEval(2.0, 2.0);
+ assertEval(-2.0, -2.0);
+ assertEval(0.9, 1.0);
+ assertEval(0.1, 0.0);
+ assertEval(-1.2, -1.0);
+ assertEval(-1.7, -2.0);
// Outside the range of long longs (there isn't enough precision for decimals in this range, so
// should just preserve the number).
double largerThanLong = numeric_limits<long long>::max() * 2.0;
- assertEvaluates(Value(largerThanLong), Value(largerThanLong));
+ assertEval(largerThanLong, largerThanLong);
double smallerThanLong = numeric_limits<long long>::min() * 2.0;
- assertEvaluates(Value(smallerThanLong), Value(smallerThanLong));
+ assertEval(smallerThanLong, smallerThanLong);
+}
+
+TEST_F(ExpressionRoundTwoArgTest, DoubleArg2) {
+ assertEval(2.0, 1.0, 2.0);
+ assertEval(-2.0, 2.0, -2.0);
+ assertEval(0.9, 0, 1.0);
+ assertEval(0.1, 0, 0.0);
+ assertEval(-1.2, 0, -1.0);
+ assertEval(-1.7, 0, -2.0);
+
+ assertEval(-3.14159265, 0, -3.0);
+ assertEval(-3.14159265, 1, -3.1);
+ assertEval(-3.14159265, 2, -3.14);
+ assertEval(-3.14159265, 3, -3.142);
+ assertEval(-3.14159265, 4, -3.1416);
+ assertEval(-3.14159265, 5, -3.14159);
+ assertEval(-3.14159265, 6, -3.141593);
+ assertEval(-3.14159265, 7, -3.1415927);
+ assertEval(-3.14159265, 100, -3.14159265);
+ assertEval(3.14159265, 0, 3.0);
+ assertEval(3.14159265, 1, 3.1);
+ assertEval(3.14159265, 2, 3.14);
+ assertEval(3.14159265, 3, 3.142);
+ assertEval(3.14159265, 4, 3.1416);
+ assertEval(3.14159265, 5, 3.14159);
+ assertEval(3.14159265, 6, 3.141593);
+ assertEval(3.14159265, 7, 3.1415927);
+ assertEval(3.14159265, 100, 3.14159265);
+ assertEval(3.14159265, -1, 0.0);
+ assertEval(335.14159265, -1, 340.0);
+ assertEval(333.14159265, -2, 300.0);
+}
+
+TEST_F(ExpressionRoundOneArgTest, DecimalArg1) {
+ assertEval(Decimal128("2"), Decimal128("2.0"));
+ assertEval(Decimal128("-2"), Decimal128("-2.0"));
+ assertEval(Decimal128("0.9"), Decimal128("1.0"));
+ assertEval(Decimal128("0.1"), Decimal128("0.0"));
+ assertEval(Decimal128("-1.2"), Decimal128("-1.0"));
+ assertEval(Decimal128("-1.7"), Decimal128("-2.0"));
+ assertEval(Decimal128("123456789.9999999999999999999999999"), Decimal128("123456790"));
+ assertEval(Decimal128("-99999999999999999999999999999.99"),
+ Decimal128("-100000000000000000000000000000"));
+ assertEval(Decimal128("3.4E-6000"), Decimal128("0"));
+}
+
+TEST_F(ExpressionRoundTwoArgTest, DecimalArg2) {
+ assertEval(Decimal128("2"), 0, Decimal128("2.0"));
+ assertEval(Decimal128("-2"), 0, Decimal128("-2.0"));
+ assertEval(Decimal128("0.9"), 0, Decimal128("1.0"));
+ assertEval(Decimal128("0.1"), 0, Decimal128("0.0"));
+ assertEval(Decimal128("-1.2"), 0, Decimal128("-1.0"));
+ assertEval(Decimal128("-1.7"), 0, Decimal128("-2.0"));
+ assertEval(Decimal128("123456789.9999999999999999999999999"), 0, Decimal128("123456790"));
+ assertEval(Decimal128("-99999999999999999999999999999.99"),
+ 0,
+ Decimal128("-100000000000000000000000000000"));
+ assertEval(Decimal128("3.4E-6000"), 0, Decimal128("0"));
+
+ assertEval(Decimal128("-3.14159265"), 0, Decimal128("-3.0"));
+ assertEval(Decimal128("-3.14159265"), 1, Decimal128("-3.1"));
+ assertEval(Decimal128("-3.14159265"), 2, Decimal128("-3.14"));
+ assertEval(Decimal128("-3.14159265"), 3, Decimal128("-3.142"));
+ assertEval(Decimal128("-3.14159265"), 4, Decimal128("-3.1416"));
+ assertEval(Decimal128("-3.14159265"), 5, Decimal128("-3.14159"));
+ assertEval(Decimal128("-3.14159265"), 6, Decimal128("-3.141593"));
+ assertEval(Decimal128("-3.14159265"), 7, Decimal128("-3.1415926"));
+ assertEval(Decimal128("-3.14159265"), 100, Decimal128("-3.14159265"));
+ assertEval(Decimal128("3.14159265"), 0, Decimal128("3.0"));
+ assertEval(Decimal128("3.14159265"), 1, Decimal128("3.1"));
+ assertEval(Decimal128("3.14159265"), 2, Decimal128("3.14"));
+ assertEval(Decimal128("3.14159265"), Decimal128("3"), Decimal128("3.142"));
+ assertEval(Decimal128("3.14159265"), 4, Decimal128("3.1416"));
+ assertEval(Decimal128("3.14159265"), Decimal128("5"), Decimal128("3.14159"));
+ assertEval(Decimal128("3.14159265"), 6, Decimal128("3.141593"));
+ assertEval(Decimal128("3.14159265"), 7, Decimal128("3.1415926"));
+ assertEval(Decimal128("3.14159265"), 100, Decimal128("3.14159265"));
+ assertEval(Decimal128("3.14159265"), Decimal128("-1"), Decimal128("0"));
+ assertEval(Decimal128("335.14159265"), -1, Decimal128("340"));
+ assertEval(Decimal128("333.14159265"), -2, Decimal128("300"));
+}
+
+TEST_F(ExpressionRoundOneArgTest, NullArg1) {
+ assertEval(BSONNULL, BSONNULL);
+}
+
+TEST_F(ExpressionRoundTwoArgTest, NullArg2) {
+ assertEval(BSONNULL, BSONNULL, BSONNULL);
+ assertEval(1, BSONNULL, BSONNULL);
+ assertEval(BSONNULL, 1, BSONNULL);
}
-TEST_F(ExpressionTruncTest, DecimalArg) {
- assertEvaluates(Value(Decimal128("2")), Value(Decimal128("2.0")));
- assertEvaluates(Value(Decimal128("-2")), Value(Decimal128("-2.0")));
- assertEvaluates(Value(Decimal128("0.9")), Value(Decimal128("0.0")));
- assertEvaluates(Value(Decimal128("0.1")), Value(Decimal128("0.0")));
- assertEvaluates(Value(Decimal128("-1.2")), Value(Decimal128("-1.0")));
- assertEvaluates(Value(Decimal128("-1.7")), Value(Decimal128("-1.0")));
- assertEvaluates(Value(Decimal128("123456789.9999999999999999999999999")),
- Value(Decimal128("123456789")));
- assertEvaluates(Value(Decimal128("-99999999999999999999999999999.99")),
- Value(Decimal128("-99999999999999999999999999999.00")));
- assertEvaluates(Value(Decimal128("3.4E-6000")), Value(Decimal128("0")));
+/* ------------------------- ExpressionTrunc -------------------------- */
+
+class ExpressionTruncOneArgTest : public ExpressionNaryTestOneArg {
+public:
+ void assertEval(ImplicitValue input, ImplicitValue output) {
+ intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ _expr = new ExpressionTrunc(expCtx);
+ ExpressionNaryTestOneArg::assertEvaluates(input, output);
+ }
+};
+
+class ExpressionTruncTwoArgTest : public ExpressionNaryTestTwoArg {
+public:
+ void assertEval(ImplicitValue input1, ImplicitValue input2, ImplicitValue output) {
+ intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ _expr = new ExpressionTrunc(expCtx);
+ ExpressionNaryTestTwoArg::assertEvaluates(input1, input2, output);
+ }
+};
+
+TEST_F(ExpressionTruncOneArgTest, IntArg1) {
+ assertEval(0, 0);
+ assertEval(numeric_limits<int>::min(), numeric_limits<int>::min());
+ assertEval(numeric_limits<int>::max(), numeric_limits<int>::max());
}
-TEST_F(ExpressionTruncTest, NullArg) {
- assertEvaluates(Value(BSONNULL), Value(BSONNULL));
+TEST_F(ExpressionTruncTwoArgTest, IntArg2) {
+ assertEval(0, 0, 0);
+ assertEval(2, -1, 0);
+ assertEval(29, -1, 20);
+ assertEval(numeric_limits<int>::min(), 10, numeric_limits<int>::min());
+ assertEval(numeric_limits<int>::max(), 42, numeric_limits<int>::max());
+}
+
+TEST_F(ExpressionTruncOneArgTest, LongArg1) {
+ assertEval(0LL, 0LL);
+ assertEval(numeric_limits<long long>::min(), numeric_limits<long long>::min());
+ assertEval(numeric_limits<long long>::max(), numeric_limits<long long>::max());
+}
+
+TEST_F(ExpressionTruncTwoArgTest, LongArg2) {
+ assertEval(0LL, 0LL, 0LL);
+ assertEval(2LL, -1LL, 0LL);
+ assertEval(29LL, -1LL, 20LL);
+ assertEval(numeric_limits<long long>::min(), 10LL, numeric_limits<long long>::min());
+ assertEval(numeric_limits<long long>::max(), 42LL, numeric_limits<long long>::max());
+}
+
+TEST_F(ExpressionTruncOneArgTest, DoubleArg1) {
+ assertEval(2.0, 2.0);
+ assertEval(-2.0, -2.0);
+ assertEval(0.9, 0.0);
+ assertEval(0.1, 0.0);
+ assertEval(-1.2, -1.0);
+ assertEval(-1.7, -1.0);
+
+ // Outside the range of long longs (there isn't enough precision for decimals in this range, so
+ // should just preserve the number).
+ double largerThanLong = numeric_limits<long long>::max() * 2.0;
+ assertEval(largerThanLong, largerThanLong);
+ double smallerThanLong = numeric_limits<long long>::min() * 2.0;
+ assertEval(smallerThanLong, smallerThanLong);
+}
+
+TEST_F(ExpressionTruncTwoArgTest, DoubleArg2) {
+ assertEval(2.0, 1.0, 2.0);
+ assertEval(-2.0, 2.0, -2.0);
+ assertEval(0.9, 0, 0.0);
+ assertEval(0.1, 0, 0.0);
+ assertEval(-1.2, 0, -1.0);
+ assertEval(-1.7, 0, -1.0);
+
+
+ assertEval(-3.14159265, 0, -3.0);
+ assertEval(-3.14159265, 1, -3.1);
+ assertEval(-3.14159265, 2, -3.14);
+ assertEval(-3.14159265, 3, -3.141);
+ assertEval(-3.14159265, 4, -3.1415);
+ assertEval(-3.14159265, 5, -3.14159);
+ assertEval(-3.14159265, 6, -3.141592);
+ assertEval(-3.14159265, 7, -3.1415926);
+ assertEval(-3.14159265, 100, -3.14159265);
+ assertEval(3.14159265, 0, 3.0);
+ assertEval(3.14159265, 1, 3.1);
+ assertEval(3.14159265, 2, 3.14);
+ assertEval(3.14159265, 3, 3.141);
+ assertEval(3.14159265, 4, 3.1415);
+ assertEval(3.14159265, 5, 3.14159);
+ assertEval(3.14159265, 6, 3.141592);
+ assertEval(3.14159265, 7, 3.1415926);
+ assertEval(3.14159265, 100, 3.14159265);
+ assertEval(3.14159265, -1, 0.0);
+ assertEval(335.14159265, -1, 330.0);
+ assertEval(333.14159265, -2, 300.0);
+}
+
+TEST_F(ExpressionTruncOneArgTest, DecimalArg1) {
+ assertEval(Decimal128("2"), Decimal128("2.0"));
+ assertEval(Decimal128("-2"), Decimal128("-2.0"));
+ assertEval(Decimal128("0.9"), Decimal128("0.0"));
+ assertEval(Decimal128("0.1"), Decimal128("0.0"));
+ assertEval(Decimal128("-1.2"), Decimal128("-1.0"));
+ assertEval(Decimal128("-1.7"), Decimal128("-1.0"));
+ assertEval(Decimal128("123456789.9999999999999999999999999"), Decimal128("123456789"));
+ assertEval(Decimal128("-99999999999999999999999999999.99"),
+ Decimal128("-99999999999999999999999999999.00"));
+ assertEval(Decimal128("3.4E-6000"), Decimal128("0"));
+}
+
+TEST_F(ExpressionTruncTwoArgTest, DecimalArg2) {
+ assertEval(Decimal128("2"), 0, Decimal128("2.0"));
+ assertEval(Decimal128("-2"), 0, Decimal128("-2.0"));
+ assertEval(Decimal128("0.9"), 0, Decimal128("0.0"));
+ assertEval(Decimal128("0.1"), 0, Decimal128("0.0"));
+ assertEval(Decimal128("-1.2"), 0, Decimal128("-1.0"));
+ assertEval(Decimal128("-1.7"), 0, Decimal128("-1.0"));
+ assertEval(Decimal128("123456789.9999999999999999999999999"), 0, Decimal128("123456789"));
+ assertEval(Decimal128("-99999999999999999999999999999.99"),
+ 0,
+ Decimal128("-99999999999999999999999999999.00"));
+ assertEval(Decimal128("3.4E-6000"), 0, Decimal128("0"));
+
+ assertEval(Decimal128("-3.14159265"), 0, Decimal128("-3.0"));
+ assertEval(Decimal128("-3.14159265"), 1, Decimal128("-3.1"));
+ assertEval(Decimal128("-3.14159265"), 2, Decimal128("-3.14"));
+ assertEval(Decimal128("-3.14159265"), 3, Decimal128("-3.141"));
+ assertEval(Decimal128("-3.14159265"), 4, Decimal128("-3.1415"));
+ assertEval(Decimal128("-3.14159265"), 5, Decimal128("-3.14159"));
+ assertEval(Decimal128("-3.14159265"), 6, Decimal128("-3.141592"));
+ assertEval(Decimal128("-3.14159265"), 7, Decimal128("-3.1415926"));
+ assertEval(Decimal128("-3.14159265"), 100, Decimal128("-3.14159265"));
+ assertEval(Decimal128("3.14159265"), 0, Decimal128("3.0"));
+ assertEval(Decimal128("3.14159265"), 1, Decimal128("3.1"));
+ assertEval(Decimal128("3.14159265"), 2, Decimal128("3.14"));
+ assertEval(Decimal128("3.14159265"), Decimal128("3"), Decimal128("3.141"));
+ assertEval(Decimal128("3.14159265"), 4, Decimal128("3.1415"));
+ assertEval(Decimal128("3.14159265"), Decimal128("5"), Decimal128("3.14159"));
+ assertEval(Decimal128("3.14159265"), 6, Decimal128("3.141592"));
+ assertEval(Decimal128("3.14159265"), 7, Decimal128("3.1415926"));
+ assertEval(Decimal128("3.14159265"), 100, Decimal128("3.14159265"));
+ assertEval(Decimal128("3.14159265"), Decimal128("-1"), Decimal128("0"));
+ assertEval(Decimal128("335.14159265"), -1, Decimal128("330"));
+ assertEval(Decimal128("333.14159265"), -2, Decimal128("300"));
+}
+
+TEST_F(ExpressionTruncOneArgTest, NullArg1) {
+ assertEval((BSONNULL), (BSONNULL));
+}
+
+TEST_F(ExpressionTruncTwoArgTest, NullArg2) {
+ assertEval((BSONNULL), (BSONNULL), (BSONNULL));
+ assertEval((1), (BSONNULL), (BSONNULL));
+ assertEval((BSONNULL), (1), (BSONNULL));
}
/* ------------------------- Old-style tests -------------------------- */