@@ -7501,6 +7501,141 @@ TEST_CASE_VERSIONS("do not evict outdated keys", "[archival][soroban]")
75017501 });
75027502}
75037503
7504+ TEST_CASE (" disable eviction scan" , " [archival][soroban]" )
7505+ {
7506+ // This test verifies that when the eviction scan size is set to 0,
7507+ // no entries are evicted and the eviction iterator does not advance.
7508+ auto cfg = getTestConfig (0 );
7509+ cfg.TESTING_SOROBAN_HIGH_LIMIT_OVERRIDE = true ;
7510+ cfg.TESTING_MINIMUM_PERSISTENT_ENTRY_LIFETIME = 10 ;
7511+ cfg.OVERRIDE_EVICTION_PARAMS_FOR_TESTING = true ;
7512+ cfg.TESTING_STARTING_EVICTION_SCAN_LEVEL = 1 ;
7513+ cfg.TESTING_MAX_ENTRIES_TO_ARCHIVE = 1 ;
7514+
7515+ SorobanTest test (cfg, false );
7516+ ContractStorageTestClient client (test);
7517+ auto & snapshotManager =
7518+ test.getApp ().getBucketManager ().getBucketSnapshotManager ();
7519+
7520+ // WASM and instance should not expire
7521+ test.invokeExtendOp (client.getContract ().getKeys (), 10'000 );
7522+
7523+ // We'll create two evictable entries, one persistent and one temporary.
7524+ auto persistentKey = client.getContract ().getDataKey (
7525+ makeSymbolSCVal (" persistent_key" ), ContractDataDurability::PERSISTENT);
7526+ client.put (" persistent_key" , ContractDataDurability::PERSISTENT, 123 );
7527+
7528+ auto firstEvictionLedger =
7529+ test.getLCLSeq () +
7530+ MinimumSorobanNetworkConfig::MINIMUM_PERSISTENT_ENTRY_LIFETIME;
7531+
7532+ auto temporaryKey = client.getContract ().getDataKey (
7533+ makeSymbolSCVal (" temporary_key" ), ContractDataDurability::TEMPORARY);
7534+ client.put (" temporary_key" , ContractDataDurability::TEMPORARY, 456 );
7535+
7536+ // modifySorobanNetworkConfig will close 4 ledgers before the upgrade will
7537+ // take affect, so close enough ledgers here such that the persistent entry
7538+ // would be evicted on the ledger immediately following the upgrade.
7539+ for (auto ledgerSeq = test.getLCLSeq () + 1 ;
7540+ ledgerSeq < firstEvictionLedger - 4 ; ++ledgerSeq)
7541+ {
7542+ closeLedgerOn (test.getApp (), ledgerSeq, 2 , 1 , 2016 );
7543+ }
7544+
7545+ // Disable eviction scan by setting evictionScanSize to 0
7546+ modifySorobanNetworkConfig (test.getApp (), [](SorobanNetworkConfig& cfg) {
7547+ cfg.mStateArchivalSettings .evictionScanSize = 0 ;
7548+ });
7549+
7550+ // Capture the eviction iterator after disabling eviction scan
7551+ auto initialIterator = test.getNetworkCfg ().evictionIterator ();
7552+
7553+ // Close ledgers well beyond when the entries would have been evicted.
7554+ auto closeLedgersUntil = test.getLCLSeq () + 20 ;
7555+ for (auto ledgerSeq = test.getLCLSeq () + 1 ; ledgerSeq <= closeLedgersUntil;
7556+ ++ledgerSeq)
7557+ {
7558+ closeLedgerOn (test.getApp (), ledgerSeq, 2 , 1 , 2016 );
7559+
7560+ // Verify iterator has not changed
7561+ REQUIRE (initialIterator == test.getNetworkCfg ().evictionIterator ());
7562+ }
7563+
7564+ auto liveBL = snapshotManager.copySearchableLiveBucketListSnapshot ();
7565+ auto hotArchive =
7566+ snapshotManager.copySearchableHotArchiveBucketListSnapshot ();
7567+
7568+ auto assertTemp = [&](bool isLive) {
7569+ liveBL = snapshotManager.copySearchableLiveBucketListSnapshot ();
7570+ hotArchive =
7571+ snapshotManager.copySearchableHotArchiveBucketListSnapshot ();
7572+ auto tempLiveLoad = liveBL->load (temporaryKey);
7573+ REQUIRE (static_cast <bool >(tempLiveLoad) == isLive);
7574+
7575+ // Temp entries are never archived
7576+ REQUIRE (!hotArchive->load (temporaryKey));
7577+ };
7578+
7579+ auto assertPersistent = [&](bool isLive) {
7580+ liveBL = snapshotManager.copySearchableLiveBucketListSnapshot ();
7581+ hotArchive =
7582+ snapshotManager.copySearchableHotArchiveBucketListSnapshot ();
7583+
7584+ auto persistentLiveLoad = liveBL->load (persistentKey);
7585+ REQUIRE (static_cast <bool >(persistentLiveLoad) == isLive);
7586+
7587+ auto hotArchiveLoad = hotArchive->load (persistentKey);
7588+ REQUIRE (static_cast <bool >(hotArchiveLoad) != isLive);
7589+ };
7590+
7591+ // Verify entries are not evicted
7592+ assertPersistent (true );
7593+ assertTemp (true );
7594+
7595+ // Now, re-enable eviction. maxEntriesToArchive = 1 limits archiving to
7596+ // one entry per ledger. Note that the first eviction will actually occur on
7597+ // the upgrade ledger itself.
7598+ modifySorobanNetworkConfig (test.getApp (), [](SorobanNetworkConfig& cfg) {
7599+ cfg.mStateArchivalSettings .evictionScanSize = 10000 ;
7600+ cfg.mStateArchivalSettings .maxEntriesToArchive = 1 ;
7601+ });
7602+
7603+ auto iteratorAfterUpgrade = test.getNetworkCfg ().evictionIterator ();
7604+
7605+ // Iterator should have advanced from initial position during the upgrade
7606+ // ledger.
7607+ REQUIRE (!(initialIterator == iteratorAfterUpgrade));
7608+ initialIterator = iteratorAfterUpgrade;
7609+
7610+ // Check that exactly one entry has been evicted
7611+ liveBL = snapshotManager.copySearchableLiveBucketListSnapshot ();
7612+ hotArchive = snapshotManager.copySearchableHotArchiveBucketListSnapshot ();
7613+
7614+ auto persistentLiveLoad = liveBL->load (persistentKey);
7615+ if (persistentLiveLoad)
7616+ {
7617+ // If perstent entry is live, assert that the temp entry is evicted.
7618+ assertPersistent (true );
7619+ assertTemp (false );
7620+ }
7621+ else
7622+ {
7623+ // If perstent entry is evicted, assert that the temp entry is live.
7624+ assertPersistent (false );
7625+ assertTemp (true );
7626+ }
7627+
7628+ // Close one more ledger to evict the last remaining entry.
7629+ closeLedgerOn (test.getApp (), test.getLCLSeq () + 1 , 2 , 1 , 2016 );
7630+
7631+ // check that the iterator has advanced
7632+ REQUIRE (!(initialIterator == test.getNetworkCfg ().evictionIterator ()));
7633+
7634+ // Verify both entries have been evicted
7635+ assertPersistent (false );
7636+ assertTemp (false );
7637+ }
7638+
75047639TEST_CASE (" Module cache cost with restore gaps" , " [tx][soroban][modulecache]" )
75057640{
75067641 VirtualClock clock;
0 commit comments