mfbt/tests/TestCheckedInt.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/mfbt/tests/TestCheckedInt.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,563 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     1.7 + * You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "mozilla/CheckedInt.h"
    1.10 +
    1.11 +#include <iostream>
    1.12 +#include <climits>
    1.13 +
    1.14 +using namespace mozilla;
    1.15 +
    1.16 +int gIntegerTypesTested = 0;
    1.17 +int gTestsPassed = 0;
    1.18 +int gTestsFailed = 0;
    1.19 +
    1.20 +void verifyImplFunction(bool x, bool expected,
    1.21 +                        const char* file, int line,
    1.22 +                        int size, bool isTSigned)
    1.23 +{
    1.24 +  if (x == expected) {
    1.25 +    gTestsPassed++;
    1.26 +  } else {
    1.27 +    gTestsFailed++;
    1.28 +    std::cerr << "Test failed at " << file << ":" << line;
    1.29 +    std::cerr << " with T a ";
    1.30 +    if (isTSigned)
    1.31 +      std::cerr << "signed";
    1.32 +    else
    1.33 +      std::cerr << "unsigned";
    1.34 +    std::cerr << " " << CHAR_BIT*size << "-bit integer type" << std::endl;
    1.35 +  }
    1.36 +}
    1.37 +
    1.38 +#define VERIFY_IMPL(x, expected) \
    1.39 +    verifyImplFunction((x), \
    1.40 +    (expected), \
    1.41 +    __FILE__, \
    1.42 +    __LINE__, \
    1.43 +    sizeof(T), \
    1.44 +    IsSigned<T>::value)
    1.45 +
    1.46 +#define VERIFY(x)            VERIFY_IMPL(x, true)
    1.47 +#define VERIFY_IS_FALSE(x)   VERIFY_IMPL(x, false)
    1.48 +#define VERIFY_IS_VALID(x)   VERIFY_IMPL((x).isValid(), true)
    1.49 +#define VERIFY_IS_INVALID(x) VERIFY_IMPL((x).isValid(), false)
    1.50 +#define VERIFY_IS_VALID_IF(x,condition) VERIFY_IMPL((x).isValid(), (condition))
    1.51 +
    1.52 +template<typename T, size_t Size = sizeof(T)>
    1.53 +struct testTwiceBiggerType
    1.54 +{
    1.55 +    static void run()
    1.56 +    {
    1.57 +      VERIFY(detail::IsSupported<typename detail::TwiceBiggerType<T>::Type>::value);
    1.58 +      VERIFY(sizeof(typename detail::TwiceBiggerType<T>::Type)
    1.59 +               == 2 * sizeof(T));
    1.60 +      VERIFY(bool(IsSigned<typename detail::TwiceBiggerType<T>::Type>::value)
    1.61 +               == bool(IsSigned<T>::value));
    1.62 +    }
    1.63 +};
    1.64 +
    1.65 +template<typename T>
    1.66 +struct testTwiceBiggerType<T, 8>
    1.67 +{
    1.68 +    static void run()
    1.69 +    {
    1.70 +      VERIFY_IS_FALSE(detail::IsSupported<
    1.71 +                        typename detail::TwiceBiggerType<T>::Type
    1.72 +                      >::value);
    1.73 +    }
    1.74 +};
    1.75 +
    1.76 +
    1.77 +template<typename T>
    1.78 +void test()
    1.79 +{
    1.80 +  static bool alreadyRun = false;
    1.81 +  // Integer types from different families may just be typedefs for types from other families.
    1.82 +  // e.g. int32_t might be just a typedef for int. No point re-running the same tests then.
    1.83 +  if (alreadyRun)
    1.84 +      return;
    1.85 +  alreadyRun = true;
    1.86 +
    1.87 +  VERIFY(detail::IsSupported<T>::value);
    1.88 +  const bool isTSigned = IsSigned<T>::value;
    1.89 +  VERIFY(bool(isTSigned) == !bool(T(-1) > T(0)));
    1.90 +
    1.91 +  testTwiceBiggerType<T>::run();
    1.92 +
    1.93 +  typedef typename MakeUnsigned<T>::Type unsignedT;
    1.94 +
    1.95 +  VERIFY(sizeof(unsignedT) == sizeof(T));
    1.96 +  VERIFY(IsSigned<unsignedT>::value == false);
    1.97 +
    1.98 +  const CheckedInt<T> max(MaxValue<T>::value);
    1.99 +  const CheckedInt<T> min(MinValue<T>::value);
   1.100 +
   1.101 +  // Check MinValue and MaxValue, since they are custom implementations and a mistake there
   1.102 +  // could potentially NOT be caught by any other tests... while making everything wrong!
   1.103 +
   1.104 +  unsignedT bit = 1;
   1.105 +  unsignedT unsignedMinValue(min.value());
   1.106 +  unsignedT unsignedMaxValue(max.value());
   1.107 +  for (size_t i = 0; i < sizeof(T) * CHAR_BIT - 1; i++)
   1.108 +  {
   1.109 +    VERIFY((unsignedMinValue & bit) == 0);
   1.110 +    bit <<= 1;
   1.111 +  }
   1.112 +  VERIFY((unsignedMinValue & bit) == (isTSigned ? bit : unsignedT(0)));
   1.113 +  VERIFY(unsignedMaxValue == unsignedT(~unsignedMinValue));
   1.114 +
   1.115 +  const CheckedInt<T> zero(0);
   1.116 +  const CheckedInt<T> one(1);
   1.117 +  const CheckedInt<T> two(2);
   1.118 +  const CheckedInt<T> three(3);
   1.119 +  const CheckedInt<T> four(4);
   1.120 +
   1.121 +  /* Addition / subtraction checks */
   1.122 +
   1.123 +  VERIFY_IS_VALID(zero + zero);
   1.124 +  VERIFY(zero + zero == zero);
   1.125 +  VERIFY_IS_FALSE(zero + zero == one); // Check that == doesn't always return true
   1.126 +  VERIFY_IS_VALID(zero + one);
   1.127 +  VERIFY(zero + one == one);
   1.128 +  VERIFY_IS_VALID(one + one);
   1.129 +  VERIFY(one + one == two);
   1.130 +
   1.131 +  const CheckedInt<T> maxMinusOne = max - one;
   1.132 +  const CheckedInt<T> maxMinusTwo = max - two;
   1.133 +  VERIFY_IS_VALID(maxMinusOne);
   1.134 +  VERIFY_IS_VALID(maxMinusTwo);
   1.135 +  VERIFY_IS_VALID(maxMinusOne + one);
   1.136 +  VERIFY_IS_VALID(maxMinusTwo + one);
   1.137 +  VERIFY_IS_VALID(maxMinusTwo + two);
   1.138 +  VERIFY(maxMinusOne + one == max);
   1.139 +  VERIFY(maxMinusTwo + one == maxMinusOne);
   1.140 +  VERIFY(maxMinusTwo + two == max);
   1.141 +
   1.142 +  VERIFY_IS_VALID(max + zero);
   1.143 +  VERIFY_IS_VALID(max - zero);
   1.144 +  VERIFY_IS_INVALID(max + one);
   1.145 +  VERIFY_IS_INVALID(max + two);
   1.146 +  VERIFY_IS_INVALID(max + maxMinusOne);
   1.147 +  VERIFY_IS_INVALID(max + max);
   1.148 +
   1.149 +  const CheckedInt<T> minPlusOne = min + one;
   1.150 +  const CheckedInt<T> minPlusTwo = min + two;
   1.151 +  VERIFY_IS_VALID(minPlusOne);
   1.152 +  VERIFY_IS_VALID(minPlusTwo);
   1.153 +  VERIFY_IS_VALID(minPlusOne - one);
   1.154 +  VERIFY_IS_VALID(minPlusTwo - one);
   1.155 +  VERIFY_IS_VALID(minPlusTwo - two);
   1.156 +  VERIFY(minPlusOne - one == min);
   1.157 +  VERIFY(minPlusTwo - one == minPlusOne);
   1.158 +  VERIFY(minPlusTwo - two == min);
   1.159 +
   1.160 +  const CheckedInt<T> minMinusOne = min - one;
   1.161 +  VERIFY_IS_VALID(min + zero);
   1.162 +  VERIFY_IS_VALID(min - zero);
   1.163 +  VERIFY_IS_INVALID(min - one);
   1.164 +  VERIFY_IS_INVALID(min - two);
   1.165 +  VERIFY_IS_INVALID(min - minMinusOne);
   1.166 +  VERIFY_IS_VALID(min - min);
   1.167 +
   1.168 +  const CheckedInt<T> maxOverTwo = max / two;
   1.169 +  VERIFY_IS_VALID(maxOverTwo + maxOverTwo);
   1.170 +  VERIFY_IS_VALID(maxOverTwo + one);
   1.171 +  VERIFY((maxOverTwo + one) - one == maxOverTwo);
   1.172 +  VERIFY_IS_VALID(maxOverTwo - maxOverTwo);
   1.173 +  VERIFY(maxOverTwo - maxOverTwo == zero);
   1.174 +
   1.175 +  const CheckedInt<T> minOverTwo = min / two;
   1.176 +  VERIFY_IS_VALID(minOverTwo + minOverTwo);
   1.177 +  VERIFY_IS_VALID(minOverTwo + one);
   1.178 +  VERIFY((minOverTwo + one) - one == minOverTwo);
   1.179 +  VERIFY_IS_VALID(minOverTwo - minOverTwo);
   1.180 +  VERIFY(minOverTwo - minOverTwo == zero);
   1.181 +
   1.182 +  VERIFY_IS_INVALID(min - one);
   1.183 +  VERIFY_IS_INVALID(min - two);
   1.184 +
   1.185 +  if (isTSigned) {
   1.186 +    VERIFY_IS_INVALID(min + min);
   1.187 +    VERIFY_IS_INVALID(minOverTwo + minOverTwo + minOverTwo);
   1.188 +    VERIFY_IS_INVALID(zero - min + min);
   1.189 +    VERIFY_IS_INVALID(one - min + min);
   1.190 +  }
   1.191 +
   1.192 +  /* Modulo checks */
   1.193 +  VERIFY_IS_INVALID(zero % zero);
   1.194 +  VERIFY_IS_INVALID(one % zero);
   1.195 +  VERIFY_IS_VALID(zero % one);
   1.196 +  VERIFY_IS_VALID(zero % max);
   1.197 +  VERIFY_IS_VALID(one % max);
   1.198 +  VERIFY_IS_VALID(max % one);
   1.199 +  VERIFY_IS_VALID(max % max);
   1.200 +  if (isTSigned) {
   1.201 +    const CheckedInt<T> minusOne = zero - one;
   1.202 +    VERIFY_IS_INVALID(minusOne % minusOne);
   1.203 +    VERIFY_IS_INVALID(zero % minusOne);
   1.204 +    VERIFY_IS_INVALID(one % minusOne);
   1.205 +    VERIFY_IS_INVALID(minusOne % one);
   1.206 +
   1.207 +    VERIFY_IS_INVALID(min % min);
   1.208 +    VERIFY_IS_INVALID(zero % min);
   1.209 +    VERIFY_IS_INVALID(min % one);
   1.210 +  }
   1.211 +
   1.212 +  /* Unary operator- checks */
   1.213 +
   1.214 +  const CheckedInt<T> negOne = -one;
   1.215 +  const CheckedInt<T> negTwo = -two;
   1.216 +
   1.217 +  if (isTSigned) {
   1.218 +    VERIFY_IS_VALID(-max);
   1.219 +    VERIFY_IS_INVALID(-min);
   1.220 +    VERIFY(-max - min == one);
   1.221 +    VERIFY_IS_VALID(-max - one);
   1.222 +    VERIFY_IS_VALID(negOne);
   1.223 +    VERIFY_IS_VALID(-max + negOne);
   1.224 +    VERIFY_IS_VALID(negOne + one);
   1.225 +    VERIFY(negOne + one == zero);
   1.226 +    VERIFY_IS_VALID(negTwo);
   1.227 +    VERIFY_IS_VALID(negOne + negOne);
   1.228 +    VERIFY(negOne + negOne == negTwo);
   1.229 +  } else {
   1.230 +    VERIFY_IS_INVALID(-max);
   1.231 +    VERIFY_IS_VALID(-min);
   1.232 +    VERIFY(min == zero);
   1.233 +    VERIFY_IS_INVALID(negOne);
   1.234 +  }
   1.235 +
   1.236 +  /* multiplication checks */
   1.237 +
   1.238 +  VERIFY_IS_VALID(zero * zero);
   1.239 +  VERIFY(zero * zero == zero);
   1.240 +  VERIFY_IS_VALID(zero * one);
   1.241 +  VERIFY(zero * one == zero);
   1.242 +  VERIFY_IS_VALID(one * zero);
   1.243 +  VERIFY(one * zero == zero);
   1.244 +  VERIFY_IS_VALID(one * one);
   1.245 +  VERIFY(one * one == one);
   1.246 +  VERIFY_IS_VALID(one * three);
   1.247 +  VERIFY(one * three == three);
   1.248 +  VERIFY_IS_VALID(two * two);
   1.249 +  VERIFY(two * two == four);
   1.250 +
   1.251 +  VERIFY_IS_INVALID(max * max);
   1.252 +  VERIFY_IS_INVALID(maxOverTwo * max);
   1.253 +  VERIFY_IS_INVALID(maxOverTwo * maxOverTwo);
   1.254 +
   1.255 +  const CheckedInt<T> maxApproxSqrt(T(T(1) << (CHAR_BIT*sizeof(T)/2)));
   1.256 +
   1.257 +  VERIFY_IS_VALID(maxApproxSqrt);
   1.258 +  VERIFY_IS_VALID(maxApproxSqrt * two);
   1.259 +  VERIFY_IS_INVALID(maxApproxSqrt * maxApproxSqrt);
   1.260 +  VERIFY_IS_INVALID(maxApproxSqrt * maxApproxSqrt * maxApproxSqrt);
   1.261 +
   1.262 +  if (isTSigned) {
   1.263 +    VERIFY_IS_INVALID(min * min);
   1.264 +    VERIFY_IS_INVALID(minOverTwo * min);
   1.265 +    VERIFY_IS_INVALID(minOverTwo * minOverTwo);
   1.266 +
   1.267 +    const CheckedInt<T> minApproxSqrt = -maxApproxSqrt;
   1.268 +
   1.269 +    VERIFY_IS_VALID(minApproxSqrt);
   1.270 +    VERIFY_IS_VALID(minApproxSqrt * two);
   1.271 +    VERIFY_IS_INVALID(minApproxSqrt * maxApproxSqrt);
   1.272 +    VERIFY_IS_INVALID(minApproxSqrt * minApproxSqrt);
   1.273 +  }
   1.274 +
   1.275 +  // make sure to check all 4 paths in signed multiplication validity check.
   1.276 +  // test positive * positive
   1.277 +  VERIFY_IS_VALID(max * one);
   1.278 +  VERIFY(max * one == max);
   1.279 +  VERIFY_IS_INVALID(max * two);
   1.280 +  VERIFY_IS_VALID(maxOverTwo * two);
   1.281 +  VERIFY((maxOverTwo + maxOverTwo) == (maxOverTwo * two));
   1.282 +
   1.283 +  if (isTSigned) {
   1.284 +    // test positive * negative
   1.285 +    VERIFY_IS_VALID(max * negOne);
   1.286 +    VERIFY_IS_VALID(-max);
   1.287 +    VERIFY(max * negOne == -max);
   1.288 +    VERIFY_IS_VALID(one * min);
   1.289 +    VERIFY_IS_INVALID(max * negTwo);
   1.290 +    VERIFY_IS_VALID(maxOverTwo * negTwo);
   1.291 +    VERIFY_IS_VALID(two * minOverTwo);
   1.292 +    VERIFY_IS_VALID((maxOverTwo + one) * negTwo);
   1.293 +    VERIFY_IS_INVALID((maxOverTwo + two) * negTwo);
   1.294 +    VERIFY_IS_INVALID(two * (minOverTwo - one));
   1.295 +
   1.296 +    // test negative * positive
   1.297 +    VERIFY_IS_VALID(min * one);
   1.298 +    VERIFY_IS_VALID(minPlusOne * one);
   1.299 +    VERIFY_IS_INVALID(min * two);
   1.300 +    VERIFY_IS_VALID(minOverTwo * two);
   1.301 +    VERIFY(minOverTwo * two == min);
   1.302 +    VERIFY_IS_INVALID((minOverTwo - one) * negTwo);
   1.303 +    VERIFY_IS_INVALID(negTwo * max);
   1.304 +    VERIFY_IS_VALID(minOverTwo * two);
   1.305 +    VERIFY(minOverTwo * two == min);
   1.306 +    VERIFY_IS_VALID(negTwo * maxOverTwo);
   1.307 +    VERIFY_IS_INVALID((minOverTwo - one) * two);
   1.308 +    VERIFY_IS_VALID(negTwo * (maxOverTwo + one));
   1.309 +    VERIFY_IS_INVALID(negTwo * (maxOverTwo + two));
   1.310 +
   1.311 +    // test negative * negative
   1.312 +    VERIFY_IS_INVALID(min * negOne);
   1.313 +    VERIFY_IS_VALID(minPlusOne * negOne);
   1.314 +    VERIFY(minPlusOne * negOne == max);
   1.315 +    VERIFY_IS_INVALID(min * negTwo);
   1.316 +    VERIFY_IS_INVALID(minOverTwo * negTwo);
   1.317 +    VERIFY_IS_INVALID(negOne * min);
   1.318 +    VERIFY_IS_VALID(negOne * minPlusOne);
   1.319 +    VERIFY(negOne * minPlusOne == max);
   1.320 +    VERIFY_IS_INVALID(negTwo * min);
   1.321 +    VERIFY_IS_INVALID(negTwo * minOverTwo);
   1.322 +  }
   1.323 +
   1.324 +  /* Division checks */
   1.325 +
   1.326 +  VERIFY_IS_VALID(one / one);
   1.327 +  VERIFY(one / one == one);
   1.328 +  VERIFY_IS_VALID(three / three);
   1.329 +  VERIFY(three / three == one);
   1.330 +  VERIFY_IS_VALID(four / two);
   1.331 +  VERIFY(four / two == two);
   1.332 +  VERIFY((four*three)/four == three);
   1.333 +
   1.334 +  // Check that div by zero is invalid
   1.335 +  VERIFY_IS_INVALID(zero / zero);
   1.336 +  VERIFY_IS_INVALID(one / zero);
   1.337 +  VERIFY_IS_INVALID(two / zero);
   1.338 +  VERIFY_IS_INVALID(negOne / zero);
   1.339 +  VERIFY_IS_INVALID(max / zero);
   1.340 +  VERIFY_IS_INVALID(min / zero);
   1.341 +
   1.342 +  if (isTSigned) {
   1.343 +    // Check that min / -1 is invalid
   1.344 +    VERIFY_IS_INVALID(min / negOne);
   1.345 +
   1.346 +    // Check that the test for div by -1 isn't banning other numerators than min
   1.347 +    VERIFY_IS_VALID(one / negOne);
   1.348 +    VERIFY_IS_VALID(zero / negOne);
   1.349 +    VERIFY_IS_VALID(negOne / negOne);
   1.350 +    VERIFY_IS_VALID(max / negOne);
   1.351 +  }
   1.352 +
   1.353 +  /* Check that invalidity is correctly preserved by arithmetic ops */
   1.354 +
   1.355 +  const CheckedInt<T> someInvalid = max + max;
   1.356 +  VERIFY_IS_INVALID(someInvalid + zero);
   1.357 +  VERIFY_IS_INVALID(someInvalid - zero);
   1.358 +  VERIFY_IS_INVALID(zero + someInvalid);
   1.359 +  VERIFY_IS_INVALID(zero - someInvalid);
   1.360 +  VERIFY_IS_INVALID(-someInvalid);
   1.361 +  VERIFY_IS_INVALID(someInvalid * zero);
   1.362 +  VERIFY_IS_INVALID(someInvalid * one);
   1.363 +  VERIFY_IS_INVALID(zero * someInvalid);
   1.364 +  VERIFY_IS_INVALID(one * someInvalid);
   1.365 +  VERIFY_IS_INVALID(someInvalid / zero);
   1.366 +  VERIFY_IS_INVALID(someInvalid / one);
   1.367 +  VERIFY_IS_INVALID(zero / someInvalid);
   1.368 +  VERIFY_IS_INVALID(one / someInvalid);
   1.369 +  VERIFY_IS_INVALID(someInvalid % zero);
   1.370 +  VERIFY_IS_INVALID(someInvalid % one);
   1.371 +  VERIFY_IS_INVALID(zero % someInvalid);
   1.372 +  VERIFY_IS_INVALID(one % someInvalid);
   1.373 +  VERIFY_IS_INVALID(someInvalid + someInvalid);
   1.374 +  VERIFY_IS_INVALID(someInvalid - someInvalid);
   1.375 +  VERIFY_IS_INVALID(someInvalid * someInvalid);
   1.376 +  VERIFY_IS_INVALID(someInvalid / someInvalid);
   1.377 +  VERIFY_IS_INVALID(someInvalid % someInvalid);
   1.378 +
   1.379 +  /* Check that mixing checked integers with plain integers in expressions is allowed */
   1.380 +
   1.381 +  VERIFY(one + T(2) == three);
   1.382 +  VERIFY(2 + one == three);
   1.383 +  {
   1.384 +    CheckedInt<T> x = one;
   1.385 +    x += 2;
   1.386 +    VERIFY(x == three);
   1.387 +  }
   1.388 +  VERIFY(two - 1 == one);
   1.389 +  VERIFY(2 - one == one);
   1.390 +  {
   1.391 +    CheckedInt<T> x = two;
   1.392 +    x -= 1;
   1.393 +    VERIFY(x == one);
   1.394 +  }
   1.395 +  VERIFY(one * 2 == two);
   1.396 +  VERIFY(2 * one == two);
   1.397 +  {
   1.398 +    CheckedInt<T> x = one;
   1.399 +    x *= 2;
   1.400 +    VERIFY(x == two);
   1.401 +  }
   1.402 +  VERIFY(four / 2 == two);
   1.403 +  VERIFY(4 / two == two);
   1.404 +  {
   1.405 +    CheckedInt<T> x = four;
   1.406 +    x /= 2;
   1.407 +    VERIFY(x == two);
   1.408 +  }
   1.409 +  VERIFY(three % 2 == one);
   1.410 +  VERIFY(3 % two == one);
   1.411 +  {
   1.412 +    CheckedInt<T> x = three;
   1.413 +    x %= 2;
   1.414 +    VERIFY(x == one);
   1.415 +  }
   1.416 +
   1.417 +  VERIFY(one == 1);
   1.418 +  VERIFY(1 == one);
   1.419 +  VERIFY_IS_FALSE(two == 1);
   1.420 +  VERIFY_IS_FALSE(1 == two);
   1.421 +  VERIFY_IS_FALSE(someInvalid == 1);
   1.422 +  VERIFY_IS_FALSE(1 == someInvalid);
   1.423 +
   1.424 +  // Check simple casting between different signedness and sizes.
   1.425 +  {
   1.426 +    CheckedInt<uint8_t> foo = CheckedInt<uint16_t>(2).toChecked<uint8_t>();
   1.427 +    VERIFY_IS_VALID(foo);
   1.428 +    VERIFY(foo == 2);
   1.429 +  }
   1.430 +  {
   1.431 +    CheckedInt<uint8_t> foo = CheckedInt<uint16_t>(255).toChecked<uint8_t>();
   1.432 +    VERIFY_IS_VALID(foo);
   1.433 +    VERIFY(foo == 255);
   1.434 +  }
   1.435 +  {
   1.436 +    CheckedInt<uint8_t> foo = CheckedInt<uint16_t>(256).toChecked<uint8_t>();
   1.437 +    VERIFY_IS_INVALID(foo);
   1.438 +  }
   1.439 +  {
   1.440 +    CheckedInt<uint8_t> foo = CheckedInt<int8_t>(-2).toChecked<uint8_t>();
   1.441 +    VERIFY_IS_INVALID(foo);
   1.442 +  }
   1.443 +
   1.444 +  // Check that construction of CheckedInt from an integer value of a mismatched type is checked
   1.445 +  // Also check casting between all types.
   1.446 +
   1.447 +  #define VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE2(U,V,PostVExpr) \
   1.448 +  { \
   1.449 +    bool isUSigned = IsSigned<U>::value; \
   1.450 +    VERIFY_IS_VALID(CheckedInt<T>(V(  0)PostVExpr)); \
   1.451 +    VERIFY_IS_VALID(CheckedInt<T>(V(  1)PostVExpr)); \
   1.452 +    VERIFY_IS_VALID(CheckedInt<T>(V(100)PostVExpr)); \
   1.453 +    if (isUSigned) \
   1.454 +      VERIFY_IS_VALID_IF(CheckedInt<T>(V(-1)PostVExpr), isTSigned); \
   1.455 +    if (sizeof(U) > sizeof(T)) \
   1.456 +      VERIFY_IS_INVALID(CheckedInt<T>(V(MaxValue<T>::value)PostVExpr + one.value())); \
   1.457 +    VERIFY_IS_VALID_IF(CheckedInt<T>(MaxValue<U>::value), \
   1.458 +      (sizeof(T) > sizeof(U) || ((sizeof(T) == sizeof(U)) && (isUSigned || !isTSigned)))); \
   1.459 +    VERIFY_IS_VALID_IF(CheckedInt<T>(MinValue<U>::value), \
   1.460 +      isUSigned == false ? 1 \
   1.461 +                         : bool(isTSigned) == false ? 0 \
   1.462 +                                                    : sizeof(T) >= sizeof(U)); \
   1.463 +  }
   1.464 +  #define VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(U) \
   1.465 +    VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE2(U,U,+0) \
   1.466 +    VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE2(U,CheckedInt<U>,.toChecked<T>())
   1.467 +
   1.468 +  VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int8_t)
   1.469 +  VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(uint8_t)
   1.470 +  VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int16_t)
   1.471 +  VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(uint16_t)
   1.472 +  VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int32_t)
   1.473 +  VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(uint32_t)
   1.474 +  VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int64_t)
   1.475 +  VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(uint64_t)
   1.476 +
   1.477 +  typedef signed char signedChar;
   1.478 +  typedef unsigned char unsignedChar;
   1.479 +  typedef unsigned short unsignedShort;
   1.480 +  typedef unsigned int  unsignedInt;
   1.481 +  typedef unsigned long unsignedLong;
   1.482 +  typedef long long longLong;
   1.483 +  typedef unsigned long long unsignedLongLong;
   1.484 +
   1.485 +  VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(char)
   1.486 +  VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(signedChar)
   1.487 +  VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(unsignedChar)
   1.488 +  VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(short)
   1.489 +  VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(unsignedShort)
   1.490 +  VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int)
   1.491 +  VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(unsignedInt)
   1.492 +  VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(long)
   1.493 +  VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(unsignedLong)
   1.494 +  VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(longLong)
   1.495 +  VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(unsignedLongLong)
   1.496 +
   1.497 +  /* Test increment/decrement operators */
   1.498 +
   1.499 +  CheckedInt<T> x, y;
   1.500 +  x = one;
   1.501 +  y = x++;
   1.502 +  VERIFY(x == two);
   1.503 +  VERIFY(y == one);
   1.504 +  x = one;
   1.505 +  y = ++x;
   1.506 +  VERIFY(x == two);
   1.507 +  VERIFY(y == two);
   1.508 +  x = one;
   1.509 +  y = x--;
   1.510 +  VERIFY(x == zero);
   1.511 +  VERIFY(y == one);
   1.512 +  x = one;
   1.513 +  y = --x;
   1.514 +  VERIFY(x == zero);
   1.515 +  VERIFY(y == zero);
   1.516 +  x = max;
   1.517 +  VERIFY_IS_VALID(x++);
   1.518 +  x = max;
   1.519 +  VERIFY_IS_INVALID(++x);
   1.520 +  x = min;
   1.521 +  VERIFY_IS_VALID(x--);
   1.522 +  x = min;
   1.523 +  VERIFY_IS_INVALID(--x);
   1.524 +
   1.525 +  gIntegerTypesTested++;
   1.526 +}
   1.527 +
   1.528 +int main()
   1.529 +{
   1.530 +  test<int8_t>();
   1.531 +  test<uint8_t>();
   1.532 +  test<int16_t>();
   1.533 +  test<uint16_t>();
   1.534 +  test<int32_t>();
   1.535 +  test<uint32_t>();
   1.536 +  test<int64_t>();
   1.537 +  test<uint64_t>();
   1.538 +
   1.539 +  test<char>();
   1.540 +  test<signed char>();
   1.541 +  test<unsigned char>();
   1.542 +  test<short>();
   1.543 +  test<unsigned short>();
   1.544 +  test<int>();
   1.545 +  test<unsigned int>();
   1.546 +  test<long>();
   1.547 +  test<unsigned long>();
   1.548 +  test<long long>();
   1.549 +  test<unsigned long long>();
   1.550 +
   1.551 +  const int MIN_TYPES_TESTED = 9;
   1.552 +  if (gIntegerTypesTested < MIN_TYPES_TESTED) {
   1.553 +    std::cerr << "Only " << gIntegerTypesTested << " have been tested. "
   1.554 +              << "This should not be less than " << MIN_TYPES_TESTED << "."
   1.555 +              << std::endl;
   1.556 +    gTestsFailed++;
   1.557 +  }
   1.558 +
   1.559 +  std::cerr << gTestsFailed << " tests failed, "
   1.560 +            << gTestsPassed << " tests passed out of "
   1.561 +            << gTestsFailed + gTestsPassed
   1.562 +            << " tests, covering " << gIntegerTypesTested
   1.563 +            << " distinct integer types." << std::endl;
   1.564 +
   1.565 +  return gTestsFailed > 0;
   1.566 +}

mercurial