aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Moore <dooglus@gmail.com>2012-04-07 10:55:03 -0700
committerLuke Dashjr <luke-jr+git@utopios.org>2012-06-04 16:36:43 +0000
commit4ce190a0157837df9a4a804f8e3f2941d1ffacf5 (patch)
tree824299c0f8b2b38a0e995f7d90bc9814cafec613
parente333ab56d5b9fd6b0510ef6b98caa8bfc5059082 (diff)
Test that the coin selection code is suitably random, and add tests re. sub-cent change.
-rw-r--r--src/test/wallet_tests.cpp72
1 files changed, 71 insertions, 1 deletions
diff --git a/src/test/wallet_tests.cpp b/src/test/wallet_tests.cpp
index 705609464a..dc8fe08439 100644
--- a/src/test/wallet_tests.cpp
+++ b/src/test/wallet_tests.cpp
@@ -9,8 +9,14 @@
// enables tests which currently fail, due to code which tries too hard to avoid sub-cent change
// #define STRICT
+// some tests fail 1% of the time due to bad luck.
+// we repeat those tests this many times and only complain if all iterations of the test fail
+#define RANDOM_REPEATS 5
+
using namespace std;
+typedef set<pair<const CWalletTx*,unsigned int> > CoinSet;
+
BOOST_AUTO_TEST_SUITE(wallet_tests)
static CWallet wallet;
@@ -44,9 +50,15 @@ static void empty_wallet(void)
vCoins.clear();
}
+static bool equal_sets(CoinSet a, CoinSet b)
+{
+ pair<CoinSet::iterator, CoinSet::iterator> ret = mismatch(a.begin(), a.end(), b.begin());
+ return ret.first == a.end() && ret.second == b.end();
+}
+
BOOST_AUTO_TEST_CASE(coin_selection_tests)
{
- static set<pair<const CWalletTx*,unsigned int> > setCoinsRet;
+ static CoinSet setCoinsRet, setCoinsRet2;
static int64 nValueRet;
// test multiple times to allow for differences in the shuffle order
@@ -250,6 +262,64 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
BOOST_CHECK_EQUAL(nValueRet, 1111 * CENT); // but since value of smaller coins < target+cent, we get the bigger coin again
BOOST_CHECK_EQUAL(setCoinsRet.size(), 1);
#endif
+
+ // test avoiding sub-cent change
+ empty_wallet();
+ add_coin(0.0005 * COIN);
+ add_coin(0.01 * COIN);
+ add_coin(1 * COIN);
+
+ // trying to make 1.0001 from these three coins
+ BOOST_CHECK( wallet.SelectCoinsMinConf(1.0001 * COIN, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 1.0105 * COIN); // we should get all coins
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 3);
+
+ // but if we try to make 0.999, we should take the bigger of the two small coins to avoid sub-cent change
+ BOOST_CHECK( wallet.SelectCoinsMinConf(0.999 * COIN, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 1.01 * COIN); // we should get 1 + 0.01
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 2);
+
+ // test randomness
+ {
+ empty_wallet();
+ for (int i2 = 0; i2 < 100; i2++)
+ add_coin(COIN);
+
+ // picking 50 from 100 coins doesn't depend on the shuffle,
+ // but does depend on randomness in the stochastic approximation code
+ BOOST_CHECK(wallet.SelectCoinsMinConf(50 * COIN, 1, 6, vCoins, setCoinsRet , nValueRet));
+ BOOST_CHECK(wallet.SelectCoinsMinConf(50 * COIN, 1, 6, vCoins, setCoinsRet2, nValueRet));
+ BOOST_CHECK(!equal_sets(setCoinsRet, setCoinsRet2));
+
+ int fails = 0;
+ for (int i = 0; i < RANDOM_REPEATS; i++)
+ {
+ // selecting 1 from 100 identical coins depends on the shuffle; this test will fail 1% of the time
+ // run the test RANDOM_REPEATS times and only complain if all of them fail
+ BOOST_CHECK(wallet.SelectCoinsMinConf(COIN, 1, 6, vCoins, setCoinsRet , nValueRet));
+ BOOST_CHECK(wallet.SelectCoinsMinConf(COIN, 1, 6, vCoins, setCoinsRet2, nValueRet));
+ if (equal_sets(setCoinsRet, setCoinsRet2))
+ fails++;
+ }
+ BOOST_CHECK_NE(fails, RANDOM_REPEATS);
+
+ // add 75 cents in small change. not enough to make 90 cents,
+ // then try making 90 cents. there are multiple competing "smallest bigger" coins,
+ // one of which should be picked at random
+ add_coin( 5*CENT); add_coin(10*CENT); add_coin(15*CENT); add_coin(20*CENT); add_coin(25*CENT);
+
+ fails = 0;
+ for (int i = 0; i < RANDOM_REPEATS; i++)
+ {
+ // selecting 1 from 100 identical coins depends on the shuffle; this test will fail 1% of the time
+ // run the test RANDOM_REPEATS times and only complain if all of them fail
+ BOOST_CHECK(wallet.SelectCoinsMinConf(90*CENT, 1, 6, vCoins, setCoinsRet , nValueRet));
+ BOOST_CHECK(wallet.SelectCoinsMinConf(90*CENT, 1, 6, vCoins, setCoinsRet2, nValueRet));
+ if (equal_sets(setCoinsRet, setCoinsRet2))
+ fails++;
+ }
+ BOOST_CHECK_NE(fails, RANDOM_REPEATS);
+ }
}
}