Index: base/numerics/safe_numerics_unittest.cc |
diff --git a/base/numerics/safe_numerics_unittest.cc b/base/numerics/safe_numerics_unittest.cc |
index 6f9a966c0156431e654e71d483d81083fe555690..bad0f5718516b4579f45cf8c4497129a149a0a28 100644 |
--- a/base/numerics/safe_numerics_unittest.cc |
+++ b/base/numerics/safe_numerics_unittest.cc |
@@ -18,6 +18,7 @@ |
using std::numeric_limits; |
using base::CheckedNumeric; |
using base::checked_cast; |
+using base::IsValueInRangeForNumericType; |
using base::SizeT; |
using base::StrictNumeric; |
using base::saturated_cast; |
@@ -36,6 +37,26 @@ using base::enable_if; |
#pragma warning(disable:4756) |
#endif |
+// This is a helper function for finding the maximum value in Src that can be |
+// wholy represented as the destination floating-point type. |
+template <typename Dst, typename Src> |
+Dst GetMaxConvertibleToFloat() { |
+ typedef numeric_limits<Dst> DstLimits; |
+ typedef numeric_limits<Src> SrcLimits; |
+ static_assert(SrcLimits::is_specialized, "Source must be numeric."); |
+ static_assert(DstLimits::is_specialized, "Destination must be numeric."); |
+ CHECK(DstLimits::is_iec559); |
+ |
+ if (SrcLimits::digits <= DstLimits::digits && |
+ MaxExponent<Src>::value <= MaxExponent<Dst>::value) |
+ return SrcLimits::max(); |
+ Src max = SrcLimits::max() / 2 + (SrcLimits::is_integer ? 1 : 0); |
+ while (max != static_cast<Src>(static_cast<Dst>(max))) { |
+ max /= 2; |
+ } |
+ return static_cast<Dst>(max); |
+} |
+ |
// Helper macros to wrap displaying the conversion types and line numbers. |
#define TEST_EXPECTED_VALIDITY(expected, actual) \ |
EXPECT_EQ(expected, CheckedNumeric<Dst>(actual).validity()) \ |
@@ -370,6 +391,18 @@ struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> { |
TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity()); |
TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1); |
TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN()); |
+ if (DstLimits::is_integer) { |
+ if (SrcLimits::digits < DstLimits::digits) { |
+ TEST_EXPECTED_RANGE(RANGE_OVERFLOW, |
+ static_cast<Src>(DstLimits::max())); |
+ } else { |
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max())); |
+ } |
+ TEST_EXPECTED_RANGE( |
+ RANGE_VALID, |
+ static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>())); |
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::min())); |
+ } |
} else if (SrcLimits::is_signed) { |
TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1)); |
TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min()); |
@@ -428,6 +461,18 @@ struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> { |
TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity()); |
TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1); |
TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN()); |
+ if (DstLimits::is_integer) { |
+ if (SrcLimits::digits < DstLimits::digits) { |
+ TEST_EXPECTED_RANGE(RANGE_OVERFLOW, |
+ static_cast<Src>(DstLimits::max())); |
+ } else { |
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max())); |
+ } |
+ TEST_EXPECTED_RANGE( |
+ RANGE_VALID, |
+ static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>())); |
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::min())); |
+ } |
} else { |
TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min()); |
} |
@@ -600,3 +645,77 @@ TEST(SafeNumerics, CastTests) { |
EXPECT_EQ(numeric_limits<int>::max(), saturated_cast<int>(double_large_int)); |
} |
+TEST(SafeNumerics, IsValueInRangeForNumericType) { |
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0)); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(1)); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(2)); |
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(-1)); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0xffffffffu)); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0xffffffff))); |
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000000))); |
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000001))); |
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>( |
+ std::numeric_limits<int32_t>::min())); |
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>( |
+ std::numeric_limits<int64_t>::min())); |
+ |
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0)); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(1)); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(2)); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(-1)); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffff)); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffffu)); |
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0x80000000u)); |
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0xffffffffu)); |
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x80000000))); |
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0xffffffff))); |
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x100000000))); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>( |
+ std::numeric_limits<int32_t>::min())); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>( |
+ implicit_cast<int64_t>(std::numeric_limits<int32_t>::min()))); |
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>( |
+ implicit_cast<int64_t>(std::numeric_limits<int32_t>::min()) - 1)); |
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>( |
+ std::numeric_limits<int64_t>::min())); |
+ |
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0)); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(1)); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(2)); |
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(-1)); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0xffffffffu)); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0xffffffff))); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000000))); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000001))); |
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>( |
+ std::numeric_limits<int32_t>::min())); |
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(INT64_C(-1))); |
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>( |
+ std::numeric_limits<int64_t>::min())); |
+ |
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0)); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(1)); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(2)); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(-1)); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffff)); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffffu)); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x80000000u)); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0xffffffffu)); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x80000000))); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0xffffffff))); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x100000000))); |
+ EXPECT_TRUE( |
+ IsValueInRangeForNumericType<int64_t>(INT64_C(0x7fffffffffffffff))); |
+ EXPECT_TRUE( |
+ IsValueInRangeForNumericType<int64_t>(UINT64_C(0x7fffffffffffffff))); |
+ EXPECT_FALSE( |
+ IsValueInRangeForNumericType<int64_t>(UINT64_C(0x8000000000000000))); |
+ EXPECT_FALSE( |
+ IsValueInRangeForNumericType<int64_t>(UINT64_C(0xffffffffffffffff))); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>( |
+ std::numeric_limits<int32_t>::min())); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>( |
+ implicit_cast<int64_t>(std::numeric_limits<int32_t>::min()))); |
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>( |
+ std::numeric_limits<int64_t>::min())); |
+} |