For CCoinsViewCache instances backed by either another cache instance or leveldb, test cache behavior and flag state (DIRTY/FRESH) by 1. Adding a random coin to the child-most cache, 2. Flushing all caches (without erasing), 3. Ensure the entry still exists in the cache and has been written to parent, 4. (if `do_erasing_flush`) Flushing the caches again (with erasing), 5. (if `do_erasing_flush`)
| 898 | //! 6. Spend the coin, ensure it no longer exists in the parent. |
| 899 | //! |
| 900 | void TestFlushBehavior( |
| 901 | CCoinsViewCacheTest* view, |
| 902 | CCoinsViewDB& base, |
| 903 | std::vector<std::unique_ptr<CCoinsViewCacheTest>>& all_caches, |
| 904 | bool do_erasing_flush) |
| 905 | { |
| 906 | size_t cache_usage; |
| 907 | size_t cache_size; |
| 908 | |
| 909 | auto flush_all = [this, &all_caches](bool erase) { |
| 910 | // Flush in reverse order to ensure that flushes happen from children up. |
| 911 | for (auto i = all_caches.rbegin(); i != all_caches.rend(); ++i) { |
| 912 | auto& cache = *i; |
| 913 | cache->SanityCheck(); |
| 914 | // block_hash must be filled before flushing to disk; value is |
| 915 | // unimportant here. This is normally done during connect/disconnect block. |
| 916 | cache->SetBestBlock(m_rng.rand256()); |
| 917 | erase ? cache->Flush() : cache->Sync(); |
| 918 | } |
| 919 | }; |
| 920 | |
| 921 | Txid txid = Txid::FromUint256(m_rng.rand256()); |
| 922 | COutPoint outp = COutPoint(txid, 0); |
| 923 | Coin coin = MakeCoin(); |
| 924 | // Ensure the coins views haven't seen this coin before. |
| 925 | BOOST_CHECK(!base.HaveCoin(outp)); |
| 926 | BOOST_CHECK(!view->HaveCoin(outp)); |
| 927 | |
| 928 | // --- 1. Adding a random coin to the child cache |
| 929 | // |
| 930 | view->AddCoin(outp, Coin(coin), false); |
| 931 | |
| 932 | cache_usage = view->DynamicMemoryUsage(); |
| 933 | cache_size = view->map().size(); |
| 934 | |
| 935 | // `base` shouldn't have coin (no flush yet) but `view` should have cached it. |
| 936 | BOOST_CHECK(!base.HaveCoin(outp)); |
| 937 | BOOST_CHECK(view->HaveCoin(outp)); |
| 938 | |
| 939 | BOOST_CHECK_EQUAL(GetCoinsMapEntry(view->map(), outp), CoinEntry(coin.out.nValue, CoinEntry::State::DIRTY_FRESH)); |
| 940 | |
| 941 | // --- 2. Flushing all caches (without erasing) |
| 942 | // |
| 943 | flush_all(/*erase=*/ false); |
| 944 | |
| 945 | // CoinsMap usage should be unchanged since we didn't erase anything. |
| 946 | BOOST_CHECK_EQUAL(cache_usage, view->DynamicMemoryUsage()); |
| 947 | BOOST_CHECK_EQUAL(cache_size, view->map().size()); |
| 948 | |
| 949 | // --- 3. Ensuring the entry still exists in the cache and has been written to parent |
| 950 | // |
| 951 | BOOST_CHECK_EQUAL(GetCoinsMapEntry(view->map(), outp), CoinEntry(coin.out.nValue, CoinEntry::State::CLEAN)); // State should have been wiped. |
| 952 | |
| 953 | // Both views should now have the coin. |
| 954 | BOOST_CHECK(base.HaveCoin(outp)); |
| 955 | BOOST_CHECK(view->HaveCoin(outp)); |
| 956 | |
| 957 | if (do_erasing_flush) { |
nothing calls this directly
no test coverage detected