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

Code before:
                if (fuzzed_data_provider.ConsumeBool()) {
                    const bool possible_overwrite{fuzzed_data_provider.ConsumeBool()};
                    try {
                        coins_view_cache.AddCoin(outpoint, std::move(coin), possible_overwrite);
                    } catch (const std::logic_error& e) {
                        assert(e.what() == std::string{"Attempted to overwrite an unspent coin (when possible_overwrite is false)"});
                        assert(!possible_overwrite);
                    }
                } else {
                    coins_view_cache.EmplaceCoinInternalDANGER(std::move(outpoint), std::move(coin));
                }
            },
            [&] {
                coins_view_cache.Flush(/*will_reuse_cache=*/fuzzed_data_provider.ConsumeBool());
            },
            [&] {
                coins_view_cache.Sync();
            },
            [&] {
                uint256 best_block{ConsumeUInt256(fuzzed_data_provider)};
                // Set best block hash to non-null to satisfy the assertion in CCoinsViewDB::BatchWrite().
                if (is_db && best_block.IsNull()) best_block = uint256::ONE;
                coins_view_cache.SetBestBlock(best_block);
            },
            [&] {
                coins_view_cache.Reset();
                // Set best block hash to non-null to satisfy the assertion in CCoinsViewDB::BatchWrite().
                if (is_db) {
                    const uint256 best_block{ConsumeUInt256(fuzzed_data_provider)};
                    if (best_block.IsNull()) {
                        good_data = false;
                        return;
                    }
                    coins_view_cache.SetBestBlock(best_block);
                }
            },
            [&] {
                Coin move_to;
                (void)coins_view_cache.SpendCoin(random_out_point, fuzzed_data_provider.ConsumeBool() ? &move_to : nullptr);
            },
            [&] {
                coins_view_cache.Uncache(random_out_point);
            },
            [&] {
                if (fuzzed_data_provider.ConsumeBool()) {
                    backend_coins_view = CCoinsView{};
                }
                coins_view_cache.SetBackend(backend_coins_view);
            },
            [&] {
                const std::optional<COutPoint> opt_out_point = ConsumeDeserializable<COutPoint>(fuzzed_data_provider);

Review comment (performance):
The tests are good, but we are now only testing a member function that does not get called directly in production code. How about making `Reset` protected and using the RAII guard here directly:

<details>
<summary>Click to expand diff</summary>

```diff
diff --git a/src/coins.h b/src/coins.h
index e8af03e2c8..c4f8dbed92 100644
--- a/src/coins.h
+++ b/src/coins.h
@@ -379,0 +380,6 @@ protected:
+    /**
+     * Discard all modifications made to this cache without flushing to the base view.
+     * This can be used to efficiently reuse a cache instance across multiple operations.
+     */
+    void Reset() noexcept;
+
@@ -456,6 +461,0 @@ public:
-    /**
-     * Discard all modifications made to this cache without flushing to the base view.
-     * This can be used to efficiently reuse a cache instance across multiple operations.
-     */
-    void Reset() noexcept;
-
diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp
index 2d061bae54..bf474498fd 100644
--- a/src/test/coins_tests.cpp
+++ b/src/test/coins_tests.cpp
@@ -1148 +1148,3 @@ BOOST_AUTO_TEST_CASE(ccoins_reset)
-        cache.Reset();
+        {
+            auto reset = cache.CreateResetGuard();
+        }
diff --git a/src/test/fuzz/coins_view.cpp b/src/test/fuzz/coins_view.cpp
index bddc34eb10..e23928083f 100644
--- a/src/test/fuzz/coins_view.cpp
+++ b/src/test/fuzz/coins_view.cpp
@@ -89 +89,3 @@ void TestCoinsView(FuzzedDataProvider& fuzzed_data_provider, CCoinsView& backend
-                coins_view_cache.Reset();
+                {
+                    auto reset{coins_view_cache.CreateResetGuard()};
+                }
diff --git a/src/test/fuzz/coinscache_sim.cpp b/src/test/fuzz/coinscache_sim.cpp
index db68dbc57f..abe7bd9af0 100644
--- a/src/test/fuzz/coinscache_sim.cpp
+++ b/src/test/fuzz/coinscache_sim.cpp
@@ -407 +407,3 @@ FUZZ_TARGET(coinscache_sim)
-                caches.back()->Reset();
+                {
+                    auto res{caches.back()->CreateResetGuard()};
+                }
```
</details>

Code after:
                if (fuzzed_data_provider.ConsumeBool()) {
                    const bool possible_overwrite{fuzzed_data_provider.ConsumeBool()};
                    try {
                        coins_view_cache.AddCoin(outpoint, std::move(coin), possible_overwrite);
                    } catch (const std::logic_error& e) {
                        assert(e.what() == std::string{"Attempted to overwrite an unspent coin (when possible_overwrite is false)"});
                        assert(!possible_overwrite);
                    }
                } else {
                    coins_view_cache.EmplaceCoinInternalDANGER(std::move(outpoint), std::move(coin));
                }
            },
            [&] {
                coins_view_cache.Flush(/*reallocate_cache=*/fuzzed_data_provider.ConsumeBool());
            },
            [&] {
                coins_view_cache.Sync();
            },
            [&] {
                uint256 best_block{ConsumeUInt256(fuzzed_data_provider)};
                // Set best block hash to non-null to satisfy the assertion in CCoinsViewDB::BatchWrite().
                if (is_db && best_block.IsNull()) best_block = uint256::ONE;
                coins_view_cache.SetBestBlock(best_block);
            },
            [&] {
                {
                    const auto reset_guard{coins_view_cache.CreateResetGuard()};
                }
                // Set best block hash to non-null to satisfy the assertion in CCoinsViewDB::BatchWrite().
                if (is_db) {
                    const uint256 best_block{ConsumeUInt256(fuzzed_data_provider)};
                    if (best_block.IsNull()) {
                        good_data = false;
                        return;
                    }
                    coins_view_cache.SetBestBlock(best_block);
                }
            },
            [&] {
                Coin move_to;
                (void)coins_view_cache.SpendCoin(random_out_point, fuzzed_data_provider.ConsumeBool() ? &move_to : nullptr);
            },
            [&] {
                coins_view_cache.Uncache(random_out_point);
            },
            [&] {
                if (fuzzed_data_provider.ConsumeBool()) {
                    backend_coins_view = CCoinsView{};
                }
                coins_view_cache.SetBackend(backend_coins_view);
            },