[go: nahoru, domu]

blob: aaf277947180c4eb22a8e5ee8f965706a5beda78 [file] [log] [blame]
scottmg@chromium.orgc1c090d32013-01-16 23:34:041// 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.org5bfecbc2014-02-27 13:49:045#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS)
6#include <mmintrin.h>
7#endif
jschuh@chromium.org4efb2c32014-01-16 06:57:258#include <stdint.h>
9
10#include <limits>
vmpstr98a2fad2015-11-30 20:15:1711#include <type_traits>
jschuh@chromium.org4efb2c32014-01-16 06:57:2512
13#include "base/compiler_specific.h"
jschuh@chromium.org5bfecbc2014-02-27 13:49:0414#include "base/numerics/safe_conversions.h"
15#include "base/numerics/safe_math.h"
16#include "base/template_util.h"
jschuh@chromium.org4efb2c32014-01-16 06:57:2517#include "testing/gtest/include/gtest/gtest.h"
scottmg@chromium.orgc1c090d32013-01-16 23:34:0418
jschuh@chromium.org5bfecbc2014-02-27 13:49:0419using std::numeric_limits;
20using base::CheckedNumeric;
21using base::checked_cast;
jschuhfafe0712015-09-14 20:21:2422using base::IsValueInRangeForNumericType;
jschuh07345e62015-09-22 22:13:3623using base::IsValueNegative;
jschuh4bf22c6d2015-05-28 02:29:2524using base::SizeT;
25using base::StrictNumeric;
jschuh@chromium.org5bfecbc2014-02-27 13:49:0426using base::saturated_cast;
jschuh4bf22c6d2015-05-28 02:29:2527using base::strict_cast;
jschuh@chromium.org5bfecbc2014-02-27 13:49:0428using base::internal::MaxExponent;
29using base::internal::RANGE_VALID;
30using base::internal::RANGE_INVALID;
31using base::internal::RANGE_OVERFLOW;
32using base::internal::RANGE_UNDERFLOW;
jschuheaf375f2015-09-17 01:04:2833using base::internal::SignedIntegerForSize;
jschuh@chromium.org5bfecbc2014-02-27 13:49:0434
ncbray@chromium.orgb6bf5c322014-08-09 05:24:0235// 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
jschuhfafe0712015-09-14 20:21:2441
42// 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}
ncbray@chromium.orgb6bf5c322014-08-09 05:24:0261
jschuh@chromium.org5bfecbc2014-02-27 13:49:0462// 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,
vmpstr98a2fad2015-11-30 20:15:1779 typename std::enable_if<numeric_limits<Dst>::is_integer &&
80 numeric_limits<Dst>::is_signed,
81 int>::type = 0) {
jschuh@chromium.org5bfecbc2014-02-27 13:49:0482 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,
vmpstr98a2fad2015-11-30 20:15:17135 typename std::enable_if<numeric_limits<Dst>::is_integer &&
136 !numeric_limits<Dst>::is_signed,
137 int>::type = 0) {
jschuh@chromium.org5bfecbc2014-02-27 13:49:04138 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);
jschuheaf375f2015-09-17 01:04:28148 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.org5bfecbc2014-02-27 13:49:04155
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,
vmpstr98a2fad2015-11-30 20:15:17175 typename std::enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0) {
jschuh@chromium.org5bfecbc2014-02-27 13:49:04176 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));
eroman0397125f2015-05-18 14:44:32275 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.org5bfecbc2014-02-27 13:49:04278 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.orgc1c090d32013-01-16 23:34:04313
jschuh@chromium.org4efb2c32014-01-16 06:57:25314// 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.orgc1c090d32013-01-16 23:34:04322
jschuh@chromium.org4efb2c32014-01-16 06:57:25323// Template covering the different conversion tests.
324template <typename Dst, typename Src, NumericConversionType conversion>
325struct TestNumericConversion {};
scottmg@chromium.orgc1c090d32013-01-16 23:34:04326
jschuh@chromium.org5bfecbc2014-02-27 13:49:04327// 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.org4efb2c32014-01-16 06:57:25332
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.org5bfecbc2014-02-27 13:49:04336 typedef numeric_limits<Src> SrcLimits;
337 typedef numeric_limits<Dst> DstLimits;
jschuh@chromium.org4efb2c32014-01-16 06:57:25338 // Integral to floating.
jschuhd2d9fe02014-10-14 14:31:37339 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.org4efb2c32014-01-16 06:57:25348
jschuh@chromium.org5bfecbc2014-02-27 13:49:04349 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.org4efb2c32014-01-16 06:57:25367 if (SrcLimits::is_iec559) {
jschuh@chromium.org5bfecbc2014-02-27 13:49:04368 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.org5bfecbc2014-02-27 13:49:04372 } 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.org4efb2c32014-01-16 06:57:25375 }
scottmg@chromium.orgc1c090d32013-01-16 23:34:04376 }
jschuh@chromium.org4efb2c32014-01-16 06:57:25377};
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.org5bfecbc2014-02-27 13:49:04382 typedef numeric_limits<Src> SrcLimits;
383 typedef numeric_limits<Dst> DstLimits;
jschuhd2d9fe02014-10-14 14:31:37384 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.org4efb2c32014-01-16 06:57:25387 (DstLimits::is_integer && SrcLimits::is_iec559),
jschuhd2d9fe02014-10-14 14:31:37388 "Destination must be narrower than source");
jschuh@chromium.org4efb2c32014-01-16 06:57:25389
jschuh@chromium.org5bfecbc2014-02-27 13:49:04390 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.org4efb2c32014-01-16 06:57:25397 if (SrcLimits::is_iec559) {
jschuh@chromium.org5bfecbc2014-02-27 13:49:04398 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());
jschuhfafe0712015-09-14 20:21:24403 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.org4efb2c32014-01-16 06:57:25415 } else if (SrcLimits::is_signed) {
jschuh@chromium.org5bfecbc2014-02-27 13:49:04416 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.org4efb2c32014-01-16 06:57:25419 } else {
jschuh@chromium.org5bfecbc2014-02-27 13:49:04420 TEST_EXPECTED_VALIDITY(RANGE_INVALID, checked_dst - static_cast<Src>(1));
421 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
jschuh@chromium.org4efb2c32014-01-16 06:57:25422 }
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.org5bfecbc2014-02-27 13:49:04429 typedef numeric_limits<Src> SrcLimits;
430 typedef numeric_limits<Dst> DstLimits;
jschuhd2d9fe02014-10-14 14:31:37431 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.org4efb2c32014-01-16 06:57:25435
jschuh@chromium.org5bfecbc2014-02-27 13:49:04436 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.org4efb2c32014-01-16 06:57:25445 }
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.org5bfecbc2014-02-27 13:49:04451 typedef numeric_limits<Src> SrcLimits;
452 typedef numeric_limits<Dst> DstLimits;
jschuhd2d9fe02014-10-14 14:31:37453 static_assert((DstLimits::is_integer && SrcLimits::is_iec559) ||
jschuh@chromium.org4efb2c32014-01-16 06:57:25454 (sizeof(Dst) < sizeof(Src)),
jschuhd2d9fe02014-10-14 14:31:37455 "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.org4efb2c32014-01-16 06:57:25458
jschuh@chromium.org5bfecbc2014-02-27 13:49:04459 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.org4efb2c32014-01-16 06:57:25468 if (SrcLimits::is_iec559) {
jschuh@chromium.org5bfecbc2014-02-27 13:49:04469 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());
jschuhfafe0712015-09-14 20:21:24473 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.org4efb2c32014-01-16 06:57:25485 } else {
jschuh@chromium.org5bfecbc2014-02-27 13:49:04486 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
jschuh@chromium.org4efb2c32014-01-16 06:57:25487 }
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.org5bfecbc2014-02-27 13:49:04494 typedef numeric_limits<Src> SrcLimits;
495 typedef numeric_limits<Dst> DstLimits;
jschuhd2d9fe02014-10-14 14:31:37496 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.org4efb2c32014-01-16 06:57:25500
jschuh@chromium.org5bfecbc2014-02-27 13:49:04501 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.org4efb2c32014-01-16 06:57:25509 }
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.org5bfecbc2014-02-27 13:49:04516TEST(SafeNumerics, IntMinOperations) {
jschuh@chromium.org4efb2c32014-01-16 06:57:25517 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.orgc1c090d32013-01-16 23:34:04532}
533
jschuh@chromium.org5bfecbc2014-02-27 13:49:04534TEST(SafeNumerics, IntOperations) {
jschuh@chromium.org4efb2c32014-01-16 06:57:25535 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.orgc1c090d32013-01-16 23:34:04557}
558
jschuh@chromium.org5bfecbc2014-02-27 13:49:04559TEST(SafeNumerics, IntMaxOperations) {
jschuh@chromium.org4efb2c32014-01-16 06:57:25560 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.org5bfecbc2014-02-27 13:49:04582TEST(SafeNumerics, FloatOperations) {
jschuh@chromium.org4efb2c32014-01-16 06:57:25583 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.org5bfecbc2014-02-27 13:49:04593TEST(SafeNumerics, DoubleOperations) {
jschuh@chromium.org4efb2c32014-01-16 06:57:25594 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.org5bfecbc2014-02-27 13:49:04602TEST(SafeNumerics, SizeTOperations) {
jschuh@chromium.org4efb2c32014-01-16 06:57:25603 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.orgc1c090d32013-01-16 23:34:04612#endif
613
scottmg@chromium.orgc1c090d32013-01-16 23:34:04614 int small_positive = 1;
615 int small_negative = -1;
jschuh@chromium.org4efb2c32014-01-16 06:57:25616 double double_small = 1.0;
jschuh@chromium.org5bfecbc2014-02-27 13:49:04617 double double_large = numeric_limits<double>::max();
618 double double_infinity = numeric_limits<float>::infinity();
danakj3193742f2015-06-05 18:15:10619 double double_large_int = numeric_limits<int>::max();
620 double double_small_int = numeric_limits<int>::min();
scottmg@chromium.orgc1c090d32013-01-16 23:34:04621
jschuh4bf22c6d2015-05-28 02:29:25622 // Just test that the casts compile, since the other tests cover logic.
jschuh@chromium.org5bfecbc2014-02-27 13:49:04623 EXPECT_EQ(0, checked_cast<int>(static_cast<size_t>(0)));
jschuh4bf22c6d2015-05-28 02:29:25624 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
jschuh07345e62015-09-22 22:13:36635 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
jschuh4bf22c6d2015-05-28 02:29:25647 // 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.orgc1c090d32013-01-16 23:34:04652
jschuh@chromium.org4efb2c32014-01-16 06:57:25653 // 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.org5bfecbc2014-02-27 13:49:04662 EXPECT_EQ(saturated_cast<int>(double_large), numeric_limits<int>::max());
jschuh@chromium.org4efb2c32014-01-16 06:57:25663 EXPECT_EQ(saturated_cast<float>(double_large), double_infinity);
664 EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity);
danakj3193742f2015-06-05 18:15:10665 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.orgc1c090d32013-01-16 23:34:04667}
jschuh@chromium.orgcb154062014-01-17 03:32:40668
jschuhfafe0712015-09-14 20:21:24669TEST(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>(
danakja5f0d962015-09-15 20:27:24697 static_cast<int64_t>(std::numeric_limits<int32_t>::min())));
jschuhfafe0712015-09-14 20:21:24698 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
danakja5f0d962015-09-15 20:27:24699 static_cast<int64_t>(std::numeric_limits<int32_t>::min()) - 1));
jschuhfafe0712015-09-14 20:21:24700 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>(
danakja5f0d962015-09-15 20:27:24739 static_cast<int64_t>(std::numeric_limits<int32_t>::min())));
jschuhfafe0712015-09-14 20:21:24740 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
741 std::numeric_limits<int64_t>::min()));
742}
vmpstr19477492015-09-29 22:34:49743
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}