|
17 | 17 |
|
18 | 18 | #include <algorithm>
|
19 | 19 | #include <cstdint>
|
| 20 | +#include <limits> |
20 | 21 | #include <random>
|
21 | 22 | #include <string>
|
22 | 23 | #include <utility>
|
@@ -594,5 +595,59 @@ TEST(CheckIntegersInRange, UnsignedInts) {
|
594 | 595 | CheckInRangeFails(uint64(), "[0, 10000000000, 10000000000]", "[0, 9999999999]");
|
595 | 596 | }
|
596 | 597 |
|
| 598 | +template <typename T> |
| 599 | +class TestAddWithOverflow : public ::testing::Test { |
| 600 | + public: |
| 601 | + void CheckOk(T a, T b, T expected_result = {}) { |
| 602 | + ARROW_SCOPED_TRACE("a = ", a, ", b = ", b); |
| 603 | + T result; |
| 604 | + ASSERT_FALSE(AddWithOverflow(a, b, &result)); |
| 605 | + ASSERT_EQ(result, expected_result); |
| 606 | + } |
| 607 | + |
| 608 | + void CheckOverflow(T a, T b) { |
| 609 | + ARROW_SCOPED_TRACE("a = ", a, ", b = ", b); |
| 610 | + T result; |
| 611 | + ASSERT_TRUE(AddWithOverflow(a, b, &result)); |
| 612 | + } |
| 613 | +}; |
| 614 | + |
| 615 | +using SignedIntegerTypes = ::testing::Types<int8_t, int16_t, int32_t, int64_t>; |
| 616 | + |
| 617 | +TYPED_TEST_SUITE(TestAddWithOverflow, SignedIntegerTypes); |
| 618 | + |
| 619 | +TYPED_TEST(TestAddWithOverflow, Basics) { |
| 620 | + using T = TypeParam; |
| 621 | + |
| 622 | + const T almost_max = std::numeric_limits<T>::max() - T{2}; |
| 623 | + const T almost_min = std::numeric_limits<T>::min() + T{2}; |
| 624 | + |
| 625 | + this->CheckOk(T{1}, T{2}, T{3}); |
| 626 | + this->CheckOk(T{-1}, T{2}, T{1}); |
| 627 | + this->CheckOk(T{-1}, T{-2}, T{-3}); |
| 628 | + |
| 629 | + this->CheckOk(almost_min, T{0}, almost_min); |
| 630 | + this->CheckOk(almost_min, T{-2}, almost_min - T{2}); |
| 631 | + this->CheckOk(almost_min, T{1}, almost_min + T{1}); |
| 632 | + this->CheckOverflow(almost_min, T{-3}); |
| 633 | + this->CheckOverflow(almost_min, almost_min); |
| 634 | + |
| 635 | + this->CheckOk(almost_max, T{0}, almost_max); |
| 636 | + this->CheckOk(almost_max, T{2}, almost_max + T{2}); |
| 637 | + this->CheckOk(almost_max, T{-1}, almost_max - T{1}); |
| 638 | + this->CheckOverflow(almost_max, T{3}); |
| 639 | + this->CheckOverflow(almost_max, almost_max); |
| 640 | + |
| 641 | + // In 2's complement, almost_min == - almost_max - 1 |
| 642 | + this->CheckOk(almost_min, almost_max, T{-1}); |
| 643 | + this->CheckOk(almost_max, almost_min, T{-1}); |
| 644 | + this->CheckOk(almost_min - T{1}, almost_max, T{-2}); |
| 645 | + this->CheckOk(almost_min + T{1}, almost_max, T{0}); |
| 646 | + this->CheckOk(almost_min + T{2}, almost_max, T{1}); |
| 647 | + this->CheckOk(almost_min, almost_max - T{1}, T{-2}); |
| 648 | + this->CheckOk(almost_min, almost_max + T{1}, T{0}); |
| 649 | + this->CheckOk(almost_min, almost_max + T{2}, T{1}); |
| 650 | +} |
| 651 | + |
597 | 652 | } // namespace internal
|
598 | 653 | } // namespace arrow
|
0 commit comments