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; | |
26 using base::ValueOrDieForType; | |
27 using base::ValueOrDefaultForType; | |
25 using base::CheckNum; | 28 using base::CheckNum; |
26 using base::CheckAdd; | 29 using base::CheckAdd; |
27 using base::CheckSub; | 30 using base::CheckSub; |
28 using base::CheckMul; | 31 using base::CheckMul; |
29 using base::CheckDiv; | 32 using base::CheckDiv; |
30 using base::CheckMod; | 33 using base::CheckMod; |
31 using base::CheckLsh; | 34 using base::CheckLsh; |
32 using base::CheckRsh; | 35 using base::CheckRsh; |
33 using base::checked_cast; | 36 using base::checked_cast; |
34 using base::IsValueInRangeForNumericType; | 37 using base::IsValueInRangeForNumericType; |
35 using base::IsValueNegative; | 38 using base::IsValueNegative; |
36 using base::SizeT; | 39 using base::SizeT; |
37 using base::StrictNumeric; | 40 using base::StrictNumeric; |
38 using base::saturated_cast; | 41 using base::saturated_cast; |
39 using base::strict_cast; | 42 using base::strict_cast; |
43 using base::StrictNumeric; | |
40 using base::internal::MaxExponent; | 44 using base::internal::MaxExponent; |
41 using base::internal::RANGE_VALID; | 45 using base::internal::RANGE_VALID; |
42 using base::internal::RANGE_INVALID; | 46 using base::internal::RANGE_INVALID; |
43 using base::internal::RANGE_OVERFLOW; | 47 using base::internal::RANGE_OVERFLOW; |
44 using base::internal::RANGE_UNDERFLOW; | 48 using base::internal::RANGE_UNDERFLOW; |
45 using base::internal::SignedIntegerForSize; | 49 using base::internal::SignedIntegerForSize; |
46 | 50 |
47 // These tests deliberately cause arithmetic boundary errors. If the compiler is | 51 // These tests deliberately cause arithmetic boundary errors. If the compiler is |
48 // aggressive enough, it can const detect these errors, so we disable warnings. | 52 // aggressive enough, it can const detect these errors, so we disable warnings. |
49 #if defined(OS_WIN) | 53 #if defined(OS_WIN) |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
101 #define TEST_EXPECTED_FAILURE(actual) TEST_EXPECTED_VALIDITY(false, actual) | 105 #define TEST_EXPECTED_FAILURE(actual) TEST_EXPECTED_VALIDITY(false, actual) |
102 | 106 |
103 #define TEST_EXPECTED_VALUE(expected, actual) \ | 107 #define TEST_EXPECTED_VALUE(expected, actual) \ |
104 EXPECT_EQ(static_cast<Dst>(expected), \ | 108 EXPECT_EQ(static_cast<Dst>(expected), \ |
105 ((actual) \ | 109 ((actual) \ |
106 .template Cast<Dst>() \ | 110 .template Cast<Dst>() \ |
107 .template ValueOrDie<Dst, LogOnFailure>())) \ | 111 .template ValueOrDie<Dst, LogOnFailure>())) \ |
108 << "Result test: Value " << GetNumericValueForTest(actual) << " as " \ | 112 << "Result test: Value " << GetNumericValueForTest(actual) << " as " \ |
109 << dst << " on line " << line | 113 << dst << " on line " << line |
110 | 114 |
115 // Test the simple pointer arithmetic overrides. | |
116 template <typename Dst> | |
117 void TestStrictPointerMath() { | |
118 Dst dummy_value = 0; | |
119 Dst* dummy_ptr = &dummy_value; | |
120 static const Dst kDummyOffset = 2; // Don't want to go too far. | |
121 EXPECT_EQ(dummy_ptr + kDummyOffset, | |
122 dummy_ptr + StrictNumeric<Dst>(kDummyOffset)); | |
123 EXPECT_EQ(dummy_ptr - kDummyOffset, | |
124 dummy_ptr - StrictNumeric<Dst>(kDummyOffset)); | |
125 EXPECT_NE(dummy_ptr, dummy_ptr + StrictNumeric<Dst>(kDummyOffset)); | |
126 EXPECT_NE(dummy_ptr, dummy_ptr - StrictNumeric<Dst>(kDummyOffset)); | |
127 } | |
Tom Sepez
2016/11/30 23:58:27
Can we have a test that adding numeric_limits<uinp
jschuh
2016/12/01 00:58:55
Unfortunately, no, because I don't have have a way
danakj
2016/12/01 01:00:25
Death tests are a possibility if I'm understanding
| |
128 | |
111 // Signed integer arithmetic. | 129 // Signed integer arithmetic. |
112 template <typename Dst> | 130 template <typename Dst> |
113 static void TestSpecializedArithmetic( | 131 static void TestSpecializedArithmetic( |
114 const char* dst, | 132 const char* dst, |
115 int line, | 133 int line, |
116 typename std::enable_if<numeric_limits<Dst>::is_integer && | 134 typename std::enable_if<numeric_limits<Dst>::is_integer && |
117 numeric_limits<Dst>::is_signed, | 135 numeric_limits<Dst>::is_signed, |
118 int>::type = 0) { | 136 int>::type = 0) { |
119 typedef numeric_limits<Dst> DstLimits; | 137 typedef numeric_limits<Dst> DstLimits; |
120 TEST_EXPECTED_FAILURE(-CheckedNumeric<Dst>(DstLimits::min())); | 138 TEST_EXPECTED_FAILURE(-CheckedNumeric<Dst>(DstLimits::min())); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
163 TEST_EXPECTED_VALUE(static_cast<Dst>(1) << (sizeof(Dst) * CHAR_BIT - 2), | 181 TEST_EXPECTED_VALUE(static_cast<Dst>(1) << (sizeof(Dst) * CHAR_BIT - 2), |
164 CheckedNumeric<Dst>(1) << (sizeof(Dst) * CHAR_BIT - 2)); | 182 CheckedNumeric<Dst>(1) << (sizeof(Dst) * CHAR_BIT - 2)); |
165 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) | 183 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) |
166 << (sizeof(Dst) * CHAR_BIT - 1)); | 184 << (sizeof(Dst) * CHAR_BIT - 1)); |
167 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) << 0); | 185 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) << 0); |
168 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1); | 186 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1); |
169 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> (sizeof(Dst) * CHAR_BIT)); | 187 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> (sizeof(Dst) * CHAR_BIT)); |
170 TEST_EXPECTED_VALUE(0, | 188 TEST_EXPECTED_VALUE(0, |
171 CheckedNumeric<Dst>(1) >> (sizeof(Dst) * CHAR_BIT - 1)); | 189 CheckedNumeric<Dst>(1) >> (sizeof(Dst) * CHAR_BIT - 1)); |
172 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one); | 190 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one); |
191 | |
192 TestStrictPointerMath<Dst>(); | |
173 } | 193 } |
174 | 194 |
175 // Unsigned integer arithmetic. | 195 // Unsigned integer arithmetic. |
176 template <typename Dst> | 196 template <typename Dst> |
177 static void TestSpecializedArithmetic( | 197 static void TestSpecializedArithmetic( |
178 const char* dst, | 198 const char* dst, |
179 int line, | 199 int line, |
180 typename std::enable_if<numeric_limits<Dst>::is_integer && | 200 typename std::enable_if<numeric_limits<Dst>::is_integer && |
181 !numeric_limits<Dst>::is_signed, | 201 !numeric_limits<Dst>::is_signed, |
182 int>::type = 0) { | 202 int>::type = 0) { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
234 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) | 0); | 254 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) | 0); |
235 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(), | 255 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(), |
236 CheckedNumeric<Dst>(0) | static_cast<Dst>(-1)); | 256 CheckedNumeric<Dst>(0) | static_cast<Dst>(-1)); |
237 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) ^ 1); | 257 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) ^ 1); |
238 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) ^ 0); | 258 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) ^ 0); |
239 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) ^ 1); | 259 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) ^ 1); |
240 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) ^ 0); | 260 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) ^ 0); |
241 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(), | 261 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(), |
242 CheckedNumeric<Dst>(0) ^ static_cast<Dst>(-1)); | 262 CheckedNumeric<Dst>(0) ^ static_cast<Dst>(-1)); |
243 TEST_EXPECTED_VALUE(DstLimits::max(), ~CheckedNumeric<Dst>(0)); | 263 TEST_EXPECTED_VALUE(DstLimits::max(), ~CheckedNumeric<Dst>(0)); |
264 | |
265 TestStrictPointerMath<Dst>(); | |
244 } | 266 } |
245 | 267 |
246 // Floating point arithmetic. | 268 // Floating point arithmetic. |
247 template <typename Dst> | 269 template <typename Dst> |
248 void TestSpecializedArithmetic( | 270 void TestSpecializedArithmetic( |
249 const char* dst, | 271 const char* dst, |
250 int line, | 272 int line, |
251 typename std::enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0) { | 273 typename std::enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0) { |
252 typedef numeric_limits<Dst> DstLimits; | 274 typedef numeric_limits<Dst> DstLimits; |
253 TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::min())); | 275 TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::min())); |
254 | 276 |
255 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()).Abs()); | 277 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()).Abs()); |
256 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs()); | 278 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs()); |
257 | 279 |
258 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) + -1); | 280 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) + -1); |
259 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + 1); | 281 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + 1); |
260 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) + | 282 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) + |
261 -DstLimits::max()); | 283 -DstLimits::max()); |
262 | 284 |
263 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - | 285 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - |
264 -DstLimits::max()); | 286 -DstLimits::max()); |
265 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) - | 287 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) - |
266 DstLimits::max()); | 288 DstLimits::max()); |
267 | 289 |
268 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) * 2); | 290 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) * 2); |
269 | 291 |
270 TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2); | 292 TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2); |
271 EXPECT_EQ(static_cast<Dst>(1.0), CheckedNumeric<Dst>(1.0).ValueFloating()); | |
272 } | 293 } |
273 | 294 |
274 // Generic arithmetic tests. | 295 // Generic arithmetic tests. |
275 template <typename Dst> | 296 template <typename Dst> |
276 static void TestArithmetic(const char* dst, int line) { | 297 static void TestArithmetic(const char* dst, int line) { |
277 typedef numeric_limits<Dst> DstLimits; | 298 typedef numeric_limits<Dst> DstLimits; |
278 | 299 |
279 EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid()); | 300 EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid()); |
280 EXPECT_EQ(false, | 301 EXPECT_EQ(false, |
281 CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) * | 302 CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) * |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
404 template <typename Dst, typename Src, NumericConversionType conversion> | 425 template <typename Dst, typename Src, NumericConversionType conversion> |
405 struct TestNumericConversion {}; | 426 struct TestNumericConversion {}; |
406 | 427 |
407 // EXPECT_EQ wrappers providing specific detail on test failures. | 428 // EXPECT_EQ wrappers providing specific detail on test failures. |
408 #define TEST_EXPECTED_RANGE(expected, actual) \ | 429 #define TEST_EXPECTED_RANGE(expected, actual) \ |
409 EXPECT_EQ(expected, base::internal::DstRangeRelationToSrcRange<Dst>(actual)) \ | 430 EXPECT_EQ(expected, base::internal::DstRangeRelationToSrcRange<Dst>(actual)) \ |
410 << "Conversion test: " << src << " value " << actual << " to " << dst \ | 431 << "Conversion test: " << src << " value " << actual << " to " << dst \ |
411 << " on line " << line | 432 << " on line " << line |
412 | 433 |
413 template <typename Dst, typename Src> | 434 template <typename Dst, typename Src> |
435 void TestStrictComparison() { | |
436 typedef numeric_limits<Dst> DstLimits; | |
437 typedef numeric_limits<Src> SrcLimits; | |
438 static_assert(StrictNumeric<Src>(SrcLimits::min()) < DstLimits::max(), ""); | |
439 static_assert(StrictNumeric<Src>(SrcLimits::min()) < SrcLimits::max(), ""); | |
440 static_assert(!(StrictNumeric<Src>(SrcLimits::min()) >= DstLimits::max()), | |
441 ""); | |
442 static_assert(!(StrictNumeric<Src>(SrcLimits::min()) >= SrcLimits::max()), | |
443 ""); | |
444 static_assert(StrictNumeric<Src>(SrcLimits::min()) <= DstLimits::max(), ""); | |
445 static_assert(StrictNumeric<Src>(SrcLimits::min()) <= SrcLimits::max(), ""); | |
446 static_assert(!(StrictNumeric<Src>(SrcLimits::min()) > DstLimits::max()), ""); | |
447 static_assert(!(StrictNumeric<Src>(SrcLimits::min()) > SrcLimits::max()), ""); | |
448 static_assert(StrictNumeric<Src>(SrcLimits::max()) > DstLimits::min(), ""); | |
449 static_assert(StrictNumeric<Src>(SrcLimits::max()) > SrcLimits::min(), ""); | |
450 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) <= DstLimits::min()), | |
451 ""); | |
452 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) <= SrcLimits::min()), | |
453 ""); | |
454 static_assert(StrictNumeric<Src>(SrcLimits::max()) >= DstLimits::min(), ""); | |
455 static_assert(StrictNumeric<Src>(SrcLimits::max()) >= SrcLimits::min(), ""); | |
456 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) < DstLimits::min()), ""); | |
457 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) < SrcLimits::min()), ""); | |
458 static_assert(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(1), | |
459 ""); | |
460 static_assert(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(0), | |
461 ""); | |
462 static_assert(StrictNumeric<Src>(SrcLimits::max()) != static_cast<Dst>(0), | |
463 ""); | |
464 static_assert(StrictNumeric<Src>(SrcLimits::max()) != DstLimits::min(), ""); | |
465 static_assert( | |
466 !(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(1)), ""); | |
467 static_assert( | |
468 !(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(0)), ""); | |
469 } | |
470 | |
471 template <typename Dst, typename Src> | |
414 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> { | 472 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> { |
415 static void Test(const char *dst, const char *src, int line) { | 473 static void Test(const char *dst, const char *src, int line) { |
416 typedef numeric_limits<Src> SrcLimits; | 474 typedef numeric_limits<Src> SrcLimits; |
417 typedef numeric_limits<Dst> DstLimits; | 475 typedef numeric_limits<Dst> DstLimits; |
418 // Integral to floating. | 476 // Integral to floating. |
419 static_assert((DstLimits::is_iec559 && SrcLimits::is_integer) || | 477 static_assert((DstLimits::is_iec559 && SrcLimits::is_integer) || |
420 // Not floating to integral and... | 478 // Not floating to integral and... |
421 (!(DstLimits::is_integer && SrcLimits::is_iec559) && | 479 (!(DstLimits::is_integer && SrcLimits::is_iec559) && |
422 // Same sign, same numeric, source is narrower or same. | 480 // Same sign, same numeric, source is narrower or same. |
423 ((SrcLimits::is_signed == DstLimits::is_signed && | 481 ((SrcLimits::is_signed == DstLimits::is_signed && |
424 sizeof(Dst) >= sizeof(Src)) || | 482 sizeof(Dst) >= sizeof(Src)) || |
425 // Or signed destination and source is smaller | 483 // Or signed destination and source is smaller |
426 (DstLimits::is_signed && sizeof(Dst) > sizeof(Src)))), | 484 (DstLimits::is_signed && sizeof(Dst) > sizeof(Src)))), |
427 "Comparison must be sign preserving and value preserving"); | 485 "Comparison must be sign preserving and value preserving"); |
428 | 486 |
487 TestStrictComparison<Dst, Src>(); | |
488 | |
429 const CheckedNumeric<Dst> checked_dst = SrcLimits::max(); | 489 const CheckedNumeric<Dst> checked_dst = SrcLimits::max(); |
430 TEST_EXPECTED_SUCCESS(checked_dst); | 490 TEST_EXPECTED_SUCCESS(checked_dst); |
431 if (MaxExponent<Dst>::value > MaxExponent<Src>::value) { | 491 if (MaxExponent<Dst>::value > MaxExponent<Src>::value) { |
432 if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1) { | 492 if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1) { |
433 // At least twice larger type. | 493 // At least twice larger type. |
434 TEST_EXPECTED_SUCCESS(SrcLimits::max() * checked_dst); | 494 TEST_EXPECTED_SUCCESS(SrcLimits::max() * checked_dst); |
435 | 495 |
436 } else { // Larger, but not at least twice as large. | 496 } else { // Larger, but not at least twice as large. |
437 TEST_EXPECTED_FAILURE(SrcLimits::max() * checked_dst); | 497 TEST_EXPECTED_FAILURE(SrcLimits::max() * checked_dst); |
438 TEST_EXPECTED_SUCCESS(checked_dst + 1); | 498 TEST_EXPECTED_SUCCESS(checked_dst + 1); |
(...skipping 20 matching lines...) Expand all Loading... | |
459 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> { | 519 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> { |
460 static void Test(const char *dst, const char *src, int line) { | 520 static void Test(const char *dst, const char *src, int line) { |
461 typedef numeric_limits<Src> SrcLimits; | 521 typedef numeric_limits<Src> SrcLimits; |
462 typedef numeric_limits<Dst> DstLimits; | 522 typedef numeric_limits<Dst> DstLimits; |
463 static_assert(SrcLimits::is_signed == DstLimits::is_signed, | 523 static_assert(SrcLimits::is_signed == DstLimits::is_signed, |
464 "Destination and source sign must be the same"); | 524 "Destination and source sign must be the same"); |
465 static_assert(sizeof(Dst) < sizeof(Src) || | 525 static_assert(sizeof(Dst) < sizeof(Src) || |
466 (DstLimits::is_integer && SrcLimits::is_iec559), | 526 (DstLimits::is_integer && SrcLimits::is_iec559), |
467 "Destination must be narrower than source"); | 527 "Destination must be narrower than source"); |
468 | 528 |
529 TestStrictComparison<Dst, Src>(); | |
530 | |
469 const CheckedNumeric<Dst> checked_dst; | 531 const CheckedNumeric<Dst> checked_dst; |
470 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max()); | 532 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max()); |
471 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1)); | 533 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1)); |
472 TEST_EXPECTED_FAILURE(checked_dst - SrcLimits::max()); | 534 TEST_EXPECTED_FAILURE(checked_dst - SrcLimits::max()); |
473 | 535 |
474 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max()); | 536 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max()); |
475 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); | 537 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); |
476 if (SrcLimits::is_iec559) { | 538 if (SrcLimits::is_iec559) { |
477 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1); | 539 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1); |
478 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1)); | 540 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1)); |
(...skipping 26 matching lines...) Expand all Loading... | |
505 template <typename Dst, typename Src> | 567 template <typename Dst, typename Src> |
506 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> { | 568 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> { |
507 static void Test(const char *dst, const char *src, int line) { | 569 static void Test(const char *dst, const char *src, int line) { |
508 typedef numeric_limits<Src> SrcLimits; | 570 typedef numeric_limits<Src> SrcLimits; |
509 typedef numeric_limits<Dst> DstLimits; | 571 typedef numeric_limits<Dst> DstLimits; |
510 static_assert(sizeof(Dst) >= sizeof(Src), | 572 static_assert(sizeof(Dst) >= sizeof(Src), |
511 "Destination must be equal or wider than source."); | 573 "Destination must be equal or wider than source."); |
512 static_assert(SrcLimits::is_signed, "Source must be signed"); | 574 static_assert(SrcLimits::is_signed, "Source must be signed"); |
513 static_assert(!DstLimits::is_signed, "Destination must be unsigned"); | 575 static_assert(!DstLimits::is_signed, "Destination must be unsigned"); |
514 | 576 |
577 TestStrictComparison<Dst, Src>(); | |
578 | |
515 const CheckedNumeric<Dst> checked_dst; | 579 const CheckedNumeric<Dst> checked_dst; |
516 TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max()); | 580 TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max()); |
517 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1)); | 581 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1)); |
518 TEST_EXPECTED_FAILURE(checked_dst + -SrcLimits::max()); | 582 TEST_EXPECTED_FAILURE(checked_dst + -SrcLimits::max()); |
519 | 583 |
520 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min()); | 584 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min()); |
521 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max()); | 585 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max()); |
522 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); | 586 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); |
523 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1)); | 587 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1)); |
524 } | 588 } |
525 }; | 589 }; |
526 | 590 |
527 template <typename Dst, typename Src> | 591 template <typename Dst, typename Src> |
528 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> { | 592 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> { |
529 static void Test(const char *dst, const char *src, int line) { | 593 static void Test(const char *dst, const char *src, int line) { |
530 typedef numeric_limits<Src> SrcLimits; | 594 typedef numeric_limits<Src> SrcLimits; |
531 typedef numeric_limits<Dst> DstLimits; | 595 typedef numeric_limits<Dst> DstLimits; |
532 static_assert((DstLimits::is_integer && SrcLimits::is_iec559) || | 596 static_assert((DstLimits::is_integer && SrcLimits::is_iec559) || |
533 (sizeof(Dst) < sizeof(Src)), | 597 (sizeof(Dst) < sizeof(Src)), |
534 "Destination must be narrower than source."); | 598 "Destination must be narrower than source."); |
535 static_assert(SrcLimits::is_signed, "Source must be signed."); | 599 static_assert(SrcLimits::is_signed, "Source must be signed."); |
536 static_assert(!DstLimits::is_signed, "Destination must be unsigned."); | 600 static_assert(!DstLimits::is_signed, "Destination must be unsigned."); |
537 | 601 |
602 TestStrictComparison<Dst, Src>(); | |
603 | |
538 const CheckedNumeric<Dst> checked_dst; | 604 const CheckedNumeric<Dst> checked_dst; |
539 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1)); | 605 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1)); |
540 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max()); | 606 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max()); |
541 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1)); | 607 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1)); |
542 TEST_EXPECTED_FAILURE(checked_dst + -SrcLimits::max()); | 608 TEST_EXPECTED_FAILURE(checked_dst + -SrcLimits::max()); |
543 | 609 |
544 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max()); | 610 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max()); |
545 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); | 611 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); |
546 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1)); | 612 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1)); |
547 if (SrcLimits::is_iec559) { | 613 if (SrcLimits::is_iec559) { |
(...skipping 22 matching lines...) Expand all Loading... | |
570 template <typename Dst, typename Src> | 636 template <typename Dst, typename Src> |
571 struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> { | 637 struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> { |
572 static void Test(const char *dst, const char *src, int line) { | 638 static void Test(const char *dst, const char *src, int line) { |
573 typedef numeric_limits<Src> SrcLimits; | 639 typedef numeric_limits<Src> SrcLimits; |
574 typedef numeric_limits<Dst> DstLimits; | 640 typedef numeric_limits<Dst> DstLimits; |
575 static_assert(sizeof(Dst) <= sizeof(Src), | 641 static_assert(sizeof(Dst) <= sizeof(Src), |
576 "Destination must be narrower or equal to source."); | 642 "Destination must be narrower or equal to source."); |
577 static_assert(!SrcLimits::is_signed, "Source must be unsigned."); | 643 static_assert(!SrcLimits::is_signed, "Source must be unsigned."); |
578 static_assert(DstLimits::is_signed, "Destination must be signed."); | 644 static_assert(DstLimits::is_signed, "Destination must be signed."); |
579 | 645 |
646 TestStrictComparison<Dst, Src>(); | |
647 | |
580 const CheckedNumeric<Dst> checked_dst; | 648 const CheckedNumeric<Dst> checked_dst; |
581 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1)); | 649 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1)); |
582 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max()); | 650 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max()); |
583 TEST_EXPECTED_VALUE(SrcLimits::min(), checked_dst + SrcLimits::min()); | 651 TEST_EXPECTED_VALUE(SrcLimits::min(), checked_dst + SrcLimits::min()); |
584 | 652 |
585 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min()); | 653 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min()); |
586 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max()); | 654 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max()); |
587 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); | 655 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); |
588 } | 656 } |
589 }; | 657 }; |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
747 float not_a_number = std::numeric_limits<float>::infinity() - | 815 float not_a_number = std::numeric_limits<float>::infinity() - |
748 std::numeric_limits<float>::infinity(); | 816 std::numeric_limits<float>::infinity(); |
749 EXPECT_TRUE(std::isnan(not_a_number)); | 817 EXPECT_TRUE(std::isnan(not_a_number)); |
750 EXPECT_EQ(0, saturated_cast<int>(not_a_number)); | 818 EXPECT_EQ(0, saturated_cast<int>(not_a_number)); |
751 | 819 |
752 // Test the CheckedNumeric value extractions functions. | 820 // Test the CheckedNumeric value extractions functions. |
753 auto int8_min = CheckNum(numeric_limits<int8_t>::min()); | 821 auto int8_min = CheckNum(numeric_limits<int8_t>::min()); |
754 auto int8_max = CheckNum(numeric_limits<int8_t>::max()); | 822 auto int8_max = CheckNum(numeric_limits<int8_t>::max()); |
755 auto double_max = CheckNum(numeric_limits<double>::max()); | 823 auto double_max = CheckNum(numeric_limits<double>::max()); |
756 static_assert( | 824 static_assert( |
757 std::is_same<int16_t, decltype(int8_min.ValueOrDie<int16_t>())>::value, | 825 std::is_same<int16_t, |
826 decltype(int8_min.ValueOrDie<int16_t>())::type>::value, | |
758 "ValueOrDie returning incorrect type."); | 827 "ValueOrDie returning incorrect type."); |
759 static_assert( | 828 static_assert( |
760 std::is_same<int16_t, | 829 std::is_same<int16_t, |
761 decltype(int8_min.ValueOrDefault<int16_t>(0))>::value, | 830 decltype(int8_min.ValueOrDefault<int16_t>(0))::type>::value, |
762 "ValueOrDefault returning incorrect type."); | 831 "ValueOrDefault returning incorrect type."); |
763 static_assert( | 832 EXPECT_FALSE(IsValidForType<uint8_t>(int8_min)); |
764 std::is_same<float, decltype(double_max.ValueFloating<float>())>::value, | 833 EXPECT_TRUE(IsValidForType<uint8_t>(int8_max)); |
765 "ValueFloating returning incorrect type."); | |
766 EXPECT_FALSE(int8_min.template IsValid<uint8_t>()); | |
767 EXPECT_TRUE(int8_max.template IsValid<uint8_t>()); | |
768 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::min()), | 834 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::min()), |
769 int8_min.template ValueOrDie<int>()); | 835 ValueOrDieForType<int>(int8_min)); |
770 EXPECT_TRUE(int8_max.template IsValid<uint32_t>()); | 836 EXPECT_TRUE(IsValidForType<uint32_t>(int8_max)); |
771 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::max()), | 837 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::max()), |
772 int8_max.template ValueOrDie<int>()); | 838 ValueOrDieForType<int>(int8_max)); |
839 EXPECT_EQ(0, ValueOrDefaultForType<int>(double_max, 0)); | |
773 uint8_t uint8_dest = 0; | 840 uint8_t uint8_dest = 0; |
774 int16_t int16_dest = 0; | 841 int16_t int16_dest = 0; |
775 double double_dest = 0; | 842 double double_dest = 0; |
776 EXPECT_TRUE(int8_max.AssignIfValid(&uint8_dest)); | 843 EXPECT_TRUE(int8_max.AssignIfValid(&uint8_dest)); |
777 EXPECT_EQ(static_cast<uint8_t>(numeric_limits<int8_t>::max()), uint8_dest); | 844 EXPECT_EQ(static_cast<uint8_t>(numeric_limits<int8_t>::max()), uint8_dest); |
778 EXPECT_FALSE(int8_min.AssignIfValid(&uint8_dest)); | 845 EXPECT_FALSE(int8_min.AssignIfValid(&uint8_dest)); |
779 EXPECT_TRUE(int8_max.AssignIfValid(&int16_dest)); | 846 EXPECT_TRUE(int8_max.AssignIfValid(&int16_dest)); |
780 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::max()), int16_dest); | 847 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::max()), int16_dest); |
781 EXPECT_TRUE(int8_min.AssignIfValid(&int16_dest)); | 848 EXPECT_TRUE(int8_min.AssignIfValid(&int16_dest)); |
782 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::min()), int16_dest); | 849 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::min()), int16_dest); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
889 too_large += d; | 956 too_large += d; |
890 EXPECT_FALSE(too_large.IsValid()); | 957 EXPECT_FALSE(too_large.IsValid()); |
891 too_large -= d; | 958 too_large -= d; |
892 EXPECT_FALSE(too_large.IsValid()); | 959 EXPECT_FALSE(too_large.IsValid()); |
893 too_large /= d; | 960 too_large /= d; |
894 EXPECT_FALSE(too_large.IsValid()); | 961 EXPECT_FALSE(too_large.IsValid()); |
895 } | 962 } |
896 | 963 |
897 TEST(SafeNumerics, VariadicNumericOperations) { | 964 TEST(SafeNumerics, VariadicNumericOperations) { |
898 auto a = CheckAdd(1, 2UL, CheckNum(3LL), 4).ValueOrDie(); | 965 auto a = CheckAdd(1, 2UL, CheckNum(3LL), 4).ValueOrDie(); |
899 EXPECT_EQ(static_cast<decltype(a)>(10), a); | 966 EXPECT_EQ(static_cast<decltype(a)::type>(10), a); |
900 auto b = CheckSub(CheckNum(20.0), 2UL, 4).ValueOrDie(); | 967 auto b = CheckSub(CheckNum(20.0), 2UL, 4).ValueOrDie(); |
901 EXPECT_EQ(static_cast<decltype(b)>(14.0), b); | 968 EXPECT_EQ(static_cast<decltype(b)::type>(14.0), b); |
902 auto c = CheckMul(20.0, CheckNum(1), 5, 3UL).ValueOrDie(); | 969 auto c = CheckMul(20.0, CheckNum(1), 5, 3UL).ValueOrDie(); |
903 EXPECT_EQ(static_cast<decltype(c)>(300.0), c); | 970 EXPECT_EQ(static_cast<decltype(c)::type>(300.0), c); |
904 auto d = CheckDiv(20.0, 2.0, CheckNum(5LL), -4).ValueOrDie(); | 971 auto d = CheckDiv(20.0, 2.0, CheckNum(5LL), -4).ValueOrDie(); |
905 EXPECT_EQ(static_cast<decltype(d)>(-.5), d); | 972 EXPECT_EQ(static_cast<decltype(d)::type>(-.5), d); |
906 auto e = CheckMod(CheckNum(20), 3).ValueOrDie(); | 973 auto e = CheckMod(CheckNum(20), 3).ValueOrDie(); |
907 EXPECT_EQ(static_cast<decltype(e)>(2), e); | 974 EXPECT_EQ(static_cast<decltype(e)::type>(2), e); |
908 auto f = CheckLsh(1, CheckNum(2)).ValueOrDie(); | 975 auto f = CheckLsh(1, CheckNum(2)).ValueOrDie(); |
909 EXPECT_EQ(static_cast<decltype(f)>(4), f); | 976 EXPECT_EQ(static_cast<decltype(f)::type>(4), f); |
910 auto g = CheckRsh(4, CheckNum(2)).ValueOrDie(); | 977 auto g = CheckRsh(4, CheckNum(2)).ValueOrDie(); |
911 EXPECT_EQ(static_cast<decltype(g)>(1), g); | 978 EXPECT_EQ(static_cast<decltype(g)::type>(1), g); |
912 auto h = CheckRsh(CheckAdd(1, 1, 1, 1), CheckSub(4, 2)).ValueOrDie(); | 979 auto h = CheckRsh(CheckAdd(1, 1, 1, 1), CheckSub(4, 2)).ValueOrDie(); |
913 EXPECT_EQ(static_cast<decltype(h)>(1), h); | 980 EXPECT_EQ(static_cast<decltype(h)::type>(1), h); |
914 } | 981 } |
OLD | NEW |