Chromium Code Reviews| Index: base/safe_numerics_unittest.cc |
| =================================================================== |
| --- base/safe_numerics_unittest.cc (revision 244596) |
| +++ base/safe_numerics_unittest.cc (working copy) |
| @@ -4,6 +4,9 @@ |
| #include <gtest/gtest.h> |
| +#include <stdint.h> |
|
akalin
2014/01/14 00:49:19
why mix c-style and c++-style libc headers? I'd go
jschuh
2014/01/14 05:24:33
Done.
|
| + |
| +#include <cmath> |
| #include <sstream> |
| #include <vector> |
| @@ -12,45 +15,6 @@ |
| namespace base { |
| namespace internal { |
| -// This is far (far, far) too slow to run normally, but if you're refactoring |
| -// it might be useful. |
| -// #define RUN_EXHAUSTIVE_TEST |
| - |
| -#ifdef RUN_EXHAUSTIVE_TEST |
| - |
| -template <class From, class To> void ExhaustiveCheckFromTo() { |
| - fprintf(stderr, "."); |
| - From i = std::numeric_limits<From>::min(); |
| - for (;;) { |
| - std::ostringstream str_from, str_to; |
| - str_from << i; |
| - To to = static_cast<To>(i); |
| - str_to << to; |
| - bool strings_equal = str_from.str() == str_to.str(); |
| - EXPECT_EQ(IsValidNumericCast<To>(i), strings_equal); |
| - fprintf(stderr, "\r%s vs %s\x1B[K", |
| - str_from.str().c_str(), str_to.str().c_str()); |
| - ++i; |
| - // If we wrap, then we've tested everything. |
| - if (i == std::numeric_limits<From>::min()) |
| - break; |
| - } |
| -} |
| - |
| -template <class From> void ExhaustiveCheckFrom() { |
| - ExhaustiveCheckFromTo<From, short>(); |
| - ExhaustiveCheckFromTo<From, unsigned short>(); |
| - ExhaustiveCheckFromTo<From, int>(); |
| - ExhaustiveCheckFromTo<From, unsigned int>(); |
| - ExhaustiveCheckFromTo<From, long long>(); |
| - ExhaustiveCheckFromTo<From, unsigned long long>(); |
| - ExhaustiveCheckFromTo<From, size_t>(); |
| - fprintf(stderr, "\n"); |
| -} |
| - |
| -#endif |
| - |
| - |
| TEST(SafeNumerics, NumericCast) { |
| int small_positive = 1; |
| int small_negative = -1; |
| @@ -58,93 +22,113 @@ |
| int large_negative = INT_MIN; |
| size_t size_t_small = 1; |
| size_t size_t_large = UINT_MAX; |
| + double double_small = 1.0; |
| + double double_large = DBL_MAX; |
| + double double_negative = -1.0; |
| + double double_nan = std::numeric_limits<double>::quiet_NaN(); |
| + double double_infinity = std::numeric_limits<double>::infinity(); |
| // Narrow signed destination. |
| - EXPECT_TRUE(IsValidNumericCast<signed char>(small_positive)); |
| - EXPECT_TRUE(IsValidNumericCast<signed char>(small_negative)); |
| - EXPECT_FALSE(IsValidNumericCast<signed char>(large_positive)); |
| - EXPECT_FALSE(IsValidNumericCast<signed char>(large_negative)); |
| - EXPECT_TRUE(IsValidNumericCast<signed short>(small_positive)); |
| - EXPECT_TRUE(IsValidNumericCast<signed short>(small_negative)); |
| + EXPECT_EQ(NumericRangeCheck<signed char>(small_positive), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<signed char>(small_negative), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<signed char>(large_positive), TYPE_OVERFLOW); |
| + EXPECT_EQ(NumericRangeCheck<signed char>(large_negative), TYPE_UNDERFLOW); |
| + EXPECT_EQ(NumericRangeCheck<int16_t>(small_positive), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<int16_t>(small_negative), TYPE_VALID); |
| // Narrow unsigned destination. |
| - EXPECT_TRUE(IsValidNumericCast<unsigned char>(small_positive)); |
| - EXPECT_FALSE(IsValidNumericCast<unsigned char>(small_negative)); |
| - EXPECT_FALSE(IsValidNumericCast<unsigned char>(large_positive)); |
| - EXPECT_FALSE(IsValidNumericCast<unsigned char>(large_negative)); |
| - EXPECT_FALSE(IsValidNumericCast<unsigned short>(small_negative)); |
| - EXPECT_FALSE(IsValidNumericCast<unsigned short>(large_negative)); |
| + EXPECT_EQ(NumericRangeCheck<unsigned char>(small_positive), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<unsigned char>(small_negative), TYPE_UNDERFLOW); |
| + EXPECT_EQ(NumericRangeCheck<unsigned char>(large_positive), TYPE_OVERFLOW); |
| + EXPECT_EQ(NumericRangeCheck<unsigned char>(large_negative), TYPE_UNDERFLOW); |
| + EXPECT_EQ(NumericRangeCheck<uint16_t>(small_negative), TYPE_UNDERFLOW); |
| + EXPECT_EQ(NumericRangeCheck<uint16_t>(large_negative), TYPE_UNDERFLOW); |
| // Same width signed destination. |
| - EXPECT_TRUE(IsValidNumericCast<signed int>(small_positive)); |
| - EXPECT_TRUE(IsValidNumericCast<signed int>(small_negative)); |
| - EXPECT_TRUE(IsValidNumericCast<signed int>(large_positive)); |
| - EXPECT_TRUE(IsValidNumericCast<signed int>(large_negative)); |
| + EXPECT_EQ(NumericRangeCheck<signed int>(small_positive), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<signed int>(small_negative), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<signed int>(large_positive), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<signed int>(large_negative), TYPE_VALID); |
| // Same width unsigned destination. |
| - EXPECT_TRUE(IsValidNumericCast<unsigned int>(small_positive)); |
| - EXPECT_FALSE(IsValidNumericCast<unsigned int>(small_negative)); |
| - EXPECT_TRUE(IsValidNumericCast<unsigned int>(large_positive)); |
| - EXPECT_FALSE(IsValidNumericCast<unsigned int>(large_negative)); |
| + EXPECT_EQ(NumericRangeCheck<unsigned int>(small_positive), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<unsigned int>(small_negative), TYPE_UNDERFLOW); |
| + EXPECT_EQ(NumericRangeCheck<unsigned int>(large_positive), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<unsigned int>(large_negative), TYPE_UNDERFLOW); |
| // Wider signed destination. |
| - EXPECT_TRUE(IsValidNumericCast<long long>(small_positive)); |
| - EXPECT_TRUE(IsValidNumericCast<long long>(large_negative)); |
| - EXPECT_TRUE(IsValidNumericCast<long long>(small_positive)); |
| - EXPECT_TRUE(IsValidNumericCast<long long>(large_negative)); |
| + EXPECT_EQ(NumericRangeCheck<int64_t>(small_positive), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<int64_t>(large_negative), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<int64_t>(small_positive), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<int64_t>(large_negative), TYPE_VALID); |
| // Wider unsigned destination. |
| - EXPECT_TRUE(IsValidNumericCast<unsigned long long>(small_positive)); |
| - EXPECT_FALSE(IsValidNumericCast<unsigned long long>(small_negative)); |
| - EXPECT_TRUE(IsValidNumericCast<unsigned long long>(large_positive)); |
| - EXPECT_FALSE(IsValidNumericCast<unsigned long long>(large_negative)); |
| + EXPECT_EQ(NumericRangeCheck<uint64_t>(small_positive), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<uint64_t>(small_negative), |
| + TYPE_UNDERFLOW); |
| + EXPECT_EQ(NumericRangeCheck<uint64_t>(large_positive), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<uint64_t>(large_negative), |
| + TYPE_UNDERFLOW); |
| // Negative to size_t. |
| - EXPECT_FALSE(IsValidNumericCast<size_t>(small_negative)); |
| - EXPECT_FALSE(IsValidNumericCast<size_t>(large_negative)); |
| + EXPECT_EQ(NumericRangeCheck<size_t>(small_negative), TYPE_UNDERFLOW); |
| + EXPECT_EQ(NumericRangeCheck<size_t>(large_negative), TYPE_UNDERFLOW); |
| + // Floating point conversions. |
| + EXPECT_EQ(NumericRangeCheck<int>(double_small), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<int>(double_large), TYPE_OVERFLOW); |
| + EXPECT_EQ(NumericRangeCheck<int>(double_negative), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<unsigned int>(double_negative), TYPE_UNDERFLOW); |
| + EXPECT_EQ(NumericRangeCheck<int>(double_infinity), TYPE_OVERFLOW); |
| + EXPECT_EQ(NumericRangeCheck<int>(-double_infinity), TYPE_UNDERFLOW); |
| + EXPECT_EQ(NumericRangeCheck<unsigned int>(double_infinity), TYPE_OVERFLOW); |
| + EXPECT_EQ(NumericRangeCheck<unsigned int>(-double_infinity), TYPE_UNDERFLOW); |
| + EXPECT_EQ(NumericRangeCheck<unsigned int>(double_nan), TYPE_INVALID); |
| + |
| // From unsigned. |
| // Small. |
| - EXPECT_TRUE(IsValidNumericCast<signed char>(size_t_small)); |
| - EXPECT_TRUE(IsValidNumericCast<unsigned char>(size_t_small)); |
| - EXPECT_TRUE(IsValidNumericCast<short>(size_t_small)); |
| - EXPECT_TRUE(IsValidNumericCast<unsigned short>(size_t_small)); |
| - EXPECT_TRUE(IsValidNumericCast<int>(size_t_small)); |
| - EXPECT_TRUE(IsValidNumericCast<unsigned int>(size_t_small)); |
| - EXPECT_TRUE(IsValidNumericCast<long long>(size_t_small)); |
| - EXPECT_TRUE(IsValidNumericCast<unsigned long long>(size_t_small)); |
| + EXPECT_EQ(NumericRangeCheck<signed char>(size_t_small), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<unsigned char>(size_t_small), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<int16_t>(size_t_small), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<uint16_t>(size_t_small), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<int>(size_t_small), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<unsigned int>(size_t_small), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<int64_t>(size_t_small), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<uint64_t>(size_t_small), TYPE_VALID); |
| // Large. |
| - EXPECT_FALSE(IsValidNumericCast<signed char>(size_t_large)); |
| - EXPECT_FALSE(IsValidNumericCast<unsigned char>(size_t_large)); |
| - EXPECT_FALSE(IsValidNumericCast<short>(size_t_large)); |
| - EXPECT_FALSE(IsValidNumericCast<unsigned short>(size_t_large)); |
| - EXPECT_FALSE(IsValidNumericCast<int>(size_t_large)); |
| - EXPECT_TRUE(IsValidNumericCast<unsigned int>(size_t_large)); |
| - EXPECT_TRUE(IsValidNumericCast<long long>(size_t_large)); |
| - EXPECT_TRUE(IsValidNumericCast<unsigned long long>(size_t_large)); |
| + EXPECT_EQ(NumericRangeCheck<signed char>(size_t_large), TYPE_OVERFLOW); |
| + EXPECT_EQ(NumericRangeCheck<unsigned char>(size_t_large), TYPE_OVERFLOW); |
| + EXPECT_EQ(NumericRangeCheck<int16_t>(size_t_large), TYPE_OVERFLOW); |
| + EXPECT_EQ(NumericRangeCheck<uint16_t>(size_t_large), TYPE_OVERFLOW); |
| + EXPECT_EQ(NumericRangeCheck<int>(size_t_large), TYPE_OVERFLOW); |
| + EXPECT_EQ(NumericRangeCheck<unsigned int>(size_t_large), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<int64_t>(size_t_large), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<uint64_t>(size_t_large), TYPE_VALID); |
| // Various edge cases. |
| - EXPECT_TRUE(IsValidNumericCast<int>(static_cast<short>(SHRT_MIN))); |
| - EXPECT_FALSE( |
| - IsValidNumericCast<unsigned short>(static_cast<short>(SHRT_MIN))); |
| - EXPECT_FALSE(IsValidNumericCast<unsigned short>(SHRT_MIN)); |
| + EXPECT_EQ(NumericRangeCheck<int>(static_cast<int16_t>(SHRT_MIN)), TYPE_VALID); |
| + EXPECT_EQ(NumericRangeCheck<uint16_t>(static_cast<int16_t>(SHRT_MIN)), |
| + TYPE_UNDERFLOW); |
| + EXPECT_EQ(NumericRangeCheck<uint16_t>(SHRT_MIN), TYPE_UNDERFLOW); |
| + // Basic saturation tests. |
| + EXPECT_EQ(saturated_cast<int>(small_negative), |
| + static_cast<int>(small_negative)); |
| + EXPECT_EQ(saturated_cast<int>(small_positive), |
|
akalin
2014/01/14 00:49:19
this repeats previous test. did you mean large_pos
jschuh
2014/01/14 05:24:33
Which does it repeat?
|
| + static_cast<int>(small_positive)); |
| + EXPECT_EQ(saturated_cast<unsigned>(small_negative), |
| + static_cast<unsigned>(0)); |
| + EXPECT_EQ(saturated_cast<int>(double_small), |
| + static_cast<int>(double_small)); |
| + EXPECT_EQ(saturated_cast<int>(double_large), |
| + std::numeric_limits<int>::max()); |
| + |
| // Confirm that checked_numeric_cast<> actually compiles. |
| std::vector<int> v; |
| unsigned int checked_size = |
| base::checked_numeric_cast<unsigned int>(v.size()); |
| EXPECT_EQ(0u, checked_size); |
| - |
| -#ifdef RUN_EXHAUSTIVE_TEST |
| - ExhaustiveCheckFrom<short>(); |
| - ExhaustiveCheckFrom<unsigned short>(); |
| - ExhaustiveCheckFrom<int>(); |
| - ExhaustiveCheckFrom<unsigned int>(); |
| - ExhaustiveCheckFrom<long long>(); |
| - ExhaustiveCheckFrom<unsigned long long>(); |
| - ExhaustiveCheckFrom<size_t>(); |
| -#endif |
| } |
| } // namespace internal |