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

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

Issue 2528243002: Fix silent truncations when extracting values from CheckedNumeric (Closed)
Patch Set: compile fix 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 EXPECT_DEATH_IF_SUPPORTED(
128 dummy_ptr + StrictNumeric<size_t>(std::numeric_limits<size_t>::max()),
129 "");
130 }
131
111 // Signed integer arithmetic. 132 // Signed integer arithmetic.
112 template <typename Dst> 133 template <typename Dst>
113 static void TestSpecializedArithmetic( 134 static void TestSpecializedArithmetic(
114 const char* dst, 135 const char* dst,
115 int line, 136 int line,
116 typename std::enable_if<numeric_limits<Dst>::is_integer && 137 typename std::enable_if<numeric_limits<Dst>::is_integer &&
117 numeric_limits<Dst>::is_signed, 138 numeric_limits<Dst>::is_signed,
118 int>::type = 0) { 139 int>::type = 0) {
119 typedef numeric_limits<Dst> DstLimits; 140 typedef numeric_limits<Dst> DstLimits;
120 TEST_EXPECTED_FAILURE(-CheckedNumeric<Dst>(DstLimits::min())); 141 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), 184 TEST_EXPECTED_VALUE(static_cast<Dst>(1) << (sizeof(Dst) * CHAR_BIT - 2),
164 CheckedNumeric<Dst>(1) << (sizeof(Dst) * CHAR_BIT - 2)); 185 CheckedNumeric<Dst>(1) << (sizeof(Dst) * CHAR_BIT - 2));
165 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) 186 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0)
166 << (sizeof(Dst) * CHAR_BIT - 1)); 187 << (sizeof(Dst) * CHAR_BIT - 1));
167 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) << 0); 188 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) << 0);
168 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1); 189 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1);
169 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> (sizeof(Dst) * CHAR_BIT)); 190 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> (sizeof(Dst) * CHAR_BIT));
170 TEST_EXPECTED_VALUE(0, 191 TEST_EXPECTED_VALUE(0,
171 CheckedNumeric<Dst>(1) >> (sizeof(Dst) * CHAR_BIT - 1)); 192 CheckedNumeric<Dst>(1) >> (sizeof(Dst) * CHAR_BIT - 1));
172 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one); 193 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one);
194
195 TestStrictPointerMath<Dst>();
173 } 196 }
174 197
175 // Unsigned integer arithmetic. 198 // Unsigned integer arithmetic.
176 template <typename Dst> 199 template <typename Dst>
177 static void TestSpecializedArithmetic( 200 static void TestSpecializedArithmetic(
178 const char* dst, 201 const char* dst,
179 int line, 202 int line,
180 typename std::enable_if<numeric_limits<Dst>::is_integer && 203 typename std::enable_if<numeric_limits<Dst>::is_integer &&
181 !numeric_limits<Dst>::is_signed, 204 !numeric_limits<Dst>::is_signed,
182 int>::type = 0) { 205 int>::type = 0) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) | 0); 257 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) | 0);
235 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(), 258 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
236 CheckedNumeric<Dst>(0) | static_cast<Dst>(-1)); 259 CheckedNumeric<Dst>(0) | static_cast<Dst>(-1));
237 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) ^ 1); 260 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) ^ 1);
238 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) ^ 0); 261 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) ^ 0);
239 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) ^ 1); 262 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) ^ 1);
240 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) ^ 0); 263 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) ^ 0);
241 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(), 264 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
242 CheckedNumeric<Dst>(0) ^ static_cast<Dst>(-1)); 265 CheckedNumeric<Dst>(0) ^ static_cast<Dst>(-1));
243 TEST_EXPECTED_VALUE(DstLimits::max(), ~CheckedNumeric<Dst>(0)); 266 TEST_EXPECTED_VALUE(DstLimits::max(), ~CheckedNumeric<Dst>(0));
267
268 TestStrictPointerMath<Dst>();
244 } 269 }
245 270
246 // Floating point arithmetic. 271 // Floating point arithmetic.
247 template <typename Dst> 272 template <typename Dst>
248 void TestSpecializedArithmetic( 273 void TestSpecializedArithmetic(
249 const char* dst, 274 const char* dst,
250 int line, 275 int line,
251 typename std::enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0) { 276 typename std::enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0) {
252 typedef numeric_limits<Dst> DstLimits; 277 typedef numeric_limits<Dst> DstLimits;
253 TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::min())); 278 TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::min()));
254 279
255 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()).Abs()); 280 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()).Abs());
256 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs()); 281 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
257 282
258 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) + -1); 283 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) + -1);
259 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + 1); 284 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + 1);
260 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) + 285 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) +
261 -DstLimits::max()); 286 -DstLimits::max());
262 287
263 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - 288 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) -
264 -DstLimits::max()); 289 -DstLimits::max());
265 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) - 290 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) -
266 DstLimits::max()); 291 DstLimits::max());
267 292
268 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) * 2); 293 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) * 2);
269 294
270 TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2); 295 TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2);
271 EXPECT_EQ(static_cast<Dst>(1.0), CheckedNumeric<Dst>(1.0).ValueFloating());
272 } 296 }
273 297
274 // Generic arithmetic tests. 298 // Generic arithmetic tests.
275 template <typename Dst> 299 template <typename Dst>
276 static void TestArithmetic(const char* dst, int line) { 300 static void TestArithmetic(const char* dst, int line) {
277 typedef numeric_limits<Dst> DstLimits; 301 typedef numeric_limits<Dst> DstLimits;
278 302
279 EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid()); 303 EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid());
280 EXPECT_EQ(false, 304 EXPECT_EQ(false,
281 CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) * 305 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> 428 template <typename Dst, typename Src, NumericConversionType conversion>
405 struct TestNumericConversion {}; 429 struct TestNumericConversion {};
406 430
407 // EXPECT_EQ wrappers providing specific detail on test failures. 431 // EXPECT_EQ wrappers providing specific detail on test failures.
408 #define TEST_EXPECTED_RANGE(expected, actual) \ 432 #define TEST_EXPECTED_RANGE(expected, actual) \
409 EXPECT_EQ(expected, base::internal::DstRangeRelationToSrcRange<Dst>(actual)) \ 433 EXPECT_EQ(expected, base::internal::DstRangeRelationToSrcRange<Dst>(actual)) \
410 << "Conversion test: " << src << " value " << actual << " to " << dst \ 434 << "Conversion test: " << src << " value " << actual << " to " << dst \
411 << " on line " << line 435 << " on line " << line
412 436
413 template <typename Dst, typename Src> 437 template <typename Dst, typename Src>
438 void TestStrictComparison() {
439 typedef numeric_limits<Dst> DstLimits;
440 typedef numeric_limits<Src> SrcLimits;
441 static_assert(StrictNumeric<Src>(SrcLimits::min()) < DstLimits::max(), "");
442 static_assert(StrictNumeric<Src>(SrcLimits::min()) < SrcLimits::max(), "");
443 static_assert(!(StrictNumeric<Src>(SrcLimits::min()) >= DstLimits::max()),
444 "");
445 static_assert(!(StrictNumeric<Src>(SrcLimits::min()) >= SrcLimits::max()),
446 "");
447 static_assert(StrictNumeric<Src>(SrcLimits::min()) <= DstLimits::max(), "");
448 static_assert(StrictNumeric<Src>(SrcLimits::min()) <= SrcLimits::max(), "");
449 static_assert(!(StrictNumeric<Src>(SrcLimits::min()) > DstLimits::max()), "");
450 static_assert(!(StrictNumeric<Src>(SrcLimits::min()) > SrcLimits::max()), "");
451 static_assert(StrictNumeric<Src>(SrcLimits::max()) > DstLimits::min(), "");
452 static_assert(StrictNumeric<Src>(SrcLimits::max()) > SrcLimits::min(), "");
453 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) <= DstLimits::min()),
454 "");
455 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) <= SrcLimits::min()),
456 "");
457 static_assert(StrictNumeric<Src>(SrcLimits::max()) >= DstLimits::min(), "");
458 static_assert(StrictNumeric<Src>(SrcLimits::max()) >= SrcLimits::min(), "");
459 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) < DstLimits::min()), "");
460 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) < SrcLimits::min()), "");
461 static_assert(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(1),
462 "");
463 static_assert(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(0),
464 "");
465 static_assert(StrictNumeric<Src>(SrcLimits::max()) != static_cast<Dst>(0),
466 "");
467 static_assert(StrictNumeric<Src>(SrcLimits::max()) != DstLimits::min(), "");
468 static_assert(
469 !(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(1)), "");
470 static_assert(
471 !(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(0)), "");
472 }
473
474 template <typename Dst, typename Src>
414 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> { 475 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> {
415 static void Test(const char *dst, const char *src, int line) { 476 static void Test(const char *dst, const char *src, int line) {
416 typedef numeric_limits<Src> SrcLimits; 477 typedef numeric_limits<Src> SrcLimits;
417 typedef numeric_limits<Dst> DstLimits; 478 typedef numeric_limits<Dst> DstLimits;
418 // Integral to floating. 479 // Integral to floating.
419 static_assert((DstLimits::is_iec559 && SrcLimits::is_integer) || 480 static_assert((DstLimits::is_iec559 && SrcLimits::is_integer) ||
420 // Not floating to integral and... 481 // Not floating to integral and...
421 (!(DstLimits::is_integer && SrcLimits::is_iec559) && 482 (!(DstLimits::is_integer && SrcLimits::is_iec559) &&
422 // Same sign, same numeric, source is narrower or same. 483 // Same sign, same numeric, source is narrower or same.
423 ((SrcLimits::is_signed == DstLimits::is_signed && 484 ((SrcLimits::is_signed == DstLimits::is_signed &&
424 sizeof(Dst) >= sizeof(Src)) || 485 sizeof(Dst) >= sizeof(Src)) ||
425 // Or signed destination and source is smaller 486 // Or signed destination and source is smaller
426 (DstLimits::is_signed && sizeof(Dst) > sizeof(Src)))), 487 (DstLimits::is_signed && sizeof(Dst) > sizeof(Src)))),
427 "Comparison must be sign preserving and value preserving"); 488 "Comparison must be sign preserving and value preserving");
428 489
490 TestStrictComparison<Dst, Src>();
491
429 const CheckedNumeric<Dst> checked_dst = SrcLimits::max(); 492 const CheckedNumeric<Dst> checked_dst = SrcLimits::max();
430 TEST_EXPECTED_SUCCESS(checked_dst); 493 TEST_EXPECTED_SUCCESS(checked_dst);
431 if (MaxExponent<Dst>::value > MaxExponent<Src>::value) { 494 if (MaxExponent<Dst>::value > MaxExponent<Src>::value) {
432 if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1) { 495 if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1) {
433 // At least twice larger type. 496 // At least twice larger type.
434 TEST_EXPECTED_SUCCESS(SrcLimits::max() * checked_dst); 497 TEST_EXPECTED_SUCCESS(SrcLimits::max() * checked_dst);
435 498
436 } else { // Larger, but not at least twice as large. 499 } else { // Larger, but not at least twice as large.
437 TEST_EXPECTED_FAILURE(SrcLimits::max() * checked_dst); 500 TEST_EXPECTED_FAILURE(SrcLimits::max() * checked_dst);
438 TEST_EXPECTED_SUCCESS(checked_dst + 1); 501 TEST_EXPECTED_SUCCESS(checked_dst + 1);
(...skipping 20 matching lines...) Expand all
459 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> { 522 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> {
460 static void Test(const char *dst, const char *src, int line) { 523 static void Test(const char *dst, const char *src, int line) {
461 typedef numeric_limits<Src> SrcLimits; 524 typedef numeric_limits<Src> SrcLimits;
462 typedef numeric_limits<Dst> DstLimits; 525 typedef numeric_limits<Dst> DstLimits;
463 static_assert(SrcLimits::is_signed == DstLimits::is_signed, 526 static_assert(SrcLimits::is_signed == DstLimits::is_signed,
464 "Destination and source sign must be the same"); 527 "Destination and source sign must be the same");
465 static_assert(sizeof(Dst) < sizeof(Src) || 528 static_assert(sizeof(Dst) < sizeof(Src) ||
466 (DstLimits::is_integer && SrcLimits::is_iec559), 529 (DstLimits::is_integer && SrcLimits::is_iec559),
467 "Destination must be narrower than source"); 530 "Destination must be narrower than source");
468 531
532 TestStrictComparison<Dst, Src>();
533
469 const CheckedNumeric<Dst> checked_dst; 534 const CheckedNumeric<Dst> checked_dst;
470 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max()); 535 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
471 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1)); 536 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
472 TEST_EXPECTED_FAILURE(checked_dst - SrcLimits::max()); 537 TEST_EXPECTED_FAILURE(checked_dst - SrcLimits::max());
473 538
474 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max()); 539 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
475 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); 540 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
476 if (SrcLimits::is_iec559) { 541 if (SrcLimits::is_iec559) {
477 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1); 542 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
478 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1)); 543 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
(...skipping 26 matching lines...) Expand all
505 template <typename Dst, typename Src> 570 template <typename Dst, typename Src>
506 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> { 571 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> {
507 static void Test(const char *dst, const char *src, int line) { 572 static void Test(const char *dst, const char *src, int line) {
508 typedef numeric_limits<Src> SrcLimits; 573 typedef numeric_limits<Src> SrcLimits;
509 typedef numeric_limits<Dst> DstLimits; 574 typedef numeric_limits<Dst> DstLimits;
510 static_assert(sizeof(Dst) >= sizeof(Src), 575 static_assert(sizeof(Dst) >= sizeof(Src),
511 "Destination must be equal or wider than source."); 576 "Destination must be equal or wider than source.");
512 static_assert(SrcLimits::is_signed, "Source must be signed"); 577 static_assert(SrcLimits::is_signed, "Source must be signed");
513 static_assert(!DstLimits::is_signed, "Destination must be unsigned"); 578 static_assert(!DstLimits::is_signed, "Destination must be unsigned");
514 579
580 TestStrictComparison<Dst, Src>();
581
515 const CheckedNumeric<Dst> checked_dst; 582 const CheckedNumeric<Dst> checked_dst;
516 TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max()); 583 TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max());
517 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1)); 584 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
518 TEST_EXPECTED_FAILURE(checked_dst + -SrcLimits::max()); 585 TEST_EXPECTED_FAILURE(checked_dst + -SrcLimits::max());
519 586
520 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min()); 587 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
521 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max()); 588 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
522 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); 589 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
523 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1)); 590 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
524 } 591 }
525 }; 592 };
526 593
527 template <typename Dst, typename Src> 594 template <typename Dst, typename Src>
528 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> { 595 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> {
529 static void Test(const char *dst, const char *src, int line) { 596 static void Test(const char *dst, const char *src, int line) {
530 typedef numeric_limits<Src> SrcLimits; 597 typedef numeric_limits<Src> SrcLimits;
531 typedef numeric_limits<Dst> DstLimits; 598 typedef numeric_limits<Dst> DstLimits;
532 static_assert((DstLimits::is_integer && SrcLimits::is_iec559) || 599 static_assert((DstLimits::is_integer && SrcLimits::is_iec559) ||
533 (sizeof(Dst) < sizeof(Src)), 600 (sizeof(Dst) < sizeof(Src)),
534 "Destination must be narrower than source."); 601 "Destination must be narrower than source.");
535 static_assert(SrcLimits::is_signed, "Source must be signed."); 602 static_assert(SrcLimits::is_signed, "Source must be signed.");
536 static_assert(!DstLimits::is_signed, "Destination must be unsigned."); 603 static_assert(!DstLimits::is_signed, "Destination must be unsigned.");
537 604
605 TestStrictComparison<Dst, Src>();
606
538 const CheckedNumeric<Dst> checked_dst; 607 const CheckedNumeric<Dst> checked_dst;
539 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1)); 608 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
540 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max()); 609 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
541 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1)); 610 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
542 TEST_EXPECTED_FAILURE(checked_dst + -SrcLimits::max()); 611 TEST_EXPECTED_FAILURE(checked_dst + -SrcLimits::max());
543 612
544 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max()); 613 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
545 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); 614 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
546 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1)); 615 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
547 if (SrcLimits::is_iec559) { 616 if (SrcLimits::is_iec559) {
(...skipping 22 matching lines...) Expand all
570 template <typename Dst, typename Src> 639 template <typename Dst, typename Src>
571 struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> { 640 struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> {
572 static void Test(const char *dst, const char *src, int line) { 641 static void Test(const char *dst, const char *src, int line) {
573 typedef numeric_limits<Src> SrcLimits; 642 typedef numeric_limits<Src> SrcLimits;
574 typedef numeric_limits<Dst> DstLimits; 643 typedef numeric_limits<Dst> DstLimits;
575 static_assert(sizeof(Dst) <= sizeof(Src), 644 static_assert(sizeof(Dst) <= sizeof(Src),
576 "Destination must be narrower or equal to source."); 645 "Destination must be narrower or equal to source.");
577 static_assert(!SrcLimits::is_signed, "Source must be unsigned."); 646 static_assert(!SrcLimits::is_signed, "Source must be unsigned.");
578 static_assert(DstLimits::is_signed, "Destination must be signed."); 647 static_assert(DstLimits::is_signed, "Destination must be signed.");
579 648
649 TestStrictComparison<Dst, Src>();
650
580 const CheckedNumeric<Dst> checked_dst; 651 const CheckedNumeric<Dst> checked_dst;
581 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1)); 652 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
582 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max()); 653 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
583 TEST_EXPECTED_VALUE(SrcLimits::min(), checked_dst + SrcLimits::min()); 654 TEST_EXPECTED_VALUE(SrcLimits::min(), checked_dst + SrcLimits::min());
584 655
585 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min()); 656 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
586 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max()); 657 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
587 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); 658 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
588 } 659 }
589 }; 660 };
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
676 TEST_NUMERIC_CONVERSION(double, int, SIGN_PRESERVING_VALUE_PRESERVING); 747 TEST_NUMERIC_CONVERSION(double, int, SIGN_PRESERVING_VALUE_PRESERVING);
677 TEST_NUMERIC_CONVERSION(double, unsigned int, 748 TEST_NUMERIC_CONVERSION(double, unsigned int,
678 SIGN_PRESERVING_VALUE_PRESERVING); 749 SIGN_PRESERVING_VALUE_PRESERVING);
679 } 750 }
680 751
681 TEST(SafeNumerics, SizeTOperations) { 752 TEST(SafeNumerics, SizeTOperations) {
682 TEST_NUMERIC_CONVERSION(size_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL); 753 TEST_NUMERIC_CONVERSION(size_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
683 TEST_NUMERIC_CONVERSION(int, size_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL); 754 TEST_NUMERIC_CONVERSION(int, size_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
684 } 755 }
685 756
757 // A one-off test to ensure StrictNumeric won't resolve to an incorrect type.
758 // If this fails we'll just get a compiler error on an ambiguous overload.
759 int TestOverload(int) { // Overload fails.
760 return 0;
761 }
762 uint8_t TestOverload(uint8_t) { // Overload fails.
763 return 0;
764 }
765 size_t TestOverload(size_t) { // Overload succeeds.
766 return 0;
767 }
768
769 static_assert(
770 std::is_same<decltype(TestOverload(StrictNumeric<int>())), int>::value,
771 "");
772 static_assert(std::is_same<decltype(TestOverload(StrictNumeric<size_t>())),
773 size_t>::value,
774 "");
775
686 TEST(SafeNumerics, CastTests) { 776 TEST(SafeNumerics, CastTests) {
687 // MSVC catches and warns that we're forcing saturation in these tests. 777 // MSVC catches and warns that we're forcing saturation in these tests.
688 // Since that's intentional, we need to shut this warning off. 778 // Since that's intentional, we need to shut this warning off.
689 #if defined(COMPILER_MSVC) 779 #if defined(COMPILER_MSVC)
690 #pragma warning(disable : 4756) 780 #pragma warning(disable : 4756)
691 #endif 781 #endif
692 782
693 int small_positive = 1; 783 int small_positive = 1;
694 int small_negative = -1; 784 int small_negative = -1;
695 double double_small = 1.0; 785 double double_small = 1.0;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
747 float not_a_number = std::numeric_limits<float>::infinity() - 837 float not_a_number = std::numeric_limits<float>::infinity() -
748 std::numeric_limits<float>::infinity(); 838 std::numeric_limits<float>::infinity();
749 EXPECT_TRUE(std::isnan(not_a_number)); 839 EXPECT_TRUE(std::isnan(not_a_number));
750 EXPECT_EQ(0, saturated_cast<int>(not_a_number)); 840 EXPECT_EQ(0, saturated_cast<int>(not_a_number));
751 841
752 // Test the CheckedNumeric value extractions functions. 842 // Test the CheckedNumeric value extractions functions.
753 auto int8_min = CheckNum(numeric_limits<int8_t>::min()); 843 auto int8_min = CheckNum(numeric_limits<int8_t>::min());
754 auto int8_max = CheckNum(numeric_limits<int8_t>::max()); 844 auto int8_max = CheckNum(numeric_limits<int8_t>::max());
755 auto double_max = CheckNum(numeric_limits<double>::max()); 845 auto double_max = CheckNum(numeric_limits<double>::max());
756 static_assert( 846 static_assert(
757 std::is_same<int16_t, decltype(int8_min.ValueOrDie<int16_t>())>::value, 847 std::is_same<int16_t,
848 decltype(int8_min.ValueOrDie<int16_t>())::type>::value,
758 "ValueOrDie returning incorrect type."); 849 "ValueOrDie returning incorrect type.");
759 static_assert( 850 static_assert(
760 std::is_same<int16_t, 851 std::is_same<int16_t,
761 decltype(int8_min.ValueOrDefault<int16_t>(0))>::value, 852 decltype(int8_min.ValueOrDefault<int16_t>(0))::type>::value,
762 "ValueOrDefault returning incorrect type."); 853 "ValueOrDefault returning incorrect type.");
763 static_assert( 854 EXPECT_FALSE(IsValidForType<uint8_t>(int8_min));
764 std::is_same<float, decltype(double_max.ValueFloating<float>())>::value, 855 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()), 856 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::min()),
769 int8_min.template ValueOrDie<int>()); 857 ValueOrDieForType<int>(int8_min));
770 EXPECT_TRUE(int8_max.template IsValid<uint32_t>()); 858 EXPECT_TRUE(IsValidForType<uint32_t>(int8_max));
771 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::max()), 859 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::max()),
772 int8_max.template ValueOrDie<int>()); 860 ValueOrDieForType<int>(int8_max));
861 EXPECT_EQ(0, ValueOrDefaultForType<int>(double_max, 0));
773 uint8_t uint8_dest = 0; 862 uint8_t uint8_dest = 0;
774 int16_t int16_dest = 0; 863 int16_t int16_dest = 0;
775 double double_dest = 0; 864 double double_dest = 0;
776 EXPECT_TRUE(int8_max.AssignIfValid(&uint8_dest)); 865 EXPECT_TRUE(int8_max.AssignIfValid(&uint8_dest));
777 EXPECT_EQ(static_cast<uint8_t>(numeric_limits<int8_t>::max()), uint8_dest); 866 EXPECT_EQ(static_cast<uint8_t>(numeric_limits<int8_t>::max()), uint8_dest);
778 EXPECT_FALSE(int8_min.AssignIfValid(&uint8_dest)); 867 EXPECT_FALSE(int8_min.AssignIfValid(&uint8_dest));
779 EXPECT_TRUE(int8_max.AssignIfValid(&int16_dest)); 868 EXPECT_TRUE(int8_max.AssignIfValid(&int16_dest));
780 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::max()), int16_dest); 869 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::max()), int16_dest);
781 EXPECT_TRUE(int8_min.AssignIfValid(&int16_dest)); 870 EXPECT_TRUE(int8_min.AssignIfValid(&int16_dest));
782 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::min()), int16_dest); 871 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::min()), int16_dest);
783 EXPECT_FALSE(double_max.AssignIfValid(&uint8_dest)); 872 EXPECT_FALSE(double_max.AssignIfValid(&uint8_dest));
784 EXPECT_FALSE(double_max.AssignIfValid(&int16_dest)); 873 EXPECT_FALSE(double_max.AssignIfValid(&int16_dest));
785 EXPECT_TRUE(double_max.AssignIfValid(&double_dest)); 874 EXPECT_TRUE(double_max.AssignIfValid(&double_dest));
786 EXPECT_EQ(numeric_limits<double>::max(), double_dest); 875 EXPECT_EQ(numeric_limits<double>::max(), double_dest);
876 EXPECT_EQ(1, checked_cast<int>(StrictNumeric<int>(1)));
877 EXPECT_EQ(1, saturated_cast<int>(StrictNumeric<int>(1)));
878 EXPECT_EQ(1, strict_cast<int>(StrictNumeric<int>(1)));
787 } 879 }
788 880
789 TEST(SafeNumerics, SaturatedCastChecks) { 881 TEST(SafeNumerics, SaturatedCastChecks) {
790 float not_a_number = std::numeric_limits<float>::infinity() - 882 float not_a_number = std::numeric_limits<float>::infinity() -
791 std::numeric_limits<float>::infinity(); 883 std::numeric_limits<float>::infinity();
792 EXPECT_TRUE(std::isnan(not_a_number)); 884 EXPECT_TRUE(std::isnan(not_a_number));
793 EXPECT_DEATH_IF_SUPPORTED( 885 EXPECT_DEATH_IF_SUPPORTED(
794 (saturated_cast<int, base::CheckOnFailure>(not_a_number)), 886 (saturated_cast<int, base::CheckOnFailure>(not_a_number)),
795 ""); 887 "");
796 } 888 }
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
889 too_large += d; 981 too_large += d;
890 EXPECT_FALSE(too_large.IsValid()); 982 EXPECT_FALSE(too_large.IsValid());
891 too_large -= d; 983 too_large -= d;
892 EXPECT_FALSE(too_large.IsValid()); 984 EXPECT_FALSE(too_large.IsValid());
893 too_large /= d; 985 too_large /= d;
894 EXPECT_FALSE(too_large.IsValid()); 986 EXPECT_FALSE(too_large.IsValid());
895 } 987 }
896 988
897 TEST(SafeNumerics, VariadicNumericOperations) { 989 TEST(SafeNumerics, VariadicNumericOperations) {
898 auto a = CheckAdd(1, 2UL, CheckNum(3LL), 4).ValueOrDie(); 990 auto a = CheckAdd(1, 2UL, CheckNum(3LL), 4).ValueOrDie();
899 EXPECT_EQ(static_cast<decltype(a)>(10), a); 991 EXPECT_EQ(static_cast<decltype(a)::type>(10), a);
900 auto b = CheckSub(CheckNum(20.0), 2UL, 4).ValueOrDie(); 992 auto b = CheckSub(CheckNum(20.0), 2UL, 4).ValueOrDie();
901 EXPECT_EQ(static_cast<decltype(b)>(14.0), b); 993 EXPECT_EQ(static_cast<decltype(b)::type>(14.0), b);
902 auto c = CheckMul(20.0, CheckNum(1), 5, 3UL).ValueOrDie(); 994 auto c = CheckMul(20.0, CheckNum(1), 5, 3UL).ValueOrDie();
903 EXPECT_EQ(static_cast<decltype(c)>(300.0), c); 995 EXPECT_EQ(static_cast<decltype(c)::type>(300.0), c);
904 auto d = CheckDiv(20.0, 2.0, CheckNum(5LL), -4).ValueOrDie(); 996 auto d = CheckDiv(20.0, 2.0, CheckNum(5LL), -4).ValueOrDie();
905 EXPECT_EQ(static_cast<decltype(d)>(-.5), d); 997 EXPECT_EQ(static_cast<decltype(d)::type>(-.5), d);
906 auto e = CheckMod(CheckNum(20), 3).ValueOrDie(); 998 auto e = CheckMod(CheckNum(20), 3).ValueOrDie();
907 EXPECT_EQ(static_cast<decltype(e)>(2), e); 999 EXPECT_EQ(static_cast<decltype(e)::type>(2), e);
908 auto f = CheckLsh(1, CheckNum(2)).ValueOrDie(); 1000 auto f = CheckLsh(1, CheckNum(2)).ValueOrDie();
909 EXPECT_EQ(static_cast<decltype(f)>(4), f); 1001 EXPECT_EQ(static_cast<decltype(f)::type>(4), f);
910 auto g = CheckRsh(4, CheckNum(2)).ValueOrDie(); 1002 auto g = CheckRsh(4, CheckNum(2)).ValueOrDie();
911 EXPECT_EQ(static_cast<decltype(g)>(1), g); 1003 EXPECT_EQ(static_cast<decltype(g)::type>(1), g);
912 auto h = CheckRsh(CheckAdd(1, 1, 1, 1), CheckSub(4, 2)).ValueOrDie(); 1004 auto h = CheckRsh(CheckAdd(1, 1, 1, 1), CheckSub(4, 2)).ValueOrDie();
913 EXPECT_EQ(static_cast<decltype(h)>(1), h); 1005 EXPECT_EQ(static_cast<decltype(h)::type>(1), h);
914 } 1006 }
OLDNEW
« no previous file with comments | « base/numerics/safe_math_impl.h ('k') | chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reader_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698