1*c2e18aaaSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*c2e18aaaSAndroid Build Coastguard Worker# 3*c2e18aaaSAndroid Build Coastguard Worker# Copyright 2024, The Android Open Source Project 4*c2e18aaaSAndroid Build Coastguard Worker# 5*c2e18aaaSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*c2e18aaaSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*c2e18aaaSAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*c2e18aaaSAndroid Build Coastguard Worker# 9*c2e18aaaSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*c2e18aaaSAndroid Build Coastguard Worker# 11*c2e18aaaSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*c2e18aaaSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*c2e18aaaSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*c2e18aaaSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*c2e18aaaSAndroid Build Coastguard Worker# limitations under the License. 16*c2e18aaaSAndroid Build Coastguard Worker 17*c2e18aaaSAndroid Build Coastguard Worker"""Unit test for the Snapshot module.""" 18*c2e18aaaSAndroid Build Coastguard Worker 19*c2e18aaaSAndroid Build Coastguard Workerimport json 20*c2e18aaaSAndroid Build Coastguard Workerimport os 21*c2e18aaaSAndroid Build Coastguard Workerimport pathlib 22*c2e18aaaSAndroid Build Coastguard Workerimport shutil 23*c2e18aaaSAndroid Build Coastguard Workerimport tempfile 24*c2e18aaaSAndroid Build Coastguard Workerimport unittest 25*c2e18aaaSAndroid Build Coastguard Worker 26*c2e18aaaSAndroid Build Coastguard Workerfrom atest.integration_tests.snapshot import Snapshot 27*c2e18aaaSAndroid Build Coastguard Worker# Disable pylint here because it conflicts with google format 28*c2e18aaaSAndroid Build Coastguard Worker# pylint: disable=wrong-import-order 29*c2e18aaaSAndroid Build Coastguard Workerfrom pyfakefs import fake_filesystem_unittest 30*c2e18aaaSAndroid Build Coastguard Worker 31*c2e18aaaSAndroid Build Coastguard Worker 32*c2e18aaaSAndroid Build Coastguard Workerclass SnapshotTest(fake_filesystem_unittest.TestCase): 33*c2e18aaaSAndroid Build Coastguard Worker """Snapshot test class unit test.""" 34*c2e18aaaSAndroid Build Coastguard Worker 35*c2e18aaaSAndroid Build Coastguard Worker def setUp(self): 36*c2e18aaaSAndroid Build Coastguard Worker self.setUpPyfakefs() 37*c2e18aaaSAndroid Build Coastguard Worker self.temp_dir = pathlib.Path(tempfile.mkdtemp()) 38*c2e18aaaSAndroid Build Coastguard Worker super().setUp() 39*c2e18aaaSAndroid Build Coastguard Worker 40*c2e18aaaSAndroid Build Coastguard Worker def tearDown(self): 41*c2e18aaaSAndroid Build Coastguard Worker shutil.rmtree(self.temp_dir) 42*c2e18aaaSAndroid Build Coastguard Worker super().tearDown() 43*c2e18aaaSAndroid Build Coastguard Worker 44*c2e18aaaSAndroid Build Coastguard Worker def test_restore_dir_and_env_and_obj_from_snapshot(self): 45*c2e18aaaSAndroid Build Coastguard Worker """Test take and restore directory, environ, and objects together.""" 46*c2e18aaaSAndroid Build Coastguard Worker workspace = self.temp_dir / 'workspace' 47*c2e18aaaSAndroid Build Coastguard Worker restore_dst_workspace = self.temp_dir / 'workspace2' 48*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace) 49*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace.joinpath('dir1')) 50*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_file(workspace.joinpath('dir1', 'file1'), contents='test') 51*c2e18aaaSAndroid Build Coastguard Worker env_key = 'env_name' 52*c2e18aaaSAndroid Build Coastguard Worker env_val = 'value' 53*c2e18aaaSAndroid Build Coastguard Worker obj_key = 'obj_name' 54*c2e18aaaSAndroid Build Coastguard Worker obj_val = 123 55*c2e18aaaSAndroid Build Coastguard Worker os.environ[env_key] = env_val 56*c2e18aaaSAndroid Build Coastguard Worker snapshot = Snapshot(self.temp_dir / 'db') 57*c2e18aaaSAndroid Build Coastguard Worker snapshot_name = 'a_snapshot_name' 58*c2e18aaaSAndroid Build Coastguard Worker snapshot.take_snapshot( 59*c2e18aaaSAndroid Build Coastguard Worker snapshot_name, 60*c2e18aaaSAndroid Build Coastguard Worker workspace, 61*c2e18aaaSAndroid Build Coastguard Worker ['*'], 62*c2e18aaaSAndroid Build Coastguard Worker env_keys=[env_key], 63*c2e18aaaSAndroid Build Coastguard Worker objs={obj_key: obj_val}, 64*c2e18aaaSAndroid Build Coastguard Worker ) 65*c2e18aaaSAndroid Build Coastguard Worker 66*c2e18aaaSAndroid Build Coastguard Worker environ, objs = snapshot.restore_snapshot( 67*c2e18aaaSAndroid Build Coastguard Worker snapshot_name, restore_dst_workspace.as_posix() 68*c2e18aaaSAndroid Build Coastguard Worker ) 69*c2e18aaaSAndroid Build Coastguard Worker 70*c2e18aaaSAndroid Build Coastguard Worker self.assertTrue(restore_dst_workspace.joinpath('dir1', 'file1').exists()) 71*c2e18aaaSAndroid Build Coastguard Worker self.assertEqual(environ[env_key], env_val) 72*c2e18aaaSAndroid Build Coastguard Worker self.assertEqual(objs[obj_key], obj_val) 73*c2e18aaaSAndroid Build Coastguard Worker 74*c2e18aaaSAndroid Build Coastguard Worker def test_restore_objects_from_snapshot(self): 75*c2e18aaaSAndroid Build Coastguard Worker """Test objects is restored from a snapshot.""" 76*c2e18aaaSAndroid Build Coastguard Worker workspace = self.temp_dir / 'workspace' 77*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace) 78*c2e18aaaSAndroid Build Coastguard Worker snapshot = Snapshot(self.temp_dir / 'db') 79*c2e18aaaSAndroid Build Coastguard Worker snapshot_name = 'a_snapshot_name' 80*c2e18aaaSAndroid Build Coastguard Worker objs = {'a': {'b': False}} 81*c2e18aaaSAndroid Build Coastguard Worker snapshot.take_snapshot('a_snapshot_name', workspace, ['*'], objs=objs) 82*c2e18aaaSAndroid Build Coastguard Worker 83*c2e18aaaSAndroid Build Coastguard Worker _, actual_objs = snapshot.restore_snapshot( 84*c2e18aaaSAndroid Build Coastguard Worker snapshot_name, workspace.as_posix() 85*c2e18aaaSAndroid Build Coastguard Worker ) 86*c2e18aaaSAndroid Build Coastguard Worker 87*c2e18aaaSAndroid Build Coastguard Worker self.assertEqual(objs, actual_objs) 88*c2e18aaaSAndroid Build Coastguard Worker 89*c2e18aaaSAndroid Build Coastguard Worker def test_take_snapshot_empty_dir_snapshot_is_created(self): 90*c2e18aaaSAndroid Build Coastguard Worker """Test taking a snapshot of an empty directory.""" 91*c2e18aaaSAndroid Build Coastguard Worker workspace = self.temp_dir / 'workspace' 92*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace) 93*c2e18aaaSAndroid Build Coastguard Worker snapshot = Snapshot(self.temp_dir / 'db') 94*c2e18aaaSAndroid Build Coastguard Worker snapshot_name = 'a_snapshot_name' 95*c2e18aaaSAndroid Build Coastguard Worker 96*c2e18aaaSAndroid Build Coastguard Worker snapshot.take_snapshot(snapshot_name, workspace, ['*']) 97*c2e18aaaSAndroid Build Coastguard Worker 98*c2e18aaaSAndroid Build Coastguard Worker self.assertTrue( 99*c2e18aaaSAndroid Build Coastguard Worker self.temp_dir.joinpath(f'db/{snapshot_name}_metadata.json').exists() 100*c2e18aaaSAndroid Build Coastguard Worker ) 101*c2e18aaaSAndroid Build Coastguard Worker 102*c2e18aaaSAndroid Build Coastguard Worker def test_take_snapshot_with_files_files_are_recorded(self): 103*c2e18aaaSAndroid Build Coastguard Worker """Test taking a snapshot of a directory with files.""" 104*c2e18aaaSAndroid Build Coastguard Worker workspace = self.temp_dir / 'workspace' 105*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace) 106*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace.joinpath('dir1')) 107*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_file(workspace.joinpath('dir1', 'file1'), contents='test') 108*c2e18aaaSAndroid Build Coastguard Worker snapshot = Snapshot(self.temp_dir / 'db') 109*c2e18aaaSAndroid Build Coastguard Worker snapshot_name = 'a_snapshot_name' 110*c2e18aaaSAndroid Build Coastguard Worker 111*c2e18aaaSAndroid Build Coastguard Worker snapshot.take_snapshot('a_snapshot_name', workspace, ['*']) 112*c2e18aaaSAndroid Build Coastguard Worker 113*c2e18aaaSAndroid Build Coastguard Worker with open( 114*c2e18aaaSAndroid Build Coastguard Worker self.temp_dir / 'db' / f'{snapshot_name}_metadata.json', 115*c2e18aaaSAndroid Build Coastguard Worker encoding='utf-8', 116*c2e18aaaSAndroid Build Coastguard Worker ) as f: 117*c2e18aaaSAndroid Build Coastguard Worker file_infos = json.load(f) 118*c2e18aaaSAndroid Build Coastguard Worker self.assertEqual(len(file_infos), 2) 119*c2e18aaaSAndroid Build Coastguard Worker self.assertIn('dir1/file1', file_infos) 120*c2e18aaaSAndroid Build Coastguard Worker self.assertIn('dir1', file_infos) 121*c2e18aaaSAndroid Build Coastguard Worker 122*c2e18aaaSAndroid Build Coastguard Worker def test_take_snapshot_with_include_paths(self): 123*c2e18aaaSAndroid Build Coastguard Worker """Test taking a snapshot with include paths.""" 124*c2e18aaaSAndroid Build Coastguard Worker workspace = self.temp_dir / 'workspace' 125*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace) 126*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace.joinpath('dir1')) 127*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_file(workspace.joinpath('dir1', 'file1'), contents='test') 128*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace.joinpath('dir2')) 129*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_file(workspace.joinpath('dir2', 'file2'), contents='test') 130*c2e18aaaSAndroid Build Coastguard Worker snapshot = Snapshot(self.temp_dir / 'db') 131*c2e18aaaSAndroid Build Coastguard Worker snapshot_name = 'a_snapshot_name' 132*c2e18aaaSAndroid Build Coastguard Worker 133*c2e18aaaSAndroid Build Coastguard Worker snapshot.take_snapshot('a_snapshot_name', workspace, include_paths=['dir2']) 134*c2e18aaaSAndroid Build Coastguard Worker 135*c2e18aaaSAndroid Build Coastguard Worker with open( 136*c2e18aaaSAndroid Build Coastguard Worker self.temp_dir / 'db' / f'{snapshot_name}_metadata.json', 137*c2e18aaaSAndroid Build Coastguard Worker encoding='utf-8', 138*c2e18aaaSAndroid Build Coastguard Worker ) as f: 139*c2e18aaaSAndroid Build Coastguard Worker file_infos = json.load(f) 140*c2e18aaaSAndroid Build Coastguard Worker self.assertEqual(len(file_infos), 2) 141*c2e18aaaSAndroid Build Coastguard Worker self.assertIn('dir2', file_infos) 142*c2e18aaaSAndroid Build Coastguard Worker self.assertIn('dir2/file2', file_infos) 143*c2e18aaaSAndroid Build Coastguard Worker 144*c2e18aaaSAndroid Build Coastguard Worker def test_take_snapshot_with_exclude_paths(self): 145*c2e18aaaSAndroid Build Coastguard Worker """Test taking a snapshot with exclude paths.""" 146*c2e18aaaSAndroid Build Coastguard Worker workspace = self.temp_dir / 'workspace' 147*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace) 148*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace.joinpath('dir1')) 149*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_file(workspace.joinpath('dir1', 'file1'), contents='test') 150*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace.joinpath('dir2')) 151*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_file(workspace.joinpath('dir2', 'file2'), contents='test') 152*c2e18aaaSAndroid Build Coastguard Worker snapshot = Snapshot(self.temp_dir / 'db') 153*c2e18aaaSAndroid Build Coastguard Worker snapshot_name = 'a_snapshot_name' 154*c2e18aaaSAndroid Build Coastguard Worker 155*c2e18aaaSAndroid Build Coastguard Worker snapshot.take_snapshot( 156*c2e18aaaSAndroid Build Coastguard Worker 'a_snapshot_name', workspace, ['*'], exclude_paths=['dir1'] 157*c2e18aaaSAndroid Build Coastguard Worker ) 158*c2e18aaaSAndroid Build Coastguard Worker 159*c2e18aaaSAndroid Build Coastguard Worker with open( 160*c2e18aaaSAndroid Build Coastguard Worker self.temp_dir / 'db' / f'{snapshot_name}_metadata.json', 161*c2e18aaaSAndroid Build Coastguard Worker encoding='utf-8', 162*c2e18aaaSAndroid Build Coastguard Worker ) as f: 163*c2e18aaaSAndroid Build Coastguard Worker file_infos = json.load(f) 164*c2e18aaaSAndroid Build Coastguard Worker self.assertEqual(len(file_infos), 2) 165*c2e18aaaSAndroid Build Coastguard Worker self.assertIn('dir2', file_infos) 166*c2e18aaaSAndroid Build Coastguard Worker self.assertIn('dir2/file2', file_infos) 167*c2e18aaaSAndroid Build Coastguard Worker 168*c2e18aaaSAndroid Build Coastguard Worker def test_take_snapshot_with_include_and_exclude_paths(self): 169*c2e18aaaSAndroid Build Coastguard Worker """Test taking a snapshot with include and exclude paths.""" 170*c2e18aaaSAndroid Build Coastguard Worker workspace = self.temp_dir / 'workspace' 171*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace) 172*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace.joinpath('dir1')) 173*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_file(workspace.joinpath('dir1', 'file1'), contents='test') 174*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace.joinpath('dir2')) 175*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_file(workspace.joinpath('dir2', 'file2'), contents='test') 176*c2e18aaaSAndroid Build Coastguard Worker snapshot = Snapshot(self.temp_dir / 'db') 177*c2e18aaaSAndroid Build Coastguard Worker snapshot_name = 'a_snapshot_name' 178*c2e18aaaSAndroid Build Coastguard Worker 179*c2e18aaaSAndroid Build Coastguard Worker snapshot.take_snapshot( 180*c2e18aaaSAndroid Build Coastguard Worker snapshot_name, 181*c2e18aaaSAndroid Build Coastguard Worker workspace, 182*c2e18aaaSAndroid Build Coastguard Worker include_paths=['dir1'], 183*c2e18aaaSAndroid Build Coastguard Worker exclude_paths=['dir1/file1'], 184*c2e18aaaSAndroid Build Coastguard Worker ) 185*c2e18aaaSAndroid Build Coastguard Worker 186*c2e18aaaSAndroid Build Coastguard Worker with open( 187*c2e18aaaSAndroid Build Coastguard Worker self.temp_dir / 'db' / f'{snapshot_name}_metadata.json', 188*c2e18aaaSAndroid Build Coastguard Worker encoding='utf-8', 189*c2e18aaaSAndroid Build Coastguard Worker ) as f: 190*c2e18aaaSAndroid Build Coastguard Worker file_infos = json.load(f) 191*c2e18aaaSAndroid Build Coastguard Worker self.assertEqual(len(file_infos), 1) 192*c2e18aaaSAndroid Build Coastguard Worker self.assertIn('dir1', file_infos) 193*c2e18aaaSAndroid Build Coastguard Worker 194*c2e18aaaSAndroid Build Coastguard Worker def test_restore_snapshot_preserve_dangling_relative_links(self): 195*c2e18aaaSAndroid Build Coastguard Worker """Test restoring a dangling link relative to the workspace.""" 196*c2e18aaaSAndroid Build Coastguard Worker workspace = self.temp_dir / 'workspace' 197*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace) 198*c2e18aaaSAndroid Build Coastguard Worker snapshot = Snapshot(self.temp_dir / 'db') 199*c2e18aaaSAndroid Build Coastguard Worker snapshot_name = 'a_snapshot_name' 200*c2e18aaaSAndroid Build Coastguard Worker restore_dir = self.temp_dir / 'restore' 201*c2e18aaaSAndroid Build Coastguard Worker link_file_name = 'link' 202*c2e18aaaSAndroid Build Coastguard Worker target_file_name = pathlib.Path('non-existent-path') 203*c2e18aaaSAndroid Build Coastguard Worker workspace.joinpath(link_file_name).symlink_to(target_file_name) 204*c2e18aaaSAndroid Build Coastguard Worker snapshot.take_snapshot(snapshot_name, workspace, ['*']) 205*c2e18aaaSAndroid Build Coastguard Worker 206*c2e18aaaSAndroid Build Coastguard Worker snapshot.restore_snapshot(snapshot_name, restore_dir) 207*c2e18aaaSAndroid Build Coastguard Worker 208*c2e18aaaSAndroid Build Coastguard Worker self.assertEqual( 209*c2e18aaaSAndroid Build Coastguard Worker restore_dir.joinpath(link_file_name).readlink(), 210*c2e18aaaSAndroid Build Coastguard Worker target_file_name, 211*c2e18aaaSAndroid Build Coastguard Worker ) 212*c2e18aaaSAndroid Build Coastguard Worker 213*c2e18aaaSAndroid Build Coastguard Worker def test_restore_snapshot_preserve_dangling_absolute_links(self): 214*c2e18aaaSAndroid Build Coastguard Worker """Test restoring a dangling absolute link within workspace.""" 215*c2e18aaaSAndroid Build Coastguard Worker workspace = self.temp_dir / 'workspace' 216*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace) 217*c2e18aaaSAndroid Build Coastguard Worker snapshot = Snapshot(self.temp_dir / 'db') 218*c2e18aaaSAndroid Build Coastguard Worker snapshot_name = 'a_snapshot_name' 219*c2e18aaaSAndroid Build Coastguard Worker restore_dir = self.temp_dir / 'restore' 220*c2e18aaaSAndroid Build Coastguard Worker link_file_name = 'link' 221*c2e18aaaSAndroid Build Coastguard Worker target_file_name = 'non-existent-path' 222*c2e18aaaSAndroid Build Coastguard Worker internal_dangling_target = workspace / target_file_name 223*c2e18aaaSAndroid Build Coastguard Worker workspace.joinpath(link_file_name).symlink_to(internal_dangling_target) 224*c2e18aaaSAndroid Build Coastguard Worker snapshot.take_snapshot(snapshot_name, workspace, ['*']) 225*c2e18aaaSAndroid Build Coastguard Worker 226*c2e18aaaSAndroid Build Coastguard Worker snapshot.restore_snapshot(snapshot_name, restore_dir) 227*c2e18aaaSAndroid Build Coastguard Worker 228*c2e18aaaSAndroid Build Coastguard Worker self.assertEqual( 229*c2e18aaaSAndroid Build Coastguard Worker restore_dir.joinpath(link_file_name).resolve(), 230*c2e18aaaSAndroid Build Coastguard Worker restore_dir / target_file_name, 231*c2e18aaaSAndroid Build Coastguard Worker ) 232*c2e18aaaSAndroid Build Coastguard Worker 233*c2e18aaaSAndroid Build Coastguard Worker def test_restore_snapshot_preserve_dangling_external_links(self): 234*c2e18aaaSAndroid Build Coastguard Worker """Test restoring a dangling link pointing to outside the workspace.""" 235*c2e18aaaSAndroid Build Coastguard Worker workspace = self.temp_dir / 'workspace' 236*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace) 237*c2e18aaaSAndroid Build Coastguard Worker snapshot = Snapshot(self.temp_dir / 'db') 238*c2e18aaaSAndroid Build Coastguard Worker snapshot_name = 'a_snapshot_name' 239*c2e18aaaSAndroid Build Coastguard Worker restore_dir = self.temp_dir / 'restore' 240*c2e18aaaSAndroid Build Coastguard Worker link_file_name = 'link' 241*c2e18aaaSAndroid Build Coastguard Worker external_dangling_target = pathlib.Path('/external/non-existent-path') 242*c2e18aaaSAndroid Build Coastguard Worker workspace.joinpath(link_file_name).symlink_to(external_dangling_target) 243*c2e18aaaSAndroid Build Coastguard Worker snapshot.take_snapshot(snapshot_name, workspace, ['*']) 244*c2e18aaaSAndroid Build Coastguard Worker 245*c2e18aaaSAndroid Build Coastguard Worker snapshot.restore_snapshot(snapshot_name, restore_dir) 246*c2e18aaaSAndroid Build Coastguard Worker 247*c2e18aaaSAndroid Build Coastguard Worker self.assertEqual( 248*c2e18aaaSAndroid Build Coastguard Worker restore_dir.joinpath(link_file_name).resolve(), external_dangling_target 249*c2e18aaaSAndroid Build Coastguard Worker ) 250*c2e18aaaSAndroid Build Coastguard Worker 251*c2e18aaaSAndroid Build Coastguard Worker def test_restore_snapshot_empty_dir(self): 252*c2e18aaaSAndroid Build Coastguard Worker """Test restoring a snapshot of an empty directory.""" 253*c2e18aaaSAndroid Build Coastguard Worker workspace = self.temp_dir / 'workspace' 254*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace) 255*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace.joinpath('dir1')) 256*c2e18aaaSAndroid Build Coastguard Worker snapshot = Snapshot(self.temp_dir / 'db') 257*c2e18aaaSAndroid Build Coastguard Worker snapshot_name = 'a_snapshot_name' 258*c2e18aaaSAndroid Build Coastguard Worker snapshot.take_snapshot(snapshot_name, workspace, ['*']) 259*c2e18aaaSAndroid Build Coastguard Worker restore_dir = self.temp_dir / 'restore' 260*c2e18aaaSAndroid Build Coastguard Worker 261*c2e18aaaSAndroid Build Coastguard Worker snapshot.restore_snapshot(snapshot_name, restore_dir) 262*c2e18aaaSAndroid Build Coastguard Worker 263*c2e18aaaSAndroid Build Coastguard Worker self.assertTrue(restore_dir.joinpath('dir1').exists()) 264*c2e18aaaSAndroid Build Coastguard Worker 265*c2e18aaaSAndroid Build Coastguard Worker def test_restore_snapshot_with_deleted_files(self): 266*c2e18aaaSAndroid Build Coastguard Worker """Test restoring a snapshot with deleted files.""" 267*c2e18aaaSAndroid Build Coastguard Worker workspace = self.temp_dir / 'workspace' 268*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace) 269*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace.joinpath('dir1')) 270*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_file(workspace.joinpath('dir1', 'file1'), contents='test') 271*c2e18aaaSAndroid Build Coastguard Worker snapshot = Snapshot(self.temp_dir / 'db') 272*c2e18aaaSAndroid Build Coastguard Worker snapshot_name = 'a_snapshot_name' 273*c2e18aaaSAndroid Build Coastguard Worker snapshot.take_snapshot(snapshot_name, workspace, ['*']) 274*c2e18aaaSAndroid Build Coastguard Worker self.fs.remove(workspace.joinpath('dir1', 'file1')) 275*c2e18aaaSAndroid Build Coastguard Worker 276*c2e18aaaSAndroid Build Coastguard Worker snapshot.restore_snapshot(snapshot_name, workspace.as_posix()) 277*c2e18aaaSAndroid Build Coastguard Worker 278*c2e18aaaSAndroid Build Coastguard Worker self.assertTrue(workspace.joinpath('dir1', 'file1').exists()) 279*c2e18aaaSAndroid Build Coastguard Worker 280*c2e18aaaSAndroid Build Coastguard Worker def test_restore_snapshot_with_extra_files(self): 281*c2e18aaaSAndroid Build Coastguard Worker """Test restoring a snapshot with extra files.""" 282*c2e18aaaSAndroid Build Coastguard Worker workspace = self.temp_dir / 'workspace' 283*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace) 284*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace.joinpath('dir1')) 285*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_file(workspace.joinpath('dir1', 'file1'), contents='test') 286*c2e18aaaSAndroid Build Coastguard Worker snapshot = Snapshot(self.temp_dir / 'db') 287*c2e18aaaSAndroid Build Coastguard Worker snapshot_name = 'a_snapshot_name' 288*c2e18aaaSAndroid Build Coastguard Worker snapshot.take_snapshot('a_snapshot_name', workspace, ['*']) 289*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_file(workspace.joinpath('dir1', 'file2'), contents='test') 290*c2e18aaaSAndroid Build Coastguard Worker 291*c2e18aaaSAndroid Build Coastguard Worker snapshot.restore_snapshot(snapshot_name, workspace.as_posix()) 292*c2e18aaaSAndroid Build Coastguard Worker 293*c2e18aaaSAndroid Build Coastguard Worker self.assertTrue(workspace.joinpath('dir1', 'file1').exists()) 294*c2e18aaaSAndroid Build Coastguard Worker self.assertFalse(workspace.joinpath('dir1', 'file2').exists()) 295*c2e18aaaSAndroid Build Coastguard Worker 296*c2e18aaaSAndroid Build Coastguard Worker def test_restore_snapshot_with_modified_files(self): 297*c2e18aaaSAndroid Build Coastguard Worker """Test restoring a snapshot with modified files.""" 298*c2e18aaaSAndroid Build Coastguard Worker workspace = self.temp_dir / 'workspace' 299*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace) 300*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_dir(workspace.joinpath('dir1')) 301*c2e18aaaSAndroid Build Coastguard Worker file_path = workspace.joinpath('dir1', 'file1') 302*c2e18aaaSAndroid Build Coastguard Worker self.fs.create_file(file_path, contents='test1') 303*c2e18aaaSAndroid Build Coastguard Worker snapshot = Snapshot(self.temp_dir / 'db') 304*c2e18aaaSAndroid Build Coastguard Worker snapshot_name = 'a_snapshot_name' 305*c2e18aaaSAndroid Build Coastguard Worker snapshot.take_snapshot(snapshot_name, workspace, ['*']) 306*c2e18aaaSAndroid Build Coastguard Worker file_path.write_text('test2', encoding='utf-8') 307*c2e18aaaSAndroid Build Coastguard Worker # Increment file's modified time by 10 milliseconds 308*c2e18aaaSAndroid Build Coastguard Worker mtime = os.path.getmtime(file_path) 309*c2e18aaaSAndroid Build Coastguard Worker os.utime(file_path, (mtime, mtime + 0.01)) 310*c2e18aaaSAndroid Build Coastguard Worker 311*c2e18aaaSAndroid Build Coastguard Worker snapshot.restore_snapshot(snapshot_name, workspace.as_posix()) 312*c2e18aaaSAndroid Build Coastguard Worker 313*c2e18aaaSAndroid Build Coastguard Worker self.assertEqual( 314*c2e18aaaSAndroid Build Coastguard Worker workspace.joinpath('dir1', 'file1').read_text('utf-8'), 'test1' 315*c2e18aaaSAndroid Build Coastguard Worker ) 316*c2e18aaaSAndroid Build Coastguard Worker 317*c2e18aaaSAndroid Build Coastguard Worker 318*c2e18aaaSAndroid Build Coastguard Workerif __name__ == '__main__': 319*c2e18aaaSAndroid Build Coastguard Worker unittest.main() 320