diff options
author | Andrew Morrow <acm@10gen.com> | 2013-08-19 16:54:09 -0400 |
---|---|---|
committer | Andrew Morrow <acm@10gen.com> | 2013-08-20 11:48:46 -0400 |
commit | 95f78edec079e130c58bed831cfe341f45250784 (patch) | |
tree | 90b17d6e3d67740e39532ad5b47f46f7d2f204df /src/mongo/util/safe_num_test.cpp | |
parent | fce3b4ce8fe848c332657f3accf596e6b087bce9 (diff) | |
download | mongo-95f78edec079e130c58bed831cfe341f45250784.tar.gz |
SERVER-375 Implement multiplication for SafeNum
Diffstat (limited to 'src/mongo/util/safe_num_test.cpp')
-rw-r--r-- | src/mongo/util/safe_num_test.cpp | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/src/mongo/util/safe_num_test.cpp b/src/mongo/util/safe_num_test.cpp index e805d4ac293..a0f7ac28752 100644 --- a/src/mongo/util/safe_num_test.cpp +++ b/src/mongo/util/safe_num_test.cpp @@ -308,4 +308,140 @@ namespace { ASSERT_TRUE(expected.isIdentical(result_b_s)); } + TEST(Multiplication, Zero) { + const SafeNum zero(0); + ASSERT_EQUALS(zero * 0, zero); + ASSERT_EQUALS(zero * zero, zero); + } + + TEST(Multiplication, LongZero) { + const SafeNum zero(0LL); + ASSERT_EQUALS(zero * 0LL, zero); + ASSERT_EQUALS(zero * zero, zero); + } + + TEST(Multiplication, DoubleZero) { + const SafeNum zero(0.0); + ASSERT_EQUALS(zero * 0.0, zero); + ASSERT_EQUALS(zero * zero, zero); + } + + TEST(Multiplication, One) { + const SafeNum plusOne(1); + ASSERT_EQUALS(plusOne * 1, plusOne); + ASSERT_EQUALS(plusOne * plusOne, plusOne); + } + + TEST(Multiplication, LongOne) { + const SafeNum plusOne(1LL); + ASSERT_EQUALS(plusOne * 1LL, plusOne); + ASSERT_EQUALS(plusOne * plusOne, plusOne); + } + + TEST(Multiplication, DoubleOne) { + const SafeNum plusOne(1.0); + ASSERT_EQUALS(plusOne * 1.0, plusOne); + ASSERT_EQUALS(plusOne * plusOne, plusOne); + } + + TEST(Multiplication, UpConvertion) { + const SafeNum zeroInt32(0); + const SafeNum zeroInt64(0LL); + const SafeNum zeroDouble(0.0); + ASSERT_EQUALS((zeroInt32 * zeroInt64).type(), mongo::NumberLong); + ASSERT_EQUALS((zeroInt64 * zeroInt32).type(), mongo::NumberLong); + ASSERT_EQUALS((zeroInt32 * zeroDouble).type(), mongo::NumberDouble); + ASSERT_EQUALS((zeroInt64 * zeroDouble).type(), mongo::NumberDouble); + ASSERT_EQUALS((zeroDouble * zeroInt32).type(), mongo::NumberDouble); + ASSERT_EQUALS((zeroDouble * zeroInt64).type(), mongo::NumberDouble); + + const SafeNum stillInt32(zeroInt32 * zeroInt32); + const SafeNum stillInt64(zeroInt64 * zeroInt64); + const SafeNum stillDouble(zeroDouble * zeroDouble); + ASSERT_EQUALS(stillInt32.type(), mongo::NumberInt); + ASSERT_EQUALS(stillInt64.type(), mongo::NumberLong); + ASSERT_EQUALS(stillDouble.type(), mongo::NumberDouble); + } + + TEST(Multiplication, Overflow32to64) { + const SafeNum maxInt32(std::numeric_limits<int>::max()); + ASSERT_EQUALS(maxInt32.type(), mongo::NumberInt); + + const SafeNum int32TimesOne(maxInt32 * 1); + ASSERT_EQUALS(int32TimesOne.type(), mongo::NumberInt); + + const SafeNum int32TimesTwo(maxInt32 * 2); + ASSERT_EQUALS(int32TimesTwo.type(), mongo::NumberLong); + } + + TEST(Multiplication, Overflow64toDouble) { + const SafeNum maxInt64(std::numeric_limits<long long>::max()); + ASSERT_EQUALS(maxInt64.type(), mongo::NumberLong); + + // We don't overflow int64 to double. + const SafeNum int64TimesTwo(maxInt64 * 2); + ASSERT_EQUALS(int64TimesTwo.type(), mongo::EOO); + + const SafeNum doubleResult(std::numeric_limits<long long>::max()*static_cast<double>(2)); + ASSERT_EQUALS(doubleResult.type(), mongo::NumberDouble); + ASSERT_NOT_EQUALS(int64TimesTwo, doubleResult); + } + + TEST(Multiplication, OverflowDouble) { + const SafeNum maxDouble(std::numeric_limits<double>::max()); + ASSERT_EQUALS(maxDouble.type(), mongo::NumberDouble); + + const SafeNum doublePlusMax(maxDouble * maxDouble); + ASSERT_EQUALS(doublePlusMax.type(), mongo::NumberDouble); + + const SafeNum infinity(std::numeric_limits<double>::infinity()); + ASSERT_EQUALS(doublePlusMax, infinity); + } + + TEST(Multiplication, Negative32to64) { + const SafeNum minInt32(std::numeric_limits<int>::min()); + ASSERT_EQUALS(minInt32.type(), mongo::NumberInt); + + const SafeNum int32TimesOne(minInt32 * 1); + ASSERT_EQUALS(int32TimesOne.type(), mongo::NumberInt); + + const SafeNum int32TimesTwo(minInt32 * 2); + ASSERT_EQUALS(int32TimesTwo.type(), mongo::NumberLong); + } + + TEST(Multiplication, Negative64toDouble) { + const SafeNum minInt64(std::numeric_limits<long long>::min()); + ASSERT_EQUALS(minInt64.type(), mongo::NumberLong); + + // We don't overflow int64 to double. + const SafeNum int64TimesTwo(minInt64 * 2); + ASSERT_EQUALS(int64TimesTwo.type(), mongo::EOO); + + const SafeNum int64TimesOne(minInt64 * 1); + ASSERT_EQUALS(int64TimesOne.type(), mongo::NumberLong); + + const SafeNum doubleResult(std::numeric_limits<long long>::min()*static_cast<double>(2)); + ASSERT_EQUALS(doubleResult.type(), mongo::NumberDouble); + ASSERT_NOT_EQUALS(int64TimesTwo, doubleResult); + } + + TEST(Multiplication, 64OverflowsFourWays) { + const SafeNum maxInt64(std::numeric_limits<long long>::max()); + const SafeNum minInt64(std::numeric_limits<long long>::min()); + ASSERT_EQUALS(mongo::EOO, (maxInt64 * maxInt64).type()); + ASSERT_EQUALS(mongo::EOO, (maxInt64 * minInt64).type()); + ASSERT_EQUALS(mongo::EOO, (minInt64 * maxInt64).type()); + ASSERT_EQUALS(mongo::EOO, (minInt64 * minInt64).type()); + } + + TEST(Multiplication, BoundsWithNegativeOne) { + const SafeNum maxInt64(std::numeric_limits<long long>::max()); + const SafeNum minInt64(std::numeric_limits<long long>::min()); + const SafeNum minusOneInt64(-1LL); + ASSERT_NOT_EQUALS(mongo::EOO, (maxInt64 * minusOneInt64).type()); + ASSERT_NOT_EQUALS(mongo::EOO, (minusOneInt64 * maxInt64).type()); + ASSERT_EQUALS(mongo::EOO, (minInt64 * minusOneInt64).type()); + ASSERT_EQUALS(mongo::EOO, (minusOneInt64 * minInt64).type()); + } + } // unnamed namespace |