MCPcopy Create free account
hub / github.com/ElementsProject/elements / SimulationTest

Function SimulationTest

src/test/coins_tests.cpp:118–264  ·  view source on GitHub ↗

This is a large randomized insert/remove simulation test on a variable-size stack of caches on top of CCoinsViewTest. It will randomly create/update/delete Coin entries to a tip of caches, with txids picked from a limited list of random 256-bit hashes. Occasionally, a new tip is added to the stack of caches, or the tip is flushed and removed. During the process, booleans are kept to make sure th

Source from the content-addressed store, hash-verified

116// otherwise we'll hit an assertion in BatchWrite.
117//
118void SimulationTest(CCoinsView* base, bool fake_best_block)
119{
120 // Various coverage trackers.
121 bool removed_all_caches = false;
122 bool reached_4_caches = false;
123 bool added_an_entry = false;
124 bool added_an_unspendable_entry = false;
125 bool removed_an_entry = false;
126 bool updated_an_entry = false;
127 bool found_an_entry = false;
128 bool missed_an_entry = false;
129 bool uncached_an_entry = false;
130
131 // A simple map to track what we expect the cache stack to represent.
132 std::map<COutPoint, Coin> result;
133
134 // The cache stack.
135 std::vector<CCoinsViewCacheTest*> stack; // A stack of CCoinsViewCaches on top.
136 stack.push_back(new CCoinsViewCacheTest(base)); // Start with one cache.
137
138 // Use a limited set of random transaction ids, so we do test overwriting entries.
139 std::vector<uint256> txids;
140 txids.resize(NUM_SIMULATION_ITERATIONS / 8);
141 for (unsigned int i = 0; i < txids.size(); i++) {
142 txids[i] = InsecureRand256();
143 }
144
145 for (unsigned int i = 0; i < NUM_SIMULATION_ITERATIONS; i++) {
146 // Do a random modification.
147 {
148 uint256 txid = txids[InsecureRandRange(txids.size())]; // txid we're going to modify in this iteration.
149 Coin& coin = result[COutPoint(txid, 0)];
150
151 // Determine whether to test HaveCoin before or after Access* (or both). As these functions
152 // can influence each other's behaviour by pulling things into the cache, all combinations
153 // are tested.
154 bool test_havecoin_before = InsecureRandBits(2) == 0;
155 bool test_havecoin_after = InsecureRandBits(2) == 0;
156
157 bool result_havecoin = test_havecoin_before ? stack.back()->HaveCoin(COutPoint(txid, 0)) : false;
158 const Coin& entry = (InsecureRandRange(500) == 0) ? AccessByTxid(*stack.back(), txid) : stack.back()->AccessCoin(COutPoint(txid, 0));
159 BOOST_CHECK(coin == entry);
160 BOOST_CHECK(!test_havecoin_before || result_havecoin == !entry.IsSpent());
161
162 if (test_havecoin_after) {
163 bool ret = stack.back()->HaveCoin(COutPoint(txid, 0));
164 BOOST_CHECK(ret == !entry.IsSpent());
165 }
166
167 if (InsecureRandRange(5) == 0 || coin.IsSpent()) {
168 Coin newcoin;
169 newcoin.out.nValue = InsecureRand32();
170 newcoin.nHeight = 1;
171 if (InsecureRandRange(16) == 0 && coin.IsSpent()) {
172 newcoin.out.scriptPubKey.assign(1 + InsecureRandBits(6), OP_RETURN);
173 BOOST_CHECK(newcoin.out.scriptPubKey.IsUnspendable());
174 added_an_unspendable_entry = true;
175 } else {

Callers 1

BOOST_AUTO_TEST_CASEFunction · 0.85

Calls 15

InsecureRand256Function · 0.85
InsecureRandRangeFunction · 0.85
InsecureRandBitsFunction · 0.85
InsecureRand32Function · 0.85
InsecureRandBoolFunction · 0.85
IsUnspendableMethod · 0.80
AddCoinMethod · 0.80
SpendCoinMethod · 0.80
UncacheMethod · 0.80
HaveCoinInCacheMethod · 0.80
SelfTestMethod · 0.80
SetBestBlockMethod · 0.80

Tested by

no test coverage detected