Skip to content

Commit 21da421

Browse files
committed
Merge bitcoin/bitcoin#34439: qa: Drop recursive deletes from test code, add lint checks.
0d1301b test: functional: drop rmtree usage and add lint check (David Gumberg) 8bfb422 test: functional: drop unused --keepcache argument (David Gumberg) a7e4a59 qa: Remove all instances of `remove_all` except test cleanup (David Gumberg) Pull request description: Both `fs::remove_all` and `shutil::rmtree()` are a bit dangerous, and most of their uses are not necessary, this PR removes most instances of both. `remove_all()` is still used in in `src/test/util/setup_common.cpp` as part of `BasicTestingSetup::BasicTestingSetup`'s constructor and destructor, and it is used in the kernel test code's [`TestDirectory`](https://github.com/bitcoin/bitcoin/blob/4ae00e9a7183cb15877c3014bf46f2e36470c304/src/test/kernel/test_kernel.cpp#L100-L112): https://github.com/bitcoin/bitcoin/blob/734899a4c404f24379d0597744465c147d9ad024/src/test/kernel/test_kernel.cpp#L100-L112 In both cases, `remove_all` is likely necessary, but the kernel's test code is RAII, ideally `BasicTestingSetup` could be made similar in a follow-up or in this PR if reviewers think it is important. Similarly in the python code, most usage was unnecessary, but there are a few places where `rmtree()` was necessary, I have added sanity checks to make sure these are inside of the `tmpdir` before doing recursive delete there. ACKs for top commit: achow101: ACK 0d1301b hodlinator: ACK 0d1301b sedited: ACK 0d1301b Tree-SHA512: da8ca23846b73eff0eaff61a5f80ba1decf63db783dcd86b25f88f4862ae28816fc9e2e9ee71283ec800d73097b1cfae64e3c5ba0e991be69c200c6098f24d6e
2 parents 8a8edc8 + 0d1301b commit 21da421

21 files changed

Lines changed: 114 additions & 56 deletions

src/bench/wallet_create.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,19 @@ static void WalletCreate(benchmark::Bench& bench, bool encrypted)
4444
bilingual_str error_string;
4545
std::vector<bilingual_str> warnings;
4646

47-
auto wallet_path = fs::PathToString(test_setup->m_path_root / "test_wallet");
47+
const auto wallet_path = test_setup->m_path_root / "test_wallet";
48+
const auto wallet_name = fs::PathToString(wallet_path);
49+
4850
bench.run([&] {
49-
auto wallet = CreateWallet(context, wallet_path, /*load_on_start=*/std::nullopt, options, status, error_string, warnings);
51+
auto wallet = CreateWallet(context, wallet_name, /*load_on_start=*/std::nullopt, options, status, error_string, warnings);
5052
assert(status == DatabaseStatus::SUCCESS);
5153
assert(wallet != nullptr);
5254

5355
// Release wallet
5456
RemoveWallet(context, wallet, /*load_on_start=*/ std::nullopt);
5557
WaitForDeleteWallet(std::move(wallet));
56-
fs::remove_all(wallet_path);
58+
fs::remove(wallet_path / "wallet.dat");
59+
fs::remove(wallet_path);
5760
});
5861
}
5962

src/test/fuzz/i2p.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ FUZZ_TARGET(i2p, .init = initialize_i2p)
6161
}
6262
}
6363

64-
fs::remove_all(private_key_path);
64+
fs::remove(private_key_path);
6565

6666
CreateSock = CreateSockOrig;
6767
}

src/test/kernel/test_kernel.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,8 +1175,8 @@ BOOST_AUTO_TEST_CASE(btck_chainman_regtest_tests)
11751175
BOOST_CHECK_EQUAL(count, chain.CountEntries());
11761176

11771177

1178-
fs::remove_all(test_directory.m_directory / "blocks" / "blk00000.dat");
1178+
fs::remove(test_directory.m_directory / "blocks" / "blk00000.dat");
11791179
BOOST_CHECK(!chainman->ReadBlock(tip_2).has_value());
1180-
fs::remove_all(test_directory.m_directory / "blocks" / "rev00000.dat");
1180+
fs::remove(test_directory.m_directory / "blocks" / "rev00000.dat");
11811181
BOOST_CHECK_THROW(chainman->ReadBlockSpentOutputs(tip), std::runtime_error);
11821182
}

src/test/util_tests.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1138,7 +1138,8 @@ BOOST_AUTO_TEST_CASE(test_LockDirectory)
11381138
#endif
11391139
// Clean up
11401140
ReleaseDirectoryLocks();
1141-
fs::remove_all(dirname);
1141+
fs::remove(dirname / lockname);
1142+
fs::remove(dirname);
11421143
}
11431144

11441145
BOOST_AUTO_TEST_CASE(test_ToLower)

