]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#3068] add unit tests for checked bigints
authorAndrei Pavel <andrei@isc.org>
Mon, 2 Oct 2023 11:36:31 +0000 (14:36 +0300)
committerAndrei Pavel <andrei@isc.org>
Thu, 5 Oct 2023 14:40:02 +0000 (17:40 +0300)
src/lib/util/tests/bigint_unittest.cc

index b811c070c035692ee7f28698bbe6f84c50dc35d2..bbd2c29892881576586f82d758cd1b65080df962 100644 (file)
 
 #include <gtest/gtest.h>
 
+#include <limits>
+
 using namespace isc::util;
 
+using namespace std;
+
 namespace {
 
 // C++ doesn't allow very big integer literals, so that's why some tests on big
@@ -22,73 +26,135 @@ namespace {
 // Checks that int128_t behaves like a signed integer should.
 TEST(BigintTest, int128) {
     // Check addition with small numbers.
-    EXPECT_EQ(24, int128_t(16) + int128_t(8));
+    EXPECT_NO_THROW({
+        EXPECT_EQ(24, int128_t(16) + int128_t(8));
+    });
 
     // Check subtraction with small numbers.
-    EXPECT_EQ(48, int128_t(64) - int128_t(16));
+    EXPECT_NO_THROW({
+        EXPECT_EQ(48, int128_t(64) - int128_t(16));
+    });
 
     // Check multiplication with small numbers.
-    EXPECT_EQ(8, int128_t(2) * int128_t(4));
+    EXPECT_NO_THROW({
+        EXPECT_EQ(8, int128_t(2) * int128_t(4));
+    });
 
     // Check division with small numbers.
-    EXPECT_EQ(16, int128_t(64) / int128_t(4));
+    EXPECT_NO_THROW({
+        EXPECT_EQ(16, int128_t(64) / int128_t(4));
+    });
 
     // Check rounded division with small numbers.
-    EXPECT_EQ(16, int128_t(65) / int128_t(4));
-
-    // Check that dividing by zero throws.
-    EXPECT_THROW(int128_t(1) / 0, std::overflow_error);
+    EXPECT_NO_THROW({
+        EXPECT_EQ(16, int128_t(65) / int128_t(4));
+    });
 
-    // Check that underflowing results in a negative number for int128_t.
-    EXPECT_EQ(-1, int128_t(0) - 1);
+    // Check that INT128_MIN < INT64_MIN.
+    EXPECT_NO_THROW({
+        EXPECT_LT(numeric_limits<int128_t>::min(), numeric_limits<int64_t>::min());
+    });
 
     // Check that UINT64_MAX < INT128_MAX.
-    EXPECT_LT(uint64_t(0) - 1, int128_t(uint128_t(0) - 1));
+    EXPECT_NO_THROW({
+        EXPECT_LT(numeric_limits<uint64_t>::max(), numeric_limits<int128_t>::max());
+    });
 
     // Check that int128_t is default-initialized to zero. Not a strict
-    // requirement, but something that the current implementation ensures.
+    // requirement by Kea, but something that the current implementation ensures.
     int128_t i128;
-    EXPECT_EQ(0, i128);
+    EXPECT_NO_THROW({
+        EXPECT_EQ(0, i128);
+    });
+
+    // Shifting to the right beyond zero does not result in an underflow error.
+    EXPECT_NO_THROW({
+        EXPECT_EQ(0, uint128_t(1) >> 2);
+    });
 
-    // Check that overflowing on big numbers has the correct result.
-    i128 = int128_t(0) - 1;
-    EXPECT_EQ(i128 - 1, i128 + i128);
+    // Check that dividing by zero throws.
+    EXPECT_THROW_MSG(int128_t(1) / 0, overflow_error, "Division by zero.");
+
+    // Check that underflowing results in an error.
+    i128 = numeric_limits<int128_t>::min();
+    EXPECT_THROW_MSG(i128 - 1, overflow_error, "overflow in addition");
+    EXPECT_THROW_MSG(i128 + i128, overflow_error, "overflow in addition");
+
+    // Check that overflowing results in an error.
+    i128 = numeric_limits<int128_t>::max();
+    EXPECT_THROW_MSG(i128 + 1, overflow_error, "overflow in addition");
+    EXPECT_THROW_MSG(i128 + i128, overflow_error, "overflow in addition");
+    EXPECT_THROW_MSG(2 * i128, overflow_error, "overflow in multiplication");
+    EXPECT_THROW_MSG(i128 << 1, overflow_error, "Shift out of range");
 }
 
 // Checks that uint128_t behaves like an unsigned integer should.
 TEST(BigintTest, uint128) {
     // Check addition with small numbers.
-    EXPECT_EQ(24, uint128_t(16) + uint128_t(8));
+    EXPECT_NO_THROW({
+        EXPECT_EQ(24, uint128_t(16) + uint128_t(8));
+    });
 
     // Check subtraction with small numbers.
-    EXPECT_EQ(48, uint128_t(64) - uint128_t(16));
+    EXPECT_NO_THROW({
+        EXPECT_EQ(48, uint128_t(64) - uint128_t(16));
+    });
 
     // Check multiplication with small numbers.
-    EXPECT_EQ(8, uint128_t(2) * uint128_t(4));
+    EXPECT_NO_THROW({
+        EXPECT_EQ(8, uint128_t(2) * uint128_t(4));
+    });
 
     // Check division with small numbers.
-    EXPECT_EQ(16, uint128_t(64) / uint128_t(4));
+    EXPECT_NO_THROW({
+        EXPECT_EQ(16, uint128_t(64) / uint128_t(4));
+    });
 
     // Check rounded division with small numbers.
-    EXPECT_EQ(16, uint128_t(65) / uint128_t(4));
+    EXPECT_NO_THROW({
+        EXPECT_EQ(16, uint128_t(65) / uint128_t(4));
+    });
 
-    // Check that dividing by zero throws.
-    EXPECT_THROW(uint128_t(1) / 0, std::overflow_error);
-
-    // Check that underflowing results in a positive number for uint128_t.
-    EXPECT_LT(0, uint128_t(0) - 1);
+    // Check that UINT128_MIN is 0.
+    EXPECT_NO_THROW({
+        EXPECT_EQ(0, numeric_limits<uint128_t>::min());
+    });
 
     // Check that UINT64_MAX < UINT128_MAX.
-    EXPECT_LT(uint64_t(0) - 1, uint128_t(0) - 1);
+    EXPECT_NO_THROW({
+        EXPECT_LT(numeric_limits<uint64_t>::max(), numeric_limits<int128_t>::max());
+    });
+
+    // Check that INT128_MAX < UINT128_MAX.
+    EXPECT_NO_THROW({
+        EXPECT_LT(numeric_limits<uint64_t>::max(), numeric_limits<int128_t>::max());
+    });
 
     // Check that uint128_t is default-initialized to zero. Not a strict
-    // requirement, but something that the current implementation ensures.
+    // requirement by Kea, but something that the current implementation ensures.
     uint128_t u128;
-    EXPECT_EQ(0, u128);
+    EXPECT_NO_THROW({
+        EXPECT_EQ(0, u128);
+    });
 
-    // Check that overflowing on big numbers has the correct result.
-    u128 = uint128_t(0) - 1;
-    EXPECT_EQ(u128 - 1, u128 + u128);
+    // Shifting to the right beyond zero does not result in an underflow error.
+    EXPECT_NO_THROW({
+        EXPECT_EQ(0, uint128_t(1) >> 2);
+    });
+
+    // Check that dividing by zero throws.
+    EXPECT_THROW_MSG(uint128_t(1) / 0, overflow_error, "Division by zero.");
+
+    // Check that underflowing results in an error.
+    u128 = numeric_limits<uint128_t>::min();
+    EXPECT_THROW_MSG(u128 - 1, range_error, "Subtraction resulted in a negative value, but the type is unsigned");
+
+    // Check that overflowing results in an error.
+    u128 = numeric_limits<uint128_t>::max();
+    EXPECT_THROW_MSG(u128 + 1, overflow_error, "overflow in addition");
+    EXPECT_THROW_MSG(u128 + u128, overflow_error, "overflow in addition");
+    EXPECT_THROW_MSG(2 * u128, overflow_error, "overflow in multiplication");
+    EXPECT_THROW_MSG(u128 << 1, overflow_error, "Shift out of range");
 }
 
 }  // namespace