Changeset View
Changeset View
Standalone View
Standalone View
src/test/scriptnum63bit_tests.cpp
- This file was added.
// Copyright (c) 2021 The Bitcoin ABC developers | |||||
// Distributed under the MIT software license, see the accompanying | |||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | |||||
#include <boost/test/unit_test.hpp> | |||||
#include <test/util/setup_common.h> | |||||
#include <functional> | |||||
#include <script/script.h> | |||||
#include <test/lcg.h> | |||||
#include <test/scriptnum63bit.h> | |||||
BOOST_FIXTURE_TEST_SUITE(scriptnum63bit_tests, BasicTestingSetup) | |||||
template <typename TScriptNum> | |||||
static void CheckOperatorsGeneric(const valtype &a_i63, const valtype &b_i63) { | |||||
const i128_t a_i128 = ToInt128(a_i63); | |||||
const i128_t b_i128 = ToInt128(b_i63); | |||||
BOOST_CHECK(IsInScriptBounds(a_i128)); | |||||
BOOST_CHECK(IsInScriptBounds(b_i128)); | |||||
const TScriptNum a((int64_t)a_i128); | |||||
const TScriptNum b((int64_t)b_i128); | |||||
{ | |||||
// Test operator+ | |||||
TScriptNum result(0); | |||||
bool expect_overflow = !IsInScriptBounds(a_i128 + b_i128); | |||||
try { | |||||
result = a + b; | |||||
BOOST_CHECK_MESSAGE( | |||||
!expect_overflow, | |||||
strprintf("%d + %d overflowed", a_i128, b_i128)); | |||||
} catch (std::runtime_error &ex) { | |||||
BOOST_CHECK_MESSAGE( | |||||
expect_overflow, | |||||
strprintf("%d + %d didn't overflow", a_i128, b_i128)); | |||||
} | |||||
} | |||||
{ | |||||
// Test operator- | |||||
TScriptNum result(0); | |||||
bool expect_overflow = !IsInScriptBounds(a_i128 - b_i128); | |||||
try { | |||||
result = a - b; | |||||
BOOST_CHECK_MESSAGE( | |||||
!expect_overflow, | |||||
strprintf("%d - %d overflowed", a_i128, b_i128)); | |||||
} catch (std::runtime_error &ex) { | |||||
BOOST_CHECK_MESSAGE( | |||||
expect_overflow, | |||||
strprintf("%d - %d didn't overflow", a_i128, b_i128)); | |||||
} | |||||
} | |||||
{ | |||||
// Test operator+= | |||||
TScriptNum result = a; | |||||
bool expect_overflow = !IsInScriptBounds(a_i128 + b_i128); | |||||
try { | |||||
result += b; | |||||
BOOST_CHECK_MESSAGE( | |||||
!expect_overflow, | |||||
strprintf("%d += %d overflowed", a_i128, b_i128)); | |||||
} catch (std::runtime_error &ex) { | |||||
BOOST_CHECK_MESSAGE( | |||||
expect_overflow, | |||||
strprintf("%d += %d didn't overflow", a_i128, b_i128)); | |||||
} | |||||
} | |||||
{ | |||||
// Test operator-= | |||||
TScriptNum result = a; | |||||
bool expect_overflow = !IsInScriptBounds(a_i128 - b_i128); | |||||
try { | |||||
result -= b; | |||||
BOOST_CHECK_MESSAGE( | |||||
!expect_overflow, | |||||
strprintf("%d -= %d overflowed", a_i128, b_i128)); | |||||
} catch (std::runtime_error &ex) { | |||||
BOOST_CHECK_MESSAGE( | |||||
expect_overflow, | |||||
strprintf("%d -= %d didn't overflow", a_i128, b_i128)); | |||||
} | |||||
} | |||||
} | |||||
static void CheckOperators(const valtype &a_i63, const valtype &b_i63) { | |||||
CheckOperatorsGeneric<CScriptNum>(a_i63, b_i63); | |||||
CheckOperatorsGeneric<scriptnum_emulated::CScriptNum>(a_i63, b_i63); | |||||
} | |||||
BOOST_AUTO_TEST_CASE(scriptnum_63_bit_arithmetic_test) { | |||||
MMIXLinearCongruentialGenerator lcg; | |||||
for (uint32_t test = 0; test < 2048; ++test) { | |||||
// Generate random numbers between 0 and 8 bytes length. | |||||
// Byte length is uniformly distributed for better test coverage. | |||||
uint32_t a_len = lcg.next() % (MAXIMUM_63_BIT_ELEMENT_SIZE + 1); | |||||
uint32_t b_len = lcg.next() % (MAXIMUM_63_BIT_ELEMENT_SIZE + 1); | |||||
valtype a_i63(a_len), b_i63(b_len); | |||||
for (uint32_t i = 0; i < a_len; ++i) { | |||||
a_i63[i] = lcg.next() % 256; | |||||
} | |||||
for (uint32_t i = 0; i < b_len; ++i) { | |||||
b_i63[i] = lcg.next() % 256; | |||||
} | |||||
CheckOperators(a_i63, b_i63); | |||||
for (const valtype &interesting_num : INTERESTING_63_BIT_NUMBERS) { | |||||
CheckOperators(a_i63, interesting_num); | |||||
CheckOperators(interesting_num, b_i63); | |||||
} | |||||
} | |||||
} | |||||
BOOST_AUTO_TEST_SUITE_END() |