Merge #9308: [test] Add CCoinsViewCache Access/Modify/Write tests
07df40b
[test] Add CCoinsViewCache Access/Modify/Write tests (Russell Yanofsky)
This commit is contained in:
commit
0698639a38
1 changed files with 364 additions and 0 deletions
|
@ -80,6 +80,8 @@ public:
|
|||
BOOST_CHECK_EQUAL(DynamicMemoryUsage(), ret);
|
||||
}
|
||||
|
||||
CCoinsMap& map() { return cacheCoins; }
|
||||
size_t& usage() { return cachedCoinsUsage; }
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -415,4 +417,366 @@ BOOST_AUTO_TEST_CASE(ccoins_serialization)
|
|||
}
|
||||
}
|
||||
|
||||
const static uint256 TXID;
|
||||
const static CAmount PRUNED = -1;
|
||||
const static CAmount ABSENT = -2;
|
||||
const static CAmount VALUE1 = 100;
|
||||
const static CAmount VALUE2 = 200;
|
||||
const static CAmount VALUE3 = 300;
|
||||
const static char DIRTY = CCoinsCacheEntry::DIRTY;
|
||||
const static char FRESH = CCoinsCacheEntry::FRESH;
|
||||
const static char NO_ENTRY = -1;
|
||||
|
||||
const static auto FLAGS = {char(0), FRESH, DIRTY, char(DIRTY | FRESH)};
|
||||
const static auto CLEAN_FLAGS = {char(0), FRESH};
|
||||
const static auto DIRTY_FLAGS = {DIRTY, char(DIRTY | FRESH)};
|
||||
const static auto ABSENT_FLAGS = {NO_ENTRY};
|
||||
|
||||
void SetCoinsValue(CAmount value, CCoins& coins)
|
||||
{
|
||||
assert(value != ABSENT);
|
||||
coins.Clear();
|
||||
assert(coins.IsPruned());
|
||||
if (value != PRUNED) {
|
||||
coins.vout.emplace_back();
|
||||
coins.vout.back().nValue = value;
|
||||
assert(!coins.IsPruned());
|
||||
}
|
||||
}
|
||||
|
||||
size_t InsertCoinsMapEntry(CCoinsMap& map, CAmount value, char flags)
|
||||
{
|
||||
if (value == ABSENT) {
|
||||
assert(flags == NO_ENTRY);
|
||||
return 0;
|
||||
}
|
||||
assert(flags != NO_ENTRY);
|
||||
CCoinsCacheEntry entry;
|
||||
entry.flags = flags;
|
||||
SetCoinsValue(value, entry.coins);
|
||||
auto inserted = map.emplace(TXID, std::move(entry));
|
||||
assert(inserted.second);
|
||||
return inserted.first->second.coins.DynamicMemoryUsage();
|
||||
}
|
||||
|
||||
void GetCoinsMapEntry(const CCoinsMap& map, CAmount& value, char& flags)
|
||||
{
|
||||
auto it = map.find(TXID);
|
||||
if (it == map.end()) {
|
||||
value = ABSENT;
|
||||
flags = NO_ENTRY;
|
||||
} else {
|
||||
if (it->second.coins.IsPruned()) {
|
||||
assert(it->second.coins.vout.size() == 0);
|
||||
value = PRUNED;
|
||||
} else {
|
||||
assert(it->second.coins.vout.size() == 1);
|
||||
value = it->second.coins.vout[0].nValue;
|
||||
}
|
||||
flags = it->second.flags;
|
||||
assert(flags != NO_ENTRY);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteCoinsViewEntry(CCoinsView& view, CAmount value, char flags)
|
||||
{
|
||||
CCoinsMap map;
|
||||
InsertCoinsMapEntry(map, value, flags);
|
||||
view.BatchWrite(map, {});
|
||||
}
|
||||
|
||||
class SingleEntryCacheTest
|
||||
{
|
||||
public:
|
||||
SingleEntryCacheTest(CAmount base_value, CAmount cache_value, char cache_flags)
|
||||
{
|
||||
WriteCoinsViewEntry(base, base_value, base_value == ABSENT ? NO_ENTRY : DIRTY);
|
||||
cache.usage() += InsertCoinsMapEntry(cache.map(), cache_value, cache_flags);
|
||||
}
|
||||
|
||||
CCoinsView root;
|
||||
CCoinsViewCacheTest base{&root};
|
||||
CCoinsViewCacheTest cache{&base};
|
||||
};
|
||||
|
||||
void CheckAccessCoins(CAmount base_value, CAmount cache_value, CAmount expected_value, char cache_flags, char expected_flags)
|
||||
{
|
||||
SingleEntryCacheTest test(base_value, cache_value, cache_flags);
|
||||
test.cache.AccessCoins(TXID);
|
||||
test.cache.SelfTest();
|
||||
|
||||
CAmount result_value;
|
||||
char result_flags;
|
||||
GetCoinsMapEntry(test.cache.map(), result_value, result_flags);
|
||||
BOOST_CHECK_EQUAL(result_value, expected_value);
|
||||
BOOST_CHECK_EQUAL(result_flags, expected_flags);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ccoins_access)
|
||||
{
|
||||
/* Check AccessCoin behavior, requesting a coin from a cache view layered on
|
||||
* top of a base view, and checking the resulting entry in the cache after
|
||||
* the access.
|
||||
*
|
||||
* Base Cache Result Cache Result
|
||||
* Value Value Value Flags Flags
|
||||
*/
|
||||
CheckAccessCoins(ABSENT, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY );
|
||||
CheckAccessCoins(ABSENT, PRUNED, PRUNED, 0 , 0 );
|
||||
CheckAccessCoins(ABSENT, PRUNED, PRUNED, FRESH , FRESH );
|
||||
CheckAccessCoins(ABSENT, PRUNED, PRUNED, DIRTY , DIRTY );
|
||||
CheckAccessCoins(ABSENT, PRUNED, PRUNED, DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckAccessCoins(ABSENT, VALUE2, VALUE2, 0 , 0 );
|
||||
CheckAccessCoins(ABSENT, VALUE2, VALUE2, FRESH , FRESH );
|
||||
CheckAccessCoins(ABSENT, VALUE2, VALUE2, DIRTY , DIRTY );
|
||||
CheckAccessCoins(ABSENT, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckAccessCoins(PRUNED, ABSENT, PRUNED, NO_ENTRY , FRESH );
|
||||
CheckAccessCoins(PRUNED, PRUNED, PRUNED, 0 , 0 );
|
||||
CheckAccessCoins(PRUNED, PRUNED, PRUNED, FRESH , FRESH );
|
||||
CheckAccessCoins(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY );
|
||||
CheckAccessCoins(PRUNED, PRUNED, PRUNED, DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckAccessCoins(PRUNED, VALUE2, VALUE2, 0 , 0 );
|
||||
CheckAccessCoins(PRUNED, VALUE2, VALUE2, FRESH , FRESH );
|
||||
CheckAccessCoins(PRUNED, VALUE2, VALUE2, DIRTY , DIRTY );
|
||||
CheckAccessCoins(PRUNED, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckAccessCoins(VALUE1, ABSENT, VALUE1, NO_ENTRY , 0 );
|
||||
CheckAccessCoins(VALUE1, PRUNED, PRUNED, 0 , 0 );
|
||||
CheckAccessCoins(VALUE1, PRUNED, PRUNED, FRESH , FRESH );
|
||||
CheckAccessCoins(VALUE1, PRUNED, PRUNED, DIRTY , DIRTY );
|
||||
CheckAccessCoins(VALUE1, PRUNED, PRUNED, DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckAccessCoins(VALUE1, VALUE2, VALUE2, 0 , 0 );
|
||||
CheckAccessCoins(VALUE1, VALUE2, VALUE2, FRESH , FRESH );
|
||||
CheckAccessCoins(VALUE1, VALUE2, VALUE2, DIRTY , DIRTY );
|
||||
CheckAccessCoins(VALUE1, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH);
|
||||
}
|
||||
|
||||
void CheckModifyCoins(CAmount base_value, CAmount cache_value, CAmount modify_value, CAmount expected_value, char cache_flags, char expected_flags)
|
||||
{
|
||||
SingleEntryCacheTest test(base_value, cache_value, cache_flags);
|
||||
SetCoinsValue(modify_value, *test.cache.ModifyCoins(TXID));
|
||||
test.cache.SelfTest();
|
||||
|
||||
CAmount result_value;
|
||||
char result_flags;
|
||||
GetCoinsMapEntry(test.cache.map(), result_value, result_flags);
|
||||
BOOST_CHECK_EQUAL(result_value, expected_value);
|
||||
BOOST_CHECK_EQUAL(result_flags, expected_flags);
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ccoins_modify)
|
||||
{
|
||||
/* Check ModifyCoin behavior, requesting a coin from a cache view layered on
|
||||
* top of a base view, writing a modification to the coin, and then checking
|
||||
* the resulting entry in the cache after the modification.
|
||||
*
|
||||
* Base Cache Write Result Cache Result
|
||||
* Value Value Value Value Flags Flags
|
||||
*/
|
||||
CheckModifyCoins(ABSENT, ABSENT, PRUNED, ABSENT, NO_ENTRY , NO_ENTRY );
|
||||
CheckModifyCoins(ABSENT, ABSENT, VALUE3, VALUE3, NO_ENTRY , DIRTY|FRESH);
|
||||
CheckModifyCoins(ABSENT, PRUNED, PRUNED, PRUNED, 0 , DIRTY );
|
||||
CheckModifyCoins(ABSENT, PRUNED, PRUNED, ABSENT, FRESH , NO_ENTRY );
|
||||
CheckModifyCoins(ABSENT, PRUNED, PRUNED, PRUNED, DIRTY , DIRTY );
|
||||
CheckModifyCoins(ABSENT, PRUNED, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY );
|
||||
CheckModifyCoins(ABSENT, PRUNED, VALUE3, VALUE3, 0 , DIRTY );
|
||||
CheckModifyCoins(ABSENT, PRUNED, VALUE3, VALUE3, FRESH , DIRTY|FRESH);
|
||||
CheckModifyCoins(ABSENT, PRUNED, VALUE3, VALUE3, DIRTY , DIRTY );
|
||||
CheckModifyCoins(ABSENT, PRUNED, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckModifyCoins(ABSENT, VALUE2, PRUNED, PRUNED, 0 , DIRTY );
|
||||
CheckModifyCoins(ABSENT, VALUE2, PRUNED, ABSENT, FRESH , NO_ENTRY );
|
||||
CheckModifyCoins(ABSENT, VALUE2, PRUNED, PRUNED, DIRTY , DIRTY );
|
||||
CheckModifyCoins(ABSENT, VALUE2, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY );
|
||||
CheckModifyCoins(ABSENT, VALUE2, VALUE3, VALUE3, 0 , DIRTY );
|
||||
CheckModifyCoins(ABSENT, VALUE2, VALUE3, VALUE3, FRESH , DIRTY|FRESH);
|
||||
CheckModifyCoins(ABSENT, VALUE2, VALUE3, VALUE3, DIRTY , DIRTY );
|
||||
CheckModifyCoins(ABSENT, VALUE2, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckModifyCoins(PRUNED, ABSENT, PRUNED, ABSENT, NO_ENTRY , NO_ENTRY );
|
||||
CheckModifyCoins(PRUNED, ABSENT, VALUE3, VALUE3, NO_ENTRY , DIRTY|FRESH);
|
||||
CheckModifyCoins(PRUNED, PRUNED, PRUNED, PRUNED, 0 , DIRTY );
|
||||
CheckModifyCoins(PRUNED, PRUNED, PRUNED, ABSENT, FRESH , NO_ENTRY );
|
||||
CheckModifyCoins(PRUNED, PRUNED, PRUNED, PRUNED, DIRTY , DIRTY );
|
||||
CheckModifyCoins(PRUNED, PRUNED, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY );
|
||||
CheckModifyCoins(PRUNED, PRUNED, VALUE3, VALUE3, 0 , DIRTY );
|
||||
CheckModifyCoins(PRUNED, PRUNED, VALUE3, VALUE3, FRESH , DIRTY|FRESH);
|
||||
CheckModifyCoins(PRUNED, PRUNED, VALUE3, VALUE3, DIRTY , DIRTY );
|
||||
CheckModifyCoins(PRUNED, PRUNED, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckModifyCoins(PRUNED, VALUE2, PRUNED, PRUNED, 0 , DIRTY );
|
||||
CheckModifyCoins(PRUNED, VALUE2, PRUNED, ABSENT, FRESH , NO_ENTRY );
|
||||
CheckModifyCoins(PRUNED, VALUE2, PRUNED, PRUNED, DIRTY , DIRTY );
|
||||
CheckModifyCoins(PRUNED, VALUE2, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY );
|
||||
CheckModifyCoins(PRUNED, VALUE2, VALUE3, VALUE3, 0 , DIRTY );
|
||||
CheckModifyCoins(PRUNED, VALUE2, VALUE3, VALUE3, FRESH , DIRTY|FRESH);
|
||||
CheckModifyCoins(PRUNED, VALUE2, VALUE3, VALUE3, DIRTY , DIRTY );
|
||||
CheckModifyCoins(PRUNED, VALUE2, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckModifyCoins(VALUE1, ABSENT, PRUNED, PRUNED, NO_ENTRY , DIRTY );
|
||||
CheckModifyCoins(VALUE1, ABSENT, VALUE3, VALUE3, NO_ENTRY , DIRTY );
|
||||
CheckModifyCoins(VALUE1, PRUNED, PRUNED, PRUNED, 0 , DIRTY );
|
||||
CheckModifyCoins(VALUE1, PRUNED, PRUNED, ABSENT, FRESH , NO_ENTRY );
|
||||
CheckModifyCoins(VALUE1, PRUNED, PRUNED, PRUNED, DIRTY , DIRTY );
|
||||
CheckModifyCoins(VALUE1, PRUNED, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY );
|
||||
CheckModifyCoins(VALUE1, PRUNED, VALUE3, VALUE3, 0 , DIRTY );
|
||||
CheckModifyCoins(VALUE1, PRUNED, VALUE3, VALUE3, FRESH , DIRTY|FRESH);
|
||||
CheckModifyCoins(VALUE1, PRUNED, VALUE3, VALUE3, DIRTY , DIRTY );
|
||||
CheckModifyCoins(VALUE1, PRUNED, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckModifyCoins(VALUE1, VALUE2, PRUNED, PRUNED, 0 , DIRTY );
|
||||
CheckModifyCoins(VALUE1, VALUE2, PRUNED, ABSENT, FRESH , NO_ENTRY );
|
||||
CheckModifyCoins(VALUE1, VALUE2, PRUNED, PRUNED, DIRTY , DIRTY );
|
||||
CheckModifyCoins(VALUE1, VALUE2, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY );
|
||||
CheckModifyCoins(VALUE1, VALUE2, VALUE3, VALUE3, 0 , DIRTY );
|
||||
CheckModifyCoins(VALUE1, VALUE2, VALUE3, VALUE3, FRESH , DIRTY|FRESH);
|
||||
CheckModifyCoins(VALUE1, VALUE2, VALUE3, VALUE3, DIRTY , DIRTY );
|
||||
CheckModifyCoins(VALUE1, VALUE2, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH);
|
||||
}
|
||||
|
||||
void CheckModifyNewCoinsBase(CAmount base_value, CAmount cache_value, CAmount modify_value, CAmount expected_value, char cache_flags, char expected_flags, bool coinbase)
|
||||
{
|
||||
SingleEntryCacheTest test(base_value, cache_value, cache_flags);
|
||||
SetCoinsValue(modify_value, *test.cache.ModifyNewCoins(TXID, coinbase));
|
||||
|
||||
CAmount result_value;
|
||||
char result_flags;
|
||||
GetCoinsMapEntry(test.cache.map(), result_value, result_flags);
|
||||
BOOST_CHECK_EQUAL(result_value, expected_value);
|
||||
BOOST_CHECK_EQUAL(result_flags, expected_flags);
|
||||
}
|
||||
|
||||
// Simple wrapper for CheckModifyNewCoinsBase function above that loops through
|
||||
// different possible base_values, making sure each one gives the same results.
|
||||
// This wrapper lets the modify_new test below be shorter and less repetitive,
|
||||
// while still verifying that the CoinsViewCache::ModifyNewCoins implementation
|
||||
// ignores base values.
|
||||
template <typename... Args>
|
||||
void CheckModifyNewCoins(Args&&... args)
|
||||
{
|
||||
for (CAmount base_value : {ABSENT, PRUNED, VALUE1})
|
||||
CheckModifyNewCoinsBase(base_value, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ccoins_modify_new)
|
||||
{
|
||||
/* Check ModifyNewCoin behavior, requesting a new coin from a cache view,
|
||||
* writing a modification to the coin, and then checking the resulting
|
||||
* entry in the cache after the modification. Verify behavior with the
|
||||
* with the ModifyNewCoin coinbase argument set to false, and to true.
|
||||
*
|
||||
* Cache Write Result Cache Result Coinbase
|
||||
* Value Value Value Flags Flags
|
||||
*/
|
||||
CheckModifyNewCoins(ABSENT, PRUNED, ABSENT, NO_ENTRY , NO_ENTRY , false);
|
||||
CheckModifyNewCoins(ABSENT, PRUNED, PRUNED, NO_ENTRY , DIRTY , true );
|
||||
CheckModifyNewCoins(ABSENT, VALUE3, VALUE3, NO_ENTRY , DIRTY|FRESH, false);
|
||||
CheckModifyNewCoins(ABSENT, VALUE3, VALUE3, NO_ENTRY , DIRTY , true );
|
||||
CheckModifyNewCoins(PRUNED, PRUNED, ABSENT, 0 , NO_ENTRY , false);
|
||||
CheckModifyNewCoins(PRUNED, PRUNED, PRUNED, 0 , DIRTY , true );
|
||||
CheckModifyNewCoins(PRUNED, PRUNED, ABSENT, FRESH , NO_ENTRY , false);
|
||||
CheckModifyNewCoins(PRUNED, PRUNED, ABSENT, FRESH , NO_ENTRY , true );
|
||||
CheckModifyNewCoins(PRUNED, PRUNED, ABSENT, DIRTY , NO_ENTRY , false);
|
||||
CheckModifyNewCoins(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY , true );
|
||||
CheckModifyNewCoins(PRUNED, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY , false);
|
||||
CheckModifyNewCoins(PRUNED, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY , true );
|
||||
CheckModifyNewCoins(PRUNED, VALUE3, VALUE3, 0 , DIRTY|FRESH, false);
|
||||
CheckModifyNewCoins(PRUNED, VALUE3, VALUE3, 0 , DIRTY , true );
|
||||
CheckModifyNewCoins(PRUNED, VALUE3, VALUE3, FRESH , DIRTY|FRESH, false);
|
||||
CheckModifyNewCoins(PRUNED, VALUE3, VALUE3, FRESH , DIRTY|FRESH, true );
|
||||
CheckModifyNewCoins(PRUNED, VALUE3, VALUE3, DIRTY , DIRTY|FRESH, false);
|
||||
CheckModifyNewCoins(PRUNED, VALUE3, VALUE3, DIRTY , DIRTY , true );
|
||||
CheckModifyNewCoins(PRUNED, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, false);
|
||||
CheckModifyNewCoins(PRUNED, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, true );
|
||||
CheckModifyNewCoins(VALUE2, PRUNED, ABSENT, 0 , NO_ENTRY , false);
|
||||
CheckModifyNewCoins(VALUE2, PRUNED, PRUNED, 0 , DIRTY , true );
|
||||
CheckModifyNewCoins(VALUE2, PRUNED, ABSENT, FRESH , NO_ENTRY , false);
|
||||
CheckModifyNewCoins(VALUE2, PRUNED, ABSENT, FRESH , NO_ENTRY , true );
|
||||
CheckModifyNewCoins(VALUE2, PRUNED, ABSENT, DIRTY , NO_ENTRY , false);
|
||||
CheckModifyNewCoins(VALUE2, PRUNED, PRUNED, DIRTY , DIRTY , true );
|
||||
CheckModifyNewCoins(VALUE2, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY , false);
|
||||
CheckModifyNewCoins(VALUE2, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY , true );
|
||||
CheckModifyNewCoins(VALUE2, VALUE3, VALUE3, 0 , DIRTY|FRESH, false);
|
||||
CheckModifyNewCoins(VALUE2, VALUE3, VALUE3, 0 , DIRTY , true );
|
||||
CheckModifyNewCoins(VALUE2, VALUE3, VALUE3, FRESH , DIRTY|FRESH, false);
|
||||
CheckModifyNewCoins(VALUE2, VALUE3, VALUE3, FRESH , DIRTY|FRESH, true );
|
||||
CheckModifyNewCoins(VALUE2, VALUE3, VALUE3, DIRTY , DIRTY|FRESH, false);
|
||||
CheckModifyNewCoins(VALUE2, VALUE3, VALUE3, DIRTY , DIRTY , true );
|
||||
CheckModifyNewCoins(VALUE2, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, false);
|
||||
CheckModifyNewCoins(VALUE2, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, true );
|
||||
}
|
||||
|
||||
void CheckWriteCoins(CAmount parent_value, CAmount child_value, CAmount expected_value, char parent_flags, char child_flags, char expected_flags)
|
||||
{
|
||||
SingleEntryCacheTest test(ABSENT, parent_value, parent_flags);
|
||||
WriteCoinsViewEntry(test.cache, child_value, child_flags);
|
||||
test.cache.SelfTest();
|
||||
|
||||
CAmount result_value;
|
||||
char result_flags;
|
||||
GetCoinsMapEntry(test.cache.map(), result_value, result_flags);
|
||||
BOOST_CHECK_EQUAL(result_value, expected_value);
|
||||
BOOST_CHECK_EQUAL(result_flags, expected_flags);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ccoins_write)
|
||||
{
|
||||
/* Check BatchWrite behavior, flushing one entry from a child cache to a
|
||||
* parent cache, and checking the resulting entry in the parent cache
|
||||
* after the write.
|
||||
*
|
||||
* Parent Child Result Parent Child Result
|
||||
* Value Value Value Flags Flags Flags
|
||||
*/
|
||||
CheckWriteCoins(ABSENT, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY , NO_ENTRY );
|
||||
CheckWriteCoins(ABSENT, PRUNED, PRUNED, NO_ENTRY , DIRTY , DIRTY );
|
||||
CheckWriteCoins(ABSENT, PRUNED, ABSENT, NO_ENTRY , DIRTY|FRESH, NO_ENTRY );
|
||||
CheckWriteCoins(ABSENT, VALUE2, VALUE2, NO_ENTRY , DIRTY , DIRTY );
|
||||
CheckWriteCoins(ABSENT, VALUE2, VALUE2, NO_ENTRY , DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckWriteCoins(PRUNED, ABSENT, PRUNED, 0 , NO_ENTRY , 0 );
|
||||
CheckWriteCoins(PRUNED, ABSENT, PRUNED, FRESH , NO_ENTRY , FRESH );
|
||||
CheckWriteCoins(PRUNED, ABSENT, PRUNED, DIRTY , NO_ENTRY , DIRTY );
|
||||
CheckWriteCoins(PRUNED, ABSENT, PRUNED, DIRTY|FRESH, NO_ENTRY , DIRTY|FRESH);
|
||||
CheckWriteCoins(PRUNED, PRUNED, PRUNED, 0 , DIRTY , DIRTY );
|
||||
CheckWriteCoins(PRUNED, PRUNED, PRUNED, 0 , DIRTY|FRESH, DIRTY );
|
||||
CheckWriteCoins(PRUNED, PRUNED, ABSENT, FRESH , DIRTY , NO_ENTRY );
|
||||
CheckWriteCoins(PRUNED, PRUNED, ABSENT, FRESH , DIRTY|FRESH, NO_ENTRY );
|
||||
CheckWriteCoins(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY , DIRTY );
|
||||
CheckWriteCoins(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY|FRESH, DIRTY );
|
||||
CheckWriteCoins(PRUNED, PRUNED, ABSENT, DIRTY|FRESH, DIRTY , NO_ENTRY );
|
||||
CheckWriteCoins(PRUNED, PRUNED, ABSENT, DIRTY|FRESH, DIRTY|FRESH, NO_ENTRY );
|
||||
CheckWriteCoins(PRUNED, VALUE2, VALUE2, 0 , DIRTY , DIRTY );
|
||||
CheckWriteCoins(PRUNED, VALUE2, VALUE2, 0 , DIRTY|FRESH, DIRTY );
|
||||
CheckWriteCoins(PRUNED, VALUE2, VALUE2, FRESH , DIRTY , DIRTY|FRESH);
|
||||
CheckWriteCoins(PRUNED, VALUE2, VALUE2, FRESH , DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckWriteCoins(PRUNED, VALUE2, VALUE2, DIRTY , DIRTY , DIRTY );
|
||||
CheckWriteCoins(PRUNED, VALUE2, VALUE2, DIRTY , DIRTY|FRESH, DIRTY );
|
||||
CheckWriteCoins(PRUNED, VALUE2, VALUE2, DIRTY|FRESH, DIRTY , DIRTY|FRESH);
|
||||
CheckWriteCoins(PRUNED, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckWriteCoins(VALUE1, ABSENT, VALUE1, 0 , NO_ENTRY , 0 );
|
||||
CheckWriteCoins(VALUE1, ABSENT, VALUE1, FRESH , NO_ENTRY , FRESH );
|
||||
CheckWriteCoins(VALUE1, ABSENT, VALUE1, DIRTY , NO_ENTRY , DIRTY );
|
||||
CheckWriteCoins(VALUE1, ABSENT, VALUE1, DIRTY|FRESH, NO_ENTRY , DIRTY|FRESH);
|
||||
CheckWriteCoins(VALUE1, PRUNED, PRUNED, 0 , DIRTY , DIRTY );
|
||||
CheckWriteCoins(VALUE1, PRUNED, PRUNED, 0 , DIRTY|FRESH, DIRTY );
|
||||
CheckWriteCoins(VALUE1, PRUNED, ABSENT, FRESH , DIRTY , NO_ENTRY );
|
||||
CheckWriteCoins(VALUE1, PRUNED, ABSENT, FRESH , DIRTY|FRESH, NO_ENTRY );
|
||||
CheckWriteCoins(VALUE1, PRUNED, PRUNED, DIRTY , DIRTY , DIRTY );
|
||||
CheckWriteCoins(VALUE1, PRUNED, PRUNED, DIRTY , DIRTY|FRESH, DIRTY );
|
||||
CheckWriteCoins(VALUE1, PRUNED, ABSENT, DIRTY|FRESH, DIRTY , NO_ENTRY );
|
||||
CheckWriteCoins(VALUE1, PRUNED, ABSENT, DIRTY|FRESH, DIRTY|FRESH, NO_ENTRY );
|
||||
CheckWriteCoins(VALUE1, VALUE2, VALUE2, 0 , DIRTY , DIRTY );
|
||||
CheckWriteCoins(VALUE1, VALUE2, VALUE2, 0 , DIRTY|FRESH, DIRTY );
|
||||
CheckWriteCoins(VALUE1, VALUE2, VALUE2, FRESH , DIRTY , DIRTY|FRESH);
|
||||
CheckWriteCoins(VALUE1, VALUE2, VALUE2, FRESH , DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckWriteCoins(VALUE1, VALUE2, VALUE2, DIRTY , DIRTY , DIRTY );
|
||||
CheckWriteCoins(VALUE1, VALUE2, VALUE2, DIRTY , DIRTY|FRESH, DIRTY );
|
||||
CheckWriteCoins(VALUE1, VALUE2, VALUE2, DIRTY|FRESH, DIRTY , DIRTY|FRESH);
|
||||
CheckWriteCoins(VALUE1, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH, DIRTY|FRESH);
|
||||
|
||||
// The checks above omit cases where the child flags are not DIRTY, since
|
||||
// they would be too repetitive (the parent cache is never updated in these
|
||||
// cases). The loop below covers these cases and makes sure the parent cache
|
||||
// is always left unchanged.
|
||||
for (CAmount parent_value : {ABSENT, PRUNED, VALUE1})
|
||||
for (CAmount child_value : {ABSENT, PRUNED, VALUE2})
|
||||
for (char parent_flags : parent_value == ABSENT ? ABSENT_FLAGS : FLAGS)
|
||||
for (char child_flags : child_value == ABSENT ? ABSENT_FLAGS : CLEAN_FLAGS)
|
||||
CheckWriteCoins(parent_value, child_value, parent_value, parent_flags, child_flags, parent_flags);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
|
Loading…
Reference in a new issue