Bug 1879774 [wpt PR 44524] - WebKit export: Implement field-sizing support for input...
[gecko.git] / mfbt / tests / TestSaturate.cpp
blob500c9eed7f3bf444724a2e33b7a37adbb7b96871
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/. */
7 #include <mozilla/Saturate.h>
9 #include <mozilla/Assertions.h>
11 #include <limits>
13 using mozilla::detail::Saturate;
15 #define A(a) MOZ_RELEASE_ASSERT(a, "Test \'" #a "\' failed.")
17 static const unsigned long sNumOps = 32;
19 template <typename T>
20 static T StartValue() {
21 // Specialize |StartValue| for the given type.
22 A(false);
25 template <>
26 int8_t StartValue<int8_t>() {
27 return 0;
30 template <>
31 int16_t StartValue<int16_t>() {
32 return 0;
35 template <>
36 int32_t StartValue<int32_t>() {
37 return 0;
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());
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());
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());
58 // Add
61 template <typename T>
62 static void TestPrefixIncr() {
63 T value = StartValue<T>();
64 Saturate<T> satValue(value);
66 for (T i = 0; i < static_cast<T>(sNumOps); ++i) {
67 A(++value == ++satValue);
71 template <typename T>
72 static void TestPostfixIncr() {
73 T value = StartValue<T>();
74 Saturate<T> satValue(value);
76 for (T i = 0; i < static_cast<T>(sNumOps); ++i) {
77 A(value++ == satValue++);
81 template <typename T>
82 static void TestAdd() {
83 T value = StartValue<T>();
84 Saturate<T> satValue(value);
86 for (T i = 0; i < static_cast<T>(sNumOps); ++i) {
87 A((value + i) == (satValue + i));
91 // Subtract
94 template <typename T>
95 static void TestPrefixDecr() {
96 T value = StartValue<T>();
97 Saturate<T> satValue(value);
99 for (T i = 0; i < static_cast<T>(sNumOps); ++i) {
100 A(--value == --satValue);
104 template <typename T>
105 static void TestPostfixDecr() {
106 T value = StartValue<T>();
107 Saturate<T> satValue(value);
109 for (T i = 0; i < static_cast<T>(sNumOps); ++i) {
110 A(value-- == satValue--);
114 template <typename T>
115 static void TestSub() {
116 T value = StartValue<T>();
117 Saturate<T> satValue(value);
119 for (T i = 0; i < static_cast<T>(sNumOps); ++i) {
120 A((value - i) == (satValue - i));
124 // Corner cases near bounds
127 template <typename T>
128 static void TestUpperBound() {
129 Saturate<T> satValue(std::numeric_limits<T>::max());
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));
139 template <typename T>
140 static void TestLowerBound() {
141 Saturate<T> satValue(std::numeric_limits<T>::min());
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));
151 // Framework
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);
161 TestPrefixIncr<T>();
162 TestPostfixIncr<T>();
163 TestAdd<T>();
165 TestPrefixDecr<T>();
166 TestPostfixDecr<T>();
167 TestSub<T>();
169 TestUpperBound<T>();
170 TestLowerBound<T>();
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;