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>
13 using mozilla::detail::Saturate
;
15 #define A(a) MOZ_RELEASE_ASSERT(a, "Test \'" #a "\' failed.")
17 static const unsigned long sNumOps
= 32;
20 static T
StartValue() {
21 // Specialize |StartValue| for the given type.
26 int8_t StartValue
<int8_t>() {
31 int16_t StartValue
<int16_t>() {
36 int32_t StartValue
<int32_t>() {
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());
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());
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());
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
);
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
++);
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
));
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));
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
);
162 TestPostfixIncr
<T
>();
166 TestPostfixDecr
<T
>();