test/functional/feature_assumeutxo.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
`CRegTestParams::m_assumeutxo_data` in `src/kernel/chainparams.cpp`.
1111
"""
1212
import contextlib
13-
from shutil import rmtree
1413

1514
from dataclasses import dataclass
1615
from test_framework.blocktools import (
@@ -192,7 +191,8 @@ def expected_error(log_msg="", error_msg=""):
192191
expected_error(log_msg=error_details, error_msg=expected_error_msg)
193192

194193
# resurrect node again
195-
rmtree(chainstate_snapshot_path)
194+
(chainstate_snapshot_path / "base_blockhash").unlink()
195+
chainstate_snapshot_path.rmdir()
196196
self.start_node(0)
197197

198198
def test_invalid_mempool_state(self, dump_output_path):
@@ -304,7 +304,7 @@ def test_sync_from_assumeutxo_node(self, snapshot):
304304
# Start test fresh by cleaning up node directories
305305
for node in (snapshot_node, ibd_node):
306306
self.stop_node(node.index)
307-
rmtree(node.chain_path)
307+
self.cleanup_folder(node.chain_path)
308308
self.start_node(node.index, extra_args=self.extra_args[node.index])
309309

310310
# Sync-up headers chain on snapshot_node to load snapshot

test/functional/feature_blocksdir.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
"""Test the blocksdir option.
66
"""
77

8-
import shutil
98
from pathlib import Path
109

1110
from test_framework.test_framework import BitcoinTestFramework, initialize_datadir
@@ -20,7 +19,7 @@ def run_test(self):
2019
self.stop_node(0)
2120
assert self.nodes[0].blocks_path.is_dir()
2221
assert not (self.nodes[0].datadir_path / "blocks").is_dir()
23-
shutil.rmtree(self.nodes[0].datadir_path)
22+
self.cleanup_folder(self.nodes[0].datadir_path)
2423
initialize_datadir(self.options.tmpdir, 0, self.chain)
2524
self.log.info("Starting with nonexistent blocksdir ...")
2625
blocksdir_path = Path(self.options.tmpdir) / 'blocksdir'

test/functional/feature_coinstatsindex_compatibility.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def _test_coin_stats_index_compatibility(self):
4949

5050
self.log.info("Test that gettxoutsetinfo() output is consistent for the new index running on a datadir with the old version")
5151
self.stop_nodes()
52-
shutil.rmtree(node.chain_path / "indexes" / "coinstatsindex")
52+
self.cleanup_folder(node.chain_path / "indexes" / "coinstatsindex")
5353
shutil.copytree(legacy_node.chain_path / "indexes" / "coinstats", node.chain_path / "indexes" / "coinstats")
5454
old_version_path = node.chain_path / "indexes" / "coinstats"
5555
msg = f'[warning] Old version of coinstatsindex found at {old_version_path}. This folder can be safely deleted unless you plan to downgrade your node to version 29 or lower.'

test/functional/feature_init.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ def start_expecting_error(err_fragment, args):
241241
start_expecting_error(err_fragment, startup_args)
242242

243243
for dir in dirs:
244-
shutil.rmtree(node.chain_path / dir)
244+
self.cleanup_folder(node.chain_path / dir)
245245
shutil.move(node.chain_path / f"{dir}_bak", node.chain_path / dir)
246246

247247
def init_pid_test(self):

test/functional/feature_reindex_init.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
from test_framework.test_framework import BitcoinTestFramework
88
from test_framework.util import assert_equal
99
import os
10-
import shutil
1110

1211

1312
class ReindexInitTest(BitcoinTestFramework):
@@ -19,7 +18,7 @@ def run_test(self):
1918
self.stop_nodes()
2019

2120
self.log.info("Removing the block index leads to init error")
22-
shutil.rmtree(node.blocks_path / "index")
21+
self.cleanup_folder(node.blocks_path / "index")
2322
node.assert_start_raises_init_error(
2423
expected_msg=f"Error initializing block database.{os.linesep}"
2524
"Please restart with -reindex or -reindex-chainstate to recover.",

test/functional/test_framework/test_framework.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from datetime import datetime, timezone
1111
import logging
1212
import os
13+
from pathlib import Path
1314
import platform
1415
import pdb
1516
import random
@@ -331,7 +332,7 @@ def shutdown(self):
331332
h.flush()
332333
rpc_logger.removeHandler(h)
333334
if cleanup_tree_on_exit:
334-
shutil.rmtree(self.options.tmpdir)
335+
self.cleanup_folder(self.options.tmpdir)
335336

336337
self.nodes.clear()
337338
return exit_code
@@ -1031,3 +1032,9 @@ def inspect_sqlite_db(self, path, fn, *args, **kwargs):
10311032
return result
10321033
except ImportError:
10331034
self.log.warning("sqlite3 module not available, skipping tests that inspect the database")
1035+
1036+
def cleanup_folder(self, _path):
1037+
path = Path(_path)
1038+
if not path.is_relative_to(self.options.tmpdir):
1039+
raise AssertionError(f"Trying to delete #{path} outside of #{self.options.tmpdir}")
1040+
shutil.rmtree(path)

0 commit comments

Comments
 (0)