Skip to content
This repository has been archived by the owner on Oct 28, 2021. It is now read-only.

Commit

Permalink
Merge pull request #4064 from ethereum/boost-shift-tests
Browse files Browse the repository at this point in the history
Boost shift tests
  • Loading branch information
chfast authored Apr 28, 2017
2 parents 65405e5 + f74dbca commit 0725111
Showing 1 changed file with 141 additions and 6 deletions.
147 changes: 141 additions & 6 deletions test/unittests/external-dependencies/boost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file boost.cpp
* @author Lefteris Karapetsas <lefteris@ethdev.com>
* @date 2015
* Tests for external dependencies: Boost
*/
/// @file
/// Unit tests for boost libraries.

#include <boost/test/unit_test.hpp>
#include <libdevcore/Common.h>
#include <test/tools/libtesteth/TestHelper.h>

using namespace dev;
using namespace dev::test;
using namespace boost;
using namespace boost::multiprecision;

BOOST_FIXTURE_TEST_SUITE(ExtDepBoost, TestOutputHelper)
BOOST_FIXTURE_TEST_SUITE(boost, TestOutputHelper)

// test that reproduces issue https://github.com/ethereum/cpp-ethereum/issues/1977
BOOST_AUTO_TEST_CASE(u256_overflow_test)
Expand All @@ -37,4 +37,139 @@ BOOST_AUTO_TEST_CASE(u256_overflow_test)
BOOST_CHECK(a < b);
}

BOOST_AUTO_TEST_CASE(u256_shift_left)
{
u256 a = 1;
uint64_t amount = 1;
auto b = a << amount;
BOOST_CHECK_EQUAL(b, 2);

auto high_bit = u256{0};
bit_set(high_bit, 255);
BOOST_CHECK_EQUAL(a << 255, high_bit);
BOOST_CHECK_EQUAL(a << uint64_t(256), 0);
BOOST_CHECK_EQUAL(a << 0, a);

u256 c = 3;
BOOST_CHECK_EQUAL(c, 3);
BOOST_CHECK_EQUAL(c << uint64_t(256), 0);
BOOST_CHECK_EQUAL(c << 0, c);

// Bug workaround:
BOOST_CHECK_EQUAL(static_cast<u256>(bigint(u256(3)) << 255), u256(1) << 255);
}

BOOST_AUTO_TEST_CASE(u256_shift_left_bug, *unit_test::expected_failures(1))
{
using uint256 = number<cpp_int_backend<256, 256, unsigned_magnitude, unchecked, void>>;
BOOST_CHECK_EQUAL(uint256(3) << 255, uint256(1) << 255);
}

BOOST_AUTO_TEST_CASE(u256_logical_shift_right)
{
u256 a = 1;
uint64_t amount = 1;
auto b = a >> amount;
BOOST_CHECK_EQUAL(b, 0);
BOOST_CHECK_EQUAL(a >> 255, 0);
BOOST_CHECK_EQUAL(a >> uint64_t(256), 0);
BOOST_CHECK_EQUAL(a >> uint64_t(-1), 0);

u256 h;
bit_set(h, 255);
BOOST_CHECK_EQUAL(h >> 0, u256(1) << 255);
BOOST_CHECK_EQUAL(h >> 1, u256(1) << 254);
BOOST_CHECK_EQUAL(h >> 2, u256(1) << 253);
BOOST_CHECK_EQUAL(h >> 254, u256(1) << 1);
BOOST_CHECK_EQUAL(h >> 255, u256(1) << 0);
BOOST_CHECK_EQUAL(h >> 256, 0);
BOOST_CHECK_EQUAL(h >> uint64_t(-1), 0);

u256 g;
bit_set(g, 255);
bit_set(g, 254);
BOOST_CHECK_EQUAL(g >> 255, 1);
BOOST_CHECK_EQUAL(g >> 254, 3);
BOOST_CHECK_EQUAL(g >> 253, 3 << 1);
BOOST_CHECK_EQUAL(g >> 252, 3 << 2);
BOOST_CHECK_EQUAL(g >> 251, 3 << 3);
BOOST_CHECK_EQUAL(g >> 0, u256(3) << 254);
BOOST_CHECK_EQUAL(g >> 1, u256(3) << 253);
BOOST_CHECK_EQUAL(g >> 2, u256(3) << 252);
BOOST_CHECK_EQUAL(g >> 3, u256(3) << 251);
BOOST_CHECK_EQUAL(g >> 100, u256(3) << 154);
BOOST_CHECK_EQUAL(g >> 256, 0);
BOOST_CHECK_EQUAL(g >> 257, 0);
BOOST_CHECK_EQUAL(g >> uint32_t(-1), 0);
BOOST_CHECK_EQUAL(g >> uint64_t(-1), 0);
BOOST_CHECK_EQUAL(g >> uint16_t(-1), 0);
BOOST_CHECK_EQUAL(g >> (uint16_t(-1) - 1), 0);
}

