| 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()));
|
| +}
|
|
|