test: restorewallet, coverage for existing dirs, unnamed wallet and prune failure
The first test verifies that restoring into an existing empty directory or a directory with no .dat db files succeeds, while restoring into a dir with a .dat file fails. The second test covers restoring into the default unnamed wallet (wallet.dat), which also implicitly exercises the recovery path used after a failed migration. The third test covers failure during restore on a prune node. When the wallet last sync was beyond the pruning height.
This commit is contained in:
1 file changed
+65
@@ -39,6 +39,7 @@ from test_framework.test_framework import BitcoinTestFramework
|
|||||||
from test_framework.util import (
|
from test_framework.util import (
|
||||||
assert_equal,
|
assert_equal,
|
||||||
assert_raises_rpc_error,
|
assert_raises_rpc_error,
|
||||||
|
sha256sum_file,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -136,6 +137,61 @@ class WalletBackupTest(BitcoinTestFramework):
|
|||||||
assert_raises_rpc_error(-36, error_message, node.restorewallet, wallet_name, backup_file)
|
assert_raises_rpc_error(-36, error_message, node.restorewallet, wallet_name, backup_file)
|
||||||
assert wallet_file.exists()
|
assert wallet_file.exists()
|
||||||
|
|
||||||
|
def test_restore_existent_dir(self):
|
||||||
|
self.log.info("Test restore on an existent empty directory")
|
||||||
|
node = self.nodes[3]
|
||||||
|
backup_file = self.nodes[0].datadir_path / 'wallet.bak'
|
||||||
|
wallet_name = "restored_wallet"
|
||||||
|
wallet_dir = node.wallets_path / wallet_name
|
||||||
|
os.mkdir(wallet_dir)
|
||||||
|
res = node.restorewallet(wallet_name, backup_file)
|
||||||
|
assert_equal(res['name'], wallet_name)
|
||||||
|
node.unloadwallet(wallet_name)
|
||||||
|
|
||||||
|
self.log.info("Test restore succeeds when the target directory contains non-wallet files")
|
||||||
|
wallet_file = node.wallets_path / wallet_name / "wallet.dat"
|
||||||
|
os.remove(wallet_file)
|
||||||
|
extra_file = node.wallets_path / wallet_name / "not_a_wallet.txt"
|
||||||
|
extra_file.touch()
|
||||||
|
res = node.restorewallet(wallet_name, backup_file)
|
||||||
|
assert_equal(res['name'], wallet_name)
|
||||||
|
assert extra_file.exists() # extra file was not removed by mistake
|
||||||
|
node.unloadwallet(wallet_name)
|
||||||
|
|
||||||
|
self.log.info("Test restore failure due to existing db file in the destination directory")
|
||||||
|
original_shasum = sha256sum_file(wallet_file)
|
||||||
|
error_message = "Failed to restore wallet. Database file exists in '{}'.".format(wallet_dir / "wallet.dat")
|
||||||
|
assert_raises_rpc_error(-36, error_message, node.restorewallet, wallet_name, backup_file)
|
||||||
|
# Ensure the wallet file remains untouched
|
||||||
|
assert wallet_dir.exists()
|
||||||
|
assert_equal(original_shasum, sha256sum_file(wallet_file))
|
||||||
|
|
||||||
|
self.log.info("Test restore succeeds when the .dat file in the destination has a different name")
|
||||||
|
second_wallet = wallet_dir / "hidden_storage.dat"
|
||||||
|
os.rename(wallet_dir / "wallet.dat", second_wallet)
|
||||||
|
original_shasum = sha256sum_file(second_wallet)
|
||||||
|
res = node.restorewallet(wallet_name, backup_file)
|
||||||
|
assert_equal(res['name'], wallet_name)
|
||||||
|
assert (wallet_dir / "hidden_storage.dat").exists()
|
||||||
|
assert_equal(original_shasum, sha256sum_file(second_wallet))
|
||||||
|
node.unloadwallet(wallet_name)
|
||||||
|
|
||||||
|
# Clean for follow-up tests
|
||||||
|
os.remove(wallet_file)
|
||||||
|
|
||||||
|
def test_restore_into_unnamed_wallet(self):
|
||||||
|
self.log.info("Test restore into a default unnamed wallet")
|
||||||
|
# This is also useful to test the migration recovery after failure logic
|
||||||
|
node = self.nodes[3]
|
||||||
|
backup_file = self.nodes[0].datadir_path / 'wallet.bak'
|
||||||
|
wallet_name = ""
|
||||||
|
res = node.restorewallet(wallet_name, backup_file)
|
||||||
|
assert_equal(res['name'], "")
|
||||||
|
assert (node.wallets_path / "wallet.dat").exists()
|
||||||
|
# Clean for follow-up tests
|
||||||
|
node.unloadwallet("")
|
||||||
|
os.remove(node.wallets_path / "wallet.dat")
|
||||||
|
|
||||||
def test_pruned_wallet_backup(self):
|
def test_pruned_wallet_backup(self):
|
||||||
self.log.info("Test loading backup on a pruned node when the backup was created close to the prune height of the restoring node")
|
self.log.info("Test loading backup on a pruned node when the backup was created close to the prune height of the restoring node")
|
||||||
node = self.nodes[3]
|
node = self.nodes[3]
|
||||||
@@ -155,6 +211,13 @@ class WalletBackupTest(BitcoinTestFramework):
|
|||||||
# the backup to load successfully this close to the prune height
|
# the backup to load successfully this close to the prune height
|
||||||
node.restorewallet('pruned', node.datadir_path / 'wallet_pruned.bak')
|
node.restorewallet('pruned', node.datadir_path / 'wallet_pruned.bak')
|
||||||
|
|
||||||
|
self.log.info("Test restore on a pruned node when the backup was beyond the pruning point")
|
||||||
|
backup_file = self.nodes[0].datadir_path / 'wallet.bak'
|
||||||
|
wallet_name = ""
|
||||||
|
error_message = "Wallet loading failed. Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of a pruned node)"
|
||||||
|
assert_raises_rpc_error(-4, error_message, node.restorewallet, wallet_name, backup_file)
|
||||||
|
assert node.wallets_path.exists() # ensure the wallets dir exists
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
self.log.info("Generating initial blockchain")
|
self.log.info("Generating initial blockchain")
|
||||||
self.generate(self.nodes[0], 1)
|
self.generate(self.nodes[0], 1)
|
||||||
@@ -219,6 +282,8 @@ class WalletBackupTest(BitcoinTestFramework):
|
|||||||
assert_equal(res2_rpc.getbalance(), balance2)
|
assert_equal(res2_rpc.getbalance(), balance2)
|
||||||
|
|
||||||
self.restore_wallet_existent_name()
|
self.restore_wallet_existent_name()
|
||||||
|
self.test_restore_existent_dir()
|
||||||
|
self.test_restore_into_unnamed_wallet()
|
||||||
|
|
||||||
# Backup to source wallet file must fail
|
# Backup to source wallet file must fail
|
||||||
sourcePaths = [
|
sourcePaths = [
|
||||||
|
|||||||
Reference in new issue
Block a user