Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1144)

Unified Diff: base/numerics/safe_numerics_unittest.cc

Issue 1338553003: Fix float to int conversion in base/numerics (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: more tests Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/numerics/safe_conversions_impl.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/numerics/safe_numerics_unittest.cc
diff --git a/base/numerics/safe_numerics_unittest.cc b/base/numerics/safe_numerics_unittest.cc
index 6f9a966c0156431e654e71d483d81083fe555690..bad0f5718516b4579f45cf8c4497129a149a0a28 100644
--- a/base/numerics/safe_numerics_unittest.cc
+++ b/base/numerics/safe_numerics_unittest.cc
@@ -18,6 +18,7 @@
using std::numeric_limits;
using base::CheckedNumeric;
using base::checked_cast;
+using base::IsValueInRangeForNumericType;
using base::SizeT;
using base::StrictNumeric;
using base::saturated_cast;
@@ -36,6 +37,26 @@ using base::enable_if;
#pragma warning(disable:4756)
#endif
+// This is a helper function for finding the maximum value in Src that can be
+// wholy represented as the destination floating-point type.
+template <typename Dst, typename Src>
+Dst GetMaxConvertibleToFloat() {
+ typedef numeric_limits<Dst> DstLimits;
+ typedef numeric_limits<Src> SrcLimits;
+ static_assert(SrcLimits::is_specialized, "Source must be numeric.");
+ static_assert(DstLimits::is_specialized, "Destination must be numeric.");
+ CHECK(DstLimits::is_iec559);
+
+ if (SrcLimits::digits <= DstLimits::digits &&
+ MaxExponent<Src>::value <= MaxExponent<Dst>::value)
+ return SrcLimits::max();
+ Src max = SrcLimits::max() / 2 + (SrcLimits::is_integer ? 1 : 0);
+ while (max != static_cast<Src>(static_cast<Dst>(max))) {
+ max /= 2;
+ }
+ return static_cast<Dst>(max);
+}
+
// Helper macros to wrap displaying the conversion types and line numbers.
#define TEST_EXPECTED_VALIDITY(expected, actual) \
EXPECT_EQ(expected, CheckedNumeric<Dst>(actual).validity()) \
@@ -370,6 +391,18 @@ struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> {
TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
+ if (DstLimits::is_integer) {
+ if (SrcLimits::digits < DstLimits::digits) {
+ TEST_EXPECTED_RANGE(RANGE_OVERFLOW,
+ static_cast<Src>(DstLimits::max()));
+ } else {
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
+ }
+ TEST_EXPECTED_RANGE(
+ RANGE_VALID,
+ static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::min()));
+ }
} else if (SrcLimits::is_signed) {
TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1));
TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
@@ -428,6 +461,18 @@ struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> {
TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
+ if (DstLimits::is_integer) {
+ if (SrcLimits::digits < DstLimits::digits) {
+ TEST_EXPECTED_RANGE(RANGE_OVERFLOW,
+ static_cast<Src>(DstLimits::max()));
+ } else {
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
+ }
+ TEST_EXPECTED_RANGE(
+ RANGE_VALID,
+ static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::min()));
+ }
} else {
TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
}
@@ -600,3 +645,77 @@ TEST(SafeNumerics, CastTests) {
EXPECT_EQ(numeric_limits<int>::max(), saturated_cast<int>(double_large_int));
}
+TEST(SafeNumerics, IsValueInRangeForNumericType) {
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(1));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(2));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(-1));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0xffffffffu));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0xffffffff)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000000)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000001)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(
+ std::numeric_limits<int32_t>::min()));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(
+ std::numeric_limits<int64_t>::min()));
+
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(1));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(2));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(-1));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffff));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffffu));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0x80000000u));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0xffffffffu));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x80000000)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0xffffffff)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x100000000)));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
+ std::numeric_limits<int32_t>::min()));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
+ implicit_cast<int64_t>(std::numeric_limits<int32_t>::min())));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
+ implicit_cast<int64_t>(std::numeric_limits<int32_t>::min()) - 1));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
+ std::numeric_limits<int64_t>::min()));
+
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(1));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(2));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(-1));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0xffffffffu));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0xffffffff)));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000000)));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000001)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(
+ std::numeric_limits<int32_t>::min()));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(INT64_C(-1)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(
+ std::numeric_limits<int64_t>::min()));
+
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(1));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(2));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(-1));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffff));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffffu));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x80000000u));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0xffffffffu));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x80000000)));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0xffffffff)));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x100000000)));
+ EXPECT_TRUE(
+ IsValueInRangeForNumericType<int64_t>(INT64_C(0x7fffffffffffffff)));
+ EXPECT_TRUE(
+ IsValueInRangeForNumericType<int64_t>(UINT64_C(0x7fffffffffffffff)));
+ EXPECT_FALSE(
+ IsValueInRangeForNumericType<int64_t>(UINT64_C(0x8000000000000000)));
+ EXPECT_FALSE(
+ IsValueInRangeForNumericType<int64_t>(UINT64_C(0xffffffffffffffff)));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
+ std::numeric_limits<int32_t>::min()));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
+ implicit_cast<int64_t>(std::numeric_limits<int32_t>::min())));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
+ std::numeric_limits<int64_t>::min()));
+}
« no previous file with comments | « base/numerics/safe_conversions_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698