summaryrefslogtreecommitdiff
path: root/src/mongo/util/safe_num_test.cpp
diff options
context:
space:
mode:
authorAndrew Morrow <acm@10gen.com>2013-08-19 16:54:09 -0400
committerAndrew Morrow <acm@10gen.com>2013-08-20 11:48:46 -0400
commit95f78edec079e130c58bed831cfe341f45250784 (patch)
tree90b17d6e3d67740e39532ad5b47f46f7d2f204df /src/mongo/util/safe_num_test.cpp
parentfce3b4ce8fe848c332657f3accf596e6b087bce9 (diff)
downloadmongo-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.cpp136
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