mediapipe/mediapipe2/framework/deps/safe_int_test.cc
2021-06-10 23:01:19 +00:00

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