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

Code before:
            old_path = master_path = Path(wallet_name)
        else:
            old_path = self.old_node.wallets_path / wallet_name
            master_path = self.master_node.wallets_path / wallet_name
            os.makedirs(master_path, exist_ok=True)
            shutil.copyfile(old_path / "wallet.dat", master_path / "wallet.dat")

        # This will be the watch-only directory the migration tries to create,
        # we make migration fail by placing a wallet.dat file there.
        wo_prefix = wallet_name or "default_wallet"
        # wo_prefix might have path characters in it, this corresponds with
        # DoMigration().
        wo_dirname = f"{wo_prefix}_watchonly"
        watch_only_dir = self.master_node.wallets_path / wo_dirname
        os.mkdir(watch_only_dir)
        shutil.copyfile(old_path / "wallet.dat", watch_only_dir / "wallet.dat")

        # Make a file in the wallets dir that must still exist after migration
        survive_path = self.master_node.wallets_path / "survive"
        open(survive_path, "w").close()
        assert survive_path.exists()

        mocked_time = int(time.time())
        self.master_node.setmocktime(mocked_time)
        if os.path.isabs(wallet_name) or is_default:
            assert_raises_rpc_error(-1, "filesystem error: cannot copy file: File exists", self.master_node.migratewallet, wallet_name)
        else:
            assert_raises_rpc_error(-4, "Failed to create database", self.master_node.migratewallet, wallet_name)
        self.master_node.setmocktime(0)

        # Verify the /wallets/ path exists.
        assert self.master_node.wallets_path.exists()

        # Verify survive is still there
        assert survive_path.exists()
        # Verify both wallet paths exist.
        assert Path(old_path / "wallet.dat").exists()
        assert Path(master_path / "wallet.dat").exists()

        backup_prefix = "default_wallet" if is_default else wallet_name
        backup_path = master_path / f"{backup_prefix}_{mocked_time}.legacy.bak"
        assert backup_path.exists()

        if os.path.isabs(wallet_name) or is_default:
            # Migration will fail to restore the original wallet
            # So verify it is now a SQLite wallet
            wallet_file_path = self.master_node.wallets_path / wallet_name / self.wallet_data_filename
            with open(wallet_file_path, 'rb') as f:
                file_magic = f.read(16)
                assert_equal(file_magic, b'SQLite format 3\x00')
        else:

Review comment (bug):
This test should also be failing, the generic exception is
```suggestion
            assert_raises_rpc_error(-1, "filesystem error: in copy_file: File exists", self.master_node.migratewallet, wallet_name)
```

Code after:
            old_path = master_path = Path(wallet_name)
        else:
            old_path = self.old_node.wallets_path / wallet_name
            master_path = self.master_node.wallets_path / wallet_name
            os.makedirs(master_path, exist_ok=True)
            shutil.copyfile(old_path / "wallet.dat", master_path / "wallet.dat")

        # This will be the watch-only directory the migration tries to create,
        # we make migration fail by placing a wallet.dat file there.
        wo_prefix = wallet_name or "default_wallet"
        # wo_prefix might have path characters in it, this corresponds with
        # DoMigration().
        wo_dirname = f"{wo_prefix}_watchonly"
        watch_only_dir = self.master_node.wallets_path / wo_dirname
        os.mkdir(watch_only_dir)
        shutil.copyfile(old_path / "wallet.dat", watch_only_dir / "wallet.dat")

        # Make a file in the wallets dir that must still exist after migration
        survive_path = self.master_node.wallets_path / "survive"
        open(survive_path, "wb").close()
        assert survive_path.exists()

        mocked_time = int(time.time())
        self.master_node.setmocktime(mocked_time)
        assert_raises_rpc_error(-4, "Failed to create database", self.master_node.migratewallet, wallet_name)
        self.master_node.setmocktime(0)

        # Verify the /wallets/ path exists.
        assert self.master_node.wallets_path.exists()

        # Verify survive is still there
        assert survive_path.exists()
        # Verify both wallet paths exist.
        assert Path(old_path / "wallet.dat").exists()
        assert Path(master_path / "wallet.dat").exists()

        backup_prefix = "default_wallet" if is_default else wallet_name
        backup_path = master_path / f"{backup_prefix}_{mocked_time}.legacy.bak"
        assert backup_path.exists()

        with open(self.master_node.wallets_path / wallet_name / self.wallet_data_filename, "rb") as f:
            data = f.read(16)
            _, _, magic = struct.unpack("QII", data)
            assert_equal(magic, BTREE_MAGIC)


        # Cleanup
        if is_default:
            self.clear_default_wallet(backup_path)
        else:
            backup_path.unlink()