tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestSaturate.cpp (4302B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include <mozilla/Saturate.h>
      8 
      9 #include <mozilla/Assertions.h>
     10 
     11 #include <limits>
     12 
     13 using mozilla::detail::Saturate;
     14 
     15 #define A(a) MOZ_RELEASE_ASSERT(a, "Test \'" #a "\'  failed.")
     16 
     17 static const unsigned long sNumOps = 32;
     18 
     19 template <typename T>
     20 static T StartValue() {
     21  // Specialize |StartValue| for the given type.
     22  A(false);
     23 }
     24 
     25 template <>
     26 int8_t StartValue<int8_t>() {
     27  return 0;
     28 }
     29 
     30 template <>
     31 int16_t StartValue<int16_t>() {
     32  return 0;
     33 }
     34 
     35 template <>
     36 int32_t StartValue<int32_t>() {
     37  return 0;
     38 }
     39 
     40 template <>
     41 uint8_t StartValue<uint8_t>() {
     42  // Picking a value near middle of uint8_t's range.
     43  return static_cast<uint8_t>(std::numeric_limits<int8_t>::max());
     44 }
     45 
     46 template <>
     47 uint16_t StartValue<uint16_t>() {
     48  // Picking a value near middle of uint16_t's range.
     49  return static_cast<uint8_t>(std::numeric_limits<int16_t>::max());
     50 }
     51 
     52 template <>
     53 uint32_t StartValue<uint32_t>() {
     54  // Picking a value near middle of uint32_t's range.
     55  return static_cast<uint8_t>(std::numeric_limits<int32_t>::max());
     56 }
     57 
     58 // Add
     59 //
     60 
     61 template <typename T>
     62 static void TestPrefixIncr() {
     63  T value = StartValue<T>();
     64  Saturate<T> satValue(value);
     65 
     66  for (T i = 0; i < static_cast<T>(sNumOps); ++i) {
     67    A(++value == ++satValue);
     68  }
     69 }
     70 
     71 template <typename T>
     72 static void TestPostfixIncr() {
     73  T value = StartValue<T>();
     74  Saturate<T> satValue(value);
     75 
     76  for (T i = 0; i < static_cast<T>(sNumOps); ++i) {
     77    A(value++ == satValue++);
     78  }
     79 }
     80 
     81 template <typename T>
     82 static void TestAdd() {
     83  T value = StartValue<T>();
     84  Saturate<T> satValue(value);
     85 
     86  for (T i = 0; i < static_cast<T>(sNumOps); ++i) {
     87    A((value + i) == (satValue + i));
     88  }
     89 }
     90 
     91 // Subtract
     92 //
     93 
     94 template <typename T>
     95 static void TestPrefixDecr() {
     96  T value = StartValue<T>();
     97  Saturate<T> satValue(value);
     98 
     99  for (T i = 0; i < static_cast<T>(sNumOps); ++i) {
    100    A(--value == --satValue);
    101  }
    102 }
    103 
    104 template <typename T>
    105 static void TestPostfixDecr() {
    106  T value = StartValue<T>();
    107  Saturate<T> satValue(value);
    108 
    109  for (T i = 0; i < static_cast<T>(sNumOps); ++i) {
    110    A(value-- == satValue--);
    111  }
    112 }
    113 
    114 template <typename T>
    115 static void TestSub() {
    116  T value = StartValue<T>();
    117  Saturate<T> satValue(value);
    118 
    119  for (T i = 0; i < static_cast<T>(sNumOps); ++i) {
    120    A((value - i) == (satValue - i));
    121  }
    122 }
    123 
    124 // Corner cases near bounds
    125 //
    126 
    127 template <typename T>
    128 static void TestUpperBound() {
    129  Saturate<T> satValue(std::numeric_limits<T>::max());
    130 
    131  A(--satValue == (std::numeric_limits<T>::max() - 1));
    132  A(++satValue == (std::numeric_limits<T>::max()));
    133  A(++satValue == (std::numeric_limits<T>::max()));      // don't overflow here
    134  A(++satValue == (std::numeric_limits<T>::max()));      // don't overflow here
    135  A(--satValue == (std::numeric_limits<T>::max() - 1));  // back at (max - 1)
    136  A(--satValue == (std::numeric_limits<T>::max() - 2));
    137 }
    138 
    139 template <typename T>
    140 static void TestLowerBound() {
    141  Saturate<T> satValue(std::numeric_limits<T>::min());
    142 
    143  A(++satValue == (std::numeric_limits<T>::min() + 1));
    144  A(--satValue == (std::numeric_limits<T>::min()));
    145  A(--satValue == (std::numeric_limits<T>::min()));      // don't overflow here
    146  A(--satValue == (std::numeric_limits<T>::min()));      // don't overflow here
    147  A(++satValue == (std::numeric_limits<T>::min() + 1));  // back at (max + 1)
    148  A(++satValue == (std::numeric_limits<T>::min() + 2));
    149 }
    150 
    151 // Framework
    152 //
    153 
    154 template <typename T>
    155 static void TestAll() {
    156  // Assert that we don't accidently hit type's range limits in tests.
    157  const T value = StartValue<T>();
    158  A(std::numeric_limits<T>::min() + static_cast<T>(sNumOps) <= value);
    159  A(std::numeric_limits<T>::max() - static_cast<T>(sNumOps) >= value);
    160 
    161  TestPrefixIncr<T>();
    162  TestPostfixIncr<T>();
    163  TestAdd<T>();
    164 
    165  TestPrefixDecr<T>();
    166  TestPostfixDecr<T>();
    167  TestSub<T>();
    168 
    169  TestUpperBound<T>();
    170  TestLowerBound<T>();
    171 }
    172 
    173 int main() {
    174  TestAll<int8_t>();
    175  TestAll<int16_t>();
    176  TestAll<int32_t>();
    177  TestAll<uint8_t>();
    178  TestAll<uint16_t>();
    179  TestAll<uint32_t>();
    180  return 0;
    181 }