| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS) | |
| 6 #include <mmintrin.h> | |
| 7 #endif | |
| 8 #include <stdint.h> | |
| 9 | |
| 10 #include <limits> | |
| 11 | |
| 12 #include "base/compiler_specific.h" | |
| 13 #include "base/numerics/safe_conversions.h" | |
| 14 #include "base/numerics/safe_math.h" | |
| 15 #include "base/template_util.h" | |
| 16 #include "testing/gtest/include/gtest/gtest.h" | |
| 17 | |
| 18 using std::numeric_limits; | |
| 19 using base::CheckedNumeric; | |
| 20 using base::checked_cast; | |
| 21 using base::SizeT; | |
| 22 using base::StrictNumeric; | |
| 23 using base::saturated_cast; | |
| 24 using base::strict_cast; | |
| 25 using base::internal::MaxExponent; | |
| 26 using base::internal::RANGE_VALID; | |
| 27 using base::internal::RANGE_INVALID; | |
| 28 using base::internal::RANGE_OVERFLOW; | |
| 29 using base::internal::RANGE_UNDERFLOW; | |
| 30 using base::enable_if; | |
| 31 | |
| 32 // These tests deliberately cause arithmetic overflows. If the compiler is | |
| 33 // aggressive enough, it can const fold these overflows. Disable warnings about | |
| 34 // overflows for const expressions. | |
| 35 #if defined(OS_WIN) | |
| 36 #pragma warning(disable:4756) | |
| 37 #endif | |
| 38 | |
| 39 // Helper macros to wrap displaying the conversion types and line numbers. | |
| 40 #define TEST_EXPECTED_VALIDITY(expected, actual) \ | |
| 41 EXPECT_EQ(expected, CheckedNumeric<Dst>(actual).validity()) \ | |
| 42 << "Result test: Value " << +(actual).ValueUnsafe() << " as " << dst \ | |
| 43 << " on line " << line; | |
| 44 | |
| 45 #define TEST_EXPECTED_VALUE(expected, actual) \ | |
| 46 EXPECT_EQ(static_cast<Dst>(expected), \ | |
| 47 CheckedNumeric<Dst>(actual).ValueUnsafe()) \ | |
| 48 << "Result test: Value " << +((actual).ValueUnsafe()) << " as " << dst \ | |
| 49 << " on line " << line; | |
| 50 | |
| 51 // Signed integer arithmetic. | |
| 52 template <typename Dst> | |
| 53 static void TestSpecializedArithmetic( | |
| 54 const char* dst, | |
| 55 int line, | |
| 56 typename enable_if< | |
| 57 numeric_limits<Dst>::is_integer&& numeric_limits<Dst>::is_signed, | |
| 58 int>::type = 0) { | |
| 59 typedef numeric_limits<Dst> DstLimits; | |
| 60 TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, | |
| 61 -CheckedNumeric<Dst>(DstLimits::min())); | |
| 62 TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, | |
| 63 CheckedNumeric<Dst>(DstLimits::min()).Abs()); | |
| 64 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs()); | |
| 65 | |
| 66 TEST_EXPECTED_VALIDITY(RANGE_VALID, | |
| 67 CheckedNumeric<Dst>(DstLimits::max()) + -1); | |
| 68 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, | |
| 69 CheckedNumeric<Dst>(DstLimits::min()) + -1); | |
| 70 TEST_EXPECTED_VALIDITY( | |
| 71 RANGE_UNDERFLOW, | |
| 72 CheckedNumeric<Dst>(-DstLimits::max()) + -DstLimits::max()); | |
| 73 | |
| 74 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, | |
| 75 CheckedNumeric<Dst>(DstLimits::min()) - 1); | |
| 76 TEST_EXPECTED_VALIDITY(RANGE_VALID, | |
| 77 CheckedNumeric<Dst>(DstLimits::min()) - -1); | |
| 78 TEST_EXPECTED_VALIDITY( | |
| 79 RANGE_OVERFLOW, | |
| 80 CheckedNumeric<Dst>(DstLimits::max()) - -DstLimits::max()); | |
| 81 TEST_EXPECTED_VALIDITY( | |
| 82 RANGE_UNDERFLOW, | |
| 83 CheckedNumeric<Dst>(-DstLimits::max()) - DstLimits::max()); | |
| 84 | |
| 85 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, | |
| 86 CheckedNumeric<Dst>(DstLimits::min()) * 2); | |
| 87 | |
| 88 TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, | |
| 89 CheckedNumeric<Dst>(DstLimits::min()) / -1); | |
| 90 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) / 2); | |
| 91 | |
| 92 // Modulus is legal only for integers. | |
| 93 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1); | |
| 94 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1); | |
| 95 TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % 2); | |
| 96 TEST_EXPECTED_VALIDITY(RANGE_INVALID, CheckedNumeric<Dst>(-1) % -2); | |
| 97 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) % 2); | |
| 98 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2); | |
| 99 // Test all the different modulus combinations. | |
| 100 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1)); | |
| 101 TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1)); | |
| 102 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1); | |
| 103 CheckedNumeric<Dst> checked_dst = 1; | |
| 104 TEST_EXPECTED_VALUE(0, checked_dst %= 1); | |
| 105 } | |
| 106 | |
| 107 // Unsigned integer arithmetic. | |
| 108 template <typename Dst> | |
| 109 static void TestSpecializedArithmetic( | |
| 110 const char* dst, | |
| 111 int line, | |
| 112 typename enable_if< | |
| 113 numeric_limits<Dst>::is_integer && !numeric_limits<Dst>::is_signed, | |
| 114 int>::type = 0) { | |
| 115 typedef numeric_limits<Dst> DstLimits; | |
| 116 TEST_EXPECTED_VALIDITY(RANGE_VALID, -CheckedNumeric<Dst>(DstLimits::min())); | |
| 117 TEST_EXPECTED_VALIDITY(RANGE_VALID, | |
| 118 CheckedNumeric<Dst>(DstLimits::min()).Abs()); | |
| 119 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, | |
| 120 CheckedNumeric<Dst>(DstLimits::min()) + -1); | |
| 121 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, | |
| 122 CheckedNumeric<Dst>(DstLimits::min()) - 1); | |
| 123 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) * 2); | |
| 124 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) / 2); | |
| 125 | |
| 126 // Modulus is legal only for integers. | |
| 127 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1); | |
| 128 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1); | |
| 129 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % 2); | |
| 130 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) % 2); | |
| 131 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2); | |
| 132 // Test all the different modulus combinations. | |
| 133 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1)); | |
| 134 TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1)); | |
| 135 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1); | |
| 136 CheckedNumeric<Dst> checked_dst = 1; | |
| 137 TEST_EXPECTED_VALUE(0, checked_dst %= 1); | |
| 138 } | |
| 139 | |
| 140 // Floating point arithmetic. | |
| 141 template <typename Dst> | |
| 142 void TestSpecializedArithmetic( | |
| 143 const char* dst, | |
| 144 int line, | |
| 145 typename enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0) { | |
| 146 typedef numeric_limits<Dst> DstLimits; | |
| 147 TEST_EXPECTED_VALIDITY(RANGE_VALID, -CheckedNumeric<Dst>(DstLimits::min())); | |
| 148 | |
| 149 TEST_EXPECTED_VALIDITY(RANGE_VALID, | |
| 150 CheckedNumeric<Dst>(DstLimits::min()).Abs()); | |
| 151 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs()); | |
| 152 | |
| 153 TEST_EXPECTED_VALIDITY(RANGE_VALID, | |
| 154 CheckedNumeric<Dst>(DstLimits::min()) + -1); | |
| 155 TEST_EXPECTED_VALIDITY(RANGE_VALID, | |
| 156 CheckedNumeric<Dst>(DstLimits::max()) + 1); | |
| 157 TEST_EXPECTED_VALIDITY( | |
| 158 RANGE_UNDERFLOW, | |
| 159 CheckedNumeric<Dst>(-DstLimits::max()) + -DstLimits::max()); | |
| 160 | |
| 161 TEST_EXPECTED_VALIDITY( | |
| 162 RANGE_OVERFLOW, | |
| 163 CheckedNumeric<Dst>(DstLimits::max()) - -DstLimits::max()); | |
| 164 TEST_EXPECTED_VALIDITY( | |
| 165 RANGE_UNDERFLOW, | |
| 166 CheckedNumeric<Dst>(-DstLimits::max()) - DstLimits::max()); | |
| 167 | |
| 168 TEST_EXPECTED_VALIDITY(RANGE_VALID, | |
| 169 CheckedNumeric<Dst>(DstLimits::min()) * 2); | |
| 170 | |
| 171 TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2); | |
| 172 EXPECT_EQ(static_cast<Dst>(1.0), CheckedNumeric<Dst>(1.0).ValueFloating()); | |
| 173 } | |
| 174 | |
| 175 // Generic arithmetic tests. | |
| 176 template <typename Dst> | |
| 177 static void TestArithmetic(const char* dst, int line) { | |
| 178 typedef numeric_limits<Dst> DstLimits; | |
| 179 | |
| 180 EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid()); | |
| 181 EXPECT_EQ(false, | |
| 182 CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) * | |
| 183 DstLimits::max()).IsValid()); | |
| 184 EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDie()); | |
| 185 EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDefault(1)); | |
| 186 EXPECT_EQ(static_cast<Dst>(1), | |
| 187 CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) * | |
| 188 DstLimits::max()).ValueOrDefault(1)); | |
| 189 | |
| 190 // Test the operator combinations. | |
| 191 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + CheckedNumeric<Dst>(1)); | |
| 192 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - CheckedNumeric<Dst>(1)); | |
| 193 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * CheckedNumeric<Dst>(1)); | |
| 194 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / CheckedNumeric<Dst>(1)); | |
| 195 TEST_EXPECTED_VALUE(2, 1 + CheckedNumeric<Dst>(1)); | |
| 196 TEST_EXPECTED_VALUE(0, 1 - CheckedNumeric<Dst>(1)); | |
| 197 TEST_EXPECTED_VALUE(1, 1 * CheckedNumeric<Dst>(1)); | |
| 198 TEST_EXPECTED_VALUE(1, 1 / CheckedNumeric<Dst>(1)); | |
| 199 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + 1); | |
| 200 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - 1); | |
| 201 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * 1); | |
| 202 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1); | |
| 203 CheckedNumeric<Dst> checked_dst = 1; | |
| 204 TEST_EXPECTED_VALUE(2, checked_dst += 1); | |
| 205 checked_dst = 1; | |
| 206 TEST_EXPECTED_VALUE(0, checked_dst -= 1); | |
| 207 checked_dst = 1; | |
| 208 TEST_EXPECTED_VALUE(1, checked_dst *= 1); | |
| 209 checked_dst = 1; | |
| 210 TEST_EXPECTED_VALUE(1, checked_dst /= 1); | |
| 211 | |
| 212 // Generic negation. | |
| 213 TEST_EXPECTED_VALUE(0, -CheckedNumeric<Dst>()); | |
| 214 TEST_EXPECTED_VALUE(-1, -CheckedNumeric<Dst>(1)); | |
| 215 TEST_EXPECTED_VALUE(1, -CheckedNumeric<Dst>(-1)); | |
| 216 TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1), | |
| 217 -CheckedNumeric<Dst>(DstLimits::max())); | |
| 218 | |
| 219 // Generic absolute value. | |
| 220 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>().Abs()); | |
| 221 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).Abs()); | |
| 222 TEST_EXPECTED_VALUE(DstLimits::max(), | |
| 223 CheckedNumeric<Dst>(DstLimits::max()).Abs()); | |
| 224 | |
| 225 // Generic addition. | |
| 226 TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>() + 1)); | |
| 227 TEST_EXPECTED_VALUE(2, (CheckedNumeric<Dst>(1) + 1)); | |
| 228 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) + 1)); | |
| 229 TEST_EXPECTED_VALIDITY(RANGE_VALID, | |
| 230 CheckedNumeric<Dst>(DstLimits::min()) + 1); | |
| 231 TEST_EXPECTED_VALIDITY( | |
| 232 RANGE_OVERFLOW, CheckedNumeric<Dst>(DstLimits::max()) + DstLimits::max()); | |
| 233 | |
| 234 // Generic subtraction. | |
| 235 TEST_EXPECTED_VALUE(-1, (CheckedNumeric<Dst>() - 1)); | |
| 236 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(1) - 1)); | |
| 237 TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) - 1)); | |
| 238 TEST_EXPECTED_VALIDITY(RANGE_VALID, | |
| 239 CheckedNumeric<Dst>(DstLimits::max()) - 1); | |
| 240 | |
| 241 // Generic multiplication. | |
| 242 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>() * 1)); | |
| 243 TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>(1) * 1)); | |
| 244 TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) * 2)); | |
| 245 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * 0)); | |
| 246 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) * 0)); | |
| 247 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * -1)); | |
| 248 TEST_EXPECTED_VALIDITY( | |
| 249 RANGE_OVERFLOW, CheckedNumeric<Dst>(DstLimits::max()) * DstLimits::max()); | |
| 250 | |
| 251 // Generic division. | |
| 252 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() / 1); | |
| 253 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1); | |
| 254 TEST_EXPECTED_VALUE(DstLimits::min() / 2, | |
| 255 CheckedNumeric<Dst>(DstLimits::min()) / 2); | |
| 256 TEST_EXPECTED_VALUE(DstLimits::max() / 2, | |
| 257 CheckedNumeric<Dst>(DstLimits::max()) / 2); | |
| 258 | |
| 259 TestSpecializedArithmetic<Dst>(dst, line); | |
| 260 } | |
| 261 | |
| 262 // Helper macro to wrap displaying the conversion types and line numbers. | |
| 263 #define TEST_ARITHMETIC(Dst) TestArithmetic<Dst>(#Dst, __LINE__) | |
| 264 | |
| 265 TEST(SafeNumerics, SignedIntegerMath) { | |
| 266 TEST_ARITHMETIC(int8_t); | |
| 267 TEST_ARITHMETIC(int); | |
| 268 TEST_ARITHMETIC(intptr_t); | |
| 269 TEST_ARITHMETIC(intmax_t); | |
| 270 } | |
| 271 | |
| 272 TEST(SafeNumerics, UnsignedIntegerMath) { | |
| 273 TEST_ARITHMETIC(uint8_t); | |
| 274 TEST_ARITHMETIC(unsigned int); | |
| 275 TEST_ARITHMETIC(uintptr_t); | |
| 276 TEST_ARITHMETIC(uintmax_t); | |
| 277 } | |
| 278 | |
| 279 TEST(SafeNumerics, FloatingPointMath) { | |
| 280 TEST_ARITHMETIC(float); | |
| 281 TEST_ARITHMETIC(double); | |
| 282 } | |
| 283 | |
| 284 // Enumerates the five different conversions types we need to test. | |
| 285 enum NumericConversionType { | |
| 286 SIGN_PRESERVING_VALUE_PRESERVING, | |
| 287 SIGN_PRESERVING_NARROW, | |
| 288 SIGN_TO_UNSIGN_WIDEN_OR_EQUAL, | |
| 289 SIGN_TO_UNSIGN_NARROW, | |
| 290 UNSIGN_TO_SIGN_NARROW_OR_EQUAL, | |
| 291 }; | |
| 292 | |
| 293 // Template covering the different conversion tests. | |
| 294 template <typename Dst, typename Src, NumericConversionType conversion> | |
| 295 struct TestNumericConversion {}; | |
| 296 | |
| 297 // EXPECT_EQ wrappers providing specific detail on test failures. | |
| 298 #define TEST_EXPECTED_RANGE(expected, actual) \ | |
| 299 EXPECT_EQ(expected, base::internal::DstRangeRelationToSrcRange<Dst>(actual)) \ | |
| 300 << "Conversion test: " << src << " value " << actual << " to " << dst \ | |
| 301 << " on line " << line; | |
| 302 | |
| 303 template <typename Dst, typename Src> | |
| 304 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> { | |
| 305 static void Test(const char *dst, const char *src, int line) { | |
| 306 typedef numeric_limits<Src> SrcLimits; | |
| 307 typedef numeric_limits<Dst> DstLimits; | |
| 308 // Integral to floating. | |
| 309 static_assert((DstLimits::is_iec559 && SrcLimits::is_integer) || | |
| 310 // Not floating to integral and... | |
| 311 (!(DstLimits::is_integer && SrcLimits::is_iec559) && | |
| 312 // Same sign, same numeric, source is narrower or same. | |
| 313 ((SrcLimits::is_signed == DstLimits::is_signed && | |
| 314 sizeof(Dst) >= sizeof(Src)) || | |
| 315 // Or signed destination and source is smaller | |
| 316 (DstLimits::is_signed && sizeof(Dst) > sizeof(Src)))), | |
| 317 "Comparison must be sign preserving and value preserving"); | |
| 318 | |
| 319 const CheckedNumeric<Dst> checked_dst = SrcLimits::max(); | |
| 320 ; | |
| 321 TEST_EXPECTED_VALIDITY(RANGE_VALID, checked_dst); | |
| 322 if (MaxExponent<Dst>::value > MaxExponent<Src>::value) { | |
| 323 if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1) { | |
| 324 // At least twice larger type. | |
| 325 TEST_EXPECTED_VALIDITY(RANGE_VALID, SrcLimits::max() * checked_dst); | |
| 326 | |
| 327 } else { // Larger, but not at least twice as large. | |
| 328 TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, SrcLimits::max() * checked_dst); | |
| 329 TEST_EXPECTED_VALIDITY(RANGE_VALID, checked_dst + 1); | |
| 330 } | |
| 331 } else { // Same width type. | |
| 332 TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, checked_dst + 1); | |
| 333 } | |
| 334 | |
| 335 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max()); | |
| 336 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); | |
| 337 if (SrcLimits::is_iec559) { | |
| 338 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max() * static_cast<Src>(-1)); | |
| 339 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity()); | |
| 340 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1); | |
| 341 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN()); | |
| 342 } else if (numeric_limits<Src>::is_signed) { | |
| 343 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1)); | |
| 344 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min()); | |
| 345 } | |
| 346 } | |
| 347 }; | |
| 348 | |
| 349 template <typename Dst, typename Src> | |
| 350 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> { | |
| 351 static void Test(const char *dst, const char *src, int line) { | |
| 352 typedef numeric_limits<Src> SrcLimits; | |
| 353 typedef numeric_limits<Dst> DstLimits; | |
| 354 static_assert(SrcLimits::is_signed == DstLimits::is_signed, | |
| 355 "Destination and source sign must be the same"); | |
| 356 static_assert(sizeof(Dst) < sizeof(Src) || | |
| 357 (DstLimits::is_integer && SrcLimits::is_iec559), | |
| 358 "Destination must be narrower than source"); | |
| 359 | |
| 360 const CheckedNumeric<Dst> checked_dst; | |
| 361 TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, checked_dst + SrcLimits::max()); | |
| 362 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1)); | |
| 363 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst - SrcLimits::max()); | |
| 364 | |
| 365 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max()); | |
| 366 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); | |
| 367 if (SrcLimits::is_iec559) { | |
| 368 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1); | |
| 369 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1)); | |
| 370 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity()); | |
| 371 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1); | |
| 372 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN()); | |
| 373 } else if (SrcLimits::is_signed) { | |
| 374 TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1)); | |
| 375 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min()); | |
| 376 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1)); | |
| 377 } else { | |
| 378 TEST_EXPECTED_VALIDITY(RANGE_INVALID, checked_dst - static_cast<Src>(1)); | |
| 379 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min()); | |
| 380 } | |
| 381 } | |
| 382 }; | |
| 383 | |
| 384 template <typename Dst, typename Src> | |
| 385 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> { | |
| 386 static void Test(const char *dst, const char *src, int line) { | |
| 387 typedef numeric_limits<Src> SrcLimits; | |
| 388 typedef numeric_limits<Dst> DstLimits; | |
| 389 static_assert(sizeof(Dst) >= sizeof(Src), | |
| 390 "Destination must be equal or wider than source."); | |
| 391 static_assert(SrcLimits::is_signed, "Source must be signed"); | |
| 392 static_assert(!DstLimits::is_signed, "Destination must be unsigned"); | |
| 393 | |
| 394 const CheckedNumeric<Dst> checked_dst; | |
| 395 TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max()); | |
| 396 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst + static_cast<Src>(-1)); | |
| 397 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst + -SrcLimits::max()); | |
| 398 | |
| 399 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min()); | |
| 400 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max()); | |
| 401 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); | |
| 402 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1)); | |
| 403 } | |
| 404 }; | |
| 405 | |
| 406 template <typename Dst, typename Src> | |
| 407 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> { | |
| 408 static void Test(const char *dst, const char *src, int line) { | |
| 409 typedef numeric_limits<Src> SrcLimits; | |
| 410 typedef numeric_limits<Dst> DstLimits; | |
| 411 static_assert((DstLimits::is_integer && SrcLimits::is_iec559) || | |
| 412 (sizeof(Dst) < sizeof(Src)), | |
| 413 "Destination must be narrower than source."); | |
| 414 static_assert(SrcLimits::is_signed, "Source must be signed."); | |
| 415 static_assert(!DstLimits::is_signed, "Destination must be unsigned."); | |
| 416 | |
| 417 const CheckedNumeric<Dst> checked_dst; | |
| 418 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1)); | |
| 419 TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, checked_dst + SrcLimits::max()); | |
| 420 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst + static_cast<Src>(-1)); | |
| 421 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst + -SrcLimits::max()); | |
| 422 | |
| 423 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max()); | |
| 424 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); | |
| 425 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1)); | |
| 426 if (SrcLimits::is_iec559) { | |
| 427 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1); | |
| 428 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity()); | |
| 429 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1); | |
| 430 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN()); | |
| 431 } else { | |
| 432 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min()); | |
| 433 } | |
| 434 } | |
| 435 }; | |
| 436 | |
| 437 template <typename Dst, typename Src> | |
| 438 struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> { | |
| 439 static void Test(const char *dst, const char *src, int line) { | |
| 440 typedef numeric_limits<Src> SrcLimits; | |
| 441 typedef numeric_limits<Dst> DstLimits; | |
| 442 static_assert(sizeof(Dst) <= sizeof(Src), | |
| 443 "Destination must be narrower or equal to source."); | |
| 444 static_assert(!SrcLimits::is_signed, "Source must be unsigned."); | |
| 445 static_assert(DstLimits::is_signed, "Destination must be signed."); | |
| 446 | |
| 447 const CheckedNumeric<Dst> checked_dst; | |
| 448 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1)); | |
| 449 TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, checked_dst + SrcLimits::max()); | |
| 450 TEST_EXPECTED_VALUE(SrcLimits::min(), checked_dst + SrcLimits::min()); | |
| 451 | |
| 452 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min()); | |
| 453 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max()); | |
| 454 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); | |
| 455 } | |
| 456 }; | |
| 457 | |
| 458 // Helper macro to wrap displaying the conversion types and line numbers | |
| 459 #define TEST_NUMERIC_CONVERSION(d, s, t) \ | |
| 460 TestNumericConversion<d, s, t>::Test(#d, #s, __LINE__) | |
| 461 | |
| 462 TEST(SafeNumerics, IntMinOperations) { | |
| 463 TEST_NUMERIC_CONVERSION(int8_t, int8_t, SIGN_PRESERVING_VALUE_PRESERVING); | |
| 464 TEST_NUMERIC_CONVERSION(uint8_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING); | |
| 465 | |
| 466 TEST_NUMERIC_CONVERSION(int8_t, int, SIGN_PRESERVING_NARROW); | |
| 467 TEST_NUMERIC_CONVERSION(uint8_t, unsigned int, SIGN_PRESERVING_NARROW); | |
| 468 TEST_NUMERIC_CONVERSION(int8_t, float, SIGN_PRESERVING_NARROW); | |
| 469 | |
| 470 TEST_NUMERIC_CONVERSION(uint8_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL); | |
| 471 | |
| 472 TEST_NUMERIC_CONVERSION(uint8_t, int, SIGN_TO_UNSIGN_NARROW); | |
| 473 TEST_NUMERIC_CONVERSION(uint8_t, intmax_t, SIGN_TO_UNSIGN_NARROW); | |
| 474 TEST_NUMERIC_CONVERSION(uint8_t, float, SIGN_TO_UNSIGN_NARROW); | |
| 475 | |
| 476 TEST_NUMERIC_CONVERSION(int8_t, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL); | |
| 477 TEST_NUMERIC_CONVERSION(int8_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL); | |
| 478 } | |
| 479 | |
| 480 TEST(SafeNumerics, IntOperations) { | |
| 481 TEST_NUMERIC_CONVERSION(int, int, SIGN_PRESERVING_VALUE_PRESERVING); | |
| 482 TEST_NUMERIC_CONVERSION(unsigned int, unsigned int, | |
| 483 SIGN_PRESERVING_VALUE_PRESERVING); | |
| 484 TEST_NUMERIC_CONVERSION(int, int8_t, SIGN_PRESERVING_VALUE_PRESERVING); | |
| 485 TEST_NUMERIC_CONVERSION(unsigned int, uint8_t, | |
| 486 SIGN_PRESERVING_VALUE_PRESERVING); | |
| 487 TEST_NUMERIC_CONVERSION(int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING); | |
| 488 | |
| 489 TEST_NUMERIC_CONVERSION(int, intmax_t, SIGN_PRESERVING_NARROW); | |
| 490 TEST_NUMERIC_CONVERSION(unsigned int, uintmax_t, SIGN_PRESERVING_NARROW); | |
| 491 TEST_NUMERIC_CONVERSION(int, float, SIGN_PRESERVING_NARROW); | |
| 492 TEST_NUMERIC_CONVERSION(int, double, SIGN_PRESERVING_NARROW); | |
| 493 | |
| 494 TEST_NUMERIC_CONVERSION(unsigned int, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL); | |
| 495 TEST_NUMERIC_CONVERSION(unsigned int, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL); | |
| 496 | |
| 497 TEST_NUMERIC_CONVERSION(unsigned int, intmax_t, SIGN_TO_UNSIGN_NARROW); | |
| 498 TEST_NUMERIC_CONVERSION(unsigned int, float, SIGN_TO_UNSIGN_NARROW); | |
| 499 TEST_NUMERIC_CONVERSION(unsigned int, double, SIGN_TO_UNSIGN_NARROW); | |
| 500 | |
| 501 TEST_NUMERIC_CONVERSION(int, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL); | |
| 502 TEST_NUMERIC_CONVERSION(int, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL); | |
| 503 } | |
| 504 | |
| 505 TEST(SafeNumerics, IntMaxOperations) { | |
| 506 TEST_NUMERIC_CONVERSION(intmax_t, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING); | |
| 507 TEST_NUMERIC_CONVERSION(uintmax_t, uintmax_t, | |
| 508 SIGN_PRESERVING_VALUE_PRESERVING); | |
| 509 TEST_NUMERIC_CONVERSION(intmax_t, int, SIGN_PRESERVING_VALUE_PRESERVING); | |
| 510 TEST_NUMERIC_CONVERSION(uintmax_t, unsigned int, | |
| 511 SIGN_PRESERVING_VALUE_PRESERVING); | |
| 512 TEST_NUMERIC_CONVERSION(intmax_t, unsigned int, | |
| 513 SIGN_PRESERVING_VALUE_PRESERVING); | |
| 514 TEST_NUMERIC_CONVERSION(intmax_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING); | |
| 515 | |
| 516 TEST_NUMERIC_CONVERSION(intmax_t, float, SIGN_PRESERVING_NARROW); | |
| 517 TEST_NUMERIC_CONVERSION(intmax_t, double, SIGN_PRESERVING_NARROW); | |
| 518 | |
| 519 TEST_NUMERIC_CONVERSION(uintmax_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL); | |
| 520 TEST_NUMERIC_CONVERSION(uintmax_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL); | |
| 521 | |
| 522 TEST_NUMERIC_CONVERSION(uintmax_t, float, SIGN_TO_UNSIGN_NARROW); | |
| 523 TEST_NUMERIC_CONVERSION(uintmax_t, double, SIGN_TO_UNSIGN_NARROW); | |
| 524 | |
| 525 TEST_NUMERIC_CONVERSION(intmax_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL); | |
| 526 } | |
| 527 | |
| 528 TEST(SafeNumerics, FloatOperations) { | |
| 529 TEST_NUMERIC_CONVERSION(float, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING); | |
| 530 TEST_NUMERIC_CONVERSION(float, uintmax_t, | |
| 531 SIGN_PRESERVING_VALUE_PRESERVING); | |
| 532 TEST_NUMERIC_CONVERSION(float, int, SIGN_PRESERVING_VALUE_PRESERVING); | |
| 533 TEST_NUMERIC_CONVERSION(float, unsigned int, | |
| 534 SIGN_PRESERVING_VALUE_PRESERVING); | |
| 535 | |
| 536 TEST_NUMERIC_CONVERSION(float, double, SIGN_PRESERVING_NARROW); | |
| 537 } | |
| 538 | |
| 539 TEST(SafeNumerics, DoubleOperations) { | |
| 540 TEST_NUMERIC_CONVERSION(double, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING); | |
| 541 TEST_NUMERIC_CONVERSION(double, uintmax_t, | |
| 542 SIGN_PRESERVING_VALUE_PRESERVING); | |
| 543 TEST_NUMERIC_CONVERSION(double, int, SIGN_PRESERVING_VALUE_PRESERVING); | |
| 544 TEST_NUMERIC_CONVERSION(double, unsigned int, | |
| 545 SIGN_PRESERVING_VALUE_PRESERVING); | |
| 546 } | |
| 547 | |
| 548 TEST(SafeNumerics, SizeTOperations) { | |
| 549 TEST_NUMERIC_CONVERSION(size_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL); | |
| 550 TEST_NUMERIC_CONVERSION(int, size_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL); | |
| 551 } | |
| 552 | |
| 553 TEST(SafeNumerics, CastTests) { | |
| 554 // MSVC catches and warns that we're forcing saturation in these tests. | |
| 555 // Since that's intentional, we need to shut this warning off. | |
| 556 #if defined(COMPILER_MSVC) | |
| 557 #pragma warning(disable : 4756) | |
| 558 #endif | |
| 559 | |
| 560 int small_positive = 1; | |
| 561 int small_negative = -1; | |
| 562 double double_small = 1.0; | |
| 563 double double_large = numeric_limits<double>::max(); | |
| 564 double double_infinity = numeric_limits<float>::infinity(); | |
| 565 double double_large_int = numeric_limits<int>::max(); | |
| 566 double double_small_int = numeric_limits<int>::min(); | |
| 567 | |
| 568 // Just test that the casts compile, since the other tests cover logic. | |
| 569 EXPECT_EQ(0, checked_cast<int>(static_cast<size_t>(0))); | |
| 570 EXPECT_EQ(0, strict_cast<int>(static_cast<char>(0))); | |
| 571 EXPECT_EQ(0, strict_cast<int>(static_cast<unsigned char>(0))); | |
| 572 EXPECT_EQ(0U, strict_cast<unsigned>(static_cast<unsigned char>(0))); | |
| 573 EXPECT_EQ(1ULL, static_cast<uint64_t>(StrictNumeric<size_t>(1U))); | |
| 574 EXPECT_EQ(1ULL, static_cast<uint64_t>(SizeT(1U))); | |
| 575 EXPECT_EQ(1U, static_cast<size_t>(StrictNumeric<unsigned>(1U))); | |
| 576 | |
| 577 EXPECT_TRUE(CheckedNumeric<uint64_t>(StrictNumeric<unsigned>(1U)).IsValid()); | |
| 578 EXPECT_TRUE(CheckedNumeric<int>(StrictNumeric<unsigned>(1U)).IsValid()); | |
| 579 EXPECT_FALSE(CheckedNumeric<unsigned>(StrictNumeric<int>(-1)).IsValid()); | |
| 580 | |
| 581 // These casts and coercions will fail to compile: | |
| 582 // EXPECT_EQ(0, strict_cast<int>(static_cast<size_t>(0))); | |
| 583 // EXPECT_EQ(0, strict_cast<size_t>(static_cast<int>(0))); | |
| 584 // EXPECT_EQ(1ULL, StrictNumeric<size_t>(1)); | |
| 585 // EXPECT_EQ(1, StrictNumeric<size_t>(1U)); | |
| 586 | |
| 587 // Test various saturation corner cases. | |
| 588 EXPECT_EQ(saturated_cast<int>(small_negative), | |
| 589 static_cast<int>(small_negative)); | |
| 590 EXPECT_EQ(saturated_cast<int>(small_positive), | |
| 591 static_cast<int>(small_positive)); | |
| 592 EXPECT_EQ(saturated_cast<unsigned>(small_negative), | |
| 593 static_cast<unsigned>(0)); | |
| 594 EXPECT_EQ(saturated_cast<int>(double_small), | |
| 595 static_cast<int>(double_small)); | |
| 596 EXPECT_EQ(saturated_cast<int>(double_large), numeric_limits<int>::max()); | |
| 597 EXPECT_EQ(saturated_cast<float>(double_large), double_infinity); | |
| 598 EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity); | |
| 599 EXPECT_EQ(numeric_limits<int>::min(), saturated_cast<int>(double_small_int)); | |
| 600 EXPECT_EQ(numeric_limits<int>::max(), saturated_cast<int>(double_large_int)); | |
| 601 } | |
| 602 | |
| OLD | NEW |