mfbt/tests/TestCheckedInt.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "mozilla/CheckedInt.h"
michael@0 7
michael@0 8 #include <iostream>
michael@0 9 #include <climits>
michael@0 10
michael@0 11 using namespace mozilla;
michael@0 12
michael@0 13 int gIntegerTypesTested = 0;
michael@0 14 int gTestsPassed = 0;
michael@0 15 int gTestsFailed = 0;
michael@0 16
michael@0 17 void verifyImplFunction(bool x, bool expected,
michael@0 18 const char* file, int line,
michael@0 19 int size, bool isTSigned)
michael@0 20 {
michael@0 21 if (x == expected) {
michael@0 22 gTestsPassed++;
michael@0 23 } else {
michael@0 24 gTestsFailed++;
michael@0 25 std::cerr << "Test failed at " << file << ":" << line;
michael@0 26 std::cerr << " with T a ";
michael@0 27 if (isTSigned)
michael@0 28 std::cerr << "signed";
michael@0 29 else
michael@0 30 std::cerr << "unsigned";
michael@0 31 std::cerr << " " << CHAR_BIT*size << "-bit integer type" << std::endl;
michael@0 32 }
michael@0 33 }
michael@0 34
michael@0 35 #define VERIFY_IMPL(x, expected) \
michael@0 36 verifyImplFunction((x), \
michael@0 37 (expected), \
michael@0 38 __FILE__, \
michael@0 39 __LINE__, \
michael@0 40 sizeof(T), \
michael@0 41 IsSigned<T>::value)
michael@0 42
michael@0 43 #define VERIFY(x) VERIFY_IMPL(x, true)
michael@0 44 #define VERIFY_IS_FALSE(x) VERIFY_IMPL(x, false)
michael@0 45 #define VERIFY_IS_VALID(x) VERIFY_IMPL((x).isValid(), true)
michael@0 46 #define VERIFY_IS_INVALID(x) VERIFY_IMPL((x).isValid(), false)
michael@0 47 #define VERIFY_IS_VALID_IF(x,condition) VERIFY_IMPL((x).isValid(), (condition))
michael@0 48
michael@0 49 template<typename T, size_t Size = sizeof(T)>
michael@0 50 struct testTwiceBiggerType
michael@0 51 {
michael@0 52 static void run()
michael@0 53 {
michael@0 54 VERIFY(detail::IsSupported<typename detail::TwiceBiggerType<T>::Type>::value);
michael@0 55 VERIFY(sizeof(typename detail::TwiceBiggerType<T>::Type)
michael@0 56 == 2 * sizeof(T));
michael@0 57 VERIFY(bool(IsSigned<typename detail::TwiceBiggerType<T>::Type>::value)
michael@0 58 == bool(IsSigned<T>::value));
michael@0 59 }
michael@0 60 };
michael@0 61
michael@0 62 template<typename T>
michael@0 63 struct testTwiceBiggerType<T, 8>
michael@0 64 {
michael@0 65 static void run()
michael@0 66 {
michael@0 67 VERIFY_IS_FALSE(detail::IsSupported<
michael@0 68 typename detail::TwiceBiggerType<T>::Type
michael@0 69 >::value);
michael@0 70 }
michael@0 71 };
michael@0 72
michael@0 73
michael@0 74 template<typename T>
michael@0 75 void test()
michael@0 76 {
michael@0 77 static bool alreadyRun = false;
michael@0 78 // Integer types from different families may just be typedefs for types from other families.
michael@0 79 // e.g. int32_t might be just a typedef for int. No point re-running the same tests then.
michael@0 80 if (alreadyRun)
michael@0 81 return;
michael@0 82 alreadyRun = true;
michael@0 83
michael@0 84 VERIFY(detail::IsSupported<T>::value);
michael@0 85 const bool isTSigned = IsSigned<T>::value;
michael@0 86 VERIFY(bool(isTSigned) == !bool(T(-1) > T(0)));
michael@0 87
michael@0 88 testTwiceBiggerType<T>::run();
michael@0 89
michael@0 90 typedef typename MakeUnsigned<T>::Type unsignedT;
michael@0 91
michael@0 92 VERIFY(sizeof(unsignedT) == sizeof(T));
michael@0 93 VERIFY(IsSigned<unsignedT>::value == false);
michael@0 94
michael@0 95 const CheckedInt<T> max(MaxValue<T>::value);
michael@0 96 const CheckedInt<T> min(MinValue<T>::value);
michael@0 97
michael@0 98 // Check MinValue and MaxValue, since they are custom implementations and a mistake there
michael@0 99 // could potentially NOT be caught by any other tests... while making everything wrong!
michael@0 100
michael@0 101 unsignedT bit = 1;
michael@0 102 unsignedT unsignedMinValue(min.value());
michael@0 103 unsignedT unsignedMaxValue(max.value());
michael@0 104 for (size_t i = 0; i < sizeof(T) * CHAR_BIT - 1; i++)
michael@0 105 {
michael@0 106 VERIFY((unsignedMinValue & bit) == 0);
michael@0 107 bit <<= 1;
michael@0 108 }
michael@0 109 VERIFY((unsignedMinValue & bit) == (isTSigned ? bit : unsignedT(0)));
michael@0 110 VERIFY(unsignedMaxValue == unsignedT(~unsignedMinValue));
michael@0 111
michael@0 112 const CheckedInt<T> zero(0);
michael@0 113 const CheckedInt<T> one(1);
michael@0 114 const CheckedInt<T> two(2);
michael@0 115 const CheckedInt<T> three(3);
michael@0 116 const CheckedInt<T> four(4);
michael@0 117
michael@0 118 /* Addition / subtraction checks */
michael@0 119
michael@0 120 VERIFY_IS_VALID(zero + zero);
michael@0 121 VERIFY(zero + zero == zero);
michael@0 122 VERIFY_IS_FALSE(zero + zero == one); // Check that == doesn't always return true
michael@0 123 VERIFY_IS_VALID(zero + one);
michael@0 124 VERIFY(zero + one == one);
michael@0 125 VERIFY_IS_VALID(one + one);
michael@0 126 VERIFY(one + one == two);
michael@0 127
michael@0 128 const CheckedInt<T> maxMinusOne = max - one;
michael@0 129 const CheckedInt<T> maxMinusTwo = max - two;
michael@0 130 VERIFY_IS_VALID(maxMinusOne);
michael@0 131 VERIFY_IS_VALID(maxMinusTwo);
michael@0 132 VERIFY_IS_VALID(maxMinusOne + one);
michael@0 133 VERIFY_IS_VALID(maxMinusTwo + one);
michael@0 134 VERIFY_IS_VALID(maxMinusTwo + two);
michael@0 135 VERIFY(maxMinusOne + one == max);
michael@0 136 VERIFY(maxMinusTwo + one == maxMinusOne);
michael@0 137 VERIFY(maxMinusTwo + two == max);
michael@0 138
michael@0 139 VERIFY_IS_VALID(max + zero);
michael@0 140 VERIFY_IS_VALID(max - zero);
michael@0 141 VERIFY_IS_INVALID(max + one);
michael@0 142 VERIFY_IS_INVALID(max + two);
michael@0 143 VERIFY_IS_INVALID(max + maxMinusOne);
michael@0 144 VERIFY_IS_INVALID(max + max);
michael@0 145
michael@0 146 const CheckedInt<T> minPlusOne = min + one;
michael@0 147 const CheckedInt<T> minPlusTwo = min + two;
michael@0 148 VERIFY_IS_VALID(minPlusOne);
michael@0 149 VERIFY_IS_VALID(minPlusTwo);
michael@0 150 VERIFY_IS_VALID(minPlusOne - one);
michael@0 151 VERIFY_IS_VALID(minPlusTwo - one);
michael@0 152 VERIFY_IS_VALID(minPlusTwo - two);
michael@0 153 VERIFY(minPlusOne - one == min);
michael@0 154 VERIFY(minPlusTwo - one == minPlusOne);
michael@0 155 VERIFY(minPlusTwo - two == min);
michael@0 156
michael@0 157 const CheckedInt<T> minMinusOne = min - one;
michael@0 158 VERIFY_IS_VALID(min + zero);
michael@0 159 VERIFY_IS_VALID(min - zero);
michael@0 160 VERIFY_IS_INVALID(min - one);
michael@0 161 VERIFY_IS_INVALID(min - two);
michael@0 162 VERIFY_IS_INVALID(min - minMinusOne);
michael@0 163 VERIFY_IS_VALID(min - min);
michael@0 164
michael@0 165 const CheckedInt<T> maxOverTwo = max / two;
michael@0 166 VERIFY_IS_VALID(maxOverTwo + maxOverTwo);
michael@0 167 VERIFY_IS_VALID(maxOverTwo + one);
michael@0 168 VERIFY((maxOverTwo + one) - one == maxOverTwo);
michael@0 169 VERIFY_IS_VALID(maxOverTwo - maxOverTwo);
michael@0 170 VERIFY(maxOverTwo - maxOverTwo == zero);
michael@0 171
michael@0 172 const CheckedInt<T> minOverTwo = min / two;
michael@0 173 VERIFY_IS_VALID(minOverTwo + minOverTwo);
michael@0 174 VERIFY_IS_VALID(minOverTwo + one);
michael@0 175 VERIFY((minOverTwo + one) - one == minOverTwo);
michael@0 176 VERIFY_IS_VALID(minOverTwo - minOverTwo);
michael@0 177 VERIFY(minOverTwo - minOverTwo == zero);
michael@0 178
michael@0 179 VERIFY_IS_INVALID(min - one);
michael@0 180 VERIFY_IS_INVALID(min - two);
michael@0 181
michael@0 182 if (isTSigned) {
michael@0 183 VERIFY_IS_INVALID(min + min);
michael@0 184 VERIFY_IS_INVALID(minOverTwo + minOverTwo + minOverTwo);
michael@0 185 VERIFY_IS_INVALID(zero - min + min);
michael@0 186 VERIFY_IS_INVALID(one - min + min);
michael@0 187 }
michael@0 188
michael@0 189 /* Modulo checks */
michael@0 190 VERIFY_IS_INVALID(zero % zero);
michael@0 191 VERIFY_IS_INVALID(one % zero);
michael@0 192 VERIFY_IS_VALID(zero % one);
michael@0 193 VERIFY_IS_VALID(zero % max);
michael@0 194 VERIFY_IS_VALID(one % max);
michael@0 195 VERIFY_IS_VALID(max % one);
michael@0 196 VERIFY_IS_VALID(max % max);
michael@0 197 if (isTSigned) {
michael@0 198 const CheckedInt<T> minusOne = zero - one;
michael@0 199 VERIFY_IS_INVALID(minusOne % minusOne);
michael@0 200 VERIFY_IS_INVALID(zero % minusOne);
michael@0 201 VERIFY_IS_INVALID(one % minusOne);
michael@0 202 VERIFY_IS_INVALID(minusOne % one);
michael@0 203
michael@0 204 VERIFY_IS_INVALID(min % min);
michael@0 205 VERIFY_IS_INVALID(zero % min);
michael@0 206 VERIFY_IS_INVALID(min % one);
michael@0 207 }
michael@0 208
michael@0 209 /* Unary operator- checks */
michael@0 210
michael@0 211 const CheckedInt<T> negOne = -one;
michael@0 212 const CheckedInt<T> negTwo = -two;
michael@0 213
michael@0 214 if (isTSigned) {
michael@0 215 VERIFY_IS_VALID(-max);
michael@0 216 VERIFY_IS_INVALID(-min);
michael@0 217 VERIFY(-max - min == one);
michael@0 218 VERIFY_IS_VALID(-max - one);
michael@0 219 VERIFY_IS_VALID(negOne);
michael@0 220 VERIFY_IS_VALID(-max + negOne);
michael@0 221 VERIFY_IS_VALID(negOne + one);
michael@0 222 VERIFY(negOne + one == zero);
michael@0 223 VERIFY_IS_VALID(negTwo);
michael@0 224 VERIFY_IS_VALID(negOne + negOne);
michael@0 225 VERIFY(negOne + negOne == negTwo);
michael@0 226 } else {
michael@0 227 VERIFY_IS_INVALID(-max);
michael@0 228 VERIFY_IS_VALID(-min);
michael@0 229 VERIFY(min == zero);
michael@0 230 VERIFY_IS_INVALID(negOne);
michael@0 231 }
michael@0 232
michael@0 233 /* multiplication checks */
michael@0 234
michael@0 235 VERIFY_IS_VALID(zero * zero);
michael@0 236 VERIFY(zero * zero == zero);
michael@0 237 VERIFY_IS_VALID(zero * one);
michael@0 238 VERIFY(zero * one == zero);
michael@0 239 VERIFY_IS_VALID(one * zero);
michael@0 240 VERIFY(one * zero == zero);
michael@0 241 VERIFY_IS_VALID(one * one);
michael@0 242 VERIFY(one * one == one);
michael@0 243 VERIFY_IS_VALID(one * three);
michael@0 244 VERIFY(one * three == three);
michael@0 245 VERIFY_IS_VALID(two * two);
michael@0 246 VERIFY(two * two == four);
michael@0 247
michael@0 248 VERIFY_IS_INVALID(max * max);
michael@0 249 VERIFY_IS_INVALID(maxOverTwo * max);
michael@0 250 VERIFY_IS_INVALID(maxOverTwo * maxOverTwo);
michael@0 251
michael@0 252 const CheckedInt<T> maxApproxSqrt(T(T(1) << (CHAR_BIT*sizeof(T)/2)));
michael@0 253
michael@0 254 VERIFY_IS_VALID(maxApproxSqrt);
michael@0 255 VERIFY_IS_VALID(maxApproxSqrt * two);
michael@0 256 VERIFY_IS_INVALID(maxApproxSqrt * maxApproxSqrt);
michael@0 257 VERIFY_IS_INVALID(maxApproxSqrt * maxApproxSqrt * maxApproxSqrt);
michael@0 258
michael@0 259 if (isTSigned) {
michael@0 260 VERIFY_IS_INVALID(min * min);
michael@0 261 VERIFY_IS_INVALID(minOverTwo * min);
michael@0 262 VERIFY_IS_INVALID(minOverTwo * minOverTwo);
michael@0 263
michael@0 264 const CheckedInt<T> minApproxSqrt = -maxApproxSqrt;
michael@0 265
michael@0 266 VERIFY_IS_VALID(minApproxSqrt);
michael@0 267 VERIFY_IS_VALID(minApproxSqrt * two);
michael@0 268 VERIFY_IS_INVALID(minApproxSqrt * maxApproxSqrt);
michael@0 269 VERIFY_IS_INVALID(minApproxSqrt * minApproxSqrt);
michael@0 270 }
michael@0 271
michael@0 272 // make sure to check all 4 paths in signed multiplication validity check.
michael@0 273 // test positive * positive
michael@0 274 VERIFY_IS_VALID(max * one);
michael@0 275 VERIFY(max * one == max);
michael@0 276 VERIFY_IS_INVALID(max * two);
michael@0 277 VERIFY_IS_VALID(maxOverTwo * two);
michael@0 278 VERIFY((maxOverTwo + maxOverTwo) == (maxOverTwo * two));
michael@0 279
michael@0 280 if (isTSigned) {
michael@0 281 // test positive * negative
michael@0 282 VERIFY_IS_VALID(max * negOne);
michael@0 283 VERIFY_IS_VALID(-max);
michael@0 284 VERIFY(max * negOne == -max);
michael@0 285 VERIFY_IS_VALID(one * min);
michael@0 286 VERIFY_IS_INVALID(max * negTwo);
michael@0 287 VERIFY_IS_VALID(maxOverTwo * negTwo);
michael@0 288 VERIFY_IS_VALID(two * minOverTwo);
michael@0 289 VERIFY_IS_VALID((maxOverTwo + one) * negTwo);
michael@0 290 VERIFY_IS_INVALID((maxOverTwo + two) * negTwo);
michael@0 291 VERIFY_IS_INVALID(two * (minOverTwo - one));
michael@0 292
michael@0 293 // test negative * positive
michael@0 294 VERIFY_IS_VALID(min * one);
michael@0 295 VERIFY_IS_VALID(minPlusOne * one);
michael@0 296 VERIFY_IS_INVALID(min * two);
michael@0 297 VERIFY_IS_VALID(minOverTwo * two);
michael@0 298 VERIFY(minOverTwo * two == min);
michael@0 299 VERIFY_IS_INVALID((minOverTwo - one) * negTwo);
michael@0 300 VERIFY_IS_INVALID(negTwo * max);
michael@0 301 VERIFY_IS_VALID(minOverTwo * two);
michael@0 302 VERIFY(minOverTwo * two == min);
michael@0 303 VERIFY_IS_VALID(negTwo * maxOverTwo);
michael@0 304 VERIFY_IS_INVALID((minOverTwo - one) * two);
michael@0 305 VERIFY_IS_VALID(negTwo * (maxOverTwo + one));
michael@0 306 VERIFY_IS_INVALID(negTwo * (maxOverTwo + two));
michael@0 307
michael@0 308 // test negative * negative
michael@0 309 VERIFY_IS_INVALID(min * negOne);
michael@0 310 VERIFY_IS_VALID(minPlusOne * negOne);
michael@0 311 VERIFY(minPlusOne * negOne == max);
michael@0 312 VERIFY_IS_INVALID(min * negTwo);
michael@0 313 VERIFY_IS_INVALID(minOverTwo * negTwo);
michael@0 314 VERIFY_IS_INVALID(negOne * min);
michael@0 315 VERIFY_IS_VALID(negOne * minPlusOne);
michael@0 316 VERIFY(negOne * minPlusOne == max);
michael@0 317 VERIFY_IS_INVALID(negTwo * min);
michael@0 318 VERIFY_IS_INVALID(negTwo * minOverTwo);
michael@0 319 }
michael@0 320
michael@0 321 /* Division checks */
michael@0 322
michael@0 323 VERIFY_IS_VALID(one / one);
michael@0 324 VERIFY(one / one == one);
michael@0 325 VERIFY_IS_VALID(three / three);
michael@0 326 VERIFY(three / three == one);
michael@0 327 VERIFY_IS_VALID(four / two);
michael@0 328 VERIFY(four / two == two);
michael@0 329 VERIFY((four*three)/four == three);
michael@0 330
michael@0 331 // Check that div by zero is invalid
michael@0 332 VERIFY_IS_INVALID(zero / zero);
michael@0 333 VERIFY_IS_INVALID(one / zero);
michael@0 334 VERIFY_IS_INVALID(two / zero);
michael@0 335 VERIFY_IS_INVALID(negOne / zero);
michael@0 336 VERIFY_IS_INVALID(max / zero);
michael@0 337 VERIFY_IS_INVALID(min / zero);
michael@0 338
michael@0 339 if (isTSigned) {
michael@0 340 // Check that min / -1 is invalid
michael@0 341 VERIFY_IS_INVALID(min / negOne);
michael@0 342
michael@0 343 // Check that the test for div by -1 isn't banning other numerators than min
michael@0 344 VERIFY_IS_VALID(one / negOne);
michael@0 345 VERIFY_IS_VALID(zero / negOne);
michael@0 346 VERIFY_IS_VALID(negOne / negOne);
michael@0 347 VERIFY_IS_VALID(max / negOne);
michael@0 348 }
michael@0 349
michael@0 350 /* Check that invalidity is correctly preserved by arithmetic ops */
michael@0 351
michael@0 352 const CheckedInt<T> someInvalid = max + max;
michael@0 353 VERIFY_IS_INVALID(someInvalid + zero);
michael@0 354 VERIFY_IS_INVALID(someInvalid - zero);
michael@0 355 VERIFY_IS_INVALID(zero + someInvalid);
michael@0 356 VERIFY_IS_INVALID(zero - someInvalid);
michael@0 357 VERIFY_IS_INVALID(-someInvalid);
michael@0 358 VERIFY_IS_INVALID(someInvalid * zero);
michael@0 359 VERIFY_IS_INVALID(someInvalid * one);
michael@0 360 VERIFY_IS_INVALID(zero * someInvalid);
michael@0 361 VERIFY_IS_INVALID(one * someInvalid);
michael@0 362 VERIFY_IS_INVALID(someInvalid / zero);
michael@0 363 VERIFY_IS_INVALID(someInvalid / one);
michael@0 364 VERIFY_IS_INVALID(zero / someInvalid);
michael@0 365 VERIFY_IS_INVALID(one / someInvalid);
michael@0 366 VERIFY_IS_INVALID(someInvalid % zero);
michael@0 367 VERIFY_IS_INVALID(someInvalid % one);
michael@0 368 VERIFY_IS_INVALID(zero % someInvalid);
michael@0 369 VERIFY_IS_INVALID(one % someInvalid);
michael@0 370 VERIFY_IS_INVALID(someInvalid + someInvalid);
michael@0 371 VERIFY_IS_INVALID(someInvalid - someInvalid);
michael@0 372 VERIFY_IS_INVALID(someInvalid * someInvalid);
michael@0 373 VERIFY_IS_INVALID(someInvalid / someInvalid);
michael@0 374 VERIFY_IS_INVALID(someInvalid % someInvalid);
michael@0 375
michael@0 376 /* Check that mixing checked integers with plain integers in expressions is allowed */
michael@0 377
michael@0 378 VERIFY(one + T(2) == three);
michael@0 379 VERIFY(2 + one == three);
michael@0 380 {
michael@0 381 CheckedInt<T> x = one;
michael@0 382 x += 2;
michael@0 383 VERIFY(x == three);
michael@0 384 }
michael@0 385 VERIFY(two - 1 == one);
michael@0 386 VERIFY(2 - one == one);
michael@0 387 {
michael@0 388 CheckedInt<T> x = two;
michael@0 389 x -= 1;
michael@0 390 VERIFY(x == one);
michael@0 391 }
michael@0 392 VERIFY(one * 2 == two);
michael@0 393 VERIFY(2 * one == two);
michael@0 394 {
michael@0 395 CheckedInt<T> x = one;
michael@0 396 x *= 2;
michael@0 397 VERIFY(x == two);
michael@0 398 }
michael@0 399 VERIFY(four / 2 == two);
michael@0 400 VERIFY(4 / two == two);
michael@0 401 {
michael@0 402 CheckedInt<T> x = four;
michael@0 403 x /= 2;
michael@0 404 VERIFY(x == two);
michael@0 405 }
michael@0 406 VERIFY(three % 2 == one);
michael@0 407 VERIFY(3 % two == one);
michael@0 408 {
michael@0 409 CheckedInt<T> x = three;
michael@0 410 x %= 2;
michael@0 411 VERIFY(x == one);
michael@0 412 }
michael@0 413
michael@0 414 VERIFY(one == 1);
michael@0 415 VERIFY(1 == one);
michael@0 416 VERIFY_IS_FALSE(two == 1);
michael@0 417 VERIFY_IS_FALSE(1 == two);
michael@0 418 VERIFY_IS_FALSE(someInvalid == 1);
michael@0 419 VERIFY_IS_FALSE(1 == someInvalid);
michael@0 420
michael@0 421 // Check simple casting between different signedness and sizes.
michael@0 422 {
michael@0 423 CheckedInt<uint8_t> foo = CheckedInt<uint16_t>(2).toChecked<uint8_t>();
michael@0 424 VERIFY_IS_VALID(foo);
michael@0 425 VERIFY(foo == 2);
michael@0 426 }
michael@0 427 {
michael@0 428 CheckedInt<uint8_t> foo = CheckedInt<uint16_t>(255).toChecked<uint8_t>();
michael@0 429 VERIFY_IS_VALID(foo);
michael@0 430 VERIFY(foo == 255);
michael@0 431 }
michael@0 432 {
michael@0 433 CheckedInt<uint8_t> foo = CheckedInt<uint16_t>(256).toChecked<uint8_t>();
michael@0 434 VERIFY_IS_INVALID(foo);
michael@0 435 }
michael@0 436 {
michael@0 437 CheckedInt<uint8_t> foo = CheckedInt<int8_t>(-2).toChecked<uint8_t>();
michael@0 438 VERIFY_IS_INVALID(foo);
michael@0 439 }
michael@0 440
michael@0 441 // Check that construction of CheckedInt from an integer value of a mismatched type is checked
michael@0 442 // Also check casting between all types.
michael@0 443
michael@0 444 #define VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE2(U,V,PostVExpr) \
michael@0 445 { \
michael@0 446 bool isUSigned = IsSigned<U>::value; \
michael@0 447 VERIFY_IS_VALID(CheckedInt<T>(V( 0)PostVExpr)); \
michael@0 448 VERIFY_IS_VALID(CheckedInt<T>(V( 1)PostVExpr)); \
michael@0 449 VERIFY_IS_VALID(CheckedInt<T>(V(100)PostVExpr)); \
michael@0 450 if (isUSigned) \
michael@0 451 VERIFY_IS_VALID_IF(CheckedInt<T>(V(-1)PostVExpr), isTSigned); \
michael@0 452 if (sizeof(U) > sizeof(T)) \
michael@0 453 VERIFY_IS_INVALID(CheckedInt<T>(V(MaxValue<T>::value)PostVExpr + one.value())); \
michael@0 454 VERIFY_IS_VALID_IF(CheckedInt<T>(MaxValue<U>::value), \
michael@0 455 (sizeof(T) > sizeof(U) || ((sizeof(T) == sizeof(U)) && (isUSigned || !isTSigned)))); \
michael@0 456 VERIFY_IS_VALID_IF(CheckedInt<T>(MinValue<U>::value), \
michael@0 457 isUSigned == false ? 1 \
michael@0 458 : bool(isTSigned) == false ? 0 \
michael@0 459 : sizeof(T) >= sizeof(U)); \
michael@0 460 }
michael@0 461 #define VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(U) \
michael@0 462 VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE2(U,U,+0) \
michael@0 463 VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE2(U,CheckedInt<U>,.toChecked<T>())
michael@0 464
michael@0 465 VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int8_t)
michael@0 466 VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(uint8_t)
michael@0 467 VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int16_t)
michael@0 468 VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(uint16_t)
michael@0 469 VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int32_t)
michael@0 470 VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(uint32_t)
michael@0 471 VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int64_t)
michael@0 472 VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(uint64_t)
michael@0 473
michael@0 474 typedef signed char signedChar;
michael@0 475 typedef unsigned char unsignedChar;
michael@0 476 typedef unsigned short unsignedShort;
michael@0 477 typedef unsigned int unsignedInt;
michael@0 478 typedef unsigned long unsignedLong;
michael@0 479 typedef long long longLong;
michael@0 480 typedef unsigned long long unsignedLongLong;
michael@0 481
michael@0 482 VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(char)
michael@0 483 VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(signedChar)
michael@0 484 VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(unsignedChar)
michael@0 485 VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(short)
michael@0 486 VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(unsignedShort)
michael@0 487 VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int)
michael@0 488 VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(unsignedInt)
michael@0 489 VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(long)
michael@0 490 VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(unsignedLong)
michael@0 491 VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(longLong)
michael@0 492 VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(unsignedLongLong)
michael@0 493
michael@0 494 /* Test increment/decrement operators */
michael@0 495
michael@0 496 CheckedInt<T> x, y;
michael@0 497 x = one;
michael@0 498 y = x++;
michael@0 499 VERIFY(x == two);
michael@0 500 VERIFY(y == one);
michael@0 501 x = one;
michael@0 502 y = ++x;
michael@0 503 VERIFY(x == two);
michael@0 504 VERIFY(y == two);
michael@0 505 x = one;
michael@0 506 y = x--;
michael@0 507 VERIFY(x == zero);
michael@0 508 VERIFY(y == one);
michael@0 509 x = one;
michael@0 510 y = --x;
michael@0 511 VERIFY(x == zero);
michael@0 512 VERIFY(y == zero);
michael@0 513 x = max;
michael@0 514 VERIFY_IS_VALID(x++);
michael@0 515 x = max;
michael@0 516 VERIFY_IS_INVALID(++x);
michael@0 517 x = min;
michael@0 518 VERIFY_IS_VALID(x--);
michael@0 519 x = min;
michael@0 520 VERIFY_IS_INVALID(--x);
michael@0 521
michael@0 522 gIntegerTypesTested++;
michael@0 523 }
michael@0 524
michael@0 525 int main()
michael@0 526 {
michael@0 527 test<int8_t>();
michael@0 528 test<uint8_t>();
michael@0 529 test<int16_t>();
michael@0 530 test<uint16_t>();
michael@0 531 test<int32_t>();
michael@0 532 test<uint32_t>();
michael@0 533 test<int64_t>();
michael@0 534 test<uint64_t>();
michael@0 535
michael@0 536 test<char>();
michael@0 537 test<signed char>();
michael@0 538 test<unsigned char>();
michael@0 539 test<short>();
michael@0 540 test<unsigned short>();
michael@0 541 test<int>();
michael@0 542 test<unsigned int>();
michael@0 543 test<long>();
michael@0 544 test<unsigned long>();
michael@0 545 test<long long>();
michael@0 546 test<unsigned long long>();
michael@0 547
michael@0 548 const int MIN_TYPES_TESTED = 9;
michael@0 549 if (gIntegerTypesTested < MIN_TYPES_TESTED) {
michael@0 550 std::cerr << "Only " << gIntegerTypesTested << " have been tested. "
michael@0 551 << "This should not be less than " << MIN_TYPES_TESTED << "."
michael@0 552 << std::endl;
michael@0 553 gTestsFailed++;
michael@0 554 }
michael@0 555
michael@0 556 std::cerr << gTestsFailed << " tests failed, "
michael@0 557 << gTestsPassed << " tests passed out of "
michael@0 558 << gTestsFailed + gTestsPassed
michael@0 559 << " tests, covering " << gIntegerTypesTested
michael@0 560 << " distinct integer types." << std::endl;
michael@0 561
michael@0 562 return gTestsFailed > 0;
michael@0 563 }

mercurial