def test_move_fs_op(self, base_dir): for dry_run in range(2): source_item = base_dir / "directory_to_move" dest_item = base_dir / "move_destination" for creator in (source_item.mkdir, source_item.touch): for dest_is_dir in range(2): if source_item.isdir(): source_item.rmdir() elif source_item.isfile(): source_item.remove() # END handle removal of existing one # prep sandbox if dest_item.isdir(): dest_item.rmdir() if dest_is_dir: dest_item.mkdir() creator() t = Transaction(log, dry_run=dry_run) mo = MoveFSItemOperation(t, source_item, str(dest_item)) assert t.apply().succeeded() assert source_item.exists() == dry_run assert mo.actual_destination().exists() != dry_run assert not t.rollback().succeeded() assert source_item.exists() assert not mo.actual_destination().exists()
def test_copy(self, base_dir): """Verify copy action works, also in case of failed copies""" source = (base_dir / "source_file").write_bytes(bytes(b"hello there")) dest_file = base_dir / "subdir" / "subsubdir" / "destination_file.ext" dk = CopyAction.data_key('foo') assert dk == 'package-actions.copy.foo' kvstore = KeyValueStoreModifier(dict()) kvstore.set_value(dk, 'foo') # make sure the key exists to get values based on our schema data = CopyAction.data(dk, kvstore) data.source.append(source) data.destination = dest_file for dry_run in range(2): t = Transaction(logging.root, dry_run=dry_run) # package_data is currently unused, so None works fco = CopyAction(t, 'doesntmatter', data, 'package', None) # apply assert not dest_file.isfile() assert t.apply().succeeded() assert dest_file.isfile() != dry_run assert source.isfile() # just to be sure :) # rollback t.rollback() assert not dest_file.exists() assert not dest_file.dirname().exists() assert not dest_file.dirname().dirname().exists()
def test_delete_op(self, rw_dir): # CHANGE OWNERSHIP base_dir = ((rw_dir / "dir").mkdir() / "other_file").touch() file = (rw_dir / "file").touch() # REMOVE FS ITEM for dry_run in reversed(list(range(2))): for item in (file, base_dir): t = Transaction(log, dry_run=dry_run) ro = DeleteOperation(t, item) assert item.exists() assert t.apply().succeeded() assert item.exists() == dry_run
def test_create_op(self, base_dir): destination = base_dir / "my_new_item" for dry_run in range(2): for content in (None, bytes(b"hello world")): for mode in (0o755, None): for gid in (None, os.getgid()): for uid in (None, os.getuid()): for dest_exists in range(2): assert not destination.exists() t = Transaction(log, dry_run=dry_run) co = TestCreateFSItemOperation( t, str(destination), content, mode=mode, uid=uid, gid=gid) if dest_exists: # Will ignore existing items, but cares about the type destination.mkdir() assert t.apply().succeeded() == (content is None) destination.rmdir() else: t.apply() if not (gid or uid and os.getuid() != 0 and type(t.exception()) is OSError): assert t.succeeded() assert destination.exists() != dry_run # end ignore non-root permissions issues assert not t.rollback().succeeded() assert not destination.exists()
def test_rsync(self, dest_dir): # Need to copy a bigger amount of files ... however it's dependent on time anyway, so this one # might fail in a few years raise SkipTest("This test is too slow and depends on timing, making it unreliable") source = Path(__file__).dirname().dirname() for subdir in (None, "rsync_destination"): destination = dest_dir if subdir is not None: destination /= subdir # END handle destination p = StoringProgressIndicator() for dry_run in reversed(list(range(2))): t = Transaction(log, dry_run=dry_run, progress=p) ro = RsyncOperation(t, source, destination) assert t.apply().succeeded(), "should work in any way" self._assert_rsync_state(ro) assert ro.actual_destination().exists() != dry_run assert not t.rollback().succeeded( ), "Rollback always works, evern in dry run mode where it doesn't do anything" assert not ro.actual_destination().exists() # END for each dryrun mode # abort operation - make it a bit slower t.clear() ro = RsyncOperation(t, source, destination, max_bandwidth_kb=1000) cr = ConcurrentRun(t.apply, log).start() time.sleep(0.25) assert t.is_running(), "transaction should still be running" assert ro.actual_destination().exists(), "destination dir should have been created at least" t.abort(True) assert t.is_aborting() s = time.time() assert cr.result() is t, "Waited for result, which was not what we expected" elapsed = time.time() - s assert elapsed < 1.0, "Should have joined much faster, it took %f" % elapsed assert not t.is_aborting(), "Shouldnt be in abort mode anymore after we aborted and rolled back" assert not ro.actual_destination().exists( ), "Destination should not exist any more as we triggered a rollback" assert not t.succeeded()