Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(184)

Side by Side Diff: base/numerics/safe_numerics_unittest.cc

Issue 2528243002: Fix silent truncations when extracting values from CheckedNumeric (Closed)
Patch Set: pointer math tests Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698