772 lines
23 KiB
C++
772 lines
23 KiB
C++
// Copyright 2019 The MediaPipe Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// Unit test cases for SafeInt. Some of this overlaps with the testing for
|
|
// StrongInt, but it's important to test not only that SafeInt fails when
|
|
// expected, but that it passes when expected.
|
|
|
|
#include "mediapipe/framework/deps/safe_int.h"
|
|
|
|
#include "mediapipe/framework/port/gtest.h"
|
|
|
|
MEDIAPIPE_DEFINE_SAFE_INT_TYPE(SafeInt8, int8,
|
|
mediapipe::intops::LogFatalOnError);
|
|
MEDIAPIPE_DEFINE_SAFE_INT_TYPE(SafeUInt8, uint8,
|
|
mediapipe::intops::LogFatalOnError);
|
|
MEDIAPIPE_DEFINE_SAFE_INT_TYPE(SafeInt16, int16,
|
|
mediapipe::intops::LogFatalOnError);
|
|
MEDIAPIPE_DEFINE_SAFE_INT_TYPE(SafeUInt16, uint16,
|
|
mediapipe::intops::LogFatalOnError);
|
|
MEDIAPIPE_DEFINE_SAFE_INT_TYPE(SafeInt32, int32,
|
|
mediapipe::intops::LogFatalOnError);
|
|
MEDIAPIPE_DEFINE_SAFE_INT_TYPE(SafeInt64, int64,
|
|
mediapipe::intops::LogFatalOnError);
|
|
MEDIAPIPE_DEFINE_SAFE_INT_TYPE(SafeUInt32, uint32,
|
|
mediapipe::intops::LogFatalOnError);
|
|
MEDIAPIPE_DEFINE_SAFE_INT_TYPE(SafeUInt64, uint64,
|
|
mediapipe::intops::LogFatalOnError);
|
|
|
|
namespace mediapipe {
|
|
namespace intops {
|
|
|
|
//
|
|
// Test cases that apply to signed and unsigned types equally.
|
|
//
|
|
|
|
template <typename T>
|
|
class SignNeutralSafeIntTest : public ::testing::Test {
|
|
public:
|
|
typedef T SafeIntTypeUnderTest;
|
|
};
|
|
|
|
typedef ::testing::Types<SafeInt8, SafeUInt8, SafeInt16, SafeUInt16, SafeInt32,
|
|
SafeUInt32, SafeInt64, SafeUInt64>
|
|
AllSafeIntTypes;
|
|
|
|
TYPED_TEST_SUITE(SignNeutralSafeIntTest, AllSafeIntTypes);
|
|
|
|
TYPED_TEST(SignNeutralSafeIntTest, TestCtors) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test default construction.
|
|
T x;
|
|
EXPECT_EQ(V(), x.value());
|
|
}
|
|
|
|
{ // Test construction from a value.
|
|
T x(93);
|
|
EXPECT_EQ(V(93), x.value());
|
|
}
|
|
|
|
{ // Test copy construction.
|
|
T x(76);
|
|
T y(x);
|
|
EXPECT_EQ(V(76), y.value());
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(SignNeutralSafeIntTest, TestUnaryOperators) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test unary plus of positive values.
|
|
T x(123);
|
|
EXPECT_EQ(V(123), (+x).value());
|
|
}
|
|
{ // Test logical not of positive values.
|
|
T x(123);
|
|
EXPECT_EQ(false, !x);
|
|
EXPECT_EQ(true, !!x);
|
|
}
|
|
{ // Test logical not of zero.
|
|
T x(0);
|
|
EXPECT_EQ(true, !x);
|
|
EXPECT_EQ(false, !!x);
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(SignNeutralSafeIntTest, TestCtorFailures) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test out-of-bounds construction.
|
|
if (std::numeric_limits<V>::is_signed || sizeof(V) < sizeof(uint64)) {
|
|
EXPECT_DEATH((T(std::numeric_limits<uint64>::max())), "bounds");
|
|
}
|
|
}
|
|
{ // Test out-of-bounds construction from float.
|
|
EXPECT_DEATH((T(std::numeric_limits<float>::max())), "bounds");
|
|
EXPECT_DEATH((T(-std::numeric_limits<float>::max())), "bounds");
|
|
}
|
|
{ // Test out-of-bounds construction from double.
|
|
EXPECT_DEATH((T(std::numeric_limits<double>::max())), "bounds");
|
|
EXPECT_DEATH((T(-std::numeric_limits<double>::max())), "bounds");
|
|
}
|
|
{ // Test out-of-bounds construction from long double.
|
|
EXPECT_DEATH((T(std::numeric_limits<long double>::max())), "bounds");
|
|
EXPECT_DEATH((T(-std::numeric_limits<long double>::max())), "bounds");
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(SignNeutralSafeIntTest, TestIncrementDecrement) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test simple increments and decrements.
|
|
T x(0);
|
|
EXPECT_EQ(V(0), x.value());
|
|
EXPECT_EQ(V(0), (x++).value());
|
|
EXPECT_EQ(V(1), x.value());
|
|
EXPECT_EQ(V(2), (++x).value());
|
|
EXPECT_EQ(V(2), x.value());
|
|
EXPECT_EQ(V(2), (x--).value());
|
|
EXPECT_EQ(V(1), x.value());
|
|
EXPECT_EQ(V(0), (--x).value());
|
|
EXPECT_EQ(V(0), x.value());
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(SignNeutralSafeIntTest, TestIncrementDecrementFailures) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test overflowing increment.
|
|
T x(std::numeric_limits<V>::max() - 1);
|
|
EXPECT_EQ(std::numeric_limits<V>::max(), (++x).value());
|
|
EXPECT_DEATH(x++, "overflow");
|
|
EXPECT_DEATH(++x, "overflow");
|
|
}
|
|
{ // Test underflowing decrement.
|
|
T x(std::numeric_limits<V>::min() + 1);
|
|
EXPECT_EQ(std::numeric_limits<V>::min(), (--x).value());
|
|
EXPECT_DEATH(x--, "underflow");
|
|
EXPECT_DEATH(--x, "underflow");
|
|
}
|
|
}
|
|
|
|
#define TEST_T_OP_T(xval, op, yval) \
|
|
{ \
|
|
T x(xval); \
|
|
T y(yval); \
|
|
V expected = x.value() op y.value(); \
|
|
EXPECT_EQ(expected, (x op y).value()); \
|
|
EXPECT_EQ(expected, (x op## = y).value()); \
|
|
EXPECT_EQ(expected, x.value()); \
|
|
}
|
|
|
|
TYPED_TEST(SignNeutralSafeIntTest, TestAdd) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
// Test positive vs. positive addition.
|
|
TEST_T_OP_T(9, +, 3)
|
|
// Test addition by zero.
|
|
TEST_T_OP_T(93, +, 0);
|
|
}
|
|
|
|
TYPED_TEST(SignNeutralSafeIntTest, TestAddFailures) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test overflowing addition.
|
|
T x(std::numeric_limits<V>::max());
|
|
EXPECT_DEATH(x + T(1), "overflow");
|
|
EXPECT_DEATH(x += T(1), "overflow");
|
|
}
|
|
{ // Test overflowing addition.
|
|
T x(std::numeric_limits<V>::max());
|
|
EXPECT_DEATH(x + T(std::numeric_limits<V>::max()), "overflow");
|
|
EXPECT_DEATH(x += T(std::numeric_limits<V>::max()), "overflow");
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(SignNeutralSafeIntTest, TestSubtract) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
// Test positive vs. positive subtraction.
|
|
TEST_T_OP_T(9, -, 3)
|
|
// Test subtraction of zero.
|
|
TEST_T_OP_T(93, -, 0);
|
|
}
|
|
|
|
TYPED_TEST(SignNeutralSafeIntTest, TestSubtractFailures) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test underflowing subtraction.
|
|
T x(std::numeric_limits<V>::min());
|
|
EXPECT_DEATH(x - T(1), "underflow");
|
|
EXPECT_DEATH(x -= T(1), "underflow");
|
|
}
|
|
{ // Test underflowing subtraction.
|
|
T x(std::numeric_limits<V>::min());
|
|
EXPECT_DEATH(x - T(std::numeric_limits<V>::max()), "underflow");
|
|
EXPECT_DEATH(x -= T(std::numeric_limits<V>::max()), "underflow");
|
|
}
|
|
}
|
|
|
|
#define TEST_T_OP_NUM(xval, op, numtype, yval) \
|
|
{ \
|
|
T x(xval); \
|
|
numtype y = yval; \
|
|
V expected = x.value() op y; \
|
|
EXPECT_EQ(expected, (x op y).value()); \
|
|
EXPECT_EQ(expected, (x op## = y).value()); \
|
|
EXPECT_EQ(expected, x.value()); \
|
|
}
|
|
|
|
TYPED_TEST(SignNeutralSafeIntTest, TestMultiply) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
// Test positive vs. positive multiplication across types.
|
|
TEST_T_OP_NUM(9, *, int32, 3);
|
|
TEST_T_OP_NUM(9, *, uint32, 3);
|
|
TEST_T_OP_NUM(9, *, float, 3);
|
|
TEST_T_OP_NUM(9, *, double, 3);
|
|
|
|
// Test positive vs. zero multiplication commutatively across types. This
|
|
// was a real bug.
|
|
TEST_T_OP_NUM(93, *, int32, 0);
|
|
TEST_T_OP_NUM(93, *, uint32, 0);
|
|
TEST_T_OP_NUM(93, *, float, 0);
|
|
TEST_T_OP_NUM(93, *, double, 0);
|
|
|
|
TEST_T_OP_NUM(0, *, int32, 76);
|
|
TEST_T_OP_NUM(0, *, uint32, 76);
|
|
TEST_T_OP_NUM(0, *, float, 76);
|
|
TEST_T_OP_NUM(0, *, double, 76);
|
|
|
|
// Test positive vs. epsilon multiplication.
|
|
TEST_T_OP_NUM(93, *, float, std::numeric_limits<float>::epsilon());
|
|
TEST_T_OP_NUM(93, *, double, std::numeric_limits<float>::epsilon());
|
|
|
|
{ // Test multiplication by float.
|
|
// Multiplication is the only operator that takes one numeric type and
|
|
// one StrongInt type *and* is commutative. This was a real bug.
|
|
T x(0);
|
|
EXPECT_EQ(0, (x * static_cast<float>(1.1)).value());
|
|
EXPECT_EQ(0, (static_cast<float>(1.1) * x).value());
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(SignNeutralSafeIntTest, TestMultiplyFailures) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test overflowing multiplication.
|
|
T x(std::numeric_limits<V>::max());
|
|
EXPECT_DEATH(x * 2, "overflow");
|
|
EXPECT_DEATH(x *= 2, "overflow");
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(SignNeutralSafeIntTest, TestDivide) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
// Test positive vs. positive division across types.
|
|
TEST_T_OP_NUM(9, /, int32, 3);
|
|
TEST_T_OP_NUM(9, /, uint32, 3);
|
|
TEST_T_OP_NUM(9, /, float, 3);
|
|
TEST_T_OP_NUM(9, /, double, 3);
|
|
|
|
// Test zero vs. positive division across types.
|
|
TEST_T_OP_NUM(0, /, int32, 76);
|
|
TEST_T_OP_NUM(0, /, uint32, 76);
|
|
TEST_T_OP_NUM(0, /, float, 76);
|
|
TEST_T_OP_NUM(0, /, double, 76);
|
|
}
|
|
|
|
TYPED_TEST(SignNeutralSafeIntTest, TestDivideFailures) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test divide by zero.
|
|
T x(93);
|
|
EXPECT_DEATH(x / 0, "divide by zero");
|
|
EXPECT_DEATH(x /= 0, "divide by zero");
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(SignNeutralSafeIntTest, TestModulo) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
// Test positive vs. positive modulo across signedness.
|
|
TEST_T_OP_NUM(7, %, int32, 6);
|
|
TEST_T_OP_NUM(7, %, uint32, 6);
|
|
|
|
// Test zero vs. positive modulo across signedness.
|
|
TEST_T_OP_NUM(0, %, int32, 6);
|
|
TEST_T_OP_NUM(0, %, uint32, 6);
|
|
}
|
|
|
|
TYPED_TEST(SignNeutralSafeIntTest, TestModuloFailures) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test modulo by zero.
|
|
T x(93);
|
|
EXPECT_DEATH(x % 0, "divide by zero");
|
|
EXPECT_DEATH(x %= 0, "divide by zero");
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(SignNeutralSafeIntTest, TestLeftShift) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
// Test basic shift.
|
|
TEST_T_OP_NUM(0x09, <<, int, 3);
|
|
// Test shift by zero.
|
|
TEST_T_OP_NUM(0x09, <<, int, 0);
|
|
}
|
|
|
|
TYPED_TEST(SignNeutralSafeIntTest, TestLeftShiftFailures) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test shift by a negative.
|
|
T x(9);
|
|
EXPECT_DEATH(x << -1, "shift by negative");
|
|
EXPECT_DEATH(x <<= -1, "shift by negative");
|
|
}
|
|
{ // Test shift by a too-large.
|
|
T x(9);
|
|
EXPECT_DEATH(x << sizeof(T) * CHAR_BIT, "shift by large");
|
|
EXPECT_DEATH(x <<= sizeof(T) * CHAR_BIT, "shift by large");
|
|
EXPECT_DEATH(x <<= 0x100000001ULL, "shift by large");
|
|
}
|
|
{ // Test overflowing shift.
|
|
T x(std::numeric_limits<V>::max());
|
|
EXPECT_DEATH(x << 1, "overflow");
|
|
EXPECT_DEATH(x <<= 1, "overflow");
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(SignNeutralSafeIntTest, TestRightShift) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
// Test basic shift.
|
|
TEST_T_OP_NUM(0x09, >>, int, 3);
|
|
// Test shift by zero.
|
|
TEST_T_OP_NUM(0x09, >>, int, 0);
|
|
}
|
|
|
|
TYPED_TEST(SignNeutralSafeIntTest, TestRightShiftFailures) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test shift by a negative.
|
|
T x(9);
|
|
EXPECT_DEATH(x >> -1, "shift by negative");
|
|
EXPECT_DEATH(x >>= -1, "shift by negative");
|
|
}
|
|
{ // Test shift by a too-large.
|
|
T x(9);
|
|
EXPECT_DEATH(x >> sizeof(T) * CHAR_BIT, "shift by large");
|
|
EXPECT_DEATH(x >>= sizeof(T) * CHAR_BIT, "shift by large");
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(SignNeutralSafeIntTest, TestFloatToIntTruncation) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
// Test construction from float.
|
|
{
|
|
float f = 93.123;
|
|
T x(f);
|
|
EXPECT_EQ(93, x.value());
|
|
}
|
|
{
|
|
float f = 93.76;
|
|
T x(f);
|
|
EXPECT_EQ(93, x.value());
|
|
}
|
|
// Test construction from double.
|
|
{
|
|
double f = 93.123;
|
|
T x(f);
|
|
EXPECT_EQ(93, x.value());
|
|
}
|
|
{
|
|
double f = 93.76;
|
|
T x(f);
|
|
EXPECT_EQ(93, x.value());
|
|
}
|
|
// Test construction from long double.
|
|
{
|
|
long double f = 93.123;
|
|
T x(f);
|
|
EXPECT_EQ(93, x.value());
|
|
}
|
|
{
|
|
long double f = 93.76;
|
|
T x(f);
|
|
EXPECT_EQ(93, x.value());
|
|
}
|
|
}
|
|
|
|
//
|
|
// Test cases that apply only to signed types.
|
|
//
|
|
|
|
template <typename T>
|
|
class SignedSafeIntTest : public ::testing::Test {
|
|
public:
|
|
typedef T SafeIntTypeUnderTest;
|
|
};
|
|
|
|
typedef ::testing::Types<SafeInt8, SafeInt16, SafeInt32, SafeInt64>
|
|
SignedSafeIntTypes;
|
|
|
|
TYPED_TEST_SUITE(SignedSafeIntTest, SignedSafeIntTypes);
|
|
|
|
TYPED_TEST(SignedSafeIntTest, TestCtors) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test construction from a negative value.
|
|
T x(-1);
|
|
EXPECT_EQ(V(-1), x.value());
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(SignedSafeIntTest, TestUnaryOperators) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test unary plus and minus of positive values.
|
|
T x(123);
|
|
EXPECT_EQ(V(123), (+x).value());
|
|
EXPECT_EQ(V(-123), (-x).value());
|
|
}
|
|
{ // Test unary plus and minus of negative values.
|
|
T x(-123);
|
|
EXPECT_EQ(V(-123), (+x).value());
|
|
EXPECT_EQ(V(123), (-x).value());
|
|
}
|
|
{ // Test logical not of negative values.
|
|
T x(-123);
|
|
EXPECT_EQ(false, !x);
|
|
EXPECT_EQ(true, !!x);
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(SignedSafeIntTest, TestUnaryOperatorsFailures) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test unary minus of negative values.
|
|
T y(std::numeric_limits<V>::min());
|
|
EXPECT_DEATH(-y, "overflow");
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(SignedSafeIntTest, TestAdd) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
// Test negative vs. positive addition.
|
|
TEST_T_OP_T(-9, +, 3)
|
|
// Test positive vs. negative addition.
|
|
TEST_T_OP_T(9, +, -3)
|
|
// Test negative vs. negative addition.
|
|
TEST_T_OP_T(-9, +, -3)
|
|
}
|
|
|
|
TYPED_TEST(SignedSafeIntTest, TestAddFailures) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test underflow by addition of a negative.
|
|
T x(std::numeric_limits<V>::min());
|
|
EXPECT_DEATH(x + T(-1), "underflow");
|
|
EXPECT_DEATH(x += T(-1), "underflow");
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(SignedSafeIntTest, TestSubtract) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
// Test negative vs. positive subtraction.
|
|
TEST_T_OP_T(-9, -, 3)
|
|
// Test positive vs. negative subtraction.
|
|
TEST_T_OP_T(9, -, -3)
|
|
// Test negative vs. negative subtraction.
|
|
TEST_T_OP_T(-9, -, -3)
|
|
// Test positive vs. positive subtraction resulting in negative.
|
|
TEST_T_OP_T(3, -, 9);
|
|
// Test subtraction from zero.
|
|
TEST_T_OP_T(0, -, 93);
|
|
}
|
|
|
|
TYPED_TEST(SignedSafeIntTest, TestSubtractFailures) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test overflow by subtraction of a negative.
|
|
T x(std::numeric_limits<V>::max());
|
|
EXPECT_DEATH(x - T(-1), "overflow");
|
|
EXPECT_DEATH(x -= T(-1), "overflow");
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(SignedSafeIntTest, TestMultiply) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
// Test negative vs. positive multiplication across types.
|
|
TEST_T_OP_NUM(-9, *, int32, 3);
|
|
TEST_T_OP_NUM(-9, *, uint32, 3);
|
|
TEST_T_OP_NUM(-9, *, float, 3);
|
|
TEST_T_OP_NUM(-9, *, double, 3);
|
|
// Test positive vs. negative multiplication across types.
|
|
TEST_T_OP_NUM(9, *, int32, -3);
|
|
// Don't cover unsigneds that are initialized from negative values.
|
|
TEST_T_OP_NUM(9, *, float, -3);
|
|
TEST_T_OP_NUM(9, *, double, -3);
|
|
// Test negative vs. negative multiplication across types.
|
|
TEST_T_OP_NUM(-9, *, int32, -3);
|
|
// Don't cover unsigneds that are initialized from negative values.
|
|
TEST_T_OP_NUM(-9, *, float, -3);
|
|
TEST_T_OP_NUM(-9, *, double, -3);
|
|
|
|
// Test negative vs. zero multiplication commutatively across types.
|
|
TEST_T_OP_NUM(-93, *, int32, 0);
|
|
TEST_T_OP_NUM(-93, *, uint32, 0);
|
|
TEST_T_OP_NUM(-93, *, float, 0);
|
|
TEST_T_OP_NUM(-93, *, double, 0);
|
|
TEST_T_OP_NUM(0, *, int32, -76);
|
|
TEST_T_OP_NUM(0, *, uint32, -76);
|
|
TEST_T_OP_NUM(0, *, float, -76);
|
|
TEST_T_OP_NUM(0, *, double, -76);
|
|
|
|
// Test negative vs. epsilon multiplication.
|
|
TEST_T_OP_NUM(-93, *, float, std::numeric_limits<float>::epsilon());
|
|
TEST_T_OP_NUM(-93, *, double, std::numeric_limits<float>::epsilon());
|
|
}
|
|
|
|
TYPED_TEST(SignedSafeIntTest, TestMultiplyFailures) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test underflowing multiplication.
|
|
T x(std::numeric_limits<V>::min());
|
|
EXPECT_DEATH(x * 2, "underflow");
|
|
EXPECT_DEATH(x *= 2, "underflow");
|
|
}
|
|
{ // Test underflowing multiplication.
|
|
T x(std::numeric_limits<V>::max());
|
|
EXPECT_DEATH(x * -2, "underflow");
|
|
EXPECT_DEATH(x *= -2, "underflow");
|
|
}
|
|
{ // Test overflowing multiplication.
|
|
T x(std::numeric_limits<V>::min());
|
|
EXPECT_DEATH(x * -2, "overflow");
|
|
EXPECT_DEATH(x *= -2, "overflow");
|
|
}
|
|
{ // Test overflowing multiplication.
|
|
T x(std::numeric_limits<V>::min());
|
|
EXPECT_DEATH(x * -1, "overflow");
|
|
EXPECT_DEATH(x *= -1, "overflow");
|
|
}
|
|
{ // Test underflowing multiplication where rhs type is uint64.
|
|
T x(-2);
|
|
EXPECT_DEATH(x * kuint64max, "underflow");
|
|
EXPECT_DEATH(x *= kuint64max, "underflow");
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(SignedSafeIntTest, TestDivide) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
// Test negative vs. positive division across types.
|
|
TEST_T_OP_NUM(-9, /, int32, 3);
|
|
TEST_T_OP_NUM(-9, /, uint32, 3);
|
|
TEST_T_OP_NUM(-9, /, float, 3);
|
|
TEST_T_OP_NUM(-9, /, double, 3);
|
|
// Test positive vs. negative division across types.
|
|
TEST_T_OP_NUM(9, /, int32, -3);
|
|
TEST_T_OP_NUM(9, /, uint32, -3);
|
|
TEST_T_OP_NUM(9, /, float, -3);
|
|
TEST_T_OP_NUM(9, /, double, -3);
|
|
// Test negative vs. negative division across types.
|
|
TEST_T_OP_NUM(-9, /, int32, -3);
|
|
TEST_T_OP_NUM(-9, /, uint32, -3);
|
|
TEST_T_OP_NUM(-9, /, float, -3);
|
|
TEST_T_OP_NUM(-9, /, double, -3);
|
|
|
|
// Test zero vs. negative division across types.
|
|
TEST_T_OP_NUM(0, /, int32, -76);
|
|
TEST_T_OP_NUM(0, /, uint32, -76);
|
|
TEST_T_OP_NUM(0, /, float, -76);
|
|
TEST_T_OP_NUM(0, /, double, -76);
|
|
}
|
|
|
|
TYPED_TEST(SignedSafeIntTest, TestDivideFailures) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test overflowing division.
|
|
T x(std::numeric_limits<V>::min());
|
|
EXPECT_DEATH(x / -1, "overflow");
|
|
EXPECT_DEATH(x /= -1, "overflow");
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(SignedSafeIntTest, TestModulo) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
// Test negative vs. positive modulo across signedness.
|
|
TEST_T_OP_NUM(-7, %, int32, 6);
|
|
TEST_T_OP_NUM(-7, %, uint32, 6);
|
|
// Test positive vs. negative modulo across signedness.
|
|
TEST_T_OP_NUM(7, %, int32, -6);
|
|
TEST_T_OP_NUM(7, %, uint32, -6);
|
|
// Test negative vs. negative modulo across signedness.
|
|
TEST_T_OP_NUM(-7, %, int32, -6);
|
|
TEST_T_OP_NUM(-7, %, uint32, -6);
|
|
|
|
// Test zero vs. negative modulo across signedness.
|
|
TEST_T_OP_NUM(0, %, int32, -6);
|
|
TEST_T_OP_NUM(0, %, uint32, -6);
|
|
}
|
|
|
|
TYPED_TEST(SignedSafeIntTest, TestModuloFailures) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test overflowing modulo.
|
|
T x(std::numeric_limits<V>::min());
|
|
EXPECT_DEATH(x % -1, "overflow");
|
|
EXPECT_DEATH(x %= -1, "overflow");
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(SignedSafeIntTest, TestLeftShiftFailures) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test shift of a negative.
|
|
T x(-9);
|
|
EXPECT_DEATH(x << 1, "shift of negative");
|
|
EXPECT_DEATH(x <<= 1, "shift of negative");
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(SignedSafeIntTest, TestRightShiftFailures) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test shift of a negative.
|
|
T x(-9);
|
|
EXPECT_DEATH(x >> 1, "shift of negative");
|
|
EXPECT_DEATH(x >>= 1, "shift of negative");
|
|
}
|
|
}
|
|
|
|
//
|
|
// Test cases that apply only to unsigned types.
|
|
//
|
|
|
|
template <typename T>
|
|
class UnsignedSafeIntTest : public ::testing::Test {
|
|
public:
|
|
typedef T SafeIntTypeUnderTest;
|
|
};
|
|
|
|
typedef ::testing::Types<SafeUInt8, SafeUInt16, SafeUInt32, SafeUInt64>
|
|
UnsignedSafeIntTypes;
|
|
|
|
TYPED_TEST_SUITE(UnsignedSafeIntTest, UnsignedSafeIntTypes);
|
|
|
|
TYPED_TEST(UnsignedSafeIntTest, TestCtors) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test out-of-bounds construction.
|
|
EXPECT_DEATH(T(-1), "bounds");
|
|
}
|
|
{ // Test out-of-bounds construction from float.
|
|
EXPECT_DEATH((T(static_cast<float>(-1))), "bounds");
|
|
}
|
|
{ // Test out-of-bounds construction from double.
|
|
EXPECT_DEATH((T(static_cast<double>(-1))), "bounds");
|
|
}
|
|
{ // Test out-of-bounds construction from long double.
|
|
EXPECT_DEATH((T(static_cast<long double>(-1))), "bounds");
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(UnsignedSafeIntTest, TestUnaryOperators) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test bitwise not of positive values.
|
|
T x(123);
|
|
EXPECT_EQ(V(~(x.value())), (~x).value());
|
|
EXPECT_EQ(x.value(), (~~x).value());
|
|
}
|
|
{ // Test bitwise not of zero.
|
|
T x(0x00);
|
|
EXPECT_EQ(V(~(x.value())), (~x).value());
|
|
EXPECT_EQ(x.value(), (~~x).value());
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(UnsignedSafeIntTest, TestMultiply) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test multiplication by a negative.
|
|
T x(93);
|
|
EXPECT_DEATH(x * -1, "negation");
|
|
EXPECT_DEATH(x *= -1, "negation");
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(UnsignedSafeIntTest, TestDivide) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test division by a negative.
|
|
T x(93);
|
|
EXPECT_DEATH(x / -1, "negation");
|
|
EXPECT_DEATH(x /= -1, "negation");
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(UnsignedSafeIntTest, TestModulo) {
|
|
typedef typename TestFixture::SafeIntTypeUnderTest T;
|
|
typedef typename T::ValueType V;
|
|
|
|
{ // Test modulo by a negative.
|
|
T x(93);
|
|
EXPECT_DEATH(x % -5, "negation");
|
|
EXPECT_DEATH(x %= -5, "negation");
|
|
}
|
|
}
|
|
|
|
} // namespace intops
|
|
} // namespace mediapipe
|