// Copyright 2014 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include <limits> #include "src/base/bounds.h" #include "src/utils/utils.h" #include "testing/gtest-support.h" namespace v8 { namespace internal { template <typename T> class UtilsTest : public ::testing::Test {}; using IntegerTypes = ::testing::Types<signed char, unsigned char, short, // NOLINT(runtime/int) unsigned short, // NOLINT(runtime/int) int, unsigned int, long, // NOLINT(runtime/int) unsigned long, // NOLINT(runtime/int) long long, // NOLINT(runtime/int) unsigned long long, // NOLINT(runtime/int) int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t>; TYPED_TEST_SUITE(UtilsTest, IntegerTypes); TYPED_TEST(UtilsTest, SaturateSub) { TypeParam min = std::numeric_limits<TypeParam>::min(); TypeParam max = std::numeric_limits<TypeParam>::max(); EXPECT_EQ(SaturateSub<TypeParam>(min, 0), min); EXPECT_EQ(SaturateSub<TypeParam>(max, 0), max); EXPECT_EQ(SaturateSub<TypeParam>(max, min), max); EXPECT_EQ(SaturateSub<TypeParam>(min, max), min); EXPECT_EQ(SaturateSub<TypeParam>(min, max / 3), min); EXPECT_EQ(SaturateSub<TypeParam>(min + 1, 2), min); if (std::numeric_limits<TypeParam>::is_signed) { EXPECT_EQ(SaturateSub<TypeParam>(min, min), static_cast<TypeParam>(0)); EXPECT_EQ(SaturateSub<TypeParam>(0, min), max); EXPECT_EQ(SaturateSub<TypeParam>(max / 3, min), max); EXPECT_EQ(SaturateSub<TypeParam>(max / 5, min), max); EXPECT_EQ(SaturateSub<TypeParam>(min / 3, max), min); EXPECT_EQ(SaturateSub<TypeParam>(min / 9, max), min); EXPECT_EQ(SaturateSub<TypeParam>(max, min / 3), max); EXPECT_EQ(SaturateSub<TypeParam>(min, max / 3), min); EXPECT_EQ(SaturateSub<TypeParam>(max / 3 * 2, min / 2), max); EXPECT_EQ(SaturateSub<TypeParam>(min / 3 * 2, max / 2), min); } else { EXPECT_EQ(SaturateSub<TypeParam>(min, min), min); EXPECT_EQ(SaturateSub<TypeParam>(0, min), min); EXPECT_EQ(SaturateSub<TypeParam>(0, max), min); EXPECT_EQ(SaturateSub<TypeParam>(max / 3, max), min); EXPECT_EQ(SaturateSub<TypeParam>(max - 3, max), min); } TypeParam test_cases[] = {static_cast<TypeParam>(min / 23), static_cast<TypeParam>(max / 3), 63, static_cast<TypeParam>(min / 6), static_cast<TypeParam>(max / 55), static_cast<TypeParam>(min / 2), static_cast<TypeParam>(max / 2), 0, 1, 2, 3, 4, 42}; TRACED_FOREACH(TypeParam, x, test_cases) { TRACED_FOREACH(TypeParam, y, test_cases) { if (std::numeric_limits<TypeParam>::is_signed) { EXPECT_EQ(SaturateSub<TypeParam>(x, y), x - y); } else { EXPECT_EQ(SaturateSub<TypeParam>(x, y), y > x ? min : x - y); } } } } TYPED_TEST(UtilsTest, SaturateAdd) { TypeParam min = std::numeric_limits<TypeParam>::min(); TypeParam max = std::numeric_limits<TypeParam>::max(); EXPECT_EQ(SaturateAdd<TypeParam>(min, min), min); EXPECT_EQ(SaturateAdd<TypeParam>(max, max), max); EXPECT_EQ(SaturateAdd<TypeParam>(min, min / 3), min); EXPECT_EQ(SaturateAdd<TypeParam>(max / 8 * 7, max / 3 * 2), max); EXPECT_EQ(SaturateAdd<TypeParam>(min / 3 * 2, min / 8 * 7), min); EXPECT_EQ(SaturateAdd<TypeParam>(max / 20 * 18, max / 25 * 18), max); EXPECT_EQ(SaturateAdd<TypeParam>(min / 3 * 2, min / 3 * 2), min); EXPECT_EQ(SaturateAdd<TypeParam>(max - 1, 2), max); EXPECT_EQ(SaturateAdd<TypeParam>(max - 100, 101), max); TypeParam test_cases[] = {static_cast<TypeParam>(min / 23), static_cast<TypeParam>(max / 3), 63, static_cast<TypeParam>(min / 6), static_cast<TypeParam>(max / 55), static_cast<TypeParam>(min / 2), static_cast<TypeParam>(max / 2), 0, 1, 2, 3, 4, 42}; TRACED_FOREACH(TypeParam, x, test_cases) { TRACED_FOREACH(TypeParam, y, test_cases) { EXPECT_EQ(SaturateAdd<TypeParam>(x, y), x + y); } } } TYPED_TEST(UtilsTest, PassesFilterTest) { EXPECT_TRUE( PassesFilter(base::CStrVector("abcdefg"), base::CStrVector("abcdefg"))); EXPECT_TRUE( PassesFilter(base::CStrVector("abcdefg"), base::CStrVector("abcdefg*"))); EXPECT_TRUE( PassesFilter(base::CStrVector("abcdefg"), base::CStrVector("abc*"))); EXPECT_TRUE(PassesFilter(base::CStrVector("abcdefg"), base::CStrVector("*"))); EXPECT_TRUE( PassesFilter(base::CStrVector("abcdefg"), base::CStrVector("-~"))); EXPECT_TRUE( PassesFilter(base::CStrVector("abcdefg"), base::CStrVector("-abcdefgh"))); EXPECT_TRUE(PassesFilter(base::CStrVector("abdefg"), base::CStrVector("-"))); EXPECT_FALSE( PassesFilter(base::CStrVector("abcdefg"), base::CStrVector("-abcdefg"))); EXPECT_FALSE( PassesFilter(base::CStrVector("abcdefg"), base::CStrVector("-abcdefg*"))); EXPECT_FALSE( PassesFilter(base::CStrVector("abcdefg"), base::CStrVector("-abc*"))); EXPECT_FALSE( PassesFilter(base::CStrVector("abcdefg"), base::CStrVector("-*"))); EXPECT_FALSE( PassesFilter(base::CStrVector("abcdefg"), base::CStrVector("~"))); EXPECT_FALSE(PassesFilter(base::CStrVector("abcdefg"), base::CStrVector(""))); EXPECT_FALSE( PassesFilter(base::CStrVector("abcdefg"), base::CStrVector("abcdefgh"))); EXPECT_TRUE(PassesFilter(base::CStrVector(""), base::CStrVector(""))); EXPECT_TRUE(PassesFilter(base::CStrVector(""), base::CStrVector("*"))); EXPECT_FALSE(PassesFilter(base::CStrVector(""), base::CStrVector("-"))); EXPECT_FALSE(PassesFilter(base::CStrVector(""), base::CStrVector("-*"))); EXPECT_FALSE(PassesFilter(base::CStrVector(""), base::CStrVector("a"))); } TEST(UtilsTest, IsInBounds) { // for column consistency and terseness #define INB(x, y, z) EXPECT_TRUE(base::IsInBounds<size_t>(x, y, z)) #define OOB(x, y, z) EXPECT_FALSE(base::IsInBounds<size_t>(x, y, z)) INB(0, 0, 1); INB(0, 1, 1); INB(1, 0, 1); OOB(0, 2, 1); OOB(2, 0, 1); INB(0, 0, 2); INB(0, 1, 2); INB(0, 2, 2); INB(0, 0, 2); INB(1, 0, 2); INB(2, 0, 2); OOB(0, 3, 2); OOB(3, 0, 2); INB(0, 1, 2); INB(1, 1, 2); OOB(1, 2, 2); OOB(2, 1, 2); const size_t max = std::numeric_limits<size_t>::max(); const size_t half = max / 2; // limit cases. INB(0, 0, max); INB(0, 1, max); INB(1, 0, max); INB(max, 0, max); INB(0, max, max); INB(max - 1, 0, max); INB(0, max - 1, max); INB(max - 1, 1, max); INB(1, max - 1, max); INB(half, half, max); INB(half + 1, half, max); INB(half, half + 1, max); OOB(max, 0, 0); OOB(0, max, 0); OOB(max, 0, 1); OOB(0, max, 1); OOB(max, 0, 2); OOB(0, max, 2); OOB(max, 0, max - 1); OOB(0, max, max - 1); // wraparound cases. OOB(max, 1, max); OOB(1, max, max); OOB(max - 1, 2, max); OOB(2, max - 1, max); OOB(half + 1, half + 1, max); OOB(half + 1, half + 1, max); #undef INB #undef OOB } } // namespace internal } // namespace v8