diff options
author | Patrick Meredith <pmeredit@gmail.com> | 2018-10-22 17:01:46 -0400 |
---|---|---|
committer | Charlie Swanson <charlie.swanson@mongodb.com> | 2019-02-14 17:54:56 -0500 |
commit | 814b1f8237db9ecb27dd0ffa96f11edd58bac73e (patch) | |
tree | 4e13cadda4f9dc3ea4f4d7156476f31c77ba9726 /src/mongo/db/pipeline/expression_test.cpp | |
parent | f1da8170c1c568762b29e44910afbcc6f01a644f (diff) | |
download | mongo-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.cpp | 336 |
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 -------------------------- */ |