// 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 class SignNeutralSafeIntTest : public ::testing::Test { public: typedef T SafeIntTypeUnderTest; }; typedef ::testing::Types 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::is_signed || sizeof(V) < sizeof(uint64)) { EXPECT_DEATH((T(std::numeric_limits::max())), "bounds"); } } { // Test out-of-bounds construction from float. EXPECT_DEATH((T(std::numeric_limits::max())), "bounds"); EXPECT_DEATH((T(-std::numeric_limits::max())), "bounds"); } { // Test out-of-bounds construction from double. EXPECT_DEATH((T(std::numeric_limits::max())), "bounds"); EXPECT_DEATH((T(-std::numeric_limits::max())), "bounds"); } { // Test out-of-bounds construction from long double. EXPECT_DEATH((T(std::numeric_limits::max())), "bounds"); EXPECT_DEATH((T(-std::numeric_limits::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::max() - 1); EXPECT_EQ(std::numeric_limits::max(), (++x).value()); EXPECT_DEATH(x++, "overflow"); EXPECT_DEATH(++x, "overflow"); } { // Test underflowing decrement. T x(std::numeric_limits::min() + 1); EXPECT_EQ(std::numeric_limits::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::max()); EXPECT_DEATH(x + T(1), "overflow"); EXPECT_DEATH(x += T(1), "overflow"); } { // Test overflowing addition. T x(std::numeric_limits::max()); EXPECT_DEATH(x + T(std::numeric_limits::max()), "overflow"); EXPECT_DEATH(x += T(std::numeric_limits::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::min()); EXPECT_DEATH(x - T(1), "underflow"); EXPECT_DEATH(x -= T(1), "underflow"); } { // Test underflowing subtraction. T x(std::numeric_limits::min()); EXPECT_DEATH(x - T(std::numeric_limits::max()), "underflow"); EXPECT_DEATH(x -= T(std::numeric_limits::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::epsilon()); TEST_T_OP_NUM(93, *, double, std::numeric_limits::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(1.1)).value()); EXPECT_EQ(0, (static_cast(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::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::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 class SignedSafeIntTest : public ::testing::Test { public: typedef T SafeIntTypeUnderTest; }; typedef ::testing::Types 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::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::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::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::epsilon()); TEST_T_OP_NUM(-93, *, double, std::numeric_limits::epsilon()); } TYPED_TEST(SignedSafeIntTest, TestMultiplyFailures) { typedef typename TestFixture::SafeIntTypeUnderTest T; typedef typename T::ValueType V; { // Test underflowing multiplication. T x(std::numeric_limits::min()); EXPECT_DEATH(x * 2, "underflow"); EXPECT_DEATH(x *= 2, "underflow"); } { // Test underflowing multiplication. T x(std::numeric_limits::max()); EXPECT_DEATH(x * -2, "underflow"); EXPECT_DEATH(x *= -2, "underflow"); } { // Test overflowing multiplication. T x(std::numeric_limits::min()); EXPECT_DEATH(x * -2, "overflow"); EXPECT_DEATH(x *= -2, "overflow"); } { // Test overflowing multiplication. T x(std::numeric_limits::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::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::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 class UnsignedSafeIntTest : public ::testing::Test { public: typedef T SafeIntTypeUnderTest; }; typedef ::testing::Types 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(-1))), "bounds"); } { // Test out-of-bounds construction from double. EXPECT_DEATH((T(static_cast(-1))), "bounds"); } { // Test out-of-bounds construction from long double. EXPECT_DEATH((T(static_cast(-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