constexpr auto int64_min = std::numeric_limits<int64_t>::min();
static_assert(int64_min >> 1 == int64_min / 2, "I cannot shift!");

BOOST_AUTO_TEST_CASE(u256_arithmetic_shift_right)
{
s256 a = 1;
uint64_t amount = 1;
auto b = a >> amount;
BOOST_CHECK_EQUAL(b, 0);
BOOST_CHECK_EQUAL(a >> 255, 0);
BOOST_CHECK_EQUAL(a >> uint64_t(256), 0);
BOOST_CHECK_EQUAL(a >> uint64_t(-1), 0);

s256 n = -1;
BOOST_CHECK_EQUAL(n >> 0, n);
BOOST_CHECK_EQUAL(n >> 1, n);
BOOST_CHECK_EQUAL(n >> 2, n);
BOOST_CHECK_EQUAL(n >> 254, n);
BOOST_CHECK_EQUAL(n >> 255, n);
BOOST_CHECK_EQUAL(n >> 256, n);
BOOST_CHECK_EQUAL(n >> 257, n);
BOOST_CHECK_EQUAL(n >> ~uint64_t(0), n);

// Test min value. This actually -(2^256-1), not -(2^255) as in C.
s256 h = std::numeric_limits<s256>::min();
BOOST_CHECK_LT(h, 0);
BOOST_CHECK_EQUAL(h >> 0, h);
BOOST_CHECK_EQUAL(h >> 256, -1);

// Test EVM min value.
s256 g = s256(-1) << 255;
BOOST_CHECK_LT(g, 0);
BOOST_CHECK_EQUAL(static_cast<u256>(g), u256(1) << 255);
BOOST_CHECK_EQUAL(g >> 0, g);
BOOST_CHECK_EQUAL(static_cast<u256>(g >> 1), u256(0b11) << 254);
BOOST_CHECK_EQUAL(static_cast<u256>(g >> 2), u256(0b111) << 253);
BOOST_CHECK_EQUAL(static_cast<u256>(g >> 3), u256(0b1111) << 252);

BOOST_CHECK_EQUAL(static_cast<u256>(g >> 255), ~u256(0));
BOOST_CHECK_EQUAL(static_cast<u256>(g >> 254), ~u256(0b1));
BOOST_CHECK_EQUAL(static_cast<u256>(g >> 253), ~u256(0b11));

// Test shifting more that one bit.
s256 k = s256(0b111) << 252;
BOOST_CHECK_EQUAL(k, u256(0b111) << 252);
BOOST_CHECK_EQUAL(k >> 1, u256(0b111) << 251);
BOOST_CHECK_EQUAL(k >> 2, u256(0b111) << 250);
BOOST_CHECK_EQUAL(k >> 252, 0b111);
BOOST_CHECK_EQUAL(k >> 253, 0b11);
BOOST_CHECK_EQUAL(k >> 254, 0b1);
BOOST_CHECK_EQUAL(k >> 255, 0);
BOOST_CHECK_EQUAL(k >> 256, 0);
BOOST_CHECK_EQUAL(k >> ~uint32_t(0), 0);

// Division equivalence.

// Built-in type:
int64_t d = int64_min;
BOOST_CHECK_EQUAL(d >> 1, d / 2);
int64_t e = d + 1;
BOOST_CHECK_EQUAL(e >> 1, e / 2 - 1);

// Boost type:
BOOST_CHECK_EQUAL(h >> 1, h / 2 - 1);
}

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit 0725111

Please sign in to comment.