Changeset View
Changeset View
Standalone View
Standalone View
src/test/amount_tests.cpp
// Copyright (c) 2016 The Bitcoin Core developers | // Copyright (c) 2016 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include "amount.h" | #include "amount.h" | ||||
#include "test/test_bitcoin.h" | #include "test/test_bitcoin.h" | ||||
#include <boost/test/unit_test.hpp> | #include <boost/test/unit_test.hpp> | ||||
// Snippit to allow compile time introspection for multiplication operator | |||||
// Used to ensure that certain operations are not implemented on CAmountNew | |||||
namespace Check { | |||||
class No { | |||||
public: | |||||
bool b[2]; | |||||
}; | |||||
template <typename T, typename Arg> No operator*(const T &, const Arg &); | |||||
bool Check(...); | |||||
No &Check(const No &); | |||||
template <typename T, typename Arg = T> struct MultiplicationExists { | |||||
enum { value = (sizeof(Check(*(T *)(0) * *(Arg *)(0))) != sizeof(No)) }; | |||||
}; | |||||
} // namespace Check | |||||
BOOST_FIXTURE_TEST_SUITE(amount_tests, BasicTestingSetup) | BOOST_FIXTURE_TEST_SUITE(amount_tests, BasicTestingSetup) | ||||
BOOST_AUTO_TEST_CASE(CAmountTests) { | |||||
BOOST_CHECK(CAmountNew(2) <= CAmountNew(2)); | |||||
BOOST_CHECK(CAmountNew(2) <= CAmountNew(3)); | |||||
BOOST_CHECK(CAmountNew(2) >= CAmountNew(2)); | |||||
BOOST_CHECK(CAmountNew(3) >= CAmountNew(2)); | |||||
BOOST_CHECK(CAmountNew(1) < CAmountNew(2)); | |||||
BOOST_CHECK(CAmountNew(-1) < CAmountNew(0)); | |||||
BOOST_CHECK(CAmountNew(2) > CAmountNew(1)); | |||||
BOOST_CHECK(CAmountNew(0) > CAmountNew(-1)); | |||||
BOOST_CHECK(CAmountNew(1) < CAmountNew(2)); | |||||
BOOST_CHECK(CAmountNew(-1) < CAmountNew(0)); | |||||
BOOST_CHECK(CAmountNew(2) > CAmountNew(1)); | |||||
BOOST_CHECK(CAmountNew(0) > CAmountNew(-1)); | |||||
BOOST_CHECK(CAmountNew(0) == CAmountNew(0)); | |||||
BOOST_CHECK(CAmountNew(0) != CAmountNew(1)); | |||||
CAmountNew amount(0); | |||||
BOOST_CHECK_EQUAL(amount += CAmountNew(1), CAmountNew(1)); | |||||
BOOST_CHECK_EQUAL(amount += CAmountNew(-1), CAmountNew(0)); | |||||
BOOST_CHECK_EQUAL(amount -= CAmountNew(1), CAmountNew(-1)); | |||||
BOOST_CHECK_EQUAL(amount -= CAmountNew(-1), CAmountNew(0)); | |||||
BOOST_CHECK_EQUAL(COIN + COIN, CAmountNew(2 * COIN)); | |||||
BOOST_CHECK_EQUAL(2 * COIN + COIN, CAmountNew(3 * COIN)); | |||||
BOOST_CHECK_EQUAL(-1 * COIN + COIN, CAmountNew(0)); | |||||
BOOST_CHECK_EQUAL(COIN - COIN, CAmountNew(0)); | |||||
BOOST_CHECK_EQUAL(COIN - 2 * COIN, -1 * COIN); | |||||
BOOST_CHECK_EQUAL(10 * CAmountNew(10), CAmountNew(100)); | |||||
BOOST_CHECK_EQUAL(-1 * CAmountNew(1), CAmountNew(-1)); | |||||
// The C preprocessor will now allow passing a template type into a macro | |||||
// directly, so we must define these aliases. | |||||
using impl_int = Check::MultiplicationExists<int64_t, CAmountNew>; | |||||
using impl_float = Check::MultiplicationExists<double, CAmountNew>; | |||||
BOOST_CHECK(impl_int::value); | |||||
BOOST_CHECK(!impl_float::value); | |||||
BOOST_CHECK_EQUAL(CAmountNew(100) / 10, 10); | |||||
// This should probably be Banker's rounding, | |||||
// but that's a large change | |||||
BOOST_CHECK_EQUAL(CAmountNew(100) / 3, 33); | |||||
BOOST_CHECK_EQUAL(CAmountNew(101) / 3, 33); | |||||
// Modulus | |||||
BOOST_CHECK_EQUAL(COIN % 1, CAmountNew(0)); | |||||
BOOST_CHECK_EQUAL((3 * COIN) % (2 * COIN.GetSatoshis()), COIN); | |||||
} | |||||
BOOST_AUTO_TEST_CASE(GetFeeTest) { | BOOST_AUTO_TEST_CASE(GetFeeTest) { | ||||
CFeeRate feeRate; | CFeeRate feeRate; | ||||
feeRate = CFeeRate(0); | feeRate = CFeeRate(0); | ||||
// Must always return 0 | // Must always return 0 | ||||
BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0); | BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0); | ||||
BOOST_CHECK_EQUAL(feeRate.GetFee(1e5), 0); | BOOST_CHECK_EQUAL(feeRate.GetFee(1e5), 0); | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | BOOST_AUTO_TEST_CASE(GetFeeTest) { | ||||
BOOST_CHECK(CFeeRate(CAmount(1), 1000) == CFeeRate(1)); | BOOST_CHECK(CFeeRate(CAmount(1), 1000) == CFeeRate(1)); | ||||
// lost precision (can only resolve satoshis per kB) | // lost precision (can only resolve satoshis per kB) | ||||
BOOST_CHECK(CFeeRate(CAmount(1), 1001) == CFeeRate(0)); | BOOST_CHECK(CFeeRate(CAmount(1), 1001) == CFeeRate(0)); | ||||
BOOST_CHECK(CFeeRate(CAmount(2), 1001) == CFeeRate(1)); | BOOST_CHECK(CFeeRate(CAmount(2), 1001) == CFeeRate(1)); | ||||
// some more integer checks | // some more integer checks | ||||
BOOST_CHECK(CFeeRate(CAmount(26), 789) == CFeeRate(32)); | BOOST_CHECK(CFeeRate(CAmount(26), 789) == CFeeRate(32)); | ||||
BOOST_CHECK(CFeeRate(CAmount(27), 789) == CFeeRate(34)); | BOOST_CHECK(CFeeRate(CAmount(27), 789) == CFeeRate(34)); | ||||
// Maximum size in bytes, should not crash | // Maximum size in bytes, should not crash | ||||
CFeeRate(MAX_MONEY, std::numeric_limits<size_t>::max() >> 1).GetFeePerK(); | CFeeRate(MAX_MONEY.GetSatoshis(), std::numeric_limits<size_t>::max() >> 1) | ||||
.GetFeePerK(); | |||||
} | } | ||||
BOOST_AUTO_TEST_SUITE_END() | BOOST_AUTO_TEST_SUITE_END() |