88#include < script/standard.h>
99#include < streams.h>
1010#include < test/util/setup_common.h>
11+ #include < txdb.h>
1112#include < uint256.h>
1213#include < undo.h>
1314#include < util/strencodings.h>
@@ -109,7 +110,12 @@ static const unsigned int NUM_SIMULATION_ITERATIONS = 40000;
109110//
110111// During the process, booleans are kept to make sure that the randomized
111112// 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)
113119{
114120 // Various coverage trackers.
115121 bool removed_all_caches = false ;
@@ -126,9 +132,8 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test)
126132 std::map<COutPoint, Coin> result;
127133
128134 // The cache stack.
129- CCoinsViewTest base; // A CCoinsViewTest at the bottom.
130135 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.
132137
133138 // Use a limited set of random transaction ids, so we do test overwriting entries.
134139 std::vector<uint256> txids;
@@ -211,20 +216,22 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test)
211216 // Every 100 iterations, flush an intermediate cache
212217 if (stack.size () > 1 && InsecureRandBool () == 0 ) {
213218 unsigned int flushIndex = InsecureRandRange (stack.size () - 1 );
219+ if (fake_best_block) stack[flushIndex]->SetBestBlock (InsecureRand256 ());
214220 BOOST_CHECK (stack[flushIndex]->Flush ());
215221 }
216222 }
217223 if (InsecureRandRange (100 ) == 0 ) {
218224 // Every 100 iterations, change the cache stack.
219225 if (stack.size () > 0 && InsecureRandBool () == 0 ) {
220226 // Remove the top cache
227+ if (fake_best_block) stack.back ()->SetBestBlock (InsecureRand256 ());
221228 BOOST_CHECK (stack.back ()->Flush ());
222229 delete stack.back ();
223230 stack.pop_back ();
224231 }
225232 if (stack.size () == 0 || (stack.size () < 4 && InsecureRandBool ())) {
226233 // Add a new cache
227- CCoinsView* tip = & base;
234+ CCoinsView* tip = base;
228235 if (stack.size () > 0 ) {
229236 tip = stack.back ();
230237 } else {
@@ -256,6 +263,16 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test)
256263 BOOST_CHECK (uncached_an_entry);
257264}
258265
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+
259276// Store of all necessary tx and undo data for next test
260277typedef std::map<COutPoint, std::tuple<CTransaction,CTxUndo,Coin>> UtxoData;
261278UtxoData utxoData;
0 commit comments