[go: nahoru, domu]

blob: 304032022a854f3ee1fe16e26efbd62898c35008 [file] [log] [blame]
scottmg@chromium.orgc1c090d32013-01-16 23:34:041// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
avi9b6f42932015-12-26 22:15:145#include <stddef.h>
jschuh@chromium.org4efb2c32014-01-16 06:57:256#include <stdint.h>
7
8#include <limits>
vmpstr98a2fad2015-11-30 20:15:179#include <type_traits>
jschuh@chromium.org4efb2c32014-01-16 06:57:2510
11#include "base/compiler_specific.h"
jschuh224f1d72016-11-25 20:08:4812#include "base/logging.h"
jschuh@chromium.org5bfecbc2014-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"
jschuh@chromium.org4efb2c32014-01-16 06:57:2517#include "testing/gtest/include/gtest/gtest.h"
scottmg@chromium.orgc1c090d32013-01-16 23:34:0418
avi9b6f42932015-12-26 22:15:1419#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS)
20#include <mmintrin.h>
21#endif
22
jschuh@chromium.org5bfecbc2014-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;
jschuh4bc919c2016-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;
jschuh@chromium.org5bfecbc2014-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;
jschuh@chromium.org5bfecbc2014-02-27 13:49:0444using base::saturated_cast;
jschuh4bf22c6d2015-05-28 02:29:2545using base::strict_cast;
jschuh@chromium.org5bfecbc2014-02-27 13:49:0446using base::internal::MaxExponent;
jschuh5030b002016-12-05 18:21:4847using base::internal::IntegerBitsPlusSign;
jschuh@chromium.org5bfecbc2014-02-27 13:49:0448using base::internal::RANGE_VALID;
49using base::internal::RANGE_INVALID;
50using base::internal::RANGE_OVERFLOW;
51using base::internal::RANGE_UNDERFLOW;
jschuh@chromium.org5bfecbc2014-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.
ncbray@chromium.orgb6bf5c322014-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.
ncbray@chromium.orgb6bf5c322014-08-09 05:24:0258#endif
jschuhfafe0712015-09-14 20:21:2459
60// 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}
ncbray@chromium.orgb6bf5c322014-08-09 05:24:0279
jschuhd1c1f2e2016-11-21 21:45:4880namespace base {
81namespace internal {
jschuh33232e02017-01-03 20:33:3682
83// Test corner case promotions used
84static_assert(IsIntegerArithmeticSafe<int32_t, int8_t, int8_t>::value, "");
85static_assert(IsIntegerArithmeticSafe<int32_t, int16_t, int8_t>::value, "");
86static_assert(IsIntegerArithmeticSafe<int32_t, int8_t, int16_t>::value, "");
87static_assert(!IsIntegerArithmeticSafe<int32_t, int32_t, int8_t>::value, "");
88static_assert(BigEnoughPromotion<int16_t, int8_t>::is_contained, "");
89static_assert(BigEnoughPromotion<int32_t, uint32_t>::is_contained, "");
90static_assert(BigEnoughPromotion<intmax_t, int8_t>::is_contained, "");
91static_assert(!BigEnoughPromotion<uintmax_t, int8_t>::is_contained, "");
92static_assert(
93 std::is_same<BigEnoughPromotion<int16_t, int8_t>::type, int16_t>::value,
94 "");
95static_assert(
96 std::is_same<BigEnoughPromotion<int32_t, uint32_t>::type, int64_t>::value,
97 "");
98static_assert(
99 std::is_same<BigEnoughPromotion<intmax_t, int8_t>::type, intmax_t>::value,
100 "");
101static_assert(
102 std::is_same<BigEnoughPromotion<uintmax_t, int8_t>::type, uintmax_t>::value,
103 "");
104static_assert(BigEnoughPromotion<int16_t, int8_t>::is_contained, "");
105static_assert(BigEnoughPromotion<int32_t, uint32_t>::is_contained, "");
106static_assert(BigEnoughPromotion<intmax_t, int8_t>::is_contained, "");
107static_assert(!BigEnoughPromotion<uintmax_t, int8_t>::is_contained, "");
108static_assert(
109 std::is_same<FastIntegerArithmeticPromotion<int16_t, int8_t>::type,
110 int32_t>::value,
111 "");
112static_assert(
113 std::is_same<FastIntegerArithmeticPromotion<int32_t, uint32_t>::type,
114 int64_t>::value,
115 "");
116static_assert(
117 std::is_same<FastIntegerArithmeticPromotion<intmax_t, int8_t>::type,
118 intmax_t>::value,
119 "");
120static_assert(
121 std::is_same<FastIntegerArithmeticPromotion<uintmax_t, int8_t>::type,
122 uintmax_t>::value,
123 "");
124static_assert(FastIntegerArithmeticPromotion<int16_t, int8_t>::is_contained,
125 "");
126static_assert(FastIntegerArithmeticPromotion<int32_t, uint32_t>::is_contained,
127 "");
128static_assert(!FastIntegerArithmeticPromotion<intmax_t, int8_t>::is_contained,
129 "");
130static_assert(!FastIntegerArithmeticPromotion<uintmax_t, int8_t>::is_contained,
131 "");
132
jschuhd1c1f2e2016-11-21 21:45:48133template <typename U>
134U GetNumericValueForTest(const CheckedNumeric<U>& src) {
135 return src.state_.value();
136}
137} // namespace internal.
138} // namespace base.
139
140using base::internal::GetNumericValueForTest;
141
jschuh224f1d72016-11-25 20:08:48142// Logs the ValueOrDie() failure instead of crashing.
143struct LogOnFailure {
144 template <typename T>
145 static T HandleFailure() {
146 LOG(WARNING) << "ValueOrDie() failed unexpectedly.";
147 return T();
148 }
149};
150
jschuh@chromium.org5bfecbc2014-02-27 13:49:04151// Helper macros to wrap displaying the conversion types and line numbers.
152#define TEST_EXPECTED_VALIDITY(expected, actual) \
jschuh4fcd6fa2016-11-24 11:58:39153 EXPECT_EQ(expected, (actual).template Cast<Dst>().IsValid()) \
jschuhd1c1f2e2016-11-21 21:45:48154 << "Result test: Value " << GetNumericValueForTest(actual) << " as " \
155 << dst << " on line " << line
jschuh819c8262016-05-21 01:39:03156
157#define TEST_EXPECTED_SUCCESS(actual) TEST_EXPECTED_VALIDITY(true, actual)
158#define TEST_EXPECTED_FAILURE(actual) TEST_EXPECTED_VALIDITY(false, actual)
jschuh@chromium.org5bfecbc2014-02-27 13:49:04159
jschuhba3c4f942016-12-10 14:03:55160// We have to handle promotions, so infer the underlying type below from actual.
161#define TEST_EXPECTED_VALUE(expected, actual) \
162 EXPECT_EQ(static_cast<typename std::decay<decltype(actual)>::type::type>( \
163 expected), \
164 ((actual) \
165 .template ValueOrDie< \
166 typename std::decay<decltype(actual)>::type::type, \
167 LogOnFailure>())) \
168 << "Result test: Value " << GetNumericValueForTest(actual) << " as " \
jschuhd1c1f2e2016-11-21 21:45:48169 << dst << " on line " << line
jschuh@chromium.org5bfecbc2014-02-27 13:49:04170
jschuh23a4b062016-12-02 02:55:08171// Test the simple pointer arithmetic overrides.
172template <typename Dst>
173void TestStrictPointerMath() {
174 Dst dummy_value = 0;
175 Dst* dummy_ptr = &dummy_value;
176 static const Dst kDummyOffset = 2; // Don't want to go too far.
177 EXPECT_EQ(dummy_ptr + kDummyOffset,
178 dummy_ptr + StrictNumeric<Dst>(kDummyOffset));
179 EXPECT_EQ(dummy_ptr - kDummyOffset,
180 dummy_ptr - StrictNumeric<Dst>(kDummyOffset));
181 EXPECT_NE(dummy_ptr, dummy_ptr + StrictNumeric<Dst>(kDummyOffset));
182 EXPECT_NE(dummy_ptr, dummy_ptr - StrictNumeric<Dst>(kDummyOffset));
183 EXPECT_DEATH_IF_SUPPORTED(
184 dummy_ptr + StrictNumeric<size_t>(std::numeric_limits<size_t>::max()),
185 "");
186}
187
jschuh@chromium.org5bfecbc2014-02-27 13:49:04188// Signed integer arithmetic.
189template <typename Dst>
190static void TestSpecializedArithmetic(
191 const char* dst,
192 int line,
vmpstr98a2fad2015-11-30 20:15:17193 typename std::enable_if<numeric_limits<Dst>::is_integer &&
194 numeric_limits<Dst>::is_signed,
195 int>::type = 0) {
jschuh5030b002016-12-05 18:21:48196 using DstLimits = numeric_limits<Dst>;
197 TEST_EXPECTED_FAILURE(-CheckedNumeric<Dst>(DstLimits::lowest()));
198 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04199 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
jschuhba3c4f942016-12-10 14:03:55200 TEST_EXPECTED_VALUE(DstLimits::max(),
201 MakeCheckedNum(-DstLimits::max()).Abs());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04202
jschuh819c8262016-05-21 01:39:03203 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + -1);
jschuh5030b002016-12-05 18:21:48204 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
205 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) +
206 DstLimits::lowest());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04207
jschuh5030b002016-12-05 18:21:48208 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) - 1);
209 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) - -1);
jschuh819c8262016-05-21 01:39:03210 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) -
jschuh5030b002016-12-05 18:21:48211 DstLimits::lowest());
212 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) -
jschuh819c8262016-05-21 01:39:03213 DstLimits::max());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04214
jschuh5030b002016-12-05 18:21:48215 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04216
jschuh5030b002016-12-05 18:21:48217 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) / -1);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04218 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) / 2);
jschuh5030b002016-12-05 18:21:48219 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * -1);
jschuh33232e02017-01-03 20:33:36220 TEST_EXPECTED_VALUE(DstLimits::max(),
221 CheckedNumeric<Dst>(DstLimits::lowest() + 1) * Dst(-1));
222 TEST_EXPECTED_VALUE(DstLimits::max(),
223 CheckedNumeric<Dst>(-1) * Dst(DstLimits::lowest() + 1));
224 TEST_EXPECTED_VALUE(DstLimits::lowest(),
225 CheckedNumeric<Dst>(DstLimits::lowest()) * Dst(1));
226 TEST_EXPECTED_VALUE(DstLimits::lowest(),
227 CheckedNumeric<Dst>(1) * Dst(DstLimits::lowest()));
jschuhba3c4f942016-12-10 14:03:55228 TEST_EXPECTED_VALUE(DstLimits::lowest(),
229 MakeCheckedNum(DstLimits::lowest()).UnsignedAbs());
230 TEST_EXPECTED_VALUE(DstLimits::max(),
231 MakeCheckedNum(DstLimits::max()).UnsignedAbs());
232 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0).UnsignedAbs());
233 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).UnsignedAbs());
234 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).UnsignedAbs());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04235
236 // Modulus is legal only for integers.
237 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
238 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
239 TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % 2);
jschuh819c8262016-05-21 01:39:03240 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-1) % -2);
jschuh5030b002016-12-05 18:21:48241 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % 2);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04242 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
243 // Test all the different modulus combinations.
244 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
245 TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
246 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
247 CheckedNumeric<Dst> checked_dst = 1;
248 TEST_EXPECTED_VALUE(0, checked_dst %= 1);
tsepezdfd77a92016-11-02 20:18:06249 // Test that div by 0 is avoided but returns invalid result.
250 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) % 0);
jschuh3ab54042016-11-17 06:58:44251 // Test bit shifts.
252 volatile Dst negative_one = -1;
253 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) << negative_one);
jschuh5030b002016-12-05 18:21:48254 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
255 << (IntegerBitsPlusSign<Dst>::value - 1));
256 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(0)
257 << IntegerBitsPlusSign<Dst>::value);
jschuh3ab54042016-11-17 06:58:44258 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) << 1);
jschuh5030b002016-12-05 18:21:48259 TEST_EXPECTED_VALUE(
260 static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2),
261 CheckedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2));
jschuh3ab54042016-11-17 06:58:44262 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0)
jschuh5030b002016-12-05 18:21:48263 << (IntegerBitsPlusSign<Dst>::value - 1));
jschuh3ab54042016-11-17 06:58:44264 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) << 0);
265 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1);
jschuh5030b002016-12-05 18:21:48266 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >>
267 IntegerBitsPlusSign<Dst>::value);
268 TEST_EXPECTED_VALUE(
269 0, CheckedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1));
jschuh3ab54042016-11-17 06:58:44270 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one);
jschuh23a4b062016-12-02 02:55:08271
272 TestStrictPointerMath<Dst>();
jschuh@chromium.org5bfecbc2014-02-27 13:49:04273}
274
275// Unsigned integer arithmetic.
276template <typename Dst>
277static void TestSpecializedArithmetic(
278 const char* dst,
279 int line,
vmpstr98a2fad2015-11-30 20:15:17280 typename std::enable_if<numeric_limits<Dst>::is_integer &&
281 !numeric_limits<Dst>::is_signed,
282 int>::type = 0) {
jschuh5030b002016-12-05 18:21:48283 using DstLimits = numeric_limits<Dst>;
284 TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::lowest()));
285 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
286 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
287 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) - 1);
288 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04289 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) / 2);
jschuh5030b002016-12-05 18:21:48290 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).UnsignedAbs());
jschuh819c8262016-05-21 01:39:03291 TEST_EXPECTED_SUCCESS(
jschuh5030b002016-12-05 18:21:48292 CheckedNumeric<typename std::make_signed<Dst>::type>(
293 std::numeric_limits<typename std::make_signed<Dst>::type>::lowest())
jschuheaf375f2015-09-17 01:04:28294 .UnsignedAbs());
jschuhba3c4f942016-12-10 14:03:55295 TEST_EXPECTED_VALUE(DstLimits::lowest(),
296 MakeCheckedNum(DstLimits::lowest()).UnsignedAbs());
297 TEST_EXPECTED_VALUE(DstLimits::max(),
298 MakeCheckedNum(DstLimits::max()).UnsignedAbs());
299 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0).UnsignedAbs());
300 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).UnsignedAbs());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04301
302 // Modulus is legal only for integers.
303 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
304 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
305 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % 2);
jschuh5030b002016-12-05 18:21:48306 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % 2);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04307 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
308 // Test all the different modulus combinations.
309 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
310 TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
311 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
312 CheckedNumeric<Dst> checked_dst = 1;
313 TEST_EXPECTED_VALUE(0, checked_dst %= 1);
tsepezdfd77a92016-11-02 20:18:06314 // Test that div by 0 is avoided but returns invalid result.
315 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) % 0);
jschuh5030b002016-12-05 18:21:48316 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
317 << IntegerBitsPlusSign<Dst>::value);
jschuh3ab54042016-11-17 06:58:44318 // Test bit shifts.
319 volatile int negative_one = -1;
320 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) << negative_one);
jschuh5030b002016-12-05 18:21:48321 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
322 << IntegerBitsPlusSign<Dst>::value);
323 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(0)
324 << IntegerBitsPlusSign<Dst>::value);
jschuh3ab54042016-11-17 06:58:44325 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) << 1);
jschuh5030b002016-12-05 18:21:48326 TEST_EXPECTED_VALUE(
327 static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1),
328 CheckedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1));
jschuh3ab54042016-11-17 06:58:44329 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) << 0);
330 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1);
jschuh5030b002016-12-05 18:21:48331 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >>
332 IntegerBitsPlusSign<Dst>::value);
333 TEST_EXPECTED_VALUE(
334 0, CheckedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1));
jschuh3ab54042016-11-17 06:58:44335 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one);
jschuhb6737bb2016-11-29 03:06:59336 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) & 1);
337 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) & 0);
338 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) & 1);
339 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) & 0);
340 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
jschuh4bc919c2016-12-04 15:08:27341 MakeCheckedNum(DstLimits::max()) & -1);
jschuhb6737bb2016-11-29 03:06:59342 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) | 1);
343 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) | 0);
344 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) | 1);
345 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) | 0);
346 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
347 CheckedNumeric<Dst>(0) | static_cast<Dst>(-1));
348 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) ^ 1);
349 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) ^ 0);
350 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) ^ 1);
351 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) ^ 0);
352 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
353 CheckedNumeric<Dst>(0) ^ static_cast<Dst>(-1));
jschuh970313c2016-11-24 21:40:58354 TEST_EXPECTED_VALUE(DstLimits::max(), ~CheckedNumeric<Dst>(0));
jschuh23a4b062016-12-02 02:55:08355
356 TestStrictPointerMath<Dst>();
jschuh@chromium.org5bfecbc2014-02-27 13:49:04357}
358
359// Floating point arithmetic.
360template <typename Dst>
361void TestSpecializedArithmetic(
362 const char* dst,
363 int line,
vmpstr98a2fad2015-11-30 20:15:17364 typename std::enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0) {
jschuh5030b002016-12-05 18:21:48365 using DstLimits = numeric_limits<Dst>;
366 TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::lowest()));
jschuh@chromium.org5bfecbc2014-02-27 13:49:04367
jschuh5030b002016-12-05 18:21:48368 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04369 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
370
jschuh5030b002016-12-05 18:21:48371 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
jschuh819c8262016-05-21 01:39:03372 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + 1);
jschuh5030b002016-12-05 18:21:48373 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) +
374 DstLimits::lowest());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04375
jschuh819c8262016-05-21 01:39:03376 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) -
jschuh5030b002016-12-05 18:21:48377 DstLimits::lowest());
378 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) -
jschuh819c8262016-05-21 01:39:03379 DstLimits::max());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04380
jschuh5030b002016-12-05 18:21:48381 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04382
383 TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04384}
385
386// Generic arithmetic tests.
387template <typename Dst>
388static void TestArithmetic(const char* dst, int line) {
jschuh5030b002016-12-05 18:21:48389 using DstLimits = numeric_limits<Dst>;
jschuh@chromium.org5bfecbc2014-02-27 13:49:04390
391 EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid());
392 EXPECT_EQ(false,
393 CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
394 DstLimits::max()).IsValid());
395 EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDie());
396 EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDefault(1));
397 EXPECT_EQ(static_cast<Dst>(1),
398 CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
399 DstLimits::max()).ValueOrDefault(1));
400
401 // Test the operator combinations.
402 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + CheckedNumeric<Dst>(1));
403 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - CheckedNumeric<Dst>(1));
404 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * CheckedNumeric<Dst>(1));
405 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / CheckedNumeric<Dst>(1));
406 TEST_EXPECTED_VALUE(2, 1 + CheckedNumeric<Dst>(1));
407 TEST_EXPECTED_VALUE(0, 1 - CheckedNumeric<Dst>(1));
408 TEST_EXPECTED_VALUE(1, 1 * CheckedNumeric<Dst>(1));
409 TEST_EXPECTED_VALUE(1, 1 / CheckedNumeric<Dst>(1));
410 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + 1);
411 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - 1);
412 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * 1);
413 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
414 CheckedNumeric<Dst> checked_dst = 1;
415 TEST_EXPECTED_VALUE(2, checked_dst += 1);
416 checked_dst = 1;
417 TEST_EXPECTED_VALUE(0, checked_dst -= 1);
418 checked_dst = 1;
419 TEST_EXPECTED_VALUE(1, checked_dst *= 1);
420 checked_dst = 1;
421 TEST_EXPECTED_VALUE(1, checked_dst /= 1);
422
423 // Generic negation.
jschuh749c7f72016-09-07 16:22:26424 if (DstLimits::is_signed) {
425 TEST_EXPECTED_VALUE(0, -CheckedNumeric<Dst>());
426 TEST_EXPECTED_VALUE(-1, -CheckedNumeric<Dst>(1));
427 TEST_EXPECTED_VALUE(1, -CheckedNumeric<Dst>(-1));
428 TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1),
429 -CheckedNumeric<Dst>(DstLimits::max()));
430 }
jschuh@chromium.org5bfecbc2014-02-27 13:49:04431
432 // Generic absolute value.
433 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>().Abs());
434 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).Abs());
435 TEST_EXPECTED_VALUE(DstLimits::max(),
436 CheckedNumeric<Dst>(DstLimits::max()).Abs());
437
438 // Generic addition.
439 TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>() + 1));
440 TEST_EXPECTED_VALUE(2, (CheckedNumeric<Dst>(1) + 1));
jschuh216b62a2016-11-08 03:53:08441 if (numeric_limits<Dst>::is_signed)
442 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) + 1));
jschuh5030b002016-12-05 18:21:48443 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) + 1);
jschuh819c8262016-05-21 01:39:03444 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) +
445 DstLimits::max());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04446
447 // Generic subtraction.
jschuh@chromium.org5bfecbc2014-02-27 13:49:04448 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(1) - 1));
jschuh819c8262016-05-21 01:39:03449 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) - 1);
jschuh216b62a2016-11-08 03:53:08450 if (numeric_limits<Dst>::is_signed) {
451 TEST_EXPECTED_VALUE(-1, (CheckedNumeric<Dst>() - 1));
452 TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) - 1));
jschuh657a3d62016-11-15 18:23:45453 } else {
454 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - -1);
jschuh216b62a2016-11-08 03:53:08455 }
jschuh@chromium.org5bfecbc2014-02-27 13:49:04456
457 // Generic multiplication.
458 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>() * 1));
459 TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>(1) * 1));
eroman0397125f2015-05-18 14:44:32460 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * 0));
jschuh216b62a2016-11-08 03:53:08461 if (numeric_limits<Dst>::is_signed) {
462 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) * 0));
463 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * -1));
jschuh749c7f72016-09-07 16:22:26464 TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) * 2));
jschuh657a3d62016-11-15 18:23:45465 } else {
466 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) * -2);
467 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) *
468 CheckedNumeric<uintmax_t>(-2));
jschuh749c7f72016-09-07 16:22:26469 }
jschuh216b62a2016-11-08 03:53:08470 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) *
471 DstLimits::max());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04472
473 // Generic division.
474 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() / 1);
475 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
jschuh5030b002016-12-05 18:21:48476 TEST_EXPECTED_VALUE(DstLimits::lowest() / 2,
477 CheckedNumeric<Dst>(DstLimits::lowest()) / 2);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04478 TEST_EXPECTED_VALUE(DstLimits::max() / 2,
479 CheckedNumeric<Dst>(DstLimits::max()) / 2);
480
481 TestSpecializedArithmetic<Dst>(dst, line);
482}
483
484// Helper macro to wrap displaying the conversion types and line numbers.
485#define TEST_ARITHMETIC(Dst) TestArithmetic<Dst>(#Dst, __LINE__)
486
487TEST(SafeNumerics, SignedIntegerMath) {
488 TEST_ARITHMETIC(int8_t);
489 TEST_ARITHMETIC(int);
490 TEST_ARITHMETIC(intptr_t);
491 TEST_ARITHMETIC(intmax_t);
492}
493
494TEST(SafeNumerics, UnsignedIntegerMath) {
495 TEST_ARITHMETIC(uint8_t);
496 TEST_ARITHMETIC(unsigned int);
497 TEST_ARITHMETIC(uintptr_t);
498 TEST_ARITHMETIC(uintmax_t);
499}
500
501TEST(SafeNumerics, FloatingPointMath) {
502 TEST_ARITHMETIC(float);
503 TEST_ARITHMETIC(double);
504}
scottmg@chromium.orgc1c090d32013-01-16 23:34:04505
jschuh@chromium.org4efb2c32014-01-16 06:57:25506// Enumerates the five different conversions types we need to test.
507enum NumericConversionType {
508 SIGN_PRESERVING_VALUE_PRESERVING,
509 SIGN_PRESERVING_NARROW,
510 SIGN_TO_UNSIGN_WIDEN_OR_EQUAL,
511 SIGN_TO_UNSIGN_NARROW,
512 UNSIGN_TO_SIGN_NARROW_OR_EQUAL,
513};
scottmg@chromium.orgc1c090d32013-01-16 23:34:04514
jschuh@chromium.org4efb2c32014-01-16 06:57:25515// Template covering the different conversion tests.
516template <typename Dst, typename Src, NumericConversionType conversion>
517struct TestNumericConversion {};
scottmg@chromium.orgc1c090d32013-01-16 23:34:04518
jschuh@chromium.org5bfecbc2014-02-27 13:49:04519// EXPECT_EQ wrappers providing specific detail on test failures.
520#define TEST_EXPECTED_RANGE(expected, actual) \
521 EXPECT_EQ(expected, base::internal::DstRangeRelationToSrcRange<Dst>(actual)) \
522 << "Conversion test: " << src << " value " << actual << " to " << dst \
jschuh657a3d62016-11-15 18:23:45523 << " on line " << line
jschuh@chromium.org4efb2c32014-01-16 06:57:25524
525template <typename Dst, typename Src>
jschuh23a4b062016-12-02 02:55:08526void TestStrictComparison() {
jschuh5030b002016-12-05 18:21:48527 using DstLimits = numeric_limits<Dst>;
528 using SrcLimits = numeric_limits<Src>;
jschuh711ac6a2016-12-04 07:17:48529 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) < DstLimits::max(), "");
530 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) < SrcLimits::max(), "");
531 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) >= DstLimits::max()),
jschuh23a4b062016-12-02 02:55:08532 "");
jschuh711ac6a2016-12-04 07:17:48533 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) >= SrcLimits::max()),
jschuh23a4b062016-12-02 02:55:08534 "");
jschuh711ac6a2016-12-04 07:17:48535 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) <= DstLimits::max(),
jschuh23a4b062016-12-02 02:55:08536 "");
jschuh711ac6a2016-12-04 07:17:48537 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) <= SrcLimits::max(),
jschuh23a4b062016-12-02 02:55:08538 "");
jschuh711ac6a2016-12-04 07:17:48539 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) > DstLimits::max()),
540 "");
541 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) > SrcLimits::max()),
542 "");
543 static_assert(StrictNumeric<Src>(SrcLimits::max()) > DstLimits::lowest(), "");
544 static_assert(StrictNumeric<Src>(SrcLimits::max()) > SrcLimits::lowest(), "");
545 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) <= DstLimits::lowest()),
546 "");
547 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) <= SrcLimits::lowest()),
548 "");
549 static_assert(StrictNumeric<Src>(SrcLimits::max()) >= DstLimits::lowest(),
550 "");
551 static_assert(StrictNumeric<Src>(SrcLimits::max()) >= SrcLimits::lowest(),
552 "");
553 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) < DstLimits::lowest()),
554 "");
555 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) < SrcLimits::lowest()),
556 "");
jschuh23a4b062016-12-02 02:55:08557 static_assert(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(1),
558 "");
559 static_assert(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(0),
560 "");
561 static_assert(StrictNumeric<Src>(SrcLimits::max()) != static_cast<Dst>(0),
562 "");
jschuh711ac6a2016-12-04 07:17:48563 static_assert(StrictNumeric<Src>(SrcLimits::max()) != DstLimits::lowest(),
564 "");
jschuh23a4b062016-12-02 02:55:08565 static_assert(
566 !(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(1)), "");
567 static_assert(
568 !(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(0)), "");
jschuh711ac6a2016-12-04 07:17:48569
570 // Due to differences in float handling between compilers, these aren't
571 // compile-time constants everywhere. So, we use run-time tests.
jschuh4bc919c2016-12-04 15:08:27572 EXPECT_EQ(
573 SrcLimits::max(),
574 MakeCheckedNum(SrcLimits::max()).Max(DstLimits::lowest()).ValueOrDie());
575 EXPECT_EQ(
576 DstLimits::max(),
577 MakeCheckedNum(SrcLimits::lowest()).Max(DstLimits::max()).ValueOrDie());
578 EXPECT_EQ(
579 DstLimits::lowest(),
580 MakeCheckedNum(SrcLimits::max()).Min(DstLimits::lowest()).ValueOrDie());
581 EXPECT_EQ(
582 SrcLimits::lowest(),
583 MakeCheckedNum(SrcLimits::lowest()).Min(DstLimits::max()).ValueOrDie());
584 EXPECT_EQ(SrcLimits::lowest(), CheckMin(MakeStrictNum(1), MakeCheckedNum(0),
jschuh711ac6a2016-12-04 07:17:48585 DstLimits::max(), SrcLimits::lowest())
586 .ValueOrDie());
jschuh4bc919c2016-12-04 15:08:27587 EXPECT_EQ(DstLimits::max(), CheckMax(MakeStrictNum(1), MakeCheckedNum(0),
jschuh711ac6a2016-12-04 07:17:48588 DstLimits::max(), SrcLimits::lowest())
589 .ValueOrDie());
jschuh23a4b062016-12-02 02:55:08590}
591
592template <typename Dst, typename Src>
jschuh@chromium.org4efb2c32014-01-16 06:57:25593struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> {
594 static void Test(const char *dst, const char *src, int line) {
jschuh5030b002016-12-05 18:21:48595 using SrcLimits = numeric_limits<Src>;
596 using DstLimits = numeric_limits<Dst>;
597 // Integral to floating.
jschuhd2d9fe02014-10-14 14:31:37598 static_assert((DstLimits::is_iec559 && SrcLimits::is_integer) ||
jschuh5030b002016-12-05 18:21:48599 // Not floating to integral and...
600 (!(DstLimits::is_integer && SrcLimits::is_iec559) &&
601 // Same sign, same numeric, source is narrower or same.
602 ((SrcLimits::is_signed == DstLimits::is_signed &&
603 MaxExponent<Dst>::value >= MaxExponent<Src>::value) ||
604 // Or signed destination and source is smaller
605 (DstLimits::is_signed &&
606 MaxExponent<Dst>::value >= MaxExponent<Src>::value))),
jschuhd2d9fe02014-10-14 14:31:37607 "Comparison must be sign preserving and value preserving");
jschuh23a4b062016-12-02 02:55:08608
609 TestStrictComparison<Dst, Src>();
jschuh@chromium.org4efb2c32014-01-16 06:57:25610
jschuh@chromium.org5bfecbc2014-02-27 13:49:04611 const CheckedNumeric<Dst> checked_dst = SrcLimits::max();
jschuh819c8262016-05-21 01:39:03612 TEST_EXPECTED_SUCCESS(checked_dst);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04613 if (MaxExponent<Dst>::value > MaxExponent<Src>::value) {
614 if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1) {
615 // At least twice larger type.
jschuh819c8262016-05-21 01:39:03616 TEST_EXPECTED_SUCCESS(SrcLimits::max() * checked_dst);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04617
618 } else { // Larger, but not at least twice as large.
jschuh819c8262016-05-21 01:39:03619 TEST_EXPECTED_FAILURE(SrcLimits::max() * checked_dst);
620 TEST_EXPECTED_SUCCESS(checked_dst + 1);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04621 }
622 } else { // Same width type.
jschuh819c8262016-05-21 01:39:03623 TEST_EXPECTED_FAILURE(checked_dst + 1);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04624 }
625
626 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
627 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
jschuh@chromium.org4efb2c32014-01-16 06:57:25628 if (SrcLimits::is_iec559) {
jschuh@chromium.org5bfecbc2014-02-27 13:49:04629 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max() * static_cast<Src>(-1));
630 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
631 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
632 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04633 } else if (numeric_limits<Src>::is_signed) {
634 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
jschuh5030b002016-12-05 18:21:48635 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
jschuh@chromium.org4efb2c32014-01-16 06:57:25636 }
scottmg@chromium.orgc1c090d32013-01-16 23:34:04637 }
jschuh@chromium.org4efb2c32014-01-16 06:57:25638};
639
640template <typename Dst, typename Src>
641struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> {
642 static void Test(const char *dst, const char *src, int line) {
jschuh5030b002016-12-05 18:21:48643 using SrcLimits = numeric_limits<Src>;
644 using DstLimits = numeric_limits<Dst>;
jschuhd2d9fe02014-10-14 14:31:37645 static_assert(SrcLimits::is_signed == DstLimits::is_signed,
646 "Destination and source sign must be the same");
jschuh5030b002016-12-05 18:21:48647 static_assert(MaxExponent<Dst>::value <= MaxExponent<Src>::value,
jschuhd2d9fe02014-10-14 14:31:37648 "Destination must be narrower than source");
jschuh23a4b062016-12-02 02:55:08649
650 TestStrictComparison<Dst, Src>();
jschuh@chromium.org4efb2c32014-01-16 06:57:25651
jschuh@chromium.org5bfecbc2014-02-27 13:49:04652 const CheckedNumeric<Dst> checked_dst;
jschuh819c8262016-05-21 01:39:03653 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04654 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
jschuh819c8262016-05-21 01:39:03655 TEST_EXPECTED_FAILURE(checked_dst - SrcLimits::max());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04656
657 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
658 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
jschuh@chromium.org4efb2c32014-01-16 06:57:25659 if (SrcLimits::is_iec559) {
jschuh@chromium.org5bfecbc2014-02-27 13:49:04660 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
661 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
662 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
663 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
664 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
jschuhfafe0712015-09-14 20:21:24665 if (DstLimits::is_integer) {
666 if (SrcLimits::digits < DstLimits::digits) {
667 TEST_EXPECTED_RANGE(RANGE_OVERFLOW,
668 static_cast<Src>(DstLimits::max()));
669 } else {
670 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
671 }
672 TEST_EXPECTED_RANGE(
673 RANGE_VALID,
674 static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
jschuh5030b002016-12-05 18:21:48675 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::lowest()));
jschuhfafe0712015-09-14 20:21:24676 }
jschuh@chromium.org4efb2c32014-01-16 06:57:25677 } else if (SrcLimits::is_signed) {
jschuh@chromium.org5bfecbc2014-02-27 13:49:04678 TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1));
jschuh5030b002016-12-05 18:21:48679 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04680 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
jschuh@chromium.org4efb2c32014-01-16 06:57:25681 } else {
jschuh819c8262016-05-21 01:39:03682 TEST_EXPECTED_FAILURE(checked_dst - static_cast<Src>(1));
jschuh5030b002016-12-05 18:21:48683 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
jschuh@chromium.org4efb2c32014-01-16 06:57:25684 }
685 }
686};
687
688template <typename Dst, typename Src>
689struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> {
690 static void Test(const char *dst, const char *src, int line) {
jschuh5030b002016-12-05 18:21:48691 using SrcLimits = numeric_limits<Src>;
692 using DstLimits = numeric_limits<Dst>;
693 static_assert(MaxExponent<Dst>::value >= MaxExponent<Src>::value,
jschuhd2d9fe02014-10-14 14:31:37694 "Destination must be equal or wider than source.");
695 static_assert(SrcLimits::is_signed, "Source must be signed");
696 static_assert(!DstLimits::is_signed, "Destination must be unsigned");
jschuh@chromium.org4efb2c32014-01-16 06:57:25697
jschuh23a4b062016-12-02 02:55:08698 TestStrictComparison<Dst, Src>();
699
jschuh@chromium.org5bfecbc2014-02-27 13:49:04700 const CheckedNumeric<Dst> checked_dst;
701 TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max());
jschuh819c8262016-05-21 01:39:03702 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
jschuh5030b002016-12-05 18:21:48703 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::lowest());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04704
jschuh5030b002016-12-05 18:21:48705 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04706 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
707 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
708 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
jschuh@chromium.org4efb2c32014-01-16 06:57:25709 }
710};
711
712template <typename Dst, typename Src>
713struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> {
714 static void Test(const char *dst, const char *src, int line) {
jschuh5030b002016-12-05 18:21:48715 using SrcLimits = numeric_limits<Src>;
716 using DstLimits = numeric_limits<Dst>;
717 static_assert(MaxExponent<Dst>::value < MaxExponent<Src>::value,
jschuhd2d9fe02014-10-14 14:31:37718 "Destination must be narrower than source.");
719 static_assert(SrcLimits::is_signed, "Source must be signed.");
720 static_assert(!DstLimits::is_signed, "Destination must be unsigned.");
jschuh23a4b062016-12-02 02:55:08721
722 TestStrictComparison<Dst, Src>();
jschuh@chromium.org4efb2c32014-01-16 06:57:25723
jschuh@chromium.org5bfecbc2014-02-27 13:49:04724 const CheckedNumeric<Dst> checked_dst;
725 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
jschuh819c8262016-05-21 01:39:03726 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
727 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
jschuh5030b002016-12-05 18:21:48728 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::lowest());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04729
730 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
731 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
732 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
jschuhe3bd1f62016-12-20 05:11:30733
734 // Additional saturation tests.
jschuhc8f03cd2017-01-05 03:40:51735 EXPECT_EQ(DstLimits::max(), saturated_cast<Dst>(SrcLimits::max())) << src;
jschuhe3bd1f62016-12-20 05:11:30736 EXPECT_EQ(DstLimits::lowest(), saturated_cast<Dst>(SrcLimits::lowest()));
737
jschuh@chromium.org4efb2c32014-01-16 06:57:25738 if (SrcLimits::is_iec559) {
jschuhe3bd1f62016-12-20 05:11:30739 EXPECT_EQ(Dst(0), saturated_cast<Dst>(SrcLimits::quiet_NaN()));
740
jschuh@chromium.org5bfecbc2014-02-27 13:49:04741 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
742 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
743 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
744 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
jschuhfafe0712015-09-14 20:21:24745 if (DstLimits::is_integer) {
746 if (SrcLimits::digits < DstLimits::digits) {
747 TEST_EXPECTED_RANGE(RANGE_OVERFLOW,
748 static_cast<Src>(DstLimits::max()));
749 } else {
750 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
751 }
752 TEST_EXPECTED_RANGE(
753 RANGE_VALID,
754 static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
jschuh5030b002016-12-05 18:21:48755 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::lowest()));
jschuhfafe0712015-09-14 20:21:24756 }
jschuh@chromium.org4efb2c32014-01-16 06:57:25757 } else {
jschuh5030b002016-12-05 18:21:48758 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
jschuh@chromium.org4efb2c32014-01-16 06:57:25759 }
760 }
761};
762
763template <typename Dst, typename Src>
764struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> {
765 static void Test(const char *dst, const char *src, int line) {
jschuh5030b002016-12-05 18:21:48766 using SrcLimits = numeric_limits<Src>;
767 using DstLimits = numeric_limits<Dst>;
768 static_assert(MaxExponent<Dst>::value <= MaxExponent<Src>::value,
jschuhd2d9fe02014-10-14 14:31:37769 "Destination must be narrower or equal to source.");
770 static_assert(!SrcLimits::is_signed, "Source must be unsigned.");
771 static_assert(DstLimits::is_signed, "Destination must be signed.");
jschuh23a4b062016-12-02 02:55:08772
773 TestStrictComparison<Dst, Src>();
jschuh@chromium.org4efb2c32014-01-16 06:57:25774
jschuh@chromium.org5bfecbc2014-02-27 13:49:04775 const CheckedNumeric<Dst> checked_dst;
776 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
jschuh819c8262016-05-21 01:39:03777 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
jschuh5030b002016-12-05 18:21:48778 TEST_EXPECTED_VALUE(SrcLimits::lowest(), checked_dst + SrcLimits::lowest());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04779
jschuh5030b002016-12-05 18:21:48780 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04781 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
782 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
jschuhe3bd1f62016-12-20 05:11:30783
784 // Additional saturation tests.
785 EXPECT_EQ(DstLimits::max(), saturated_cast<Dst>(SrcLimits::max()));
786 EXPECT_EQ(Dst(0), saturated_cast<Dst>(SrcLimits::lowest()));
jschuh@chromium.org4efb2c32014-01-16 06:57:25787 }
788};
789
790// Helper macro to wrap displaying the conversion types and line numbers
791#define TEST_NUMERIC_CONVERSION(d, s, t) \
792 TestNumericConversion<d, s, t>::Test(#d, #s, __LINE__)
793
jschuh@chromium.org5bfecbc2014-02-27 13:49:04794TEST(SafeNumerics, IntMinOperations) {
jschuh@chromium.org4efb2c32014-01-16 06:57:25795 TEST_NUMERIC_CONVERSION(int8_t, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
796 TEST_NUMERIC_CONVERSION(uint8_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
797
798 TEST_NUMERIC_CONVERSION(int8_t, int, SIGN_PRESERVING_NARROW);
799 TEST_NUMERIC_CONVERSION(uint8_t, unsigned int, SIGN_PRESERVING_NARROW);
800 TEST_NUMERIC_CONVERSION(int8_t, float, SIGN_PRESERVING_NARROW);
801
802 TEST_NUMERIC_CONVERSION(uint8_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
803
804 TEST_NUMERIC_CONVERSION(uint8_t, int, SIGN_TO_UNSIGN_NARROW);
805 TEST_NUMERIC_CONVERSION(uint8_t, intmax_t, SIGN_TO_UNSIGN_NARROW);
806 TEST_NUMERIC_CONVERSION(uint8_t, float, SIGN_TO_UNSIGN_NARROW);
807
808 TEST_NUMERIC_CONVERSION(int8_t, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
809 TEST_NUMERIC_CONVERSION(int8_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
scottmg@chromium.orgc1c090d32013-01-16 23:34:04810}
811
jschuh@chromium.org5bfecbc2014-02-27 13:49:04812TEST(SafeNumerics, IntOperations) {
jschuh@chromium.org4efb2c32014-01-16 06:57:25813 TEST_NUMERIC_CONVERSION(int, int, SIGN_PRESERVING_VALUE_PRESERVING);
814 TEST_NUMERIC_CONVERSION(unsigned int, unsigned int,
815 SIGN_PRESERVING_VALUE_PRESERVING);
816 TEST_NUMERIC_CONVERSION(int, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
817 TEST_NUMERIC_CONVERSION(unsigned int, uint8_t,
818 SIGN_PRESERVING_VALUE_PRESERVING);
819 TEST_NUMERIC_CONVERSION(int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
820
821 TEST_NUMERIC_CONVERSION(int, intmax_t, SIGN_PRESERVING_NARROW);
822 TEST_NUMERIC_CONVERSION(unsigned int, uintmax_t, SIGN_PRESERVING_NARROW);
823 TEST_NUMERIC_CONVERSION(int, float, SIGN_PRESERVING_NARROW);
824 TEST_NUMERIC_CONVERSION(int, double, SIGN_PRESERVING_NARROW);
825
826 TEST_NUMERIC_CONVERSION(unsigned int, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
827 TEST_NUMERIC_CONVERSION(unsigned int, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
828
829 TEST_NUMERIC_CONVERSION(unsigned int, intmax_t, SIGN_TO_UNSIGN_NARROW);
830 TEST_NUMERIC_CONVERSION(unsigned int, float, SIGN_TO_UNSIGN_NARROW);
831 TEST_NUMERIC_CONVERSION(unsigned int, double, SIGN_TO_UNSIGN_NARROW);
832
833 TEST_NUMERIC_CONVERSION(int, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
834 TEST_NUMERIC_CONVERSION(int, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
scottmg@chromium.orgc1c090d32013-01-16 23:34:04835}
836
jschuh@chromium.org5bfecbc2014-02-27 13:49:04837TEST(SafeNumerics, IntMaxOperations) {
jschuh@chromium.org4efb2c32014-01-16 06:57:25838 TEST_NUMERIC_CONVERSION(intmax_t, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
839 TEST_NUMERIC_CONVERSION(uintmax_t, uintmax_t,
840 SIGN_PRESERVING_VALUE_PRESERVING);
841 TEST_NUMERIC_CONVERSION(intmax_t, int, SIGN_PRESERVING_VALUE_PRESERVING);
842 TEST_NUMERIC_CONVERSION(uintmax_t, unsigned int,
843 SIGN_PRESERVING_VALUE_PRESERVING);
844 TEST_NUMERIC_CONVERSION(intmax_t, unsigned int,
845 SIGN_PRESERVING_VALUE_PRESERVING);
846 TEST_NUMERIC_CONVERSION(intmax_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
847
848 TEST_NUMERIC_CONVERSION(intmax_t, float, SIGN_PRESERVING_NARROW);
849 TEST_NUMERIC_CONVERSION(intmax_t, double, SIGN_PRESERVING_NARROW);
850
851 TEST_NUMERIC_CONVERSION(uintmax_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
852 TEST_NUMERIC_CONVERSION(uintmax_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
853
854 TEST_NUMERIC_CONVERSION(uintmax_t, float, SIGN_TO_UNSIGN_NARROW);
855 TEST_NUMERIC_CONVERSION(uintmax_t, double, SIGN_TO_UNSIGN_NARROW);
856
857 TEST_NUMERIC_CONVERSION(intmax_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
858}
859
jschuh@chromium.org5bfecbc2014-02-27 13:49:04860TEST(SafeNumerics, FloatOperations) {
jschuh@chromium.org4efb2c32014-01-16 06:57:25861 TEST_NUMERIC_CONVERSION(float, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
862 TEST_NUMERIC_CONVERSION(float, uintmax_t,
863 SIGN_PRESERVING_VALUE_PRESERVING);
864 TEST_NUMERIC_CONVERSION(float, int, SIGN_PRESERVING_VALUE_PRESERVING);
865 TEST_NUMERIC_CONVERSION(float, unsigned int,
866 SIGN_PRESERVING_VALUE_PRESERVING);
867
868 TEST_NUMERIC_CONVERSION(float, double, SIGN_PRESERVING_NARROW);
869}
870
jschuh@chromium.org5bfecbc2014-02-27 13:49:04871TEST(SafeNumerics, DoubleOperations) {
jschuh@chromium.org4efb2c32014-01-16 06:57:25872 TEST_NUMERIC_CONVERSION(double, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
873 TEST_NUMERIC_CONVERSION(double, uintmax_t,
874 SIGN_PRESERVING_VALUE_PRESERVING);
875 TEST_NUMERIC_CONVERSION(double, int, SIGN_PRESERVING_VALUE_PRESERVING);
876 TEST_NUMERIC_CONVERSION(double, unsigned int,
877 SIGN_PRESERVING_VALUE_PRESERVING);
878}
879
jschuh@chromium.org5bfecbc2014-02-27 13:49:04880TEST(SafeNumerics, SizeTOperations) {
jschuh@chromium.org4efb2c32014-01-16 06:57:25881 TEST_NUMERIC_CONVERSION(size_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
882 TEST_NUMERIC_CONVERSION(int, size_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
883}
884
jschuh23a4b062016-12-02 02:55:08885// A one-off test to ensure StrictNumeric won't resolve to an incorrect type.
886// If this fails we'll just get a compiler error on an ambiguous overload.
887int TestOverload(int) { // Overload fails.
888 return 0;
889}
890uint8_t TestOverload(uint8_t) { // Overload fails.
891 return 0;
892}
893size_t TestOverload(size_t) { // Overload succeeds.
894 return 0;
895}
896
897static_assert(
898 std::is_same<decltype(TestOverload(StrictNumeric<int>())), int>::value,
899 "");
900static_assert(std::is_same<decltype(TestOverload(StrictNumeric<size_t>())),
901 size_t>::value,
902 "");
903
jschuh71b669a2016-12-17 01:13:31904template <typename T>
905struct CastTest1 {
jschuhc8f03cd2017-01-05 03:40:51906 static constexpr T NaN() { return -1; }
jschuh71b669a2016-12-17 01:13:31907 static constexpr T max() { return numeric_limits<T>::max() - 1; }
jschuhc8f03cd2017-01-05 03:40:51908 static constexpr T Overflow() { return max(); }
jschuh71b669a2016-12-17 01:13:31909 static constexpr T lowest() { return numeric_limits<T>::lowest() + 1; }
jschuhc8f03cd2017-01-05 03:40:51910 static constexpr T Underflow() { return lowest(); }
jschuh71b669a2016-12-17 01:13:31911};
912
913template <typename T>
914struct CastTest2 {
jschuhc8f03cd2017-01-05 03:40:51915 static constexpr T NaN() { return 11; }
jschuh71b669a2016-12-17 01:13:31916 static constexpr T max() { return 10; }
jschuhc8f03cd2017-01-05 03:40:51917 static constexpr T Overflow() { return max(); }
jschuh71b669a2016-12-17 01:13:31918 static constexpr T lowest() { return 1; }
jschuhc8f03cd2017-01-05 03:40:51919 static constexpr T Underflow() { return lowest(); }
jschuh71b669a2016-12-17 01:13:31920};
921
agrieve7772a0502016-12-16 18:18:48922TEST(SafeNumerics, CastTests) {
jschuh@chromium.org4efb2c32014-01-16 06:57:25923// MSVC catches and warns that we're forcing saturation in these tests.
924// Since that's intentional, we need to shut this warning off.
925#if defined(COMPILER_MSVC)
926#pragma warning(disable : 4756)
scottmg@chromium.orgc1c090d32013-01-16 23:34:04927#endif
928
scottmg@chromium.orgc1c090d32013-01-16 23:34:04929 int small_positive = 1;
930 int small_negative = -1;
jschuh@chromium.org4efb2c32014-01-16 06:57:25931 double double_small = 1.0;
jschuh@chromium.org5bfecbc2014-02-27 13:49:04932 double double_large = numeric_limits<double>::max();
933 double double_infinity = numeric_limits<float>::infinity();
danakj3193742f2015-06-05 18:15:10934 double double_large_int = numeric_limits<int>::max();
jschuh5030b002016-12-05 18:21:48935 double double_small_int = numeric_limits<int>::lowest();
scottmg@chromium.orgc1c090d32013-01-16 23:34:04936
jschuh4bf22c6d2015-05-28 02:29:25937 // Just test that the casts compile, since the other tests cover logic.
jschuh@chromium.org5bfecbc2014-02-27 13:49:04938 EXPECT_EQ(0, checked_cast<int>(static_cast<size_t>(0)));
jschuh4bf22c6d2015-05-28 02:29:25939 EXPECT_EQ(0, strict_cast<int>(static_cast<char>(0)));
940 EXPECT_EQ(0, strict_cast<int>(static_cast<unsigned char>(0)));
941 EXPECT_EQ(0U, strict_cast<unsigned>(static_cast<unsigned char>(0)));
942 EXPECT_EQ(1ULL, static_cast<uint64_t>(StrictNumeric<size_t>(1U)));
943 EXPECT_EQ(1ULL, static_cast<uint64_t>(SizeT(1U)));
944 EXPECT_EQ(1U, static_cast<size_t>(StrictNumeric<unsigned>(1U)));
945
946 EXPECT_TRUE(CheckedNumeric<uint64_t>(StrictNumeric<unsigned>(1U)).IsValid());
947 EXPECT_TRUE(CheckedNumeric<int>(StrictNumeric<unsigned>(1U)).IsValid());
948 EXPECT_FALSE(CheckedNumeric<unsigned>(StrictNumeric<int>(-1)).IsValid());
949
jschuh07345e62015-09-22 22:13:36950 EXPECT_TRUE(IsValueNegative(-1));
jschuh5030b002016-12-05 18:21:48951 EXPECT_TRUE(IsValueNegative(numeric_limits<int>::lowest()));
952 EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::lowest()));
953 EXPECT_TRUE(IsValueNegative(numeric_limits<double>::lowest()));
jschuh07345e62015-09-22 22:13:36954 EXPECT_FALSE(IsValueNegative(0));
955 EXPECT_FALSE(IsValueNegative(1));
956 EXPECT_FALSE(IsValueNegative(0u));
957 EXPECT_FALSE(IsValueNegative(1u));
958 EXPECT_FALSE(IsValueNegative(numeric_limits<int>::max()));
959 EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::max()));
960 EXPECT_FALSE(IsValueNegative(numeric_limits<double>::max()));
961
jschuh4bf22c6d2015-05-28 02:29:25962 // These casts and coercions will fail to compile:
963 // EXPECT_EQ(0, strict_cast<int>(static_cast<size_t>(0)));
964 // EXPECT_EQ(0, strict_cast<size_t>(static_cast<int>(0)));
965 // EXPECT_EQ(1ULL, StrictNumeric<size_t>(1));
966 // EXPECT_EQ(1, StrictNumeric<size_t>(1U));
scottmg@chromium.orgc1c090d32013-01-16 23:34:04967
jschuh@chromium.org4efb2c32014-01-16 06:57:25968 // Test various saturation corner cases.
969 EXPECT_EQ(saturated_cast<int>(small_negative),
970 static_cast<int>(small_negative));
971 EXPECT_EQ(saturated_cast<int>(small_positive),
972 static_cast<int>(small_positive));
973 EXPECT_EQ(saturated_cast<unsigned>(small_negative),
974 static_cast<unsigned>(0));
975 EXPECT_EQ(saturated_cast<int>(double_small),
976 static_cast<int>(double_small));
jschuh@chromium.org5bfecbc2014-02-27 13:49:04977 EXPECT_EQ(saturated_cast<int>(double_large), numeric_limits<int>::max());
jschuh@chromium.org4efb2c32014-01-16 06:57:25978 EXPECT_EQ(saturated_cast<float>(double_large), double_infinity);
979 EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity);
jschuh5030b002016-12-05 18:21:48980 EXPECT_EQ(numeric_limits<int>::lowest(),
981 saturated_cast<int>(double_small_int));
danakj3193742f2015-06-05 18:15:10982 EXPECT_EQ(numeric_limits<int>::max(), saturated_cast<int>(double_large_int));
vmpstredf1e182015-12-14 20:09:42983
jschuh71b669a2016-12-17 01:13:31984 // Test the saturated cast overrides.
985 using FloatLimits = numeric_limits<float>;
986 using IntLimits = numeric_limits<int>;
987 EXPECT_EQ(-1, (saturated_cast<int, CastTest1>(FloatLimits::quiet_NaN())));
988 EXPECT_EQ(CastTest1<int>::max(),
989 (saturated_cast<int, CastTest1>(FloatLimits::infinity())));
990 EXPECT_EQ(CastTest1<int>::max(),
991 (saturated_cast<int, CastTest1>(FloatLimits::max())));
992 EXPECT_EQ(CastTest1<int>::max(),
993 (saturated_cast<int, CastTest1>(float(IntLimits::max()))));
994 EXPECT_EQ(CastTest1<int>::lowest(),
995 (saturated_cast<int, CastTest1>(-FloatLimits::infinity())));
996 EXPECT_EQ(CastTest1<int>::lowest(),
997 (saturated_cast<int, CastTest1>(FloatLimits::lowest())));
998 EXPECT_EQ(0, (saturated_cast<int, CastTest1>(0.0)));
999 EXPECT_EQ(1, (saturated_cast<int, CastTest1>(1.0)));
1000 EXPECT_EQ(-1, (saturated_cast<int, CastTest1>(-1.0)));
1001 EXPECT_EQ(0, (saturated_cast<int, CastTest1>(0)));
1002 EXPECT_EQ(1, (saturated_cast<int, CastTest1>(1)));
1003 EXPECT_EQ(-1, (saturated_cast<int, CastTest1>(-1)));
1004 EXPECT_EQ(CastTest1<int>::lowest(),
1005 (saturated_cast<int, CastTest1>(float(IntLimits::lowest()))));
1006 EXPECT_EQ(11, (saturated_cast<int, CastTest2>(FloatLimits::quiet_NaN())));
1007 EXPECT_EQ(10, (saturated_cast<int, CastTest2>(FloatLimits::infinity())));
1008 EXPECT_EQ(10, (saturated_cast<int, CastTest2>(FloatLimits::max())));
1009 EXPECT_EQ(1, (saturated_cast<int, CastTest2>(-FloatLimits::infinity())));
1010 EXPECT_EQ(1, (saturated_cast<int, CastTest2>(FloatLimits::lowest())));
1011 EXPECT_EQ(1, (saturated_cast<int, CastTest2>(0U)));
1012
vmpstredf1e182015-12-14 20:09:421013 float not_a_number = std::numeric_limits<float>::infinity() -
1014 std::numeric_limits<float>::infinity();
1015 EXPECT_TRUE(std::isnan(not_a_number));
1016 EXPECT_EQ(0, saturated_cast<int>(not_a_number));
jschuh224f1d72016-11-25 20:08:481017
1018 // Test the CheckedNumeric value extractions functions.
jschuh5030b002016-12-05 18:21:481019 auto int8_min = MakeCheckedNum(numeric_limits<int8_t>::lowest());
jschuh4bc919c2016-12-04 15:08:271020 auto int8_max = MakeCheckedNum(numeric_limits<int8_t>::max());
1021 auto double_max = MakeCheckedNum(numeric_limits<double>::max());
jschuh224f1d72016-11-25 20:08:481022 static_assert(
jschuh23a4b062016-12-02 02:55:081023 std::is_same<int16_t,
1024 decltype(int8_min.ValueOrDie<int16_t>())::type>::value,
jschuh224f1d72016-11-25 20:08:481025 "ValueOrDie returning incorrect type.");
1026 static_assert(
1027 std::is_same<int16_t,
jschuh23a4b062016-12-02 02:55:081028 decltype(int8_min.ValueOrDefault<int16_t>(0))::type>::value,
jschuh224f1d72016-11-25 20:08:481029 "ValueOrDefault returning incorrect type.");
jschuh23a4b062016-12-02 02:55:081030 EXPECT_FALSE(IsValidForType<uint8_t>(int8_min));
1031 EXPECT_TRUE(IsValidForType<uint8_t>(int8_max));
jschuh5030b002016-12-05 18:21:481032 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::lowest()),
jschuh23a4b062016-12-02 02:55:081033 ValueOrDieForType<int>(int8_min));
1034 EXPECT_TRUE(IsValidForType<uint32_t>(int8_max));
jschuh224f1d72016-11-25 20:08:481035 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::max()),
jschuh23a4b062016-12-02 02:55:081036 ValueOrDieForType<int>(int8_max));
1037 EXPECT_EQ(0, ValueOrDefaultForType<int>(double_max, 0));
jschuhe17e0f12016-11-26 03:00:081038 uint8_t uint8_dest = 0;
1039 int16_t int16_dest = 0;
1040 double double_dest = 0;
1041 EXPECT_TRUE(int8_max.AssignIfValid(&uint8_dest));
1042 EXPECT_EQ(static_cast<uint8_t>(numeric_limits<int8_t>::max()), uint8_dest);
1043 EXPECT_FALSE(int8_min.AssignIfValid(&uint8_dest));
1044 EXPECT_TRUE(int8_max.AssignIfValid(&int16_dest));
1045 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::max()), int16_dest);
1046 EXPECT_TRUE(int8_min.AssignIfValid(&int16_dest));
jschuh5030b002016-12-05 18:21:481047 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::lowest()), int16_dest);
jschuhe17e0f12016-11-26 03:00:081048 EXPECT_FALSE(double_max.AssignIfValid(&uint8_dest));
1049 EXPECT_FALSE(double_max.AssignIfValid(&int16_dest));
1050 EXPECT_TRUE(double_max.AssignIfValid(&double_dest));
1051 EXPECT_EQ(numeric_limits<double>::max(), double_dest);
jschuh23a4b062016-12-02 02:55:081052 EXPECT_EQ(1, checked_cast<int>(StrictNumeric<int>(1)));
1053 EXPECT_EQ(1, saturated_cast<int>(StrictNumeric<int>(1)));
1054 EXPECT_EQ(1, strict_cast<int>(StrictNumeric<int>(1)));
agrieve7772a0502016-12-16 18:18:481055}
1056
jschuhfafe0712015-09-14 20:21:241057TEST(SafeNumerics, IsValueInRangeForNumericType) {
1058 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0));
1059 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(1));
1060 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(2));
1061 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(-1));
1062 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0xffffffffu));
1063 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0xffffffff)));
1064 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000000)));
1065 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000001)));
1066 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(
jschuh5030b002016-12-05 18:21:481067 std::numeric_limits<int32_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241068 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(
jschuh5030b002016-12-05 18:21:481069 std::numeric_limits<int64_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241070
1071 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0));
1072 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(1));
1073 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(2));
1074 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(-1));
1075 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffff));
1076 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffffu));
1077 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0x80000000u));
1078 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0xffffffffu));
1079 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x80000000)));
1080 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0xffffffff)));
1081 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x100000000)));
1082 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
jschuh5030b002016-12-05 18:21:481083 std::numeric_limits<int32_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241084 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
jschuh5030b002016-12-05 18:21:481085 static_cast<int64_t>(std::numeric_limits<int32_t>::lowest())));
jschuhfafe0712015-09-14 20:21:241086 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
jschuh5030b002016-12-05 18:21:481087 static_cast<int64_t>(std::numeric_limits<int32_t>::lowest()) - 1));
jschuhfafe0712015-09-14 20:21:241088 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
jschuh5030b002016-12-05 18:21:481089 std::numeric_limits<int64_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241090
1091 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0));
1092 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(1));
1093 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(2));
1094 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(-1));
1095 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0xffffffffu));
1096 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0xffffffff)));
1097 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000000)));
1098 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000001)));
1099 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(
jschuh5030b002016-12-05 18:21:481100 std::numeric_limits<int32_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241101 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(INT64_C(-1)));
1102 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(
jschuh5030b002016-12-05 18:21:481103 std::numeric_limits<int64_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241104
1105 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0));
1106 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(1));
1107 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(2));
1108 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(-1));
1109 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffff));
1110 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffffu));
1111 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x80000000u));
1112 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0xffffffffu));
1113 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x80000000)));
1114 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0xffffffff)));
1115 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x100000000)));
1116 EXPECT_TRUE(
1117 IsValueInRangeForNumericType<int64_t>(INT64_C(0x7fffffffffffffff)));
1118 EXPECT_TRUE(
1119 IsValueInRangeForNumericType<int64_t>(UINT64_C(0x7fffffffffffffff)));
1120 EXPECT_FALSE(
1121 IsValueInRangeForNumericType<int64_t>(UINT64_C(0x8000000000000000)));
1122 EXPECT_FALSE(
1123 IsValueInRangeForNumericType<int64_t>(UINT64_C(0xffffffffffffffff)));
1124 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
jschuh5030b002016-12-05 18:21:481125 std::numeric_limits<int32_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241126 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
jschuh5030b002016-12-05 18:21:481127 static_cast<int64_t>(std::numeric_limits<int32_t>::lowest())));
jschuhfafe0712015-09-14 20:21:241128 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
jschuh5030b002016-12-05 18:21:481129 std::numeric_limits<int64_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241130}
vmpstr19477492015-09-29 22:34:491131
1132TEST(SafeNumerics, CompoundNumericOperations) {
1133 CheckedNumeric<int> a = 1;
1134 CheckedNumeric<int> b = 2;
1135 CheckedNumeric<int> c = 3;
1136 CheckedNumeric<int> d = 4;
1137 a += b;
1138 EXPECT_EQ(3, a.ValueOrDie());
1139 a -= c;
1140 EXPECT_EQ(0, a.ValueOrDie());
1141 d /= b;
1142 EXPECT_EQ(2, d.ValueOrDie());
1143 d *= d;
1144 EXPECT_EQ(4, d.ValueOrDie());
1145
1146 CheckedNumeric<int> too_large = std::numeric_limits<int>::max();
1147 EXPECT_TRUE(too_large.IsValid());
1148 too_large += d;
1149 EXPECT_FALSE(too_large.IsValid());
1150 too_large -= d;
1151 EXPECT_FALSE(too_large.IsValid());
1152 too_large /= d;
1153 EXPECT_FALSE(too_large.IsValid());
1154}
jschuh4fcd6fa2016-11-24 11:58:391155
1156TEST(SafeNumerics, VariadicNumericOperations) {
jschuh4bc919c2016-12-04 15:08:271157 auto a = CheckAdd(1, 2UL, MakeCheckedNum(3LL), 4).ValueOrDie();
jschuh23a4b062016-12-02 02:55:081158 EXPECT_EQ(static_cast<decltype(a)::type>(10), a);
jschuh4bc919c2016-12-04 15:08:271159 auto b = CheckSub(MakeCheckedNum(20.0), 2UL, 4).ValueOrDie();
jschuh23a4b062016-12-02 02:55:081160 EXPECT_EQ(static_cast<decltype(b)::type>(14.0), b);
jschuh4bc919c2016-12-04 15:08:271161 auto c = CheckMul(20.0, MakeCheckedNum(1), 5, 3UL).ValueOrDie();
jschuh23a4b062016-12-02 02:55:081162 EXPECT_EQ(static_cast<decltype(c)::type>(300.0), c);
jschuh4bc919c2016-12-04 15:08:271163 auto d = CheckDiv(20.0, 2.0, MakeCheckedNum(5LL), -4).ValueOrDie();
jschuh23a4b062016-12-02 02:55:081164 EXPECT_EQ(static_cast<decltype(d)::type>(-.5), d);
jschuh4bc919c2016-12-04 15:08:271165 auto e = CheckMod(MakeCheckedNum(20), 3).ValueOrDie();
jschuh23a4b062016-12-02 02:55:081166 EXPECT_EQ(static_cast<decltype(e)::type>(2), e);
jschuh4bc919c2016-12-04 15:08:271167 auto f = CheckLsh(1, MakeCheckedNum(2)).ValueOrDie();
jschuh23a4b062016-12-02 02:55:081168 EXPECT_EQ(static_cast<decltype(f)::type>(4), f);
jschuh4bc919c2016-12-04 15:08:271169 auto g = CheckRsh(4, MakeCheckedNum(2)).ValueOrDie();
jschuh23a4b062016-12-02 02:55:081170 EXPECT_EQ(static_cast<decltype(g)::type>(1), g);
jschuh4fcd6fa2016-11-24 11:58:391171 auto h = CheckRsh(CheckAdd(1, 1, 1, 1), CheckSub(4, 2)).ValueOrDie();
jschuh23a4b062016-12-02 02:55:081172 EXPECT_EQ(static_cast<decltype(h)::type>(1), h);
jschuh4fcd6fa2016-11-24 11:58:391173}