1 // 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
5 #include <stddef.h>
6 #include <stdint.h>
7
8 #include <limits>
9 #include <type_traits>
10
11 #include "base/compiler_specific.h"
12 #include "base/numerics/safe_conversions.h"
13 #include "base/numerics/safe_math.h"
14 #include "base/template_util.h"
15 #include "build/build_config.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 #if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS)
19 #include <mmintrin.h>
20 #endif
21
22 using std::numeric_limits;
23 using base::CheckedNumeric;
24 using base::checked_cast;
25 using base::IsValueInRangeForNumericType;
26 using base::IsValueNegative;
27 using base::SizeT;
28 using base::StrictNumeric;
29 using base::saturated_cast;
30 using base::strict_cast;
31 using base::internal::MaxExponent;
32 using base::internal::RANGE_VALID;
33 using base::internal::RANGE_INVALID;
34 using base::internal::RANGE_OVERFLOW;
35 using base::internal::RANGE_UNDERFLOW;
36 using base::internal::SignedIntegerForSize;
37
38 // These tests deliberately cause arithmetic overflows. If the compiler is
39 // aggressive enough, it can const fold these overflows. Disable warnings about
40 // overflows for const expressions.
41 #if defined(OS_WIN)
42 #pragma warning(disable:4756)
43 #endif
44
45 // This is a helper function for finding the maximum value in Src that can be
46 // wholy represented as the destination floating-point type.
47 template <typename Dst, typename Src>
GetMaxConvertibleToFloat()48 Dst GetMaxConvertibleToFloat() {
49 typedef numeric_limits<Dst> DstLimits;
50 typedef numeric_limits<Src> SrcLimits;
51 static_assert(SrcLimits::is_specialized, "Source must be numeric.");
52 static_assert(DstLimits::is_specialized, "Destination must be numeric.");
53 CHECK(DstLimits::is_iec559);
54
55 if (SrcLimits::digits <= DstLimits::digits &&
56 MaxExponent<Src>::value <= MaxExponent<Dst>::value)
57 return SrcLimits::max();
58 Src max = SrcLimits::max() / 2 + (SrcLimits::is_integer ? 1 : 0);
59 while (max != static_cast<Src>(static_cast<Dst>(max))) {
60 max /= 2;
61 }
62 return static_cast<Dst>(max);
63 }
64
65 // Helper macros to wrap displaying the conversion types and line numbers.
66 #define TEST_EXPECTED_VALIDITY(expected, actual) \
67 EXPECT_EQ(expected, CheckedNumeric<Dst>(actual).validity()) \
68 << "Result test: Value " << +(actual).ValueUnsafe() << " as " << dst \
69 << " on line " << line;
70
71 #define TEST_EXPECTED_VALUE(expected, actual) \
72 EXPECT_EQ(static_cast<Dst>(expected), \
73 CheckedNumeric<Dst>(actual).ValueUnsafe()) \
74 << "Result test: Value " << +((actual).ValueUnsafe()) << " as " << dst \
75 << " on line " << line;
76
77 // Signed integer arithmetic.
78 template <typename Dst>
TestSpecializedArithmetic(const char * dst,int line,typename std::enable_if<numeric_limits<Dst>::is_integer && numeric_limits<Dst>::is_signed,int>::type=0)79 static void TestSpecializedArithmetic(
80 const char* dst,
81 int line,
82 typename std::enable_if<numeric_limits<Dst>::is_integer &&
83 numeric_limits<Dst>::is_signed,
84 int>::type = 0) {
85 typedef numeric_limits<Dst> DstLimits;
86 TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW,
87 -CheckedNumeric<Dst>(DstLimits::min()));
88 TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW,
89 CheckedNumeric<Dst>(DstLimits::min()).Abs());
90 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
91
92 TEST_EXPECTED_VALIDITY(RANGE_VALID,
93 CheckedNumeric<Dst>(DstLimits::max()) + -1);
94 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW,
95 CheckedNumeric<Dst>(DstLimits::min()) + -1);
96 TEST_EXPECTED_VALIDITY(
97 RANGE_UNDERFLOW,
98 CheckedNumeric<Dst>(-DstLimits::max()) + -DstLimits::max());
99
100 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW,
101 CheckedNumeric<Dst>(DstLimits::min()) - 1);
102 TEST_EXPECTED_VALIDITY(RANGE_VALID,
103 CheckedNumeric<Dst>(DstLimits::min()) - -1);
104 TEST_EXPECTED_VALIDITY(
105 RANGE_OVERFLOW,
106 CheckedNumeric<Dst>(DstLimits::max()) - -DstLimits::max());
107 TEST_EXPECTED_VALIDITY(
108 RANGE_UNDERFLOW,
109 CheckedNumeric<Dst>(-DstLimits::max()) - DstLimits::max());
110
111 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW,
112 CheckedNumeric<Dst>(DstLimits::min()) * 2);
113
114 TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW,
115 CheckedNumeric<Dst>(DstLimits::min()) / -1);
116 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) / 2);
117
118 // Modulus is legal only for integers.
119 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
120 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
121 TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % 2);
122 TEST_EXPECTED_VALIDITY(RANGE_INVALID, CheckedNumeric<Dst>(-1) % -2);
123 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) % 2);
124 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
125 // Test all the different modulus combinations.
126 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
127 TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
128 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
129 CheckedNumeric<Dst> checked_dst = 1;
130 TEST_EXPECTED_VALUE(0, checked_dst %= 1);
131 }
132
133 // Unsigned integer arithmetic.
134 template <typename Dst>
TestSpecializedArithmetic(const char * dst,int line,typename std::enable_if<numeric_limits<Dst>::is_integer &&!numeric_limits<Dst>::is_signed,int>::type=0)135 static void TestSpecializedArithmetic(
136 const char* dst,
137 int line,
138 typename std::enable_if<numeric_limits<Dst>::is_integer &&
139 !numeric_limits<Dst>::is_signed,
140 int>::type = 0) {
141 typedef numeric_limits<Dst> DstLimits;
142 TEST_EXPECTED_VALIDITY(RANGE_VALID, -CheckedNumeric<Dst>(DstLimits::min()));
143 TEST_EXPECTED_VALIDITY(RANGE_VALID,
144 CheckedNumeric<Dst>(DstLimits::min()).Abs());
145 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW,
146 CheckedNumeric<Dst>(DstLimits::min()) + -1);
147 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW,
148 CheckedNumeric<Dst>(DstLimits::min()) - 1);
149 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) * 2);
150 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) / 2);
151 TEST_EXPECTED_VALIDITY(RANGE_VALID,
152 CheckedNumeric<Dst>(DstLimits::min()).UnsignedAbs());
153 TEST_EXPECTED_VALIDITY(
154 RANGE_VALID,
155 CheckedNumeric<typename SignedIntegerForSize<Dst>::type>(
156 std::numeric_limits<typename SignedIntegerForSize<Dst>::type>::min())
157 .UnsignedAbs());
158
159 // Modulus is legal only for integers.
160 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
161 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
162 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % 2);
163 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) % 2);
164 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
165 // Test all the different modulus combinations.
166 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
167 TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
168 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
169 CheckedNumeric<Dst> checked_dst = 1;
170 TEST_EXPECTED_VALUE(0, checked_dst %= 1);
171 }
172
173 // Floating point arithmetic.
174 template <typename Dst>
TestSpecializedArithmetic(const char * dst,int line,typename std::enable_if<numeric_limits<Dst>::is_iec559,int>::type=0)175 void TestSpecializedArithmetic(
176 const char* dst,
177 int line,
178 typename std::enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0) {
179 typedef numeric_limits<Dst> DstLimits;
180 TEST_EXPECTED_VALIDITY(RANGE_VALID, -CheckedNumeric<Dst>(DstLimits::min()));
181
182 TEST_EXPECTED_VALIDITY(RANGE_VALID,
183 CheckedNumeric<Dst>(DstLimits::min()).Abs());
184 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
185
186 TEST_EXPECTED_VALIDITY(RANGE_VALID,
187 CheckedNumeric<Dst>(DstLimits::min()) + -1);
188 TEST_EXPECTED_VALIDITY(RANGE_VALID,
189 CheckedNumeric<Dst>(DstLimits::max()) + 1);
190 TEST_EXPECTED_VALIDITY(
191 RANGE_UNDERFLOW,
192 CheckedNumeric<Dst>(-DstLimits::max()) + -DstLimits::max());
193
194 TEST_EXPECTED_VALIDITY(
195 RANGE_OVERFLOW,
196 CheckedNumeric<Dst>(DstLimits::max()) - -DstLimits::max());
197 TEST_EXPECTED_VALIDITY(
198 RANGE_UNDERFLOW,
199 CheckedNumeric<Dst>(-DstLimits::max()) - DstLimits::max());
200
201 TEST_EXPECTED_VALIDITY(RANGE_VALID,
202 CheckedNumeric<Dst>(DstLimits::min()) * 2);
203
204 TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2);
205 EXPECT_EQ(static_cast<Dst>(1.0), CheckedNumeric<Dst>(1.0).ValueFloating());
206 }
207
208 // Generic arithmetic tests.
209 template <typename Dst>
TestArithmetic(const char * dst,int line)210 static void TestArithmetic(const char* dst, int line) {
211 typedef numeric_limits<Dst> DstLimits;
212
213 EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid());
214 EXPECT_EQ(false,
215 CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
216 DstLimits::max()).IsValid());
217 EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDie());
218 EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDefault(1));
219 EXPECT_EQ(static_cast<Dst>(1),
220 CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
221 DstLimits::max()).ValueOrDefault(1));
222
223 // Test the operator combinations.
224 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + CheckedNumeric<Dst>(1));
225 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - CheckedNumeric<Dst>(1));
226 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * CheckedNumeric<Dst>(1));
227 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / CheckedNumeric<Dst>(1));
228 TEST_EXPECTED_VALUE(2, 1 + CheckedNumeric<Dst>(1));
229 TEST_EXPECTED_VALUE(0, 1 - CheckedNumeric<Dst>(1));
230 TEST_EXPECTED_VALUE(1, 1 * CheckedNumeric<Dst>(1));
231 TEST_EXPECTED_VALUE(1, 1 / CheckedNumeric<Dst>(1));
232 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + 1);
233 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - 1);
234 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * 1);
235 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
236 CheckedNumeric<Dst> checked_dst = 1;
237 TEST_EXPECTED_VALUE(2, checked_dst += 1);
238 checked_dst = 1;
239 TEST_EXPECTED_VALUE(0, checked_dst -= 1);
240 checked_dst = 1;
241 TEST_EXPECTED_VALUE(1, checked_dst *= 1);
242 checked_dst = 1;
243 TEST_EXPECTED_VALUE(1, checked_dst /= 1);
244
245 // Generic negation.
246 TEST_EXPECTED_VALUE(0, -CheckedNumeric<Dst>());
247 TEST_EXPECTED_VALUE(-1, -CheckedNumeric<Dst>(1));
248 TEST_EXPECTED_VALUE(1, -CheckedNumeric<Dst>(-1));
249 TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1),
250 -CheckedNumeric<Dst>(DstLimits::max()));
251
252 // Generic absolute value.
253 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>().Abs());
254 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).Abs());
255 TEST_EXPECTED_VALUE(DstLimits::max(),
256 CheckedNumeric<Dst>(DstLimits::max()).Abs());
257
258 // Generic addition.
259 TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>() + 1));
260 TEST_EXPECTED_VALUE(2, (CheckedNumeric<Dst>(1) + 1));
261 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) + 1));
262 TEST_EXPECTED_VALIDITY(RANGE_VALID,
263 CheckedNumeric<Dst>(DstLimits::min()) + 1);
264 TEST_EXPECTED_VALIDITY(
265 RANGE_OVERFLOW, CheckedNumeric<Dst>(DstLimits::max()) + DstLimits::max());
266
267 // Generic subtraction.
268 TEST_EXPECTED_VALUE(-1, (CheckedNumeric<Dst>() - 1));
269 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(1) - 1));
270 TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) - 1));
271 TEST_EXPECTED_VALIDITY(RANGE_VALID,
272 CheckedNumeric<Dst>(DstLimits::max()) - 1);
273
274 // Generic multiplication.
275 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>() * 1));
276 TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>(1) * 1));
277 TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) * 2));
278 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * 0));
279 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) * 0));
280 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * -1));
281 TEST_EXPECTED_VALIDITY(
282 RANGE_OVERFLOW, CheckedNumeric<Dst>(DstLimits::max()) * DstLimits::max());
283
284 // Generic division.
285 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() / 1);
286 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
287 TEST_EXPECTED_VALUE(DstLimits::min() / 2,
288 CheckedNumeric<Dst>(DstLimits::min()) / 2);
289 TEST_EXPECTED_VALUE(DstLimits::max() / 2,
290 CheckedNumeric<Dst>(DstLimits::max()) / 2);
291
292 TestSpecializedArithmetic<Dst>(dst, line);
293 }
294
295 // Helper macro to wrap displaying the conversion types and line numbers.
296 #define TEST_ARITHMETIC(Dst) TestArithmetic<Dst>(#Dst, __LINE__)
297
TEST(SafeNumerics,SignedIntegerMath)298 TEST(SafeNumerics, SignedIntegerMath) {
299 TEST_ARITHMETIC(int8_t);
300 TEST_ARITHMETIC(int);
301 TEST_ARITHMETIC(intptr_t);
302 TEST_ARITHMETIC(intmax_t);
303 }
304
TEST(SafeNumerics,UnsignedIntegerMath)305 TEST(SafeNumerics, UnsignedIntegerMath) {
306 TEST_ARITHMETIC(uint8_t);
307 TEST_ARITHMETIC(unsigned int);
308 TEST_ARITHMETIC(uintptr_t);
309 TEST_ARITHMETIC(uintmax_t);
310 }
311
TEST(SafeNumerics,FloatingPointMath)312 TEST(SafeNumerics, FloatingPointMath) {
313 TEST_ARITHMETIC(float);
314 TEST_ARITHMETIC(double);
315 }
316
317 // Enumerates the five different conversions types we need to test.
318 enum NumericConversionType {
319 SIGN_PRESERVING_VALUE_PRESERVING,
320 SIGN_PRESERVING_NARROW,
321 SIGN_TO_UNSIGN_WIDEN_OR_EQUAL,
322 SIGN_TO_UNSIGN_NARROW,
323 UNSIGN_TO_SIGN_NARROW_OR_EQUAL,
324 };
325
326 // Template covering the different conversion tests.
327 template <typename Dst, typename Src, NumericConversionType conversion>
328 struct TestNumericConversion {};
329
330 // EXPECT_EQ wrappers providing specific detail on test failures.
331 #define TEST_EXPECTED_RANGE(expected, actual) \
332 EXPECT_EQ(expected, base::internal::DstRangeRelationToSrcRange<Dst>(actual)) \
333 << "Conversion test: " << src << " value " << actual << " to " << dst \
334 << " on line " << line;
335
336 template <typename Dst, typename Src>
337 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> {
TestTestNumericConversion338 static void Test(const char *dst, const char *src, int line) {
339 typedef numeric_limits<Src> SrcLimits;
340 typedef numeric_limits<Dst> DstLimits;
341 // Integral to floating.
342 static_assert((DstLimits::is_iec559 && SrcLimits::is_integer) ||
343 // Not floating to integral and...
344 (!(DstLimits::is_integer && SrcLimits::is_iec559) &&
345 // Same sign, same numeric, source is narrower or same.
346 ((SrcLimits::is_signed == DstLimits::is_signed &&
347 sizeof(Dst) >= sizeof(Src)) ||
348 // Or signed destination and source is smaller
349 (DstLimits::is_signed && sizeof(Dst) > sizeof(Src)))),
350 "Comparison must be sign preserving and value preserving");
351
352 const CheckedNumeric<Dst> checked_dst = SrcLimits::max();
353 TEST_EXPECTED_VALIDITY(RANGE_VALID, checked_dst);
354 if (MaxExponent<Dst>::value > MaxExponent<Src>::value) {
355 if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1) {
356 // At least twice larger type.
357 TEST_EXPECTED_VALIDITY(RANGE_VALID, SrcLimits::max() * checked_dst);
358
359 } else { // Larger, but not at least twice as large.
360 TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, SrcLimits::max() * checked_dst);
361 TEST_EXPECTED_VALIDITY(RANGE_VALID, checked_dst + 1);
362 }
363 } else { // Same width type.
364 TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, checked_dst + 1);
365 }
366
367 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
368 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
369 if (SrcLimits::is_iec559) {
370 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max() * static_cast<Src>(-1));
371 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
372 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
373 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
374 } else if (numeric_limits<Src>::is_signed) {
375 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
376 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
377 }
378 }
379 };
380
381 template <typename Dst, typename Src>
382 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> {
TestTestNumericConversion383 static void Test(const char *dst, const char *src, int line) {
384 typedef numeric_limits<Src> SrcLimits;
385 typedef numeric_limits<Dst> DstLimits;
386 static_assert(SrcLimits::is_signed == DstLimits::is_signed,
387 "Destination and source sign must be the same");
388 static_assert(sizeof(Dst) < sizeof(Src) ||
389 (DstLimits::is_integer && SrcLimits::is_iec559),
390 "Destination must be narrower than source");
391
392 const CheckedNumeric<Dst> checked_dst;
393 TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, checked_dst + SrcLimits::max());
394 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
395 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst - SrcLimits::max());
396
397 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
398 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
399 if (SrcLimits::is_iec559) {
400 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
401 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
402 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
403 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
404 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
405 if (DstLimits::is_integer) {
406 if (SrcLimits::digits < DstLimits::digits) {
407 TEST_EXPECTED_RANGE(RANGE_OVERFLOW,
408 static_cast<Src>(DstLimits::max()));
409 } else {
410 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
411 }
412 TEST_EXPECTED_RANGE(
413 RANGE_VALID,
414 static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
415 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::min()));
416 }
417 } else if (SrcLimits::is_signed) {
418 TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1));
419 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
420 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
421 } else {
422 TEST_EXPECTED_VALIDITY(RANGE_INVALID, checked_dst - static_cast<Src>(1));
423 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
424 }
425 }
426 };
427
428 template <typename Dst, typename Src>
429 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> {
TestTestNumericConversion430 static void Test(const char *dst, const char *src, int line) {
431 typedef numeric_limits<Src> SrcLimits;
432 typedef numeric_limits<Dst> DstLimits;
433 static_assert(sizeof(Dst) >= sizeof(Src),
434 "Destination must be equal or wider than source.");
435 static_assert(SrcLimits::is_signed, "Source must be signed");
436 static_assert(!DstLimits::is_signed, "Destination must be unsigned");
437
438 const CheckedNumeric<Dst> checked_dst;
439 TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max());
440 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst + static_cast<Src>(-1));
441 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst + -SrcLimits::max());
442
443 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
444 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
445 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
446 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
447 }
448 };
449
450 template <typename Dst, typename Src>
451 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> {
TestTestNumericConversion452 static void Test(const char *dst, const char *src, int line) {
453 typedef numeric_limits<Src> SrcLimits;
454 typedef numeric_limits<Dst> DstLimits;
455 static_assert((DstLimits::is_integer && SrcLimits::is_iec559) ||
456 (sizeof(Dst) < sizeof(Src)),
457 "Destination must be narrower than source.");
458 static_assert(SrcLimits::is_signed, "Source must be signed.");
459 static_assert(!DstLimits::is_signed, "Destination must be unsigned.");
460
461 const CheckedNumeric<Dst> checked_dst;
462 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
463 TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, checked_dst + SrcLimits::max());
464 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst + static_cast<Src>(-1));
465 TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst + -SrcLimits::max());
466
467 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
468 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
469 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
470 if (SrcLimits::is_iec559) {
471 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
472 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
473 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
474 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
475 if (DstLimits::is_integer) {
476 if (SrcLimits::digits < DstLimits::digits) {
477 TEST_EXPECTED_RANGE(RANGE_OVERFLOW,
478 static_cast<Src>(DstLimits::max()));
479 } else {
480 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
481 }
482 TEST_EXPECTED_RANGE(
483 RANGE_VALID,
484 static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
485 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::min()));
486 }
487 } else {
488 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
489 }
490 }
491 };
492
493 template <typename Dst, typename Src>
494 struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> {
TestTestNumericConversion495 static void Test(const char *dst, const char *src, int line) {
496 typedef numeric_limits<Src> SrcLimits;
497 typedef numeric_limits<Dst> DstLimits;
498 static_assert(sizeof(Dst) <= sizeof(Src),
499 "Destination must be narrower or equal to source.");
500 static_assert(!SrcLimits::is_signed, "Source must be unsigned.");
501 static_assert(DstLimits::is_signed, "Destination must be signed.");
502
503 const CheckedNumeric<Dst> checked_dst;
504 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
505 TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, checked_dst + SrcLimits::max());
506 TEST_EXPECTED_VALUE(SrcLimits::min(), checked_dst + SrcLimits::min());
507
508 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
509 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
510 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
511 }
512 };
513
514 // Helper macro to wrap displaying the conversion types and line numbers
515 #define TEST_NUMERIC_CONVERSION(d, s, t) \
516 TestNumericConversion<d, s, t>::Test(#d, #s, __LINE__)
517
TEST(SafeNumerics,IntMinOperations)518 TEST(SafeNumerics, IntMinOperations) {
519 TEST_NUMERIC_CONVERSION(int8_t, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
520 TEST_NUMERIC_CONVERSION(uint8_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
521
522 TEST_NUMERIC_CONVERSION(int8_t, int, SIGN_PRESERVING_NARROW);
523 TEST_NUMERIC_CONVERSION(uint8_t, unsigned int, SIGN_PRESERVING_NARROW);
524 TEST_NUMERIC_CONVERSION(int8_t, float, SIGN_PRESERVING_NARROW);
525
526 TEST_NUMERIC_CONVERSION(uint8_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
527
528 TEST_NUMERIC_CONVERSION(uint8_t, int, SIGN_TO_UNSIGN_NARROW);
529 TEST_NUMERIC_CONVERSION(uint8_t, intmax_t, SIGN_TO_UNSIGN_NARROW);
530 TEST_NUMERIC_CONVERSION(uint8_t, float, SIGN_TO_UNSIGN_NARROW);
531
532 TEST_NUMERIC_CONVERSION(int8_t, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
533 TEST_NUMERIC_CONVERSION(int8_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
534 }
535
TEST(SafeNumerics,IntOperations)536 TEST(SafeNumerics, IntOperations) {
537 TEST_NUMERIC_CONVERSION(int, int, SIGN_PRESERVING_VALUE_PRESERVING);
538 TEST_NUMERIC_CONVERSION(unsigned int, unsigned int,
539 SIGN_PRESERVING_VALUE_PRESERVING);
540 TEST_NUMERIC_CONVERSION(int, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
541 TEST_NUMERIC_CONVERSION(unsigned int, uint8_t,
542 SIGN_PRESERVING_VALUE_PRESERVING);
543 TEST_NUMERIC_CONVERSION(int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
544
545 TEST_NUMERIC_CONVERSION(int, intmax_t, SIGN_PRESERVING_NARROW);
546 TEST_NUMERIC_CONVERSION(unsigned int, uintmax_t, SIGN_PRESERVING_NARROW);
547 TEST_NUMERIC_CONVERSION(int, float, SIGN_PRESERVING_NARROW);
548 TEST_NUMERIC_CONVERSION(int, double, SIGN_PRESERVING_NARROW);
549
550 TEST_NUMERIC_CONVERSION(unsigned int, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
551 TEST_NUMERIC_CONVERSION(unsigned int, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
552
553 TEST_NUMERIC_CONVERSION(unsigned int, intmax_t, SIGN_TO_UNSIGN_NARROW);
554 TEST_NUMERIC_CONVERSION(unsigned int, float, SIGN_TO_UNSIGN_NARROW);
555 TEST_NUMERIC_CONVERSION(unsigned int, double, SIGN_TO_UNSIGN_NARROW);
556
557 TEST_NUMERIC_CONVERSION(int, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
558 TEST_NUMERIC_CONVERSION(int, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
559 }
560
TEST(SafeNumerics,IntMaxOperations)561 TEST(SafeNumerics, IntMaxOperations) {
562 TEST_NUMERIC_CONVERSION(intmax_t, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
563 TEST_NUMERIC_CONVERSION(uintmax_t, uintmax_t,
564 SIGN_PRESERVING_VALUE_PRESERVING);
565 TEST_NUMERIC_CONVERSION(intmax_t, int, SIGN_PRESERVING_VALUE_PRESERVING);
566 TEST_NUMERIC_CONVERSION(uintmax_t, unsigned int,
567 SIGN_PRESERVING_VALUE_PRESERVING);
568 TEST_NUMERIC_CONVERSION(intmax_t, unsigned int,
569 SIGN_PRESERVING_VALUE_PRESERVING);
570 TEST_NUMERIC_CONVERSION(intmax_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
571
572 TEST_NUMERIC_CONVERSION(intmax_t, float, SIGN_PRESERVING_NARROW);
573 TEST_NUMERIC_CONVERSION(intmax_t, double, SIGN_PRESERVING_NARROW);
574
575 TEST_NUMERIC_CONVERSION(uintmax_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
576 TEST_NUMERIC_CONVERSION(uintmax_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
577
578 TEST_NUMERIC_CONVERSION(uintmax_t, float, SIGN_TO_UNSIGN_NARROW);
579 TEST_NUMERIC_CONVERSION(uintmax_t, double, SIGN_TO_UNSIGN_NARROW);
580
581 TEST_NUMERIC_CONVERSION(intmax_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
582 }
583
TEST(SafeNumerics,FloatOperations)584 TEST(SafeNumerics, FloatOperations) {
585 TEST_NUMERIC_CONVERSION(float, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
586 TEST_NUMERIC_CONVERSION(float, uintmax_t,
587 SIGN_PRESERVING_VALUE_PRESERVING);
588 TEST_NUMERIC_CONVERSION(float, int, SIGN_PRESERVING_VALUE_PRESERVING);
589 TEST_NUMERIC_CONVERSION(float, unsigned int,
590 SIGN_PRESERVING_VALUE_PRESERVING);
591
592 TEST_NUMERIC_CONVERSION(float, double, SIGN_PRESERVING_NARROW);
593 }
594
TEST(SafeNumerics,DoubleOperations)595 TEST(SafeNumerics, DoubleOperations) {
596 TEST_NUMERIC_CONVERSION(double, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
597 TEST_NUMERIC_CONVERSION(double, uintmax_t,
598 SIGN_PRESERVING_VALUE_PRESERVING);
599 TEST_NUMERIC_CONVERSION(double, int, SIGN_PRESERVING_VALUE_PRESERVING);
600 TEST_NUMERIC_CONVERSION(double, unsigned int,
601 SIGN_PRESERVING_VALUE_PRESERVING);
602 }
603
TEST(SafeNumerics,SizeTOperations)604 TEST(SafeNumerics, SizeTOperations) {
605 TEST_NUMERIC_CONVERSION(size_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
606 TEST_NUMERIC_CONVERSION(int, size_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
607 }
608
TEST(SafeNumerics,CastTests)609 TEST(SafeNumerics, CastTests) {
610 // MSVC catches and warns that we're forcing saturation in these tests.
611 // Since that's intentional, we need to shut this warning off.
612 #if defined(COMPILER_MSVC)
613 #pragma warning(disable : 4756)
614 #endif
615
616 int small_positive = 1;
617 int small_negative = -1;
618 double double_small = 1.0;
619 double double_large = numeric_limits<double>::max();
620 double double_infinity = numeric_limits<float>::infinity();
621 double double_large_int = numeric_limits<int>::max();
622 double double_small_int = numeric_limits<int>::min();
623
624 // Just test that the casts compile, since the other tests cover logic.
625 EXPECT_EQ(0, checked_cast<int>(static_cast<size_t>(0)));
626 EXPECT_EQ(0, strict_cast<int>(static_cast<char>(0)));
627 EXPECT_EQ(0, strict_cast<int>(static_cast<unsigned char>(0)));
628 EXPECT_EQ(0U, strict_cast<unsigned>(static_cast<unsigned char>(0)));
629 EXPECT_EQ(1ULL, static_cast<uint64_t>(StrictNumeric<size_t>(1U)));
630 EXPECT_EQ(1ULL, static_cast<uint64_t>(SizeT(1U)));
631 EXPECT_EQ(1U, static_cast<size_t>(StrictNumeric<unsigned>(1U)));
632
633 EXPECT_TRUE(CheckedNumeric<uint64_t>(StrictNumeric<unsigned>(1U)).IsValid());
634 EXPECT_TRUE(CheckedNumeric<int>(StrictNumeric<unsigned>(1U)).IsValid());
635 EXPECT_FALSE(CheckedNumeric<unsigned>(StrictNumeric<int>(-1)).IsValid());
636
637 EXPECT_TRUE(IsValueNegative(-1));
638 EXPECT_TRUE(IsValueNegative(numeric_limits<int>::min()));
639 EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::min()));
640 EXPECT_TRUE(IsValueNegative(-numeric_limits<double>::max()));
641 EXPECT_FALSE(IsValueNegative(0));
642 EXPECT_FALSE(IsValueNegative(1));
643 EXPECT_FALSE(IsValueNegative(0u));
644 EXPECT_FALSE(IsValueNegative(1u));
645 EXPECT_FALSE(IsValueNegative(numeric_limits<int>::max()));
646 EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::max()));
647 EXPECT_FALSE(IsValueNegative(numeric_limits<double>::max()));
648
649 // These casts and coercions will fail to compile:
650 // EXPECT_EQ(0, strict_cast<int>(static_cast<size_t>(0)));
651 // EXPECT_EQ(0, strict_cast<size_t>(static_cast<int>(0)));
652 // EXPECT_EQ(1ULL, StrictNumeric<size_t>(1));
653 // EXPECT_EQ(1, StrictNumeric<size_t>(1U));
654
655 // Test various saturation corner cases.
656 EXPECT_EQ(saturated_cast<int>(small_negative),
657 static_cast<int>(small_negative));
658 EXPECT_EQ(saturated_cast<int>(small_positive),
659 static_cast<int>(small_positive));
660 EXPECT_EQ(saturated_cast<unsigned>(small_negative),
661 static_cast<unsigned>(0));
662 EXPECT_EQ(saturated_cast<int>(double_small),
663 static_cast<int>(double_small));
664 EXPECT_EQ(saturated_cast<int>(double_large), numeric_limits<int>::max());
665 EXPECT_EQ(saturated_cast<float>(double_large), double_infinity);
666 EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity);
667 EXPECT_EQ(numeric_limits<int>::min(), saturated_cast<int>(double_small_int));
668 EXPECT_EQ(numeric_limits<int>::max(), saturated_cast<int>(double_large_int));
669
670 float not_a_number = std::numeric_limits<float>::infinity() -
671 std::numeric_limits<float>::infinity();
672 EXPECT_TRUE(std::isnan(not_a_number));
673 EXPECT_EQ(0, saturated_cast<int>(not_a_number));
674 }
675
676 #if GTEST_HAS_DEATH_TEST
677
TEST(SafeNumerics,SaturatedCastChecks)678 TEST(SafeNumerics, SaturatedCastChecks) {
679 float not_a_number = std::numeric_limits<float>::infinity() -
680 std::numeric_limits<float>::infinity();
681 EXPECT_TRUE(std::isnan(not_a_number));
682 EXPECT_DEATH((saturated_cast<int, base::SaturatedCastNaNBehaviorCheck>(
683 not_a_number)), "");
684 }
685
686 #endif // GTEST_HAS_DEATH_TEST
687
TEST(SafeNumerics,IsValueInRangeForNumericType)688 TEST(SafeNumerics, IsValueInRangeForNumericType) {
689 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0));
690 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(1));
691 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(2));
692 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(-1));
693 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0xffffffffu));
694 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0xffffffff)));
695 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000000)));
696 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000001)));
697 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(
698 std::numeric_limits<int32_t>::min()));
699 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(
700 std::numeric_limits<int64_t>::min()));
701
702 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0));
703 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(1));
704 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(2));
705 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(-1));
706 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffff));
707 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffffu));
708 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0x80000000u));
709 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0xffffffffu));
710 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x80000000)));
711 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0xffffffff)));
712 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x100000000)));
713 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
714 std::numeric_limits<int32_t>::min()));
715 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
716 static_cast<int64_t>(std::numeric_limits<int32_t>::min())));
717 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
718 static_cast<int64_t>(std::numeric_limits<int32_t>::min()) - 1));
719 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
720 std::numeric_limits<int64_t>::min()));
721
722 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0));
723 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(1));
724 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(2));
725 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(-1));
726 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0xffffffffu));
727 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0xffffffff)));
728 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000000)));
729 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000001)));
730 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(
731 std::numeric_limits<int32_t>::min()));
732 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(INT64_C(-1)));
733 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(
734 std::numeric_limits<int64_t>::min()));
735
736 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0));
737 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(1));
738 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(2));
739 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(-1));
740 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffff));
741 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffffu));
742 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x80000000u));
743 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0xffffffffu));
744 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x80000000)));
745 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0xffffffff)));
746 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x100000000)));
747 EXPECT_TRUE(
748 IsValueInRangeForNumericType<int64_t>(INT64_C(0x7fffffffffffffff)));
749 EXPECT_TRUE(
750 IsValueInRangeForNumericType<int64_t>(UINT64_C(0x7fffffffffffffff)));
751 EXPECT_FALSE(
752 IsValueInRangeForNumericType<int64_t>(UINT64_C(0x8000000000000000)));
753 EXPECT_FALSE(
754 IsValueInRangeForNumericType<int64_t>(UINT64_C(0xffffffffffffffff)));
755 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
756 std::numeric_limits<int32_t>::min()));
757 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
758 static_cast<int64_t>(std::numeric_limits<int32_t>::min())));
759 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
760 std::numeric_limits<int64_t>::min()));
761 }
762
TEST(SafeNumerics,CompoundNumericOperations)763 TEST(SafeNumerics, CompoundNumericOperations) {
764 CheckedNumeric<int> a = 1;
765 CheckedNumeric<int> b = 2;
766 CheckedNumeric<int> c = 3;
767 CheckedNumeric<int> d = 4;
768 a += b;
769 EXPECT_EQ(3, a.ValueOrDie());
770 a -= c;
771 EXPECT_EQ(0, a.ValueOrDie());
772 d /= b;
773 EXPECT_EQ(2, d.ValueOrDie());
774 d *= d;
775 EXPECT_EQ(4, d.ValueOrDie());
776
777 CheckedNumeric<int> too_large = std::numeric_limits<int>::max();
778 EXPECT_TRUE(too_large.IsValid());
779 too_large += d;
780 EXPECT_FALSE(too_large.IsValid());
781 too_large -= d;
782 EXPECT_FALSE(too_large.IsValid());
783 too_large /= d;
784 EXPECT_FALSE(too_large.IsValid());
785 }
786