| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <stddef.h> | 5 #include <stddef.h> |
| 6 #include <stdint.h> | 6 #include <stdint.h> |
| 7 | 7 |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <type_traits> | 9 #include <type_traits> |
| 10 | 10 |
| 11 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/numerics/safe_conversions.h" | 13 #include "base/numerics/safe_conversions.h" |
| 14 #include "base/numerics/safe_math.h" | 14 #include "base/numerics/safe_math.h" |
| 15 #include "base/test/gtest_util.h" | 15 #include "base/test/gtest_util.h" |
| 16 #include "build/build_config.h" | 16 #include "build/build_config.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
| 18 | 18 |
| 19 #if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS) | 19 #if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS) |
| 20 #include <mmintrin.h> | 20 #include <mmintrin.h> |
| 21 #endif | 21 #endif |
| 22 | 22 |
| 23 using std::numeric_limits; | 23 using std::numeric_limits; |
| 24 using base::CheckedNumeric; | 24 using base::CheckedNumeric; |
| 25 using base::IsValidForType; | 25 using base::IsValidForType; |
| 26 using base::ValueOrDieForType; | 26 using base::ValueOrDieForType; |
| 27 using base::ValueOrDefaultForType; | 27 using base::ValueOrDefaultForType; |
| 28 using base::CheckNum; | 28 using base::MakeCheckedNum; |
| 29 using base::CheckMax; | 29 using base::CheckMax; |
| 30 using base::CheckMin; | 30 using base::CheckMin; |
| 31 using base::CheckAdd; | 31 using base::CheckAdd; |
| 32 using base::CheckSub; | 32 using base::CheckSub; |
| 33 using base::CheckMul; | 33 using base::CheckMul; |
| 34 using base::CheckDiv; | 34 using base::CheckDiv; |
| 35 using base::CheckMod; | 35 using base::CheckMod; |
| 36 using base::CheckLsh; | 36 using base::CheckLsh; |
| 37 using base::CheckRsh; | 37 using base::CheckRsh; |
| 38 using base::checked_cast; | 38 using base::checked_cast; |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1); | 245 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1); |
| 246 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> (sizeof(Dst) * CHAR_BIT)); | 246 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> (sizeof(Dst) * CHAR_BIT)); |
| 247 TEST_EXPECTED_VALUE(0, | 247 TEST_EXPECTED_VALUE(0, |
| 248 CheckedNumeric<Dst>(1) >> (sizeof(Dst) * CHAR_BIT - 1)); | 248 CheckedNumeric<Dst>(1) >> (sizeof(Dst) * CHAR_BIT - 1)); |
| 249 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one); | 249 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one); |
| 250 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) & 1); | 250 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) & 1); |
| 251 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) & 0); | 251 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) & 0); |
| 252 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) & 1); | 252 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) & 1); |
| 253 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) & 0); | 253 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) & 0); |
| 254 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(), | 254 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(), |
| 255 CheckNum(DstLimits::max()) & -1); | 255 MakeCheckedNum(DstLimits::max()) & -1); |
| 256 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) | 1); | 256 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) | 1); |
| 257 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) | 0); | 257 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) | 0); |
| 258 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) | 1); | 258 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) | 1); |
| 259 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) | 0); | 259 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) | 0); |
| 260 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(), | 260 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(), |
| 261 CheckedNumeric<Dst>(0) | static_cast<Dst>(-1)); | 261 CheckedNumeric<Dst>(0) | static_cast<Dst>(-1)); |
| 262 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) ^ 1); | 262 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) ^ 1); |
| 263 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) ^ 0); | 263 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) ^ 0); |
| 264 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) ^ 1); | 264 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) ^ 1); |
| 265 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) ^ 0); | 265 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) ^ 0); |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 ""); | 476 ""); |
| 477 static_assert(StrictNumeric<Src>(SrcLimits::max()) != DstLimits::lowest(), | 477 static_assert(StrictNumeric<Src>(SrcLimits::max()) != DstLimits::lowest(), |
| 478 ""); | 478 ""); |
| 479 static_assert( | 479 static_assert( |
| 480 !(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(1)), ""); | 480 !(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(1)), ""); |
| 481 static_assert( | 481 static_assert( |
| 482 !(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(0)), ""); | 482 !(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(0)), ""); |
| 483 | 483 |
| 484 // Due to differences in float handling between compilers, these aren't | 484 // Due to differences in float handling between compilers, these aren't |
| 485 // compile-time constants everywhere. So, we use run-time tests. | 485 // compile-time constants everywhere. So, we use run-time tests. |
| 486 EXPECT_EQ(SrcLimits::max(), | 486 EXPECT_EQ( |
| 487 CheckNum(SrcLimits::max()).Max(DstLimits::lowest()).ValueOrDie()); | 487 SrcLimits::max(), |
| 488 EXPECT_EQ(DstLimits::max(), | 488 MakeCheckedNum(SrcLimits::max()).Max(DstLimits::lowest()).ValueOrDie()); |
| 489 CheckNum(SrcLimits::lowest()).Max(DstLimits::max()).ValueOrDie()); | 489 EXPECT_EQ( |
| 490 EXPECT_EQ(DstLimits::lowest(), | 490 DstLimits::max(), |
| 491 CheckNum(SrcLimits::max()).Min(DstLimits::lowest()).ValueOrDie()); | 491 MakeCheckedNum(SrcLimits::lowest()).Max(DstLimits::max()).ValueOrDie()); |
| 492 EXPECT_EQ(SrcLimits::lowest(), | 492 EXPECT_EQ( |
| 493 CheckNum(SrcLimits::lowest()).Min(DstLimits::max()).ValueOrDie()); | 493 DstLimits::lowest(), |
| 494 EXPECT_EQ(SrcLimits::lowest(), CheckMin(MakeStrictNum(1), CheckNum(0), | 494 MakeCheckedNum(SrcLimits::max()).Min(DstLimits::lowest()).ValueOrDie()); |
| 495 EXPECT_EQ( |
| 496 SrcLimits::lowest(), |
| 497 MakeCheckedNum(SrcLimits::lowest()).Min(DstLimits::max()).ValueOrDie()); |
| 498 EXPECT_EQ(SrcLimits::lowest(), CheckMin(MakeStrictNum(1), MakeCheckedNum(0), |
| 495 DstLimits::max(), SrcLimits::lowest()) | 499 DstLimits::max(), SrcLimits::lowest()) |
| 496 .ValueOrDie()); | 500 .ValueOrDie()); |
| 497 EXPECT_EQ(DstLimits::max(), CheckMax(MakeStrictNum(1), CheckNum(0), | 501 EXPECT_EQ(DstLimits::max(), CheckMax(MakeStrictNum(1), MakeCheckedNum(0), |
| 498 DstLimits::max(), SrcLimits::lowest()) | 502 DstLimits::max(), SrcLimits::lowest()) |
| 499 .ValueOrDie()); | 503 .ValueOrDie()); |
| 500 } | 504 } |
| 501 | 505 |
| 502 template <typename Dst, typename Src> | 506 template <typename Dst, typename Src> |
| 503 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> { | 507 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> { |
| 504 static void Test(const char *dst, const char *src, int line) { | 508 static void Test(const char *dst, const char *src, int line) { |
| 505 typedef numeric_limits<Src> SrcLimits; | 509 typedef numeric_limits<Src> SrcLimits; |
| 506 typedef numeric_limits<Dst> DstLimits; | 510 typedef numeric_limits<Dst> DstLimits; |
| 507 // Integral to floating. | 511 // Integral to floating. |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 861 EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity); | 865 EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity); |
| 862 EXPECT_EQ(numeric_limits<int>::min(), saturated_cast<int>(double_small_int)); | 866 EXPECT_EQ(numeric_limits<int>::min(), saturated_cast<int>(double_small_int)); |
| 863 EXPECT_EQ(numeric_limits<int>::max(), saturated_cast<int>(double_large_int)); | 867 EXPECT_EQ(numeric_limits<int>::max(), saturated_cast<int>(double_large_int)); |
| 864 | 868 |
| 865 float not_a_number = std::numeric_limits<float>::infinity() - | 869 float not_a_number = std::numeric_limits<float>::infinity() - |
| 866 std::numeric_limits<float>::infinity(); | 870 std::numeric_limits<float>::infinity(); |
| 867 EXPECT_TRUE(std::isnan(not_a_number)); | 871 EXPECT_TRUE(std::isnan(not_a_number)); |
| 868 EXPECT_EQ(0, saturated_cast<int>(not_a_number)); | 872 EXPECT_EQ(0, saturated_cast<int>(not_a_number)); |
| 869 | 873 |
| 870 // Test the CheckedNumeric value extractions functions. | 874 // Test the CheckedNumeric value extractions functions. |
| 871 auto int8_min = CheckNum(numeric_limits<int8_t>::min()); | 875 auto int8_min = MakeCheckedNum(numeric_limits<int8_t>::min()); |
| 872 auto int8_max = CheckNum(numeric_limits<int8_t>::max()); | 876 auto int8_max = MakeCheckedNum(numeric_limits<int8_t>::max()); |
| 873 auto double_max = CheckNum(numeric_limits<double>::max()); | 877 auto double_max = MakeCheckedNum(numeric_limits<double>::max()); |
| 874 static_assert( | 878 static_assert( |
| 875 std::is_same<int16_t, | 879 std::is_same<int16_t, |
| 876 decltype(int8_min.ValueOrDie<int16_t>())::type>::value, | 880 decltype(int8_min.ValueOrDie<int16_t>())::type>::value, |
| 877 "ValueOrDie returning incorrect type."); | 881 "ValueOrDie returning incorrect type."); |
| 878 static_assert( | 882 static_assert( |
| 879 std::is_same<int16_t, | 883 std::is_same<int16_t, |
| 880 decltype(int8_min.ValueOrDefault<int16_t>(0))::type>::value, | 884 decltype(int8_min.ValueOrDefault<int16_t>(0))::type>::value, |
| 881 "ValueOrDefault returning incorrect type."); | 885 "ValueOrDefault returning incorrect type."); |
| 882 EXPECT_FALSE(IsValidForType<uint8_t>(int8_min)); | 886 EXPECT_FALSE(IsValidForType<uint8_t>(int8_min)); |
| 883 EXPECT_TRUE(IsValidForType<uint8_t>(int8_max)); | 887 EXPECT_TRUE(IsValidForType<uint8_t>(int8_max)); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1008 EXPECT_TRUE(too_large.IsValid()); | 1012 EXPECT_TRUE(too_large.IsValid()); |
| 1009 too_large += d; | 1013 too_large += d; |
| 1010 EXPECT_FALSE(too_large.IsValid()); | 1014 EXPECT_FALSE(too_large.IsValid()); |
| 1011 too_large -= d; | 1015 too_large -= d; |
| 1012 EXPECT_FALSE(too_large.IsValid()); | 1016 EXPECT_FALSE(too_large.IsValid()); |
| 1013 too_large /= d; | 1017 too_large /= d; |
| 1014 EXPECT_FALSE(too_large.IsValid()); | 1018 EXPECT_FALSE(too_large.IsValid()); |
| 1015 } | 1019 } |
| 1016 | 1020 |
| 1017 TEST(SafeNumerics, VariadicNumericOperations) { | 1021 TEST(SafeNumerics, VariadicNumericOperations) { |
| 1018 auto a = CheckAdd(1, 2UL, CheckNum(3LL), 4).ValueOrDie(); | 1022 auto a = CheckAdd(1, 2UL, MakeCheckedNum(3LL), 4).ValueOrDie(); |
| 1019 EXPECT_EQ(static_cast<decltype(a)::type>(10), a); | 1023 EXPECT_EQ(static_cast<decltype(a)::type>(10), a); |
| 1020 auto b = CheckSub(CheckNum(20.0), 2UL, 4).ValueOrDie(); | 1024 auto b = CheckSub(MakeCheckedNum(20.0), 2UL, 4).ValueOrDie(); |
| 1021 EXPECT_EQ(static_cast<decltype(b)::type>(14.0), b); | 1025 EXPECT_EQ(static_cast<decltype(b)::type>(14.0), b); |
| 1022 auto c = CheckMul(20.0, CheckNum(1), 5, 3UL).ValueOrDie(); | 1026 auto c = CheckMul(20.0, MakeCheckedNum(1), 5, 3UL).ValueOrDie(); |
| 1023 EXPECT_EQ(static_cast<decltype(c)::type>(300.0), c); | 1027 EXPECT_EQ(static_cast<decltype(c)::type>(300.0), c); |
| 1024 auto d = CheckDiv(20.0, 2.0, CheckNum(5LL), -4).ValueOrDie(); | 1028 auto d = CheckDiv(20.0, 2.0, MakeCheckedNum(5LL), -4).ValueOrDie(); |
| 1025 EXPECT_EQ(static_cast<decltype(d)::type>(-.5), d); | 1029 EXPECT_EQ(static_cast<decltype(d)::type>(-.5), d); |
| 1026 auto e = CheckMod(CheckNum(20), 3).ValueOrDie(); | 1030 auto e = CheckMod(MakeCheckedNum(20), 3).ValueOrDie(); |
| 1027 EXPECT_EQ(static_cast<decltype(e)::type>(2), e); | 1031 EXPECT_EQ(static_cast<decltype(e)::type>(2), e); |
| 1028 auto f = CheckLsh(1, CheckNum(2)).ValueOrDie(); | 1032 auto f = CheckLsh(1, MakeCheckedNum(2)).ValueOrDie(); |
| 1029 EXPECT_EQ(static_cast<decltype(f)::type>(4), f); | 1033 EXPECT_EQ(static_cast<decltype(f)::type>(4), f); |
| 1030 auto g = CheckRsh(4, CheckNum(2)).ValueOrDie(); | 1034 auto g = CheckRsh(4, MakeCheckedNum(2)).ValueOrDie(); |
| 1031 EXPECT_EQ(static_cast<decltype(g)::type>(1), g); | 1035 EXPECT_EQ(static_cast<decltype(g)::type>(1), g); |
| 1032 auto h = CheckRsh(CheckAdd(1, 1, 1, 1), CheckSub(4, 2)).ValueOrDie(); | 1036 auto h = CheckRsh(CheckAdd(1, 1, 1, 1), CheckSub(4, 2)).ValueOrDie(); |
| 1033 EXPECT_EQ(static_cast<decltype(h)::type>(1), h); | 1037 EXPECT_EQ(static_cast<decltype(h)::type>(1), h); |
| 1034 } | 1038 } |
| OLD | NEW |