8
8
#include < script/standard.h>
9
9
#include < streams.h>
10
10
#include < test/util/setup_common.h>
11
+ #include < txdb.h>
11
12
#include < uint256.h>
12
13
#include < undo.h>
13
14
#include < util/strencodings.h>
@@ -109,7 +110,12 @@ static const unsigned int NUM_SIMULATION_ITERATIONS = 40000;
109
110
//
110
111
// During the process, booleans are kept to make sure that the randomized
111
112
// operation hits all branches.
112
- BOOST_AUTO_TEST_CASE (coins_cache_simulation_test)
113
+ //
114
+ // If fake_best_block is true, assign a random uint256 to mock the recording
115
+ // of best block on flush. This is necessary when using CCoinsViewDB as the base,
116
+ // otherwise we'll hit an assertion in BatchWrite.
117
+ //
118
+ void SimulationTest (CCoinsView* base, bool fake_best_block)
113
119
{
114
120
// Various coverage trackers.
115
121
bool removed_all_caches = false ;
@@ -126,9 +132,8 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test)
126
132
std::map<COutPoint, Coin> result;
127
133
128
134
// The cache stack.
129
- CCoinsViewTest base; // A CCoinsViewTest at the bottom.
130
135
std::vector<CCoinsViewCacheTest*> stack; // A stack of CCoinsViewCaches on top.
131
- stack.push_back (new CCoinsViewCacheTest (& base)); // Start with one cache.
136
+ stack.push_back (new CCoinsViewCacheTest (base)); // Start with one cache.
132
137
133
138
// Use a limited set of random transaction ids, so we do test overwriting entries.
134
139
std::vector<uint256> txids;
@@ -211,20 +216,22 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test)
211
216
// Every 100 iterations, flush an intermediate cache
212
217
if (stack.size () > 1 && InsecureRandBool () == 0 ) {
213
218
unsigned int flushIndex = InsecureRandRange (stack.size () - 1 );
219
+ if (fake_best_block) stack[flushIndex]->SetBestBlock (InsecureRand256 ());
214
220
BOOST_CHECK (stack[flushIndex]->Flush ());
215
221
}
216
222
}
217
223
if (InsecureRandRange (100 ) == 0 ) {
218
224
// Every 100 iterations, change the cache stack.
219
225
if (stack.size () > 0 && InsecureRandBool () == 0 ) {
220
226
// Remove the top cache
227
+ if (fake_best_block) stack.back ()->SetBestBlock (InsecureRand256 ());
221
228
BOOST_CHECK (stack.back ()->Flush ());
222
229
delete stack.back ();
223
230
stack.pop_back ();
224
231
}
225
232
if (stack.size () == 0 || (stack.size () < 4 && InsecureRandBool ())) {
226
233
// Add a new cache
227
- CCoinsView* tip = & base;
234
+ CCoinsView* tip = base;
228
235
if (stack.size () > 0 ) {
229
236
tip = stack.back ();
230
237
} else {
@@ -256,6 +263,16 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test)
256
263
BOOST_CHECK (uncached_an_entry);
257
264
}
258
265
266
+ // Run the above simulation for multiple base types.
267
+ BOOST_AUTO_TEST_CASE (coins_cache_simulation_test)
268
+ {
269
+ CCoinsViewTest base;
270
+ SimulationTest (&base, false );
271
+
272
+ CCoinsViewDB db_base{" test" , /* nCacheSize*/ 1 << 23 , /* fMemory*/ true , /* fWipe*/ false };
273
+ SimulationTest (&db_base, true );
274
+ }
275
+
259
276
// Store of all necessary tx and undo data for next test
260
277
typedef std::map<COutPoint, std::tuple<CTransaction,CTxUndo,Coin>> UtxoData;
261
278
UtxoData utxoData;
0 commit comments