Repository: bitcoin/bitcoin
File: test/functional/wallet_migration.py (Python)

Code before:
        assert {"name": info["walletname"]} in walletdir_list["wallets"]

        # Check backup existence and its non-empty wallet filename
        backup_filename = f"default_wallet_{curr_time}.legacy.bak"
        backup_path = self.master_node.wallets_path / backup_filename
        assert backup_path.exists()
        assert_equal(str(backup_path), res['backup_path'])
        assert {"name": backup_filename} not in walletdir_list["wallets"]

        self.master_node.setmocktime(0)

    def test_default_wallet_failure(self):
        self.log.info("Test failure during unnamed (default) wallet migration")
        master_wallet = self.master_node.get_wallet_rpc(self.default_wallet_name)
        wallet = self.create_legacy_wallet("", blank=True)
        wallet.importaddress(master_wallet.getnewaddress(address_type="legacy"))

        # Create wallet directory with the watch-only name and a wallet file.
        # Because the wallet dir exists, this will cause migration to fail.
        watch_only_dir = self.master_node.wallets_path / "_watchonly"
        os.mkdir(watch_only_dir)
        shutil.copyfile(self.old_node.wallets_path / "wallet.dat", watch_only_dir / "wallet.dat")

        mocked_time = int(time.time())
        self.master_node.setmocktime(mocked_time)
        assert_raises_rpc_error(-1, "filesystem error: cannot copy file: File exists", self.migrate_and_get_rpc, "")
        self.master_node.setmocktime(0)

        # Verify the /wallets/ path exists
        assert self.master_node.wallets_path.exists()
        # Check backup file exists. Because the wallet has no name, the backup is prefixed with 'default_wallet'
        backup_path = self.master_node.wallets_path / f"default_wallet_{mocked_time}.legacy.bak"
        assert backup_path.exists()
        # Migration will fail to restore the original unnamed wallet
        # Verify that there is a wallet file
        assert (self.master_node.wallets_path / "wallet.dat").exists()
        # And verify it is now a SQLite wallet
        with open(self.master_node.wallets_path / "wallet.dat", 'rb') as f:
            file_magic = f.read(16)
            assert_equal(file_magic, b'SQLite format 3\x00')

        # Test cleanup: clear default wallet for next test
        os.remove(self.old_node.wallets_path / "wallet.dat")

    def test_direct_file(self):
        self.log.info("Test migration of a wallet that is not in a wallet directory")
        wallet = self.create_legacy_wallet("plainfile")
        wallet.unloadwallet()

        shutil.copyfile(
            self.old_node.wallets_path / "plainfile" / "wallet.dat" ,

Review comment (bug):
In c95b1121809e50322b4bf7fd7868e8d0f2a96199:
this should be:
```
assert_raises_rpc_error(-4, "Failed to create database", self.migrate_and_get_rpc, "")
```

Also, should pull https://github.com/bitcoin/bitcoin/pull/34221/commits/cbf0bd35bbf312f3b13d92d281d7112e4b43b9c3 from #34221.

Remember that this is setting the mock time twice, one outside `migrate_and_get_rpc` and another time inside it.

Code after:
        curr_time = int(time.time())
        self.master_node.setmocktime(curr_time)

        res, wallet = self.migrate_and_get_rpc("")
        self.master_node.setmocktime(0)
        info = wallet.getwalletinfo()
        assert_equal(info["descriptors"], True)
        assert_equal(info["format"], "sqlite")

        walletdir_list = wallet.listwalletdir()
        assert {"name": info["walletname"]} in walletdir_list["wallets"]

        # Check backup existence and its non-empty wallet filename
        backup_filename = f"default_wallet_{curr_time}.legacy.bak"
        backup_path = self.master_node.wallets_path / backup_filename
        assert backup_path.exists()
        assert_equal(str(backup_path), res['backup_path'])
        assert {"name": backup_filename} not in walletdir_list["wallets"]

        self.master_node.setmocktime(0)

        wallet.unloadwallet()
        self.clear_default_wallet(backup_file=Path(res["backup_path"]))

    def test_default_wallet_watch_only(self):
        self.log.info("Test unnamed (default) watch-only wallet migration")
        master_wallet = self.master_node.get_wallet_rpc(self.default_wallet_name)
        wallet = self.create_legacy_wallet("", blank=True)
        wallet.importaddress(master_wallet.getnewaddress(address_type="legacy"))

        res, def_wallet = self.migrate_and_get_rpc("")
        wallet = self.master_node.get_wallet_rpc("default_wallet_watchonly")

        info = wallet.getwalletinfo()
        assert_equal(info["descriptors"], True)
        assert_equal(info["format"], "sqlite")
        assert_equal(info["private_keys_enabled"], False)
        assert_equal(info["walletname"], "default_wallet_watchonly")

        # The default wallet will still exist and have newly generated descriptors
        assert (self.master_node.wallets_path / "wallet.dat").exists()
        def_wallet_info = def_wallet.getwalletinfo()
        assert_equal(def_wallet_info["descriptors"], True)
        assert_equal(def_wallet_info["format"], "sqlite")
        assert_equal(def_wallet_info["private_keys_enabled"], True)
        assert_equal(def_wallet_info["walletname"], "")
        assert_greater_than(def_wallet_info["keypoolsize"], 0)

        wallet.unloadwallet()
        self.clear_default_wallet(backup_file=Path(res["backup_path"]))