blob: 5304593725b67d12540228db8895e05c48d5d4d6 [file] [log] [blame]
[email protected]c1c090d32013-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
avi9b6f42932015-12-26 22:15:145#include <stddef.h>
[email protected]4efb2c32014-01-16 06:57:256#include <stdint.h>
7
8#include <limits>
vmpstr98a2fad2015-11-30 20:15:179#include <type_traits>
[email protected]4efb2c32014-01-16 06:57:2510
11#include "base/compiler_specific.h"
jschuh224f1d72016-11-25 20:08:4812#include "base/logging.h"
[email protected]5bfecbc2014-02-27 13:49:0413#include "base/numerics/safe_conversions.h"
14#include "base/numerics/safe_math.h"
gab190f7542016-08-01 20:03:4115#include "base/test/gtest_util.h"
avi9b6f42932015-12-26 22:15:1416#include "build/build_config.h"
[email protected]4efb2c32014-01-16 06:57:2517#include "testing/gtest/include/gtest/gtest.h"
18
avi9b6f42932015-12-26 22:15:1419#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS)
20#include <mmintrin.h>
21#endif
22
[email protected]5bfecbc2014-02-27 13:49:0423using std::numeric_limits;
24using base::CheckedNumeric;
jschuh23a4b062016-12-02 02:55:0825using base::IsValidForType;
26using base::ValueOrDieForType;
27using base::ValueOrDefaultForType;
jschuh4bc919cb52016-12-04 15:08:2728using base::MakeCheckedNum;
jschuh711ac6a2016-12-04 07:17:4829using base::CheckMax;
30using base::CheckMin;
jschuh4fcd6fa2016-11-24 11:58:3931using base::CheckAdd;
32using base::CheckSub;
33using base::CheckMul;
34using base::CheckDiv;
35using base::CheckMod;
36using base::CheckLsh;
37using base::CheckRsh;
[email protected]5bfecbc2014-02-27 13:49:0438using base::checked_cast;
jschuhfafe0712015-09-14 20:21:2439using base::IsValueInRangeForNumericType;
jschuh07345e62015-09-22 22:13:3640using base::IsValueNegative;
jschuh4bf22c6d2015-05-28 02:29:2541using base::SizeT;
42using base::StrictNumeric;
jschuh711ac6a2016-12-04 07:17:4843using base::MakeStrictNum;
[email protected]5bfecbc2014-02-27 13:49:0444using base::saturated_cast;
jschuh4bf22c6d2015-05-28 02:29:2545using base::strict_cast;
[email protected]5bfecbc2014-02-27 13:49:0446using base::internal::MaxExponent;
jschuh5030b002016-12-05 18:21:4847using base::internal::IntegerBitsPlusSign;
[email protected]5bfecbc2014-02-27 13:49:0448using base::internal::RANGE_VALID;
49using base::internal::RANGE_INVALID;
50using base::internal::RANGE_OVERFLOW;
51using base::internal::RANGE_UNDERFLOW;
[email protected]5bfecbc2014-02-27 13:49:0452
jschuh3ab54042016-11-17 06:58:4453// These tests deliberately cause arithmetic boundary errors. If the compiler is
54// aggressive enough, it can const detect these errors, so we disable warnings.
[email protected]b6bf5c322014-08-09 05:24:0255#if defined(OS_WIN)
jschuh3ab54042016-11-17 06:58:4456#pragma warning(disable : 4756) // Arithmetic overflow.
57#pragma warning(disable : 4293) // Invalid shift.
[email protected]b6bf5c322014-08-09 05:24:0258#endif
59
jschuhfafe0712015-09-14 20:21:2460// This is a helper function for finding the maximum value in Src that can be
61// wholy represented as the destination floating-point type.
62template <typename Dst, typename Src>
63Dst GetMaxConvertibleToFloat() {
jschuh5030b002016-12-05 18:21:4864 using DstLimits = numeric_limits<Dst>;
65 using SrcLimits = numeric_limits<Src>;
jschuhfafe0712015-09-14 20:21:2466 static_assert(SrcLimits::is_specialized, "Source must be numeric.");
67 static_assert(DstLimits::is_specialized, "Destination must be numeric.");
68 CHECK(DstLimits::is_iec559);
69
70 if (SrcLimits::digits <= DstLimits::digits &&
71 MaxExponent<Src>::value <= MaxExponent<Dst>::value)
72 return SrcLimits::max();
73 Src max = SrcLimits::max() / 2 + (SrcLimits::is_integer ? 1 : 0);
74 while (max != static_cast<Src>(static_cast<Dst>(max))) {
75 max /= 2;
76 }
77 return static_cast<Dst>(max);
78}
79
jschuhd1c1f2e2016-11-21 21:45:4880namespace base {
81namespace internal {
82template <typename U>
83U GetNumericValueForTest(const CheckedNumeric<U>& src) {
84 return src.state_.value();
85}
86} // namespace internal.
87} // namespace base.
88
89using base::internal::GetNumericValueForTest;
90
jschuh224f1d72016-11-25 20:08:4891// Logs the ValueOrDie() failure instead of crashing.
92struct LogOnFailure {
93 template <typename T>
94 static T HandleFailure() {
95 LOG(WARNING) << "ValueOrDie() failed unexpectedly.";
96 return T();
97 }
98};
99
[email protected]5bfecbc2014-02-27 13:49:04100// Helper macros to wrap displaying the conversion types and line numbers.
101#define TEST_EXPECTED_VALIDITY(expected, actual) \
jschuh4fcd6fa2016-11-24 11:58:39102 EXPECT_EQ(expected, (actual).template Cast<Dst>().IsValid()) \
jschuhd1c1f2e2016-11-21 21:45:48103 << "Result test: Value " << GetNumericValueForTest(actual) << " as " \
104 << dst << " on line " << line
[email protected]5bfecbc2014-02-27 13:49:04105
jschuh819c8262016-05-21 01:39:03106#define TEST_EXPECTED_SUCCESS(actual) TEST_EXPECTED_VALIDITY(true, actual)
107#define TEST_EXPECTED_FAILURE(actual) TEST_EXPECTED_VALIDITY(false, actual)
108
jschuhba3c4f942016-12-10 14:03:55109// We have to handle promotions, so infer the underlying type below from actual.
110#define TEST_EXPECTED_VALUE(expected, actual) \
111 EXPECT_EQ(static_cast<typename std::decay<decltype(actual)>::type::type>( \
112 expected), \
113 ((actual) \
114 .template ValueOrDie< \
115 typename std::decay<decltype(actual)>::type::type, \
116 LogOnFailure>())) \
117 << "Result test: Value " << GetNumericValueForTest(actual) << " as " \
jschuhd1c1f2e2016-11-21 21:45:48118 << dst << " on line " << line
[email protected]5bfecbc2014-02-27 13:49:04119
jschuh23a4b062016-12-02 02:55:08120// Test the simple pointer arithmetic overrides.
121template <typename Dst>
122void TestStrictPointerMath() {
123 Dst dummy_value = 0;
124 Dst* dummy_ptr = &dummy_value;
125 static const Dst kDummyOffset = 2; // Don't want to go too far.
126 EXPECT_EQ(dummy_ptr + kDummyOffset,
127 dummy_ptr + StrictNumeric<Dst>(kDummyOffset));
128 EXPECT_EQ(dummy_ptr - kDummyOffset,
129 dummy_ptr - StrictNumeric<Dst>(kDummyOffset));
130 EXPECT_NE(dummy_ptr, dummy_ptr + StrictNumeric<Dst>(kDummyOffset));
131 EXPECT_NE(dummy_ptr, dummy_ptr - StrictNumeric<Dst>(kDummyOffset));
132 EXPECT_DEATH_IF_SUPPORTED(
133 dummy_ptr + StrictNumeric<size_t>(std::numeric_limits<size_t>::max()),
134 "");
135}
136
[email protected]5bfecbc2014-02-27 13:49:04137// Signed integer arithmetic.
138template <typename Dst>
139static void TestSpecializedArithmetic(
140 const char* dst,
141 int line,
vmpstr98a2fad2015-11-30 20:15:17142 typename std::enable_if<numeric_limits<Dst>::is_integer &&
143 numeric_limits<Dst>::is_signed,
144 int>::type = 0) {
jschuh5030b002016-12-05 18:21:48145 using DstLimits = numeric_limits<Dst>;
146 TEST_EXPECTED_FAILURE(-CheckedNumeric<Dst>(DstLimits::lowest()));
147 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
[email protected]5bfecbc2014-02-27 13:49:04148 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
jschuhba3c4f942016-12-10 14:03:55149 TEST_EXPECTED_VALUE(DstLimits::max(),
150 MakeCheckedNum(-DstLimits::max()).Abs());
[email protected]5bfecbc2014-02-27 13:49:04151
jschuh819c8262016-05-21 01:39:03152 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + -1);
jschuh5030b002016-12-05 18:21:48153 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
154 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) +
155 DstLimits::lowest());
[email protected]5bfecbc2014-02-27 13:49:04156
jschuh5030b002016-12-05 18:21:48157 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) - 1);
158 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) - -1);
jschuh819c8262016-05-21 01:39:03159 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) -
jschuh5030b002016-12-05 18:21:48160 DstLimits::lowest());
161 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) -
jschuh819c8262016-05-21 01:39:03162 DstLimits::max());
[email protected]5bfecbc2014-02-27 13:49:04163
jschuh5030b002016-12-05 18:21:48164 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
[email protected]5bfecbc2014-02-27 13:49:04165
jschuh5030b002016-12-05 18:21:48166 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) / -1);
[email protected]5bfecbc2014-02-27 13:49:04167 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) / 2);
jschuh5030b002016-12-05 18:21:48168 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * -1);
jschuhba3c4f942016-12-10 14:03:55169 TEST_EXPECTED_VALUE(DstLimits::lowest(),
170 MakeCheckedNum(DstLimits::lowest()).UnsignedAbs());
171 TEST_EXPECTED_VALUE(DstLimits::max(),
172 MakeCheckedNum(DstLimits::max()).UnsignedAbs());
173 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0).UnsignedAbs());
174 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).UnsignedAbs());
175 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).UnsignedAbs());
[email protected]5bfecbc2014-02-27 13:49:04176
177 // Modulus is legal only for integers.
178 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
179 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
180 TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % 2);
jschuh819c8262016-05-21 01:39:03181 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-1) % -2);
jschuh5030b002016-12-05 18:21:48182 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % 2);
[email protected]5bfecbc2014-02-27 13:49:04183 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
184 // Test all the different modulus combinations.
185 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
186 TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
187 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
188 CheckedNumeric<Dst> checked_dst = 1;
189 TEST_EXPECTED_VALUE(0, checked_dst %= 1);
tsepezdfd77a92016-11-02 20:18:06190 // Test that div by 0 is avoided but returns invalid result.
191 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) % 0);
jschuh3ab54042016-11-17 06:58:44192 // Test bit shifts.
193 volatile Dst negative_one = -1;
194 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) << negative_one);
jschuh5030b002016-12-05 18:21:48195 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
196 << (IntegerBitsPlusSign<Dst>::value - 1));
197 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(0)
198 << IntegerBitsPlusSign<Dst>::value);
jschuh3ab54042016-11-17 06:58:44199 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) << 1);
jschuh5030b002016-12-05 18:21:48200 TEST_EXPECTED_VALUE(
201 static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2),
202 CheckedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2));
jschuh3ab54042016-11-17 06:58:44203 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0)
jschuh5030b002016-12-05 18:21:48204 << (IntegerBitsPlusSign<Dst>::value - 1));
jschuh3ab54042016-11-17 06:58:44205 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) << 0);
206 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1);
jschuh5030b002016-12-05 18:21:48207 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >>
208 IntegerBitsPlusSign<Dst>::value);
209 TEST_EXPECTED_VALUE(
210 0, CheckedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1));
jschuh3ab54042016-11-17 06:58:44211 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one);
jschuh23a4b062016-12-02 02:55:08212
213 TestStrictPointerMath<Dst>();
[email protected]5bfecbc2014-02-27 13:49:04214}
215
216// Unsigned integer arithmetic.
217template <typename Dst>
218static void TestSpecializedArithmetic(
219 const char* dst,
220 int line,
vmpstr98a2fad2015-11-30 20:15:17221 typename std::enable_if<numeric_limits<Dst>::is_integer &&
222 !numeric_limits<Dst>::is_signed,
223 int>::type = 0) {
jschuh5030b002016-12-05 18:21:48224 using DstLimits = numeric_limits<Dst>;
225 TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::lowest()));
226 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
227 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
228 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) - 1);
229 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
[email protected]5bfecbc2014-02-27 13:49:04230 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) / 2);
jschuh5030b002016-12-05 18:21:48231 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).UnsignedAbs());
jschuh819c8262016-05-21 01:39:03232 TEST_EXPECTED_SUCCESS(
jschuh5030b002016-12-05 18:21:48233 CheckedNumeric<typename std::make_signed<Dst>::type>(
234 std::numeric_limits<typename std::make_signed<Dst>::type>::lowest())
jschuheaf375f2015-09-17 01:04:28235 .UnsignedAbs());
jschuhba3c4f942016-12-10 14:03:55236 TEST_EXPECTED_VALUE(DstLimits::lowest(),
237 MakeCheckedNum(DstLimits::lowest()).UnsignedAbs());
238 TEST_EXPECTED_VALUE(DstLimits::max(),
239 MakeCheckedNum(DstLimits::max()).UnsignedAbs());
240 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0).UnsignedAbs());
241 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).UnsignedAbs());
[email protected]5bfecbc2014-02-27 13:49:04242
243 // Modulus is legal only for integers.
244 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
245 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
246 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % 2);
jschuh5030b002016-12-05 18:21:48247 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % 2);
[email protected]5bfecbc2014-02-27 13:49:04248 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
249 // Test all the different modulus combinations.
250 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
251 TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
252 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
253 CheckedNumeric<Dst> checked_dst = 1;
254 TEST_EXPECTED_VALUE(0, checked_dst %= 1);
tsepezdfd77a92016-11-02 20:18:06255 // Test that div by 0 is avoided but returns invalid result.
256 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) % 0);
jschuh5030b002016-12-05 18:21:48257 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
258 << IntegerBitsPlusSign<Dst>::value);
jschuh3ab54042016-11-17 06:58:44259 // Test bit shifts.
260 volatile int negative_one = -1;
261 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) << negative_one);
jschuh5030b002016-12-05 18:21:48262 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
263 << IntegerBitsPlusSign<Dst>::value);
264 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(0)
265 << IntegerBitsPlusSign<Dst>::value);
jschuh3ab54042016-11-17 06:58:44266 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) << 1);
jschuh5030b002016-12-05 18:21:48267 TEST_EXPECTED_VALUE(
268 static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1),
269 CheckedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1));
jschuh3ab54042016-11-17 06:58:44270 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) << 0);
271 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1);
jschuh5030b002016-12-05 18:21:48272 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >>
273 IntegerBitsPlusSign<Dst>::value);
274 TEST_EXPECTED_VALUE(
275 0, CheckedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1));
jschuh3ab54042016-11-17 06:58:44276 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one);
jschuhb6737bb2016-11-29 03:06:59277 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) & 1);
278 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) & 0);
279 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) & 1);
280 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) & 0);
281 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
jschuh4bc919cb52016-12-04 15:08:27282 MakeCheckedNum(DstLimits::max()) & -1);
jschuhb6737bb2016-11-29 03:06:59283 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) | 1);
284 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) | 0);
285 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) | 1);
286 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) | 0);
287 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
288 CheckedNumeric<Dst>(0) | static_cast<Dst>(-1));
289 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) ^ 1);
290 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) ^ 0);
291 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) ^ 1);
292 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) ^ 0);
293 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
294 CheckedNumeric<Dst>(0) ^ static_cast<Dst>(-1));
jschuh970313c2016-11-24 21:40:58295 TEST_EXPECTED_VALUE(DstLimits::max(), ~CheckedNumeric<Dst>(0));
jschuh23a4b062016-12-02 02:55:08296
297 TestStrictPointerMath<Dst>();
[email protected]5bfecbc2014-02-27 13:49:04298}
299
300// Floating point arithmetic.
301template <typename Dst>
302void TestSpecializedArithmetic(
303 const char* dst,
304 int line,
vmpstr98a2fad2015-11-30 20:15:17305 typename std::enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0) {
jschuh5030b002016-12-05 18:21:48306 using DstLimits = numeric_limits<Dst>;
307 TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::lowest()));
[email protected]5bfecbc2014-02-27 13:49:04308
jschuh5030b002016-12-05 18:21:48309 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
[email protected]5bfecbc2014-02-27 13:49:04310 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
311
jschuh5030b002016-12-05 18:21:48312 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
jschuh819c8262016-05-21 01:39:03313 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + 1);
jschuh5030b002016-12-05 18:21:48314 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) +
315 DstLimits::lowest());
[email protected]5bfecbc2014-02-27 13:49:04316
jschuh819c8262016-05-21 01:39:03317 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) -
jschuh5030b002016-12-05 18:21:48318 DstLimits::lowest());
319 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) -
jschuh819c8262016-05-21 01:39:03320 DstLimits::max());
[email protected]5bfecbc2014-02-27 13:49:04321
jschuh5030b002016-12-05 18:21:48322 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
[email protected]5bfecbc2014-02-27 13:49:04323
324 TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2);
[email protected]5bfecbc2014-02-27 13:49:04325}
326
327// Generic arithmetic tests.
328template <typename Dst>
329static void TestArithmetic(const char* dst, int line) {
jschuh5030b002016-12-05 18:21:48330 using DstLimits = numeric_limits<Dst>;
[email protected]5bfecbc2014-02-27 13:49:04331
332 EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid());
333 EXPECT_EQ(false,
334 CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
335 DstLimits::max()).IsValid());
336 EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDie());
337 EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDefault(1));
338 EXPECT_EQ(static_cast<Dst>(1),
339 CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
340 DstLimits::max()).ValueOrDefault(1));
341
342 // Test the operator combinations.
343 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + CheckedNumeric<Dst>(1));
344 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - CheckedNumeric<Dst>(1));
345 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * CheckedNumeric<Dst>(1));
346 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / CheckedNumeric<Dst>(1));
347 TEST_EXPECTED_VALUE(2, 1 + CheckedNumeric<Dst>(1));
348 TEST_EXPECTED_VALUE(0, 1 - CheckedNumeric<Dst>(1));
349 TEST_EXPECTED_VALUE(1, 1 * CheckedNumeric<Dst>(1));
350 TEST_EXPECTED_VALUE(1, 1 / CheckedNumeric<Dst>(1));
351 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + 1);
352 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - 1);
353 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * 1);
354 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
355 CheckedNumeric<Dst> checked_dst = 1;
356 TEST_EXPECTED_VALUE(2, checked_dst += 1);
357 checked_dst = 1;
358 TEST_EXPECTED_VALUE(0, checked_dst -= 1);
359 checked_dst = 1;
360 TEST_EXPECTED_VALUE(1, checked_dst *= 1);
361 checked_dst = 1;
362 TEST_EXPECTED_VALUE(1, checked_dst /= 1);
363
364 // Generic negation.
jschuh749c7f72016-09-07 16:22:26365 if (DstLimits::is_signed) {
366 TEST_EXPECTED_VALUE(0, -CheckedNumeric<Dst>());
367 TEST_EXPECTED_VALUE(-1, -CheckedNumeric<Dst>(1));
368 TEST_EXPECTED_VALUE(1, -CheckedNumeric<Dst>(-1));
369 TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1),
370 -CheckedNumeric<Dst>(DstLimits::max()));
371 }
[email protected]5bfecbc2014-02-27 13:49:04372
373 // Generic absolute value.
374 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>().Abs());
375 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).Abs());
376 TEST_EXPECTED_VALUE(DstLimits::max(),
377 CheckedNumeric<Dst>(DstLimits::max()).Abs());
378
379 // Generic addition.
380 TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>() + 1));
381 TEST_EXPECTED_VALUE(2, (CheckedNumeric<Dst>(1) + 1));
jschuh216b62a92016-11-08 03:53:08382 if (numeric_limits<Dst>::is_signed)
383 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) + 1));
jschuh5030b002016-12-05 18:21:48384 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) + 1);
jschuh819c8262016-05-21 01:39:03385 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) +
386 DstLimits::max());
[email protected]5bfecbc2014-02-27 13:49:04387
388 // Generic subtraction.
[email protected]5bfecbc2014-02-27 13:49:04389 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(1) - 1));
jschuh819c8262016-05-21 01:39:03390 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) - 1);
jschuh216b62a92016-11-08 03:53:08391 if (numeric_limits<Dst>::is_signed) {
392 TEST_EXPECTED_VALUE(-1, (CheckedNumeric<Dst>() - 1));
393 TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) - 1));
jschuh657a3d62016-11-15 18:23:45394 } else {
395 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - -1);
jschuh216b62a92016-11-08 03:53:08396 }
[email protected]5bfecbc2014-02-27 13:49:04397
398 // Generic multiplication.
399 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>() * 1));
400 TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>(1) * 1));
eroman0397125f2015-05-18 14:44:32401 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * 0));
jschuh216b62a92016-11-08 03:53:08402 if (numeric_limits<Dst>::is_signed) {
403 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) * 0));
404 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * -1));
jschuh749c7f72016-09-07 16:22:26405 TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) * 2));
jschuh657a3d62016-11-15 18:23:45406 } else {
407 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) * -2);
408 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) *
409 CheckedNumeric<uintmax_t>(-2));
jschuh749c7f72016-09-07 16:22:26410 }
jschuh216b62a92016-11-08 03:53:08411 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) *
412 DstLimits::max());
[email protected]5bfecbc2014-02-27 13:49:04413
414 // Generic division.
415 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() / 1);
416 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
jschuh5030b002016-12-05 18:21:48417 TEST_EXPECTED_VALUE(DstLimits::lowest() / 2,
418 CheckedNumeric<Dst>(DstLimits::lowest()) / 2);
[email protected]5bfecbc2014-02-27 13:49:04419 TEST_EXPECTED_VALUE(DstLimits::max() / 2,
420 CheckedNumeric<Dst>(DstLimits::max()) / 2);
421
422 TestSpecializedArithmetic<Dst>(dst, line);
423}
424
425// Helper macro to wrap displaying the conversion types and line numbers.
426#define TEST_ARITHMETIC(Dst) TestArithmetic<Dst>(#Dst, __LINE__)
427
428TEST(SafeNumerics, SignedIntegerMath) {
429 TEST_ARITHMETIC(int8_t);
430 TEST_ARITHMETIC(int);
431 TEST_ARITHMETIC(intptr_t);
432 TEST_ARITHMETIC(intmax_t);
433}
434
435TEST(SafeNumerics, UnsignedIntegerMath) {
436 TEST_ARITHMETIC(uint8_t);
437 TEST_ARITHMETIC(unsigned int);
438 TEST_ARITHMETIC(uintptr_t);
439 TEST_ARITHMETIC(uintmax_t);
440}
441
442TEST(SafeNumerics, FloatingPointMath) {
443 TEST_ARITHMETIC(float);
444 TEST_ARITHMETIC(double);
445}
[email protected]c1c090d32013-01-16 23:34:04446
[email protected]4efb2c32014-01-16 06:57:25447// Enumerates the five different conversions types we need to test.
448enum NumericConversionType {
449 SIGN_PRESERVING_VALUE_PRESERVING,
450 SIGN_PRESERVING_NARROW,
451 SIGN_TO_UNSIGN_WIDEN_OR_EQUAL,
452 SIGN_TO_UNSIGN_NARROW,
453 UNSIGN_TO_SIGN_NARROW_OR_EQUAL,
454};
[email protected]c1c090d32013-01-16 23:34:04455
[email protected]4efb2c32014-01-16 06:57:25456// Template covering the different conversion tests.
457template <typename Dst, typename Src, NumericConversionType conversion>
458struct TestNumericConversion {};
[email protected]c1c090d32013-01-16 23:34:04459
[email protected]5bfecbc2014-02-27 13:49:04460// EXPECT_EQ wrappers providing specific detail on test failures.
461#define TEST_EXPECTED_RANGE(expected, actual) \
462 EXPECT_EQ(expected, base::internal::DstRangeRelationToSrcRange<Dst>(actual)) \
463 << "Conversion test: " << src << " value " << actual << " to " << dst \
jschuh657a3d62016-11-15 18:23:45464 << " on line " << line
[email protected]4efb2c32014-01-16 06:57:25465
466template <typename Dst, typename Src>
jschuh23a4b062016-12-02 02:55:08467void TestStrictComparison() {
jschuh5030b002016-12-05 18:21:48468 using DstLimits = numeric_limits<Dst>;
469 using SrcLimits = numeric_limits<Src>;
jschuh711ac6a2016-12-04 07:17:48470 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) < DstLimits::max(), "");
471 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) < SrcLimits::max(), "");
472 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) >= DstLimits::max()),
jschuh23a4b062016-12-02 02:55:08473 "");
jschuh711ac6a2016-12-04 07:17:48474 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) >= SrcLimits::max()),
jschuh23a4b062016-12-02 02:55:08475 "");
jschuh711ac6a2016-12-04 07:17:48476 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) <= DstLimits::max(),
jschuh23a4b062016-12-02 02:55:08477 "");
jschuh711ac6a2016-12-04 07:17:48478 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) <= SrcLimits::max(),
jschuh23a4b062016-12-02 02:55:08479 "");
jschuh711ac6a2016-12-04 07:17:48480 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) > DstLimits::max()),
481 "");
482 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) > SrcLimits::max()),
483 "");
484 static_assert(StrictNumeric<Src>(SrcLimits::max()) > DstLimits::lowest(), "");
485 static_assert(StrictNumeric<Src>(SrcLimits::max()) > SrcLimits::lowest(), "");
486 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) <= DstLimits::lowest()),
487 "");
488 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) <= SrcLimits::lowest()),
489 "");
490 static_assert(StrictNumeric<Src>(SrcLimits::max()) >= DstLimits::lowest(),
491 "");
492 static_assert(StrictNumeric<Src>(SrcLimits::max()) >= SrcLimits::lowest(),
493 "");
494 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) < DstLimits::lowest()),
495 "");
496 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) < SrcLimits::lowest()),
497 "");
jschuh23a4b062016-12-02 02:55:08498 static_assert(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(1),
499 "");
500 static_assert(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(0),
501 "");
502 static_assert(StrictNumeric<Src>(SrcLimits::max()) != static_cast<Dst>(0),
503 "");
jschuh711ac6a2016-12-04 07:17:48504 static_assert(StrictNumeric<Src>(SrcLimits::max()) != DstLimits::lowest(),
505 "");
jschuh23a4b062016-12-02 02:55:08506 static_assert(
507 !(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(1)), "");
508 static_assert(
509 !(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(0)), "");
jschuh711ac6a2016-12-04 07:17:48510
511 // Due to differences in float handling between compilers, these aren't
512 // compile-time constants everywhere. So, we use run-time tests.
jschuh4bc919cb52016-12-04 15:08:27513 EXPECT_EQ(
514 SrcLimits::max(),
515 MakeCheckedNum(SrcLimits::max()).Max(DstLimits::lowest()).ValueOrDie());
516 EXPECT_EQ(
517 DstLimits::max(),
518 MakeCheckedNum(SrcLimits::lowest()).Max(DstLimits::max()).ValueOrDie());
519 EXPECT_EQ(
520 DstLimits::lowest(),
521 MakeCheckedNum(SrcLimits::max()).Min(DstLimits::lowest()).ValueOrDie());
522 EXPECT_EQ(
523 SrcLimits::lowest(),
524 MakeCheckedNum(SrcLimits::lowest()).Min(DstLimits::max()).ValueOrDie());
525 EXPECT_EQ(SrcLimits::lowest(), CheckMin(MakeStrictNum(1), MakeCheckedNum(0),
jschuh711ac6a2016-12-04 07:17:48526 DstLimits::max(), SrcLimits::lowest())
527 .ValueOrDie());
jschuh4bc919cb52016-12-04 15:08:27528 EXPECT_EQ(DstLimits::max(), CheckMax(MakeStrictNum(1), MakeCheckedNum(0),
jschuh711ac6a2016-12-04 07:17:48529 DstLimits::max(), SrcLimits::lowest())
530 .ValueOrDie());
jschuh23a4b062016-12-02 02:55:08531}
532
533template <typename Dst, typename Src>
[email protected]4efb2c32014-01-16 06:57:25534struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> {
535 static void Test(const char *dst, const char *src, int line) {
jschuh5030b002016-12-05 18:21:48536 using SrcLimits = numeric_limits<Src>;
537 using DstLimits = numeric_limits<Dst>;
538 // Integral to floating.
jschuhd2d9fe02014-10-14 14:31:37539 static_assert((DstLimits::is_iec559 && SrcLimits::is_integer) ||
jschuh5030b002016-12-05 18:21:48540 // Not floating to integral and...
541 (!(DstLimits::is_integer && SrcLimits::is_iec559) &&
542 // Same sign, same numeric, source is narrower or same.
543 ((SrcLimits::is_signed == DstLimits::is_signed &&
544 MaxExponent<Dst>::value >= MaxExponent<Src>::value) ||
545 // Or signed destination and source is smaller
546 (DstLimits::is_signed &&
547 MaxExponent<Dst>::value >= MaxExponent<Src>::value))),
jschuhd2d9fe02014-10-14 14:31:37548 "Comparison must be sign preserving and value preserving");
[email protected]4efb2c32014-01-16 06:57:25549
jschuh23a4b062016-12-02 02:55:08550 TestStrictComparison<Dst, Src>();
551
[email protected]5bfecbc2014-02-27 13:49:04552 const CheckedNumeric<Dst> checked_dst = SrcLimits::max();
jschuh819c8262016-05-21 01:39:03553 TEST_EXPECTED_SUCCESS(checked_dst);
[email protected]5bfecbc2014-02-27 13:49:04554 if (MaxExponent<Dst>::value > MaxExponent<Src>::value) {
555 if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1) {
556 // At least twice larger type.
jschuh819c8262016-05-21 01:39:03557 TEST_EXPECTED_SUCCESS(SrcLimits::max() * checked_dst);
[email protected]5bfecbc2014-02-27 13:49:04558
559 } else { // Larger, but not at least twice as large.
jschuh819c8262016-05-21 01:39:03560 TEST_EXPECTED_FAILURE(SrcLimits::max() * checked_dst);
561 TEST_EXPECTED_SUCCESS(checked_dst + 1);
[email protected]5bfecbc2014-02-27 13:49:04562 }
563 } else { // Same width type.
jschuh819c8262016-05-21 01:39:03564 TEST_EXPECTED_FAILURE(checked_dst + 1);
[email protected]5bfecbc2014-02-27 13:49:04565 }
566
567 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
568 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
[email protected]4efb2c32014-01-16 06:57:25569 if (SrcLimits::is_iec559) {
[email protected]5bfecbc2014-02-27 13:49:04570 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max() * static_cast<Src>(-1));
571 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
572 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
573 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
[email protected]5bfecbc2014-02-27 13:49:04574 } else if (numeric_limits<Src>::is_signed) {
575 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
jschuh5030b002016-12-05 18:21:48576 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
[email protected]4efb2c32014-01-16 06:57:25577 }
[email protected]c1c090d32013-01-16 23:34:04578 }
[email protected]4efb2c32014-01-16 06:57:25579};
580
581template <typename Dst, typename Src>
582struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> {
583 static void Test(const char *dst, const char *src, int line) {
jschuh5030b002016-12-05 18:21:48584 using SrcLimits = numeric_limits<Src>;
585 using DstLimits = numeric_limits<Dst>;
jschuhd2d9fe02014-10-14 14:31:37586 static_assert(SrcLimits::is_signed == DstLimits::is_signed,
587 "Destination and source sign must be the same");
jschuh5030b002016-12-05 18:21:48588 static_assert(MaxExponent<Dst>::value <= MaxExponent<Src>::value,
jschuhd2d9fe02014-10-14 14:31:37589 "Destination must be narrower than source");
[email protected]4efb2c32014-01-16 06:57:25590
jschuh23a4b062016-12-02 02:55:08591 TestStrictComparison<Dst, Src>();
592
[email protected]5bfecbc2014-02-27 13:49:04593 const CheckedNumeric<Dst> checked_dst;
jschuh819c8262016-05-21 01:39:03594 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
[email protected]5bfecbc2014-02-27 13:49:04595 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
jschuh819c8262016-05-21 01:39:03596 TEST_EXPECTED_FAILURE(checked_dst - SrcLimits::max());
[email protected]5bfecbc2014-02-27 13:49:04597
598 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
599 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
[email protected]4efb2c32014-01-16 06:57:25600 if (SrcLimits::is_iec559) {
[email protected]5bfecbc2014-02-27 13:49:04601 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
602 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
603 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
604 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
605 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
jschuhfafe0712015-09-14 20:21:24606 if (DstLimits::is_integer) {
607 if (SrcLimits::digits < DstLimits::digits) {
608 TEST_EXPECTED_RANGE(RANGE_OVERFLOW,
609 static_cast<Src>(DstLimits::max()));
610 } else {
611 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
612 }
613 TEST_EXPECTED_RANGE(
614 RANGE_VALID,
615 static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
jschuh5030b002016-12-05 18:21:48616 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::lowest()));
jschuhfafe0712015-09-14 20:21:24617 }
[email protected]4efb2c32014-01-16 06:57:25618 } else if (SrcLimits::is_signed) {
[email protected]5bfecbc2014-02-27 13:49:04619 TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1));
jschuh5030b002016-12-05 18:21:48620 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
[email protected]5bfecbc2014-02-27 13:49:04621 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
[email protected]4efb2c32014-01-16 06:57:25622 } else {
jschuh819c8262016-05-21 01:39:03623 TEST_EXPECTED_FAILURE(checked_dst - static_cast<Src>(1));
jschuh5030b002016-12-05 18:21:48624 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
[email protected]4efb2c32014-01-16 06:57:25625 }
626 }
627};
628
629template <typename Dst, typename Src>
630struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> {
631 static void Test(const char *dst, const char *src, int line) {
jschuh5030b002016-12-05 18:21:48632 using SrcLimits = numeric_limits<Src>;
633 using DstLimits = numeric_limits<Dst>;
634 static_assert(MaxExponent<Dst>::value >= MaxExponent<Src>::value,
jschuhd2d9fe02014-10-14 14:31:37635 "Destination must be equal or wider than source.");
636 static_assert(SrcLimits::is_signed, "Source must be signed");
637 static_assert(!DstLimits::is_signed, "Destination must be unsigned");
[email protected]4efb2c32014-01-16 06:57:25638
jschuh23a4b062016-12-02 02:55:08639 TestStrictComparison<Dst, Src>();
640
[email protected]5bfecbc2014-02-27 13:49:04641 const CheckedNumeric<Dst> checked_dst;
642 TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max());
jschuh819c8262016-05-21 01:39:03643 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
jschuh5030b002016-12-05 18:21:48644 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::lowest());
[email protected]5bfecbc2014-02-27 13:49:04645
jschuh5030b002016-12-05 18:21:48646 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
[email protected]5bfecbc2014-02-27 13:49:04647 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
648 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
649 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
[email protected]4efb2c32014-01-16 06:57:25650 }
651};
652
653template <typename Dst, typename Src>
654struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> {
655 static void Test(const char *dst, const char *src, int line) {
jschuh5030b002016-12-05 18:21:48656 using SrcLimits = numeric_limits<Src>;
657 using DstLimits = numeric_limits<Dst>;
658 static_assert(MaxExponent<Dst>::value < MaxExponent<Src>::value,
jschuhd2d9fe02014-10-14 14:31:37659 "Destination must be narrower than source.");
660 static_assert(SrcLimits::is_signed, "Source must be signed.");
661 static_assert(!DstLimits::is_signed, "Destination must be unsigned.");
[email protected]4efb2c32014-01-16 06:57:25662
jschuh23a4b062016-12-02 02:55:08663 TestStrictComparison<Dst, Src>();
664
[email protected]5bfecbc2014-02-27 13:49:04665 const CheckedNumeric<Dst> checked_dst;
666 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
jschuh819c8262016-05-21 01:39:03667 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
668 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
jschuh5030b002016-12-05 18:21:48669 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::lowest());
[email protected]5bfecbc2014-02-27 13:49:04670
671 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
672 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
673 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
jschuhe3bd1f62016-12-20 05:11:30674
675 // Additional saturation tests.
676 EXPECT_EQ(DstLimits::max(), saturated_cast<Dst>(SrcLimits::max()));
677 EXPECT_EQ(DstLimits::lowest(), saturated_cast<Dst>(SrcLimits::lowest()));
678
[email protected]4efb2c32014-01-16 06:57:25679 if (SrcLimits::is_iec559) {
jschuhe3bd1f62016-12-20 05:11:30680 EXPECT_EQ(Dst(0), saturated_cast<Dst>(SrcLimits::quiet_NaN()));
681
[email protected]5bfecbc2014-02-27 13:49:04682 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
683 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
684 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
685 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
jschuhfafe0712015-09-14 20:21:24686 if (DstLimits::is_integer) {
687 if (SrcLimits::digits < DstLimits::digits) {
688 TEST_EXPECTED_RANGE(RANGE_OVERFLOW,
689 static_cast<Src>(DstLimits::max()));
690 } else {
691 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
692 }
693 TEST_EXPECTED_RANGE(
694 RANGE_VALID,
695 static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
jschuh5030b002016-12-05 18:21:48696 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::lowest()));
jschuhfafe0712015-09-14 20:21:24697 }
[email protected]4efb2c32014-01-16 06:57:25698 } else {
jschuh5030b002016-12-05 18:21:48699 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
[email protected]4efb2c32014-01-16 06:57:25700 }
701 }
702};
703
704template <typename Dst, typename Src>
705struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> {
706 static void Test(const char *dst, const char *src, int line) {
jschuh5030b002016-12-05 18:21:48707 using SrcLimits = numeric_limits<Src>;
708 using DstLimits = numeric_limits<Dst>;
709 static_assert(MaxExponent<Dst>::value <= MaxExponent<Src>::value,
jschuhd2d9fe02014-10-14 14:31:37710 "Destination must be narrower or equal to source.");
711 static_assert(!SrcLimits::is_signed, "Source must be unsigned.");
712 static_assert(DstLimits::is_signed, "Destination must be signed.");
[email protected]4efb2c32014-01-16 06:57:25713
jschuh23a4b062016-12-02 02:55:08714 TestStrictComparison<Dst, Src>();
715
[email protected]5bfecbc2014-02-27 13:49:04716 const CheckedNumeric<Dst> checked_dst;
717 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
jschuh819c8262016-05-21 01:39:03718 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
jschuh5030b002016-12-05 18:21:48719 TEST_EXPECTED_VALUE(SrcLimits::lowest(), checked_dst + SrcLimits::lowest());
[email protected]5bfecbc2014-02-27 13:49:04720
jschuh5030b002016-12-05 18:21:48721 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
[email protected]5bfecbc2014-02-27 13:49:04722 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
723 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
jschuhe3bd1f62016-12-20 05:11:30724
725 // Additional saturation tests.
726 EXPECT_EQ(DstLimits::max(), saturated_cast<Dst>(SrcLimits::max()));
727 EXPECT_EQ(Dst(0), saturated_cast<Dst>(SrcLimits::lowest()));
[email protected]4efb2c32014-01-16 06:57:25728 }
729};
730
731// Helper macro to wrap displaying the conversion types and line numbers
732#define TEST_NUMERIC_CONVERSION(d, s, t) \
733 TestNumericConversion<d, s, t>::Test(#d, #s, __LINE__)
734
[email protected]5bfecbc2014-02-27 13:49:04735TEST(SafeNumerics, IntMinOperations) {
[email protected]4efb2c32014-01-16 06:57:25736 TEST_NUMERIC_CONVERSION(int8_t, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
737 TEST_NUMERIC_CONVERSION(uint8_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
738
739 TEST_NUMERIC_CONVERSION(int8_t, int, SIGN_PRESERVING_NARROW);
740 TEST_NUMERIC_CONVERSION(uint8_t, unsigned int, SIGN_PRESERVING_NARROW);
741 TEST_NUMERIC_CONVERSION(int8_t, float, SIGN_PRESERVING_NARROW);
742
743 TEST_NUMERIC_CONVERSION(uint8_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
744
745 TEST_NUMERIC_CONVERSION(uint8_t, int, SIGN_TO_UNSIGN_NARROW);
746 TEST_NUMERIC_CONVERSION(uint8_t, intmax_t, SIGN_TO_UNSIGN_NARROW);
747 TEST_NUMERIC_CONVERSION(uint8_t, float, SIGN_TO_UNSIGN_NARROW);
748
749 TEST_NUMERIC_CONVERSION(int8_t, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
750 TEST_NUMERIC_CONVERSION(int8_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
[email protected]c1c090d32013-01-16 23:34:04751}
752
[email protected]5bfecbc2014-02-27 13:49:04753TEST(SafeNumerics, IntOperations) {
[email protected]4efb2c32014-01-16 06:57:25754 TEST_NUMERIC_CONVERSION(int, int, SIGN_PRESERVING_VALUE_PRESERVING);
755 TEST_NUMERIC_CONVERSION(unsigned int, unsigned int,
756 SIGN_PRESERVING_VALUE_PRESERVING);
757 TEST_NUMERIC_CONVERSION(int, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
758 TEST_NUMERIC_CONVERSION(unsigned int, uint8_t,
759 SIGN_PRESERVING_VALUE_PRESERVING);
760 TEST_NUMERIC_CONVERSION(int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
761
762 TEST_NUMERIC_CONVERSION(int, intmax_t, SIGN_PRESERVING_NARROW);
763 TEST_NUMERIC_CONVERSION(unsigned int, uintmax_t, SIGN_PRESERVING_NARROW);
764 TEST_NUMERIC_CONVERSION(int, float, SIGN_PRESERVING_NARROW);
765 TEST_NUMERIC_CONVERSION(int, double, SIGN_PRESERVING_NARROW);
766
767 TEST_NUMERIC_CONVERSION(unsigned int, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
768 TEST_NUMERIC_CONVERSION(unsigned int, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
769
770 TEST_NUMERIC_CONVERSION(unsigned int, intmax_t, SIGN_TO_UNSIGN_NARROW);
771 TEST_NUMERIC_CONVERSION(unsigned int, float, SIGN_TO_UNSIGN_NARROW);
772 TEST_NUMERIC_CONVERSION(unsigned int, double, SIGN_TO_UNSIGN_NARROW);
773
774 TEST_NUMERIC_CONVERSION(int, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
775 TEST_NUMERIC_CONVERSION(int, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
[email protected]c1c090d32013-01-16 23:34:04776}
777
[email protected]5bfecbc2014-02-27 13:49:04778TEST(SafeNumerics, IntMaxOperations) {
[email protected]4efb2c32014-01-16 06:57:25779 TEST_NUMERIC_CONVERSION(intmax_t, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
780 TEST_NUMERIC_CONVERSION(uintmax_t, uintmax_t,
781 SIGN_PRESERVING_VALUE_PRESERVING);
782 TEST_NUMERIC_CONVERSION(intmax_t, int, SIGN_PRESERVING_VALUE_PRESERVING);
783 TEST_NUMERIC_CONVERSION(uintmax_t, unsigned int,
784 SIGN_PRESERVING_VALUE_PRESERVING);
785 TEST_NUMERIC_CONVERSION(intmax_t, unsigned int,
786 SIGN_PRESERVING_VALUE_PRESERVING);
787 TEST_NUMERIC_CONVERSION(intmax_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
788
789 TEST_NUMERIC_CONVERSION(intmax_t, float, SIGN_PRESERVING_NARROW);
790 TEST_NUMERIC_CONVERSION(intmax_t, double, SIGN_PRESERVING_NARROW);
791
792 TEST_NUMERIC_CONVERSION(uintmax_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
793 TEST_NUMERIC_CONVERSION(uintmax_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
794
795 TEST_NUMERIC_CONVERSION(uintmax_t, float, SIGN_TO_UNSIGN_NARROW);
796 TEST_NUMERIC_CONVERSION(uintmax_t, double, SIGN_TO_UNSIGN_NARROW);
797
798 TEST_NUMERIC_CONVERSION(intmax_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
799}
800
[email protected]5bfecbc2014-02-27 13:49:04801TEST(SafeNumerics, FloatOperations) {
[email protected]4efb2c32014-01-16 06:57:25802 TEST_NUMERIC_CONVERSION(float, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
803 TEST_NUMERIC_CONVERSION(float, uintmax_t,
804 SIGN_PRESERVING_VALUE_PRESERVING);
805 TEST_NUMERIC_CONVERSION(float, int, SIGN_PRESERVING_VALUE_PRESERVING);
806 TEST_NUMERIC_CONVERSION(float, unsigned int,
807 SIGN_PRESERVING_VALUE_PRESERVING);
808
809 TEST_NUMERIC_CONVERSION(float, double, SIGN_PRESERVING_NARROW);
810}
811
[email protected]5bfecbc2014-02-27 13:49:04812TEST(SafeNumerics, DoubleOperations) {
[email protected]4efb2c32014-01-16 06:57:25813 TEST_NUMERIC_CONVERSION(double, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
814 TEST_NUMERIC_CONVERSION(double, uintmax_t,
815 SIGN_PRESERVING_VALUE_PRESERVING);
816 TEST_NUMERIC_CONVERSION(double, int, SIGN_PRESERVING_VALUE_PRESERVING);
817 TEST_NUMERIC_CONVERSION(double, unsigned int,
818 SIGN_PRESERVING_VALUE_PRESERVING);
819}
820
[email protected]5bfecbc2014-02-27 13:49:04821TEST(SafeNumerics, SizeTOperations) {
[email protected]4efb2c32014-01-16 06:57:25822 TEST_NUMERIC_CONVERSION(size_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
823 TEST_NUMERIC_CONVERSION(int, size_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
824}
825
jschuh23a4b062016-12-02 02:55:08826// A one-off test to ensure StrictNumeric won't resolve to an incorrect type.
827// If this fails we'll just get a compiler error on an ambiguous overload.
828int TestOverload(int) { // Overload fails.
829 return 0;
830}
831uint8_t TestOverload(uint8_t) { // Overload fails.
832 return 0;
833}
834size_t TestOverload(size_t) { // Overload succeeds.
835 return 0;
836}
837
838static_assert(
839 std::is_same<decltype(TestOverload(StrictNumeric<int>())), int>::value,
840 "");
841static_assert(std::is_same<decltype(TestOverload(StrictNumeric<size_t>())),
842 size_t>::value,
843 "");
844
jschuh71b669a2016-12-17 01:13:31845template <typename T>
846struct CastTest1 {
847 static constexpr T HandleNaN() { return -1; }
848 static constexpr T max() { return numeric_limits<T>::max() - 1; }
849 static constexpr T HandleOverflow() { return max(); }
850 static constexpr T lowest() { return numeric_limits<T>::lowest() + 1; }
851 static constexpr T HandleUnderflow() { return lowest(); }
852};
853
854template <typename T>
855struct CastTest2 {
856 static constexpr T HandleNaN() { return 11; }
857 static constexpr T max() { return 10; }
858 static constexpr T HandleOverflow() { return max(); }
859 static constexpr T lowest() { return 1; }
860 static constexpr T HandleUnderflow() { return lowest(); }
861};
862
agrieve7772a0502016-12-16 18:18:48863TEST(SafeNumerics, CastTests) {
[email protected]4efb2c32014-01-16 06:57:25864// MSVC catches and warns that we're forcing saturation in these tests.
865// Since that's intentional, we need to shut this warning off.
866#if defined(COMPILER_MSVC)
867#pragma warning(disable : 4756)
[email protected]c1c090d32013-01-16 23:34:04868#endif
869
[email protected]c1c090d32013-01-16 23:34:04870 int small_positive = 1;
871 int small_negative = -1;
[email protected]4efb2c32014-01-16 06:57:25872 double double_small = 1.0;
[email protected]5bfecbc2014-02-27 13:49:04873 double double_large = numeric_limits<double>::max();
874 double double_infinity = numeric_limits<float>::infinity();
danakj3193742f2015-06-05 18:15:10875 double double_large_int = numeric_limits<int>::max();
jschuh5030b002016-12-05 18:21:48876 double double_small_int = numeric_limits<int>::lowest();
[email protected]c1c090d32013-01-16 23:34:04877
jschuh4bf22c6d2015-05-28 02:29:25878 // Just test that the casts compile, since the other tests cover logic.
[email protected]5bfecbc2014-02-27 13:49:04879 EXPECT_EQ(0, checked_cast<int>(static_cast<size_t>(0)));
jschuh4bf22c6d2015-05-28 02:29:25880 EXPECT_EQ(0, strict_cast<int>(static_cast<char>(0)));
881 EXPECT_EQ(0, strict_cast<int>(static_cast<unsigned char>(0)));
882 EXPECT_EQ(0U, strict_cast<unsigned>(static_cast<unsigned char>(0)));
883 EXPECT_EQ(1ULL, static_cast<uint64_t>(StrictNumeric<size_t>(1U)));
884 EXPECT_EQ(1ULL, static_cast<uint64_t>(SizeT(1U)));
885 EXPECT_EQ(1U, static_cast<size_t>(StrictNumeric<unsigned>(1U)));
886
887 EXPECT_TRUE(CheckedNumeric<uint64_t>(StrictNumeric<unsigned>(1U)).IsValid());
888 EXPECT_TRUE(CheckedNumeric<int>(StrictNumeric<unsigned>(1U)).IsValid());
889 EXPECT_FALSE(CheckedNumeric<unsigned>(StrictNumeric<int>(-1)).IsValid());
890
jschuh07345e62015-09-22 22:13:36891 EXPECT_TRUE(IsValueNegative(-1));
jschuh5030b002016-12-05 18:21:48892 EXPECT_TRUE(IsValueNegative(numeric_limits<int>::lowest()));
893 EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::lowest()));
894 EXPECT_TRUE(IsValueNegative(numeric_limits<double>::lowest()));
jschuh07345e62015-09-22 22:13:36895 EXPECT_FALSE(IsValueNegative(0));
896 EXPECT_FALSE(IsValueNegative(1));
897 EXPECT_FALSE(IsValueNegative(0u));
898 EXPECT_FALSE(IsValueNegative(1u));
899 EXPECT_FALSE(IsValueNegative(numeric_limits<int>::max()));
900 EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::max()));
901 EXPECT_FALSE(IsValueNegative(numeric_limits<double>::max()));
902
jschuh4bf22c6d2015-05-28 02:29:25903 // These casts and coercions will fail to compile:
904 // EXPECT_EQ(0, strict_cast<int>(static_cast<size_t>(0)));
905 // EXPECT_EQ(0, strict_cast<size_t>(static_cast<int>(0)));
906 // EXPECT_EQ(1ULL, StrictNumeric<size_t>(1));
907 // EXPECT_EQ(1, StrictNumeric<size_t>(1U));
[email protected]c1c090d32013-01-16 23:34:04908
[email protected]4efb2c32014-01-16 06:57:25909 // Test various saturation corner cases.
910 EXPECT_EQ(saturated_cast<int>(small_negative),
911 static_cast<int>(small_negative));
912 EXPECT_EQ(saturated_cast<int>(small_positive),
913 static_cast<int>(small_positive));
914 EXPECT_EQ(saturated_cast<unsigned>(small_negative),
915 static_cast<unsigned>(0));
916 EXPECT_EQ(saturated_cast<int>(double_small),
917 static_cast<int>(double_small));
[email protected]5bfecbc2014-02-27 13:49:04918 EXPECT_EQ(saturated_cast<int>(double_large), numeric_limits<int>::max());
[email protected]4efb2c32014-01-16 06:57:25919 EXPECT_EQ(saturated_cast<float>(double_large), double_infinity);
920 EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity);
jschuh5030b002016-12-05 18:21:48921 EXPECT_EQ(numeric_limits<int>::lowest(),
922 saturated_cast<int>(double_small_int));
danakj3193742f2015-06-05 18:15:10923 EXPECT_EQ(numeric_limits<int>::max(), saturated_cast<int>(double_large_int));
vmpstredf1e182015-12-14 20:09:42924
jschuh71b669a2016-12-17 01:13:31925 // Test the saturated cast overrides.
926 using FloatLimits = numeric_limits<float>;
927 using IntLimits = numeric_limits<int>;
928 EXPECT_EQ(-1, (saturated_cast<int, CastTest1>(FloatLimits::quiet_NaN())));
929 EXPECT_EQ(CastTest1<int>::max(),
930 (saturated_cast<int, CastTest1>(FloatLimits::infinity())));
931 EXPECT_EQ(CastTest1<int>::max(),
932 (saturated_cast<int, CastTest1>(FloatLimits::max())));
933 EXPECT_EQ(CastTest1<int>::max(),
934 (saturated_cast<int, CastTest1>(float(IntLimits::max()))));
935 EXPECT_EQ(CastTest1<int>::lowest(),
936 (saturated_cast<int, CastTest1>(-FloatLimits::infinity())));
937 EXPECT_EQ(CastTest1<int>::lowest(),
938 (saturated_cast<int, CastTest1>(FloatLimits::lowest())));
939 EXPECT_EQ(0, (saturated_cast<int, CastTest1>(0.0)));
940 EXPECT_EQ(1, (saturated_cast<int, CastTest1>(1.0)));
941 EXPECT_EQ(-1, (saturated_cast<int, CastTest1>(-1.0)));
942 EXPECT_EQ(0, (saturated_cast<int, CastTest1>(0)));
943 EXPECT_EQ(1, (saturated_cast<int, CastTest1>(1)));
944 EXPECT_EQ(-1, (saturated_cast<int, CastTest1>(-1)));
945 EXPECT_EQ(CastTest1<int>::lowest(),
946 (saturated_cast<int, CastTest1>(float(IntLimits::lowest()))));
947 EXPECT_EQ(11, (saturated_cast<int, CastTest2>(FloatLimits::quiet_NaN())));
948 EXPECT_EQ(10, (saturated_cast<int, CastTest2>(FloatLimits::infinity())));
949 EXPECT_EQ(10, (saturated_cast<int, CastTest2>(FloatLimits::max())));
950 EXPECT_EQ(1, (saturated_cast<int, CastTest2>(-FloatLimits::infinity())));
951 EXPECT_EQ(1, (saturated_cast<int, CastTest2>(FloatLimits::lowest())));
952 EXPECT_EQ(1, (saturated_cast<int, CastTest2>(0U)));
953
vmpstredf1e182015-12-14 20:09:42954 float not_a_number = std::numeric_limits<float>::infinity() -
955 std::numeric_limits<float>::infinity();
956 EXPECT_TRUE(std::isnan(not_a_number));
957 EXPECT_EQ(0, saturated_cast<int>(not_a_number));
jschuh224f1d72016-11-25 20:08:48958
959 // Test the CheckedNumeric value extractions functions.
jschuh5030b002016-12-05 18:21:48960 auto int8_min = MakeCheckedNum(numeric_limits<int8_t>::lowest());
jschuh4bc919cb52016-12-04 15:08:27961 auto int8_max = MakeCheckedNum(numeric_limits<int8_t>::max());
962 auto double_max = MakeCheckedNum(numeric_limits<double>::max());
jschuh224f1d72016-11-25 20:08:48963 static_assert(
jschuh23a4b062016-12-02 02:55:08964 std::is_same<int16_t,
965 decltype(int8_min.ValueOrDie<int16_t>())::type>::value,
jschuh224f1d72016-11-25 20:08:48966 "ValueOrDie returning incorrect type.");
967 static_assert(
968 std::is_same<int16_t,
jschuh23a4b062016-12-02 02:55:08969 decltype(int8_min.ValueOrDefault<int16_t>(0))::type>::value,
jschuh224f1d72016-11-25 20:08:48970 "ValueOrDefault returning incorrect type.");
jschuh23a4b062016-12-02 02:55:08971 EXPECT_FALSE(IsValidForType<uint8_t>(int8_min));
972 EXPECT_TRUE(IsValidForType<uint8_t>(int8_max));
jschuh5030b002016-12-05 18:21:48973 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::lowest()),
jschuh23a4b062016-12-02 02:55:08974 ValueOrDieForType<int>(int8_min));
975 EXPECT_TRUE(IsValidForType<uint32_t>(int8_max));
jschuh224f1d72016-11-25 20:08:48976 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::max()),
jschuh23a4b062016-12-02 02:55:08977 ValueOrDieForType<int>(int8_max));
978 EXPECT_EQ(0, ValueOrDefaultForType<int>(double_max, 0));
jschuhe17e0f12016-11-26 03:00:08979 uint8_t uint8_dest = 0;
980 int16_t int16_dest = 0;
981 double double_dest = 0;
982 EXPECT_TRUE(int8_max.AssignIfValid(&uint8_dest));
983 EXPECT_EQ(static_cast<uint8_t>(numeric_limits<int8_t>::max()), uint8_dest);
984 EXPECT_FALSE(int8_min.AssignIfValid(&uint8_dest));
985 EXPECT_TRUE(int8_max.AssignIfValid(&int16_dest));
986 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::max()), int16_dest);
987 EXPECT_TRUE(int8_min.AssignIfValid(&int16_dest));
jschuh5030b002016-12-05 18:21:48988 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::lowest()), int16_dest);
jschuhe17e0f12016-11-26 03:00:08989 EXPECT_FALSE(double_max.AssignIfValid(&uint8_dest));
990 EXPECT_FALSE(double_max.AssignIfValid(&int16_dest));
991 EXPECT_TRUE(double_max.AssignIfValid(&double_dest));
992 EXPECT_EQ(numeric_limits<double>::max(), double_dest);
jschuh23a4b062016-12-02 02:55:08993 EXPECT_EQ(1, checked_cast<int>(StrictNumeric<int>(1)));
994 EXPECT_EQ(1, saturated_cast<int>(StrictNumeric<int>(1)));
995 EXPECT_EQ(1, strict_cast<int>(StrictNumeric<int>(1)));
[email protected]c1c090d32013-01-16 23:34:04996}
997
jschuhfafe0712015-09-14 20:21:24998TEST(SafeNumerics, IsValueInRangeForNumericType) {
999 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0));
1000 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(1));
1001 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(2));
1002 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(-1));
1003 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0xffffffffu));
1004 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0xffffffff)));
1005 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000000)));
1006 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000001)));
1007 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(
jschuh5030b002016-12-05 18:21:481008 std::numeric_limits<int32_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241009 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(
jschuh5030b002016-12-05 18:21:481010 std::numeric_limits<int64_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241011
1012 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0));
1013 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(1));
1014 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(2));
1015 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(-1));
1016 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffff));
1017 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffffu));
1018 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0x80000000u));
1019 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0xffffffffu));
1020 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x80000000)));
1021 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0xffffffff)));
1022 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x100000000)));
1023 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
jschuh5030b002016-12-05 18:21:481024 std::numeric_limits<int32_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241025 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
jschuh5030b002016-12-05 18:21:481026 static_cast<int64_t>(std::numeric_limits<int32_t>::lowest())));
jschuhfafe0712015-09-14 20:21:241027 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
jschuh5030b002016-12-05 18:21:481028 static_cast<int64_t>(std::numeric_limits<int32_t>::lowest()) - 1));
jschuhfafe0712015-09-14 20:21:241029 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
jschuh5030b002016-12-05 18:21:481030 std::numeric_limits<int64_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241031
1032 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0));
1033 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(1));
1034 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(2));
1035 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(-1));
1036 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0xffffffffu));
1037 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0xffffffff)));
1038 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000000)));
1039 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000001)));
1040 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(
jschuh5030b002016-12-05 18:21:481041 std::numeric_limits<int32_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241042 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(INT64_C(-1)));
1043 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(
jschuh5030b002016-12-05 18:21:481044 std::numeric_limits<int64_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241045
1046 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0));
1047 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(1));
1048 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(2));
1049 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(-1));
1050 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffff));
1051 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffffu));
1052 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x80000000u));
1053 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0xffffffffu));
1054 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x80000000)));
1055 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0xffffffff)));
1056 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x100000000)));
1057 EXPECT_TRUE(
1058 IsValueInRangeForNumericType<int64_t>(INT64_C(0x7fffffffffffffff)));
1059 EXPECT_TRUE(
1060 IsValueInRangeForNumericType<int64_t>(UINT64_C(0x7fffffffffffffff)));
1061 EXPECT_FALSE(
1062 IsValueInRangeForNumericType<int64_t>(UINT64_C(0x8000000000000000)));
1063 EXPECT_FALSE(
1064 IsValueInRangeForNumericType<int64_t>(UINT64_C(0xffffffffffffffff)));
1065 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
jschuh5030b002016-12-05 18:21:481066 std::numeric_limits<int32_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241067 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
jschuh5030b002016-12-05 18:21:481068 static_cast<int64_t>(std::numeric_limits<int32_t>::lowest())));
jschuhfafe0712015-09-14 20:21:241069 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
jschuh5030b002016-12-05 18:21:481070 std::numeric_limits<int64_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241071}
vmpstr19477492015-09-29 22:34:491072
1073TEST(SafeNumerics, CompoundNumericOperations) {
1074 CheckedNumeric<int> a = 1;
1075 CheckedNumeric<int> b = 2;
1076 CheckedNumeric<int> c = 3;
1077 CheckedNumeric<int> d = 4;
1078 a += b;
1079 EXPECT_EQ(3, a.ValueOrDie());
1080 a -= c;
1081 EXPECT_EQ(0, a.ValueOrDie());
1082 d /= b;
1083 EXPECT_EQ(2, d.ValueOrDie());
1084 d *= d;
1085 EXPECT_EQ(4, d.ValueOrDie());
1086
1087 CheckedNumeric<int> too_large = std::numeric_limits<int>::max();
1088 EXPECT_TRUE(too_large.IsValid());
1089 too_large += d;
1090 EXPECT_FALSE(too_large.IsValid());
1091 too_large -= d;
1092 EXPECT_FALSE(too_large.IsValid());
1093 too_large /= d;
1094 EXPECT_FALSE(too_large.IsValid());
1095}
jschuh4fcd6fa2016-11-24 11:58:391096
1097TEST(SafeNumerics, VariadicNumericOperations) {
jschuh4bc919cb52016-12-04 15:08:271098 auto a = CheckAdd(1, 2UL, MakeCheckedNum(3LL), 4).ValueOrDie();
jschuh23a4b062016-12-02 02:55:081099 EXPECT_EQ(static_cast<decltype(a)::type>(10), a);
jschuh4bc919cb52016-12-04 15:08:271100 auto b = CheckSub(MakeCheckedNum(20.0), 2UL, 4).ValueOrDie();
jschuh23a4b062016-12-02 02:55:081101 EXPECT_EQ(static_cast<decltype(b)::type>(14.0), b);
jschuh4bc919cb52016-12-04 15:08:271102 auto c = CheckMul(20.0, MakeCheckedNum(1), 5, 3UL).ValueOrDie();
jschuh23a4b062016-12-02 02:55:081103 EXPECT_EQ(static_cast<decltype(c)::type>(300.0), c);
jschuh4bc919cb52016-12-04 15:08:271104 auto d = CheckDiv(20.0, 2.0, MakeCheckedNum(5LL), -4).ValueOrDie();
jschuh23a4b062016-12-02 02:55:081105 EXPECT_EQ(static_cast<decltype(d)::type>(-.5), d);
jschuh4bc919cb52016-12-04 15:08:271106 auto e = CheckMod(MakeCheckedNum(20), 3).ValueOrDie();
jschuh23a4b062016-12-02 02:55:081107 EXPECT_EQ(static_cast<decltype(e)::type>(2), e);
jschuh4bc919cb52016-12-04 15:08:271108 auto f = CheckLsh(1, MakeCheckedNum(2)).ValueOrDie();
jschuh23a4b062016-12-02 02:55:081109 EXPECT_EQ(static_cast<decltype(f)::type>(4), f);
jschuh4bc919cb52016-12-04 15:08:271110 auto g = CheckRsh(4, MakeCheckedNum(2)).ValueOrDie();
jschuh23a4b062016-12-02 02:55:081111 EXPECT_EQ(static_cast<decltype(g)::type>(1), g);
jschuh4fcd6fa2016-11-24 11:58:391112 auto h = CheckRsh(CheckAdd(1, 1, 1, 1), CheckSub(4, 2)).ValueOrDie();
jschuh23a4b062016-12-02 02:55:081113 EXPECT_EQ(static_cast<decltype(h)::type>(1), h);
jschuh4fcd6fa2016-11-24 11:58:391114}