Repository: bitcoin/bitcoin
File: src/test/coins_tests.cpp (C++)

Code before:
    BOOST_CHECK_EQUAL(value, coin.out.nValue);
    BOOST_CHECK_EQUAL(flags, DIRTY|FRESH);

    // Base shouldn't have seen coin.
    BOOST_CHECK(!base.HaveCoin(outp));

    BOOST_CHECK(all_caches[0]->SpendCoin(outp));
    all_caches[0]->Sync();

    // Ensure there is no sign of the coin after spend/flush.
    GetCoinsMapEntry(all_caches[0]->map(), value, flags, outp);
    BOOST_CHECK_EQUAL(value, ABSENT);
    BOOST_CHECK_EQUAL(flags, NO_ENTRY);
    BOOST_CHECK(!all_caches[0]->HaveCoinInCache(outp));
    BOOST_CHECK(!base.HaveCoin(outp));
}

BOOST_AUTO_TEST_CASE(ccoins_flush_behavior)
{
    // Create two in-memory caches atop a leveldb view.
    CCoinsViewDB base{"test", /*nCacheSize*/ 1 << 23, /*fMemory*/ true, /*fWipe*/ false};
    std::vector<CCoinsViewCacheTest*> caches;
    caches.push_back(new CCoinsViewCacheTest(&base));
    caches.push_back(new CCoinsViewCacheTest(caches.back()));

    for (CCoinsViewCacheTest* view : caches) {
        TestFlushBehavior(view, base, caches, /*do_erasing_flush*/ false);
        TestFlushBehavior(view, base, caches, /*do_erasing_flush*/ true);
    }

    // Clean up the caches.
    while (caches.size() > 0) {
        delete caches.back();
        caches.pop_back();
    }
}

BOOST_AUTO_TEST_SUITE_END()


Review comment (bug):
nit: I don't think we need these three lines. Just checking that `HaveCoinInCache()` fails is enough to show that the coin doesn't exist in the cache.

Code after:
    txid = InsecureRand256();
    outp = COutPoint(txid, 0);
    coin = MakeCoin();
    CAmount coin_val = coin.out.nValue;
    BOOST_CHECK(!base.HaveCoin(outp));
    BOOST_CHECK(!all_caches[0]->HaveCoin(outp));
    BOOST_CHECK(!all_caches[1]->HaveCoin(outp));

    // Add and spend from same cache without flushing.
    all_caches[0]->AddCoin(outp, std::move(coin), false);

    // Coin should be FRESH in the cache.
    GetCoinsMapEntry(all_caches[0]->map(), value, flags, outp);
    BOOST_CHECK_EQUAL(value, coin_val);
    BOOST_CHECK_EQUAL(flags, DIRTY|FRESH);

    // Base shouldn't have seen coin.
    BOOST_CHECK(!base.HaveCoin(outp));

    BOOST_CHECK(all_caches[0]->SpendCoin(outp));
    all_caches[0]->Sync();

    // Ensure there is no sign of the coin after spend/flush.
    GetCoinsMapEntry(all_caches[0]->map(), value, flags, outp);
    BOOST_CHECK_EQUAL(value, ABSENT);
    BOOST_CHECK_EQUAL(flags, NO_ENTRY);
    BOOST_CHECK(!all_caches[0]->HaveCoinInCache(outp));
    BOOST_CHECK(!base.HaveCoin(outp));
}

BOOST_AUTO_TEST_CASE(ccoins_flush_behavior)
{
    // Create two in-memory caches atop a leveldb view.
    CCoinsViewDB base{"test", /*nCacheSize=*/ 1 << 23, /*fMemory=*/ true, /*fWipe=*/ false};
    std::vector<CCoinsViewCacheTest*> caches;
    caches.push_back(new CCoinsViewCacheTest(&base));
    caches.push_back(new CCoinsViewCacheTest(caches.back()));

    for (CCoinsViewCacheTest* view : caches) {
        TestFlushBehavior(view, base, caches, /*do_erasing_flush=*/ false);
        TestFlushBehavior(view, base, caches, /*do_erasing_flush=*/ true);
    }

    // Clean up the caches.
    while (caches.size() > 0) {
        delete caches.back();
        caches.pop_back();
    }
}

BOOST_AUTO_TEST_SUITE_END()