blob: 81873ea2eba76976d045d968a2b6255a571fbd2b [file] [log] [blame]
scottmg@chromium.org347c3652013-01-17 08:34:04 +09001// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +09005#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS)
6#include <mmintrin.h>
7#endif
jschuh@chromium.orgecd46052014-01-16 15:57:25 +09008#include <stdint.h>
9
10#include <limits>
11
12#include "base/compiler_specific.h"
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +090013#include "base/numerics/safe_conversions.h"
14#include "base/numerics/safe_math.h"
15#include "base/template_util.h"
jschuh@chromium.orgecd46052014-01-16 15:57:25 +090016#include "testing/gtest/include/gtest/gtest.h"
17
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +090018using std::numeric_limits;
19using base::CheckedNumeric;
20using base::checked_cast;
jschuh5f9a10b2015-09-15 05:21:24 +090021using base::IsValueInRangeForNumericType;
jschuh5131e452015-09-23 07:13:36 +090022using base::IsValueNegative;
jschuh7940ae92015-05-28 11:29:25 +090023using base::SizeT;
24using base::StrictNumeric;
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +090025using base::saturated_cast;
jschuh7940ae92015-05-28 11:29:25 +090026using base::strict_cast;
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +090027using base::internal::MaxExponent;
28using base::internal::RANGE_VALID;
29using base::internal::RANGE_INVALID;
30using base::internal::RANGE_OVERFLOW;
31using base::internal::RANGE_UNDERFLOW;
jschuh02b9ef62015-09-17 10:04:28 +090032using base::internal::SignedIntegerForSize;
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +090033using base::enable_if;
34
ncbray@chromium.org62bf6ba2014-08-09 14:24:02 +090035// These tests deliberately cause arithmetic overflows. If the compiler is
36// aggressive enough, it can const fold these overflows. Disable warnings about
37// overflows for const expressions.
38#if defined(OS_WIN)
39#pragma warning(disable:4756)
40#endif
41
jschuh5f9a10b2015-09-15 05:21:24 +090042// This is a helper function for finding the maximum value in Src that can be
43// wholy represented as the destination floating-point type.
44template <typename Dst, typename Src>
45Dst GetMaxConvertibleToFloat() {
46 typedef numeric_limits<Dst> DstLimits;
47 typedef numeric_limits<Src> SrcLimits;
48 static_assert(SrcLimits::is_specialized, "Source must be numeric.");
49 static_assert(DstLimits::is_specialized, "Destination must be numeric.");
50 CHECK(DstLimits::is_iec559);
51
52 if (SrcLimits::digits <= DstLimits::digits &&
53 MaxExponent<Src>::value <= MaxExponent<Dst>::value)
54 return SrcLimits::max();
55 Src max = SrcLimits::max() / 2 + (SrcLimits::is_integer ? 1 : 0);
56 while (max != static_cast<Src>(static_cast<Dst>(max))) {
57 max /= 2;
58 }
59 return static_cast<Dst>(max);
60}
61
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +090062// Helper macros to wrap displaying the conversion types and line numbers.
63#define TEST_EXPECTED_VALIDITY(expected, actual) \
64 EXPECT_EQ(expected, CheckedNumeric<Dst>(actual).validity()) \
65 << "Result test: Value " << +(actual).ValueUnsafe() << " as " << dst \
66 << " on line " << line;
67
68#define TEST_EXPECTED_VALUE(expected, actual) \
69 EXPECT_EQ(static_cast<Dst>(expected), \
70 CheckedNumeric<Dst>(actual).ValueUnsafe()) \
71 << "Result test: Value " << +((actual).ValueUnsafe()) << " as " << dst \
72 << " on line " << line;
73
74// Signed integer arithmetic.
75template <typename Dst>
76static void TestSpecializedArithmetic(
77 const char* dst,
78 int line,
79 typename enable_if<
80 numeric_limits<Dst>::is_integer&& numeric_limits<Dst>::is_signed,
81 int>::type = 0) {
82 typedef numeric_limits<Dst> DstLimits;
83 TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW,
84 -CheckedNumeric<Dst>(DstLimits::min()));
85 TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW,
86 CheckedNumeric<Dst>(DstLimits::min()).Abs());
87 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
88
89 TEST_EXPECTED_VALIDITY(RANGE_VALID,
90 CheckedNumeric<Dst>(DstLimits::max()) + -1);
91 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW,
92 CheckedNumeric<Dst>(DstLimits::min()) + -1);
93 TEST_EXPECTED_VALIDITY(
94 RANGE_UNDERFLOW,
95 CheckedNumeric<Dst>(-DstLimits::max()) + -DstLimits::max());
96
97 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW,
98 CheckedNumeric<Dst>(DstLimits::min()) - 1);
99 TEST_EXPECTED_VALIDITY(RANGE_VALID,
100 CheckedNumeric<Dst>(DstLimits::min()) - -1);
101 TEST_EXPECTED_VALIDITY(
102 RANGE_OVERFLOW,
103 CheckedNumeric<Dst>(DstLimits::max()) - -DstLimits::max());
104 TEST_EXPECTED_VALIDITY(
105 RANGE_UNDERFLOW,
106 CheckedNumeric<Dst>(-DstLimits::max()) - DstLimits::max());
107
108 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW,
109 CheckedNumeric<Dst>(DstLimits::min()) * 2);
110
111 TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW,
112 CheckedNumeric<Dst>(DstLimits::min()) / -1);
113 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) / 2);
114
115 // Modulus is legal only for integers.
116 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
117 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
118 TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % 2);
119 TEST_EXPECTED_VALIDITY(RANGE_INVALID, CheckedNumeric<Dst>(-1) % -2);
120 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) % 2);
121 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
122 // Test all the different modulus combinations.
123 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
124 TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
125 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
126 CheckedNumeric<Dst> checked_dst = 1;
127 TEST_EXPECTED_VALUE(0, checked_dst %= 1);
128}
129
130// Unsigned integer arithmetic.
131template <typename Dst>
132static void TestSpecializedArithmetic(
133 const char* dst,
134 int line,
135 typename enable_if<
136 numeric_limits<Dst>::is_integer && !numeric_limits<Dst>::is_signed,
137 int>::type = 0) {
138 typedef numeric_limits<Dst> DstLimits;
139 TEST_EXPECTED_VALIDITY(RANGE_VALID, -CheckedNumeric<Dst>(DstLimits::min()));
140 TEST_EXPECTED_VALIDITY(RANGE_VALID,
141 CheckedNumeric<Dst>(DstLimits::min()).Abs());
142 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW,
143 CheckedNumeric<Dst>(DstLimits::min()) + -1);
144 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW,
145 CheckedNumeric<Dst>(DstLimits::min()) - 1);
146 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) * 2);
147 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) / 2);
jschuh02b9ef62015-09-17 10:04:28 +0900148 TEST_EXPECTED_VALIDITY(RANGE_VALID,
149 CheckedNumeric<Dst>(DstLimits::min()).UnsignedAbs());
150 TEST_EXPECTED_VALIDITY(
151 RANGE_VALID,
152 CheckedNumeric<typename SignedIntegerForSize<Dst>::type>(
153 std::numeric_limits<typename SignedIntegerForSize<Dst>::type>::min())
154 .UnsignedAbs());
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900155
156 // Modulus is legal only for integers.
157 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
158 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
159 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % 2);
160 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) % 2);
161 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
162 // Test all the different modulus combinations.
163 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
164 TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
165 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
166 CheckedNumeric<Dst> checked_dst = 1;
167 TEST_EXPECTED_VALUE(0, checked_dst %= 1);
168}
169
170// Floating point arithmetic.
171template <typename Dst>
172void TestSpecializedArithmetic(
173 const char* dst,
174 int line,
175 typename enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0) {
176 typedef numeric_limits<Dst> DstLimits;
177 TEST_EXPECTED_VALIDITY(RANGE_VALID, -CheckedNumeric<Dst>(DstLimits::min()));
178
179 TEST_EXPECTED_VALIDITY(RANGE_VALID,
180 CheckedNumeric<Dst>(DstLimits::min()).Abs());
181 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
182
183 TEST_EXPECTED_VALIDITY(RANGE_VALID,
184 CheckedNumeric<Dst>(DstLimits::min()) + -1);
185 TEST_EXPECTED_VALIDITY(RANGE_VALID,
186 CheckedNumeric<Dst>(DstLimits::max()) + 1);
187 TEST_EXPECTED_VALIDITY(
188 RANGE_UNDERFLOW,
189 CheckedNumeric<Dst>(-DstLimits::max()) + -DstLimits::max());
190
191 TEST_EXPECTED_VALIDITY(
192 RANGE_OVERFLOW,
193 CheckedNumeric<Dst>(DstLimits::max()) - -DstLimits::max());
194 TEST_EXPECTED_VALIDITY(
195 RANGE_UNDERFLOW,
196 CheckedNumeric<Dst>(-DstLimits::max()) - DstLimits::max());
197
198 TEST_EXPECTED_VALIDITY(RANGE_VALID,
199 CheckedNumeric<Dst>(DstLimits::min()) * 2);
200
201 TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2);
202 EXPECT_EQ(static_cast<Dst>(1.0), CheckedNumeric<Dst>(1.0).ValueFloating());
203}
204
205// Generic arithmetic tests.
206template <typename Dst>
207static void TestArithmetic(const char* dst, int line) {
208 typedef numeric_limits<Dst> DstLimits;
209
210 EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid());
211 EXPECT_EQ(false,
212 CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
213 DstLimits::max()).IsValid());
214 EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDie());
215 EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDefault(1));
216 EXPECT_EQ(static_cast<Dst>(1),
217 CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
218 DstLimits::max()).ValueOrDefault(1));
219
220 // Test the operator combinations.
221 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + CheckedNumeric<Dst>(1));
222 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - CheckedNumeric<Dst>(1));
223 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * CheckedNumeric<Dst>(1));
224 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / CheckedNumeric<Dst>(1));
225 TEST_EXPECTED_VALUE(2, 1 + CheckedNumeric<Dst>(1));
226 TEST_EXPECTED_VALUE(0, 1 - CheckedNumeric<Dst>(1));
227 TEST_EXPECTED_VALUE(1, 1 * CheckedNumeric<Dst>(1));
228 TEST_EXPECTED_VALUE(1, 1 / CheckedNumeric<Dst>(1));
229 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + 1);
230 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - 1);
231 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * 1);
232 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
233 CheckedNumeric<Dst> checked_dst = 1;
234 TEST_EXPECTED_VALUE(2, checked_dst += 1);
235 checked_dst = 1;
236 TEST_EXPECTED_VALUE(0, checked_dst -= 1);
237 checked_dst = 1;
238 TEST_EXPECTED_VALUE(1, checked_dst *= 1);
239 checked_dst = 1;
240 TEST_EXPECTED_VALUE(1, checked_dst /= 1);
241
242 // Generic negation.
243 TEST_EXPECTED_VALUE(0, -CheckedNumeric<Dst>());
244 TEST_EXPECTED_VALUE(-1, -CheckedNumeric<Dst>(1));
245 TEST_EXPECTED_VALUE(1, -CheckedNumeric<Dst>(-1));
246 TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1),
247 -CheckedNumeric<Dst>(DstLimits::max()));
248
249 // Generic absolute value.
250 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>().Abs());
251 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).Abs());
252 TEST_EXPECTED_VALUE(DstLimits::max(),
253 CheckedNumeric<Dst>(DstLimits::max()).Abs());
254
255 // Generic addition.
256 TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>() + 1));
257 TEST_EXPECTED_VALUE(2, (CheckedNumeric<Dst>(1) + 1));
258 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) + 1));
259 TEST_EXPECTED_VALIDITY(RANGE_VALID,
260 CheckedNumeric<Dst>(DstLimits::min()) + 1);
261 TEST_EXPECTED_VALIDITY(
262 RANGE_OVERFLOW, CheckedNumeric<Dst>(DstLimits::max()) + DstLimits::max());
263
264 // Generic subtraction.
265 TEST_EXPECTED_VALUE(-1, (CheckedNumeric<Dst>() - 1));
266 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(1) - 1));
267 TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) - 1));
268 TEST_EXPECTED_VALIDITY(RANGE_VALID,
269 CheckedNumeric<Dst>(DstLimits::max()) - 1);
270
271 // Generic multiplication.
272 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>() * 1));
273 TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>(1) * 1));
274 TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) * 2));
eromanbdace952015-05-18 23:44:32 +0900275 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * 0));
276 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) * 0));
277 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * -1));
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900278 TEST_EXPECTED_VALIDITY(
279 RANGE_OVERFLOW, CheckedNumeric<Dst>(DstLimits::max()) * DstLimits::max());
280
281 // Generic division.
282 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() / 1);
283 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
284 TEST_EXPECTED_VALUE(DstLimits::min() / 2,
285 CheckedNumeric<Dst>(DstLimits::min()) / 2);
286 TEST_EXPECTED_VALUE(DstLimits::max() / 2,
287 CheckedNumeric<Dst>(DstLimits::max()) / 2);
288
289 TestSpecializedArithmetic<Dst>(dst, line);
290}
291
292// Helper macro to wrap displaying the conversion types and line numbers.
293#define TEST_ARITHMETIC(Dst) TestArithmetic<Dst>(#Dst, __LINE__)
294
295TEST(SafeNumerics, SignedIntegerMath) {
296 TEST_ARITHMETIC(int8_t);
297 TEST_ARITHMETIC(int);
298 TEST_ARITHMETIC(intptr_t);
299 TEST_ARITHMETIC(intmax_t);
300}
301
302TEST(SafeNumerics, UnsignedIntegerMath) {
303 TEST_ARITHMETIC(uint8_t);
304 TEST_ARITHMETIC(unsigned int);
305 TEST_ARITHMETIC(uintptr_t);
306 TEST_ARITHMETIC(uintmax_t);
307}
308
309TEST(SafeNumerics, FloatingPointMath) {
310 TEST_ARITHMETIC(float);
311 TEST_ARITHMETIC(double);
312}
scottmg@chromium.org347c3652013-01-17 08:34:04 +0900313
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900314// Enumerates the five different conversions types we need to test.
315enum NumericConversionType {
316 SIGN_PRESERVING_VALUE_PRESERVING,
317 SIGN_PRESERVING_NARROW,
318 SIGN_TO_UNSIGN_WIDEN_OR_EQUAL,
319 SIGN_TO_UNSIGN_NARROW,
320 UNSIGN_TO_SIGN_NARROW_OR_EQUAL,
321};
scottmg@chromium.org347c3652013-01-17 08:34:04 +0900322
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900323// Template covering the different conversion tests.
324template <typename Dst, typename Src, NumericConversionType conversion>
325struct TestNumericConversion {};
scottmg@chromium.org347c3652013-01-17 08:34:04 +0900326
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900327// EXPECT_EQ wrappers providing specific detail on test failures.
328#define TEST_EXPECTED_RANGE(expected, actual) \
329 EXPECT_EQ(expected, base::internal::DstRangeRelationToSrcRange<Dst>(actual)) \
330 << "Conversion test: " << src << " value " << actual << " to " << dst \
331 << " on line " << line;
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900332
333template <typename Dst, typename Src>
334struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> {
335 static void Test(const char *dst, const char *src, int line) {
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900336 typedef numeric_limits<Src> SrcLimits;
337 typedef numeric_limits<Dst> DstLimits;
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900338 // Integral to floating.
jschuhd80eded2014-10-14 23:31:37 +0900339 static_assert((DstLimits::is_iec559 && SrcLimits::is_integer) ||
340 // Not floating to integral and...
341 (!(DstLimits::is_integer && SrcLimits::is_iec559) &&
342 // Same sign, same numeric, source is narrower or same.
343 ((SrcLimits::is_signed == DstLimits::is_signed &&
344 sizeof(Dst) >= sizeof(Src)) ||
345 // Or signed destination and source is smaller
346 (DstLimits::is_signed && sizeof(Dst) > sizeof(Src)))),
347 "Comparison must be sign preserving and value preserving");
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900348
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900349 const CheckedNumeric<Dst> checked_dst = SrcLimits::max();
350 ;
351 TEST_EXPECTED_VALIDITY(RANGE_VALID, checked_dst);
352 if (MaxExponent<Dst>::value > MaxExponent<Src>::value) {
353 if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1) {
354 // At least twice larger type.
355 TEST_EXPECTED_VALIDITY(RANGE_VALID, SrcLimits::max() * checked_dst);
356
357 } else { // Larger, but not at least twice as large.
358 TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, SrcLimits::max() * checked_dst);
359 TEST_EXPECTED_VALIDITY(RANGE_VALID, checked_dst + 1);
360 }
361 } else { // Same width type.
362 TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, checked_dst + 1);
363 }
364
365 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
366 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900367 if (SrcLimits::is_iec559) {
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900368 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max() * static_cast<Src>(-1));
369 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
370 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
371 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900372 } else if (numeric_limits<Src>::is_signed) {
373 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
374 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900375 }
scottmg@chromium.org347c3652013-01-17 08:34:04 +0900376 }
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900377};
378
379template <typename Dst, typename Src>
380struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> {
381 static void Test(const char *dst, const char *src, int line) {
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900382 typedef numeric_limits<Src> SrcLimits;
383 typedef numeric_limits<Dst> DstLimits;
jschuhd80eded2014-10-14 23:31:37 +0900384 static_assert(SrcLimits::is_signed == DstLimits::is_signed,
385 "Destination and source sign must be the same");
386 static_assert(sizeof(Dst) < sizeof(Src) ||
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900387 (DstLimits::is_integer && SrcLimits::is_iec559),
jschuhd80eded2014-10-14 23:31:37 +0900388 "Destination must be narrower than source");
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900389
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900390 const CheckedNumeric<Dst> checked_dst;
391 TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, checked_dst + SrcLimits::max());
392 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
393 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst - SrcLimits::max());
394
395 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
396 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900397 if (SrcLimits::is_iec559) {
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900398 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
399 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
400 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
401 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
402 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
jschuh5f9a10b2015-09-15 05:21:24 +0900403 if (DstLimits::is_integer) {
404 if (SrcLimits::digits < DstLimits::digits) {
405 TEST_EXPECTED_RANGE(RANGE_OVERFLOW,
406 static_cast<Src>(DstLimits::max()));
407 } else {
408 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
409 }
410 TEST_EXPECTED_RANGE(
411 RANGE_VALID,
412 static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
413 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::min()));
414 }
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900415 } else if (SrcLimits::is_signed) {
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900416 TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1));
417 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
418 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900419 } else {
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900420 TEST_EXPECTED_VALIDITY(RANGE_INVALID, checked_dst - static_cast<Src>(1));
421 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900422 }
423 }
424};
425
426template <typename Dst, typename Src>
427struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> {
428 static void Test(const char *dst, const char *src, int line) {
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900429 typedef numeric_limits<Src> SrcLimits;
430 typedef numeric_limits<Dst> DstLimits;
jschuhd80eded2014-10-14 23:31:37 +0900431 static_assert(sizeof(Dst) >= sizeof(Src),
432 "Destination must be equal or wider than source.");
433 static_assert(SrcLimits::is_signed, "Source must be signed");
434 static_assert(!DstLimits::is_signed, "Destination must be unsigned");
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900435
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900436 const CheckedNumeric<Dst> checked_dst;
437 TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max());
438 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst + static_cast<Src>(-1));
439 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst + -SrcLimits::max());
440
441 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
442 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
443 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
444 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900445 }
446};
447
448template <typename Dst, typename Src>
449struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> {
450 static void Test(const char *dst, const char *src, int line) {
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900451 typedef numeric_limits<Src> SrcLimits;
452 typedef numeric_limits<Dst> DstLimits;
jschuhd80eded2014-10-14 23:31:37 +0900453 static_assert((DstLimits::is_integer && SrcLimits::is_iec559) ||
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900454 (sizeof(Dst) < sizeof(Src)),
jschuhd80eded2014-10-14 23:31:37 +0900455 "Destination must be narrower than source.");
456 static_assert(SrcLimits::is_signed, "Source must be signed.");
457 static_assert(!DstLimits::is_signed, "Destination must be unsigned.");
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900458
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900459 const CheckedNumeric<Dst> checked_dst;
460 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
461 TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, checked_dst + SrcLimits::max());
462 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst + static_cast<Src>(-1));
463 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst + -SrcLimits::max());
464
465 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
466 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
467 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900468 if (SrcLimits::is_iec559) {
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900469 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
470 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
471 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
472 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
jschuh5f9a10b2015-09-15 05:21:24 +0900473 if (DstLimits::is_integer) {
474 if (SrcLimits::digits < DstLimits::digits) {
475 TEST_EXPECTED_RANGE(RANGE_OVERFLOW,
476 static_cast<Src>(DstLimits::max()));
477 } else {
478 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
479 }
480 TEST_EXPECTED_RANGE(
481 RANGE_VALID,
482 static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
483 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::min()));
484 }
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900485 } else {
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900486 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900487 }
488 }
489};
490
491template <typename Dst, typename Src>
492struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> {
493 static void Test(const char *dst, const char *src, int line) {
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900494 typedef numeric_limits<Src> SrcLimits;
495 typedef numeric_limits<Dst> DstLimits;
jschuhd80eded2014-10-14 23:31:37 +0900496 static_assert(sizeof(Dst) <= sizeof(Src),
497 "Destination must be narrower or equal to source.");
498 static_assert(!SrcLimits::is_signed, "Source must be unsigned.");
499 static_assert(DstLimits::is_signed, "Destination must be signed.");
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900500
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900501 const CheckedNumeric<Dst> checked_dst;
502 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
503 TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, checked_dst + SrcLimits::max());
504 TEST_EXPECTED_VALUE(SrcLimits::min(), checked_dst + SrcLimits::min());
505
506 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
507 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
508 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900509 }
510};
511
512// Helper macro to wrap displaying the conversion types and line numbers
513#define TEST_NUMERIC_CONVERSION(d, s, t) \
514 TestNumericConversion<d, s, t>::Test(#d, #s, __LINE__)
515
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900516TEST(SafeNumerics, IntMinOperations) {
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900517 TEST_NUMERIC_CONVERSION(int8_t, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
518 TEST_NUMERIC_CONVERSION(uint8_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
519
520 TEST_NUMERIC_CONVERSION(int8_t, int, SIGN_PRESERVING_NARROW);
521 TEST_NUMERIC_CONVERSION(uint8_t, unsigned int, SIGN_PRESERVING_NARROW);
522 TEST_NUMERIC_CONVERSION(int8_t, float, SIGN_PRESERVING_NARROW);
523
524 TEST_NUMERIC_CONVERSION(uint8_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
525
526 TEST_NUMERIC_CONVERSION(uint8_t, int, SIGN_TO_UNSIGN_NARROW);
527 TEST_NUMERIC_CONVERSION(uint8_t, intmax_t, SIGN_TO_UNSIGN_NARROW);
528 TEST_NUMERIC_CONVERSION(uint8_t, float, SIGN_TO_UNSIGN_NARROW);
529
530 TEST_NUMERIC_CONVERSION(int8_t, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
531 TEST_NUMERIC_CONVERSION(int8_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
scottmg@chromium.org347c3652013-01-17 08:34:04 +0900532}
533
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900534TEST(SafeNumerics, IntOperations) {
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900535 TEST_NUMERIC_CONVERSION(int, int, SIGN_PRESERVING_VALUE_PRESERVING);
536 TEST_NUMERIC_CONVERSION(unsigned int, unsigned int,
537 SIGN_PRESERVING_VALUE_PRESERVING);
538 TEST_NUMERIC_CONVERSION(int, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
539 TEST_NUMERIC_CONVERSION(unsigned int, uint8_t,
540 SIGN_PRESERVING_VALUE_PRESERVING);
541 TEST_NUMERIC_CONVERSION(int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
542
543 TEST_NUMERIC_CONVERSION(int, intmax_t, SIGN_PRESERVING_NARROW);
544 TEST_NUMERIC_CONVERSION(unsigned int, uintmax_t, SIGN_PRESERVING_NARROW);
545 TEST_NUMERIC_CONVERSION(int, float, SIGN_PRESERVING_NARROW);
546 TEST_NUMERIC_CONVERSION(int, double, SIGN_PRESERVING_NARROW);
547
548 TEST_NUMERIC_CONVERSION(unsigned int, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
549 TEST_NUMERIC_CONVERSION(unsigned int, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
550
551 TEST_NUMERIC_CONVERSION(unsigned int, intmax_t, SIGN_TO_UNSIGN_NARROW);
552 TEST_NUMERIC_CONVERSION(unsigned int, float, SIGN_TO_UNSIGN_NARROW);
553 TEST_NUMERIC_CONVERSION(unsigned int, double, SIGN_TO_UNSIGN_NARROW);
554
555 TEST_NUMERIC_CONVERSION(int, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
556 TEST_NUMERIC_CONVERSION(int, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
scottmg@chromium.org347c3652013-01-17 08:34:04 +0900557}
558
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900559TEST(SafeNumerics, IntMaxOperations) {
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900560 TEST_NUMERIC_CONVERSION(intmax_t, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
561 TEST_NUMERIC_CONVERSION(uintmax_t, uintmax_t,
562 SIGN_PRESERVING_VALUE_PRESERVING);
563 TEST_NUMERIC_CONVERSION(intmax_t, int, SIGN_PRESERVING_VALUE_PRESERVING);
564 TEST_NUMERIC_CONVERSION(uintmax_t, unsigned int,
565 SIGN_PRESERVING_VALUE_PRESERVING);
566 TEST_NUMERIC_CONVERSION(intmax_t, unsigned int,
567 SIGN_PRESERVING_VALUE_PRESERVING);
568 TEST_NUMERIC_CONVERSION(intmax_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
569
570 TEST_NUMERIC_CONVERSION(intmax_t, float, SIGN_PRESERVING_NARROW);
571 TEST_NUMERIC_CONVERSION(intmax_t, double, SIGN_PRESERVING_NARROW);
572
573 TEST_NUMERIC_CONVERSION(uintmax_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
574 TEST_NUMERIC_CONVERSION(uintmax_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
575
576 TEST_NUMERIC_CONVERSION(uintmax_t, float, SIGN_TO_UNSIGN_NARROW);
577 TEST_NUMERIC_CONVERSION(uintmax_t, double, SIGN_TO_UNSIGN_NARROW);
578
579 TEST_NUMERIC_CONVERSION(intmax_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
580}
581
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900582TEST(SafeNumerics, FloatOperations) {
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900583 TEST_NUMERIC_CONVERSION(float, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
584 TEST_NUMERIC_CONVERSION(float, uintmax_t,
585 SIGN_PRESERVING_VALUE_PRESERVING);
586 TEST_NUMERIC_CONVERSION(float, int, SIGN_PRESERVING_VALUE_PRESERVING);
587 TEST_NUMERIC_CONVERSION(float, unsigned int,
588 SIGN_PRESERVING_VALUE_PRESERVING);
589
590 TEST_NUMERIC_CONVERSION(float, double, SIGN_PRESERVING_NARROW);
591}
592
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900593TEST(SafeNumerics, DoubleOperations) {
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900594 TEST_NUMERIC_CONVERSION(double, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
595 TEST_NUMERIC_CONVERSION(double, uintmax_t,
596 SIGN_PRESERVING_VALUE_PRESERVING);
597 TEST_NUMERIC_CONVERSION(double, int, SIGN_PRESERVING_VALUE_PRESERVING);
598 TEST_NUMERIC_CONVERSION(double, unsigned int,
599 SIGN_PRESERVING_VALUE_PRESERVING);
600}
601
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900602TEST(SafeNumerics, SizeTOperations) {
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900603 TEST_NUMERIC_CONVERSION(size_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
604 TEST_NUMERIC_CONVERSION(int, size_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
605}
606
607TEST(SafeNumerics, CastTests) {
608// MSVC catches and warns that we're forcing saturation in these tests.
609// Since that's intentional, we need to shut this warning off.
610#if defined(COMPILER_MSVC)
611#pragma warning(disable : 4756)
scottmg@chromium.org347c3652013-01-17 08:34:04 +0900612#endif
613
scottmg@chromium.org347c3652013-01-17 08:34:04 +0900614 int small_positive = 1;
615 int small_negative = -1;
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900616 double double_small = 1.0;
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900617 double double_large = numeric_limits<double>::max();
618 double double_infinity = numeric_limits<float>::infinity();
danakj5d945ad2015-06-06 03:15:10 +0900619 double double_large_int = numeric_limits<int>::max();
620 double double_small_int = numeric_limits<int>::min();
scottmg@chromium.org347c3652013-01-17 08:34:04 +0900621
jschuh7940ae92015-05-28 11:29:25 +0900622 // Just test that the casts compile, since the other tests cover logic.
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900623 EXPECT_EQ(0, checked_cast<int>(static_cast<size_t>(0)));
jschuh7940ae92015-05-28 11:29:25 +0900624 EXPECT_EQ(0, strict_cast<int>(static_cast<char>(0)));
625 EXPECT_EQ(0, strict_cast<int>(static_cast<unsigned char>(0)));
626 EXPECT_EQ(0U, strict_cast<unsigned>(static_cast<unsigned char>(0)));
627 EXPECT_EQ(1ULL, static_cast<uint64_t>(StrictNumeric<size_t>(1U)));
628 EXPECT_EQ(1ULL, static_cast<uint64_t>(SizeT(1U)));
629 EXPECT_EQ(1U, static_cast<size_t>(StrictNumeric<unsigned>(1U)));
630
631 EXPECT_TRUE(CheckedNumeric<uint64_t>(StrictNumeric<unsigned>(1U)).IsValid());
632 EXPECT_TRUE(CheckedNumeric<int>(StrictNumeric<unsigned>(1U)).IsValid());
633 EXPECT_FALSE(CheckedNumeric<unsigned>(StrictNumeric<int>(-1)).IsValid());
634
jschuh5131e452015-09-23 07:13:36 +0900635 EXPECT_TRUE(IsValueNegative(-1));
636 EXPECT_TRUE(IsValueNegative(numeric_limits<int>::min()));
637 EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::min()));
638 EXPECT_TRUE(IsValueNegative(-numeric_limits<double>::max()));
639 EXPECT_FALSE(IsValueNegative(0));
640 EXPECT_FALSE(IsValueNegative(1));
641 EXPECT_FALSE(IsValueNegative(0u));
642 EXPECT_FALSE(IsValueNegative(1u));
643 EXPECT_FALSE(IsValueNegative(numeric_limits<int>::max()));
644 EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::max()));
645 EXPECT_FALSE(IsValueNegative(numeric_limits<double>::max()));
646
jschuh7940ae92015-05-28 11:29:25 +0900647 // These casts and coercions will fail to compile:
648 // EXPECT_EQ(0, strict_cast<int>(static_cast<size_t>(0)));
649 // EXPECT_EQ(0, strict_cast<size_t>(static_cast<int>(0)));
650 // EXPECT_EQ(1ULL, StrictNumeric<size_t>(1));
651 // EXPECT_EQ(1, StrictNumeric<size_t>(1U));
scottmg@chromium.org347c3652013-01-17 08:34:04 +0900652
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900653 // Test various saturation corner cases.
654 EXPECT_EQ(saturated_cast<int>(small_negative),
655 static_cast<int>(small_negative));
656 EXPECT_EQ(saturated_cast<int>(small_positive),
657 static_cast<int>(small_positive));
658 EXPECT_EQ(saturated_cast<unsigned>(small_negative),
659 static_cast<unsigned>(0));
660 EXPECT_EQ(saturated_cast<int>(double_small),
661 static_cast<int>(double_small));
jschuh@chromium.org4fe236b2014-02-27 22:49:04 +0900662 EXPECT_EQ(saturated_cast<int>(double_large), numeric_limits<int>::max());
jschuh@chromium.orgecd46052014-01-16 15:57:25 +0900663 EXPECT_EQ(saturated_cast<float>(double_large), double_infinity);
664 EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity);
danakj5d945ad2015-06-06 03:15:10 +0900665 EXPECT_EQ(numeric_limits<int>::min(), saturated_cast<int>(double_small_int));
666 EXPECT_EQ(numeric_limits<int>::max(), saturated_cast<int>(double_large_int));
scottmg@chromium.org347c3652013-01-17 08:34:04 +0900667}
668
jschuh5f9a10b2015-09-15 05:21:24 +0900669TEST(SafeNumerics, IsValueInRangeForNumericType) {
670 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0));
671 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(1));
672 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(2));
673 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(-1));
674 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0xffffffffu));
675 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0xffffffff)));
676 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000000)));
677 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000001)));
678 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(
679 std::numeric_limits<int32_t>::min()));
680 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(
681 std::numeric_limits<int64_t>::min()));
682
683 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0));
684 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(1));
685 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(2));
686 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(-1));
687 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffff));
688 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffffu));
689 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0x80000000u));
690 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0xffffffffu));
691 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x80000000)));
692 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0xffffffff)));
693 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x100000000)));
694 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
695 std::numeric_limits<int32_t>::min()));
696 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
danakj91101312015-09-16 05:27:24 +0900697 static_cast<int64_t>(std::numeric_limits<int32_t>::min())));
jschuh5f9a10b2015-09-15 05:21:24 +0900698 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
danakj91101312015-09-16 05:27:24 +0900699 static_cast<int64_t>(std::numeric_limits<int32_t>::min()) - 1));
jschuh5f9a10b2015-09-15 05:21:24 +0900700 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
701 std::numeric_limits<int64_t>::min()));
702
703 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0));
704 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(1));
705 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(2));
706 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(-1));
707 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0xffffffffu));
708 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0xffffffff)));
709 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000000)));
710 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000001)));
711 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(
712 std::numeric_limits<int32_t>::min()));
713 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(INT64_C(-1)));
714 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(
715 std::numeric_limits<int64_t>::min()));
716
717 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0));
718 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(1));
719 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(2));
720 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(-1));
721 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffff));
722 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffffu));
723 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x80000000u));
724 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0xffffffffu));
725 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x80000000)));
726 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0xffffffff)));
727 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x100000000)));
728 EXPECT_TRUE(
729 IsValueInRangeForNumericType<int64_t>(INT64_C(0x7fffffffffffffff)));
730 EXPECT_TRUE(
731 IsValueInRangeForNumericType<int64_t>(UINT64_C(0x7fffffffffffffff)));
732 EXPECT_FALSE(
733 IsValueInRangeForNumericType<int64_t>(UINT64_C(0x8000000000000000)));
734 EXPECT_FALSE(
735 IsValueInRangeForNumericType<int64_t>(UINT64_C(0xffffffffffffffff)));
736 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
737 std::numeric_limits<int32_t>::min()));
738 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
danakj91101312015-09-16 05:27:24 +0900739 static_cast<int64_t>(std::numeric_limits<int32_t>::min())));
jschuh5f9a10b2015-09-15 05:21:24 +0900740 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
741 std::numeric_limits<int64_t>::min()));
742}
vmpstr076fb522015-09-30 07:34:49 +0900743
744TEST(SafeNumerics, CompoundNumericOperations) {
745 CheckedNumeric<int> a = 1;
746 CheckedNumeric<int> b = 2;
747 CheckedNumeric<int> c = 3;
748 CheckedNumeric<int> d = 4;
749 a += b;
750 EXPECT_EQ(3, a.ValueOrDie());
751 a -= c;
752 EXPECT_EQ(0, a.ValueOrDie());
753 d /= b;
754 EXPECT_EQ(2, d.ValueOrDie());
755 d *= d;
756 EXPECT_EQ(4, d.ValueOrDie());
757
758 CheckedNumeric<int> too_large = std::numeric_limits<int>::max();
759 EXPECT_TRUE(too_large.IsValid());
760 too_large += d;
761 EXPECT_FALSE(too_large.IsValid());
762 too_large -= d;
763 EXPECT_FALSE(too_large.IsValid());
764 too_large /= d;
765 EXPECT_FALSE(too_large.IsValid());
766}