diff --git a/src/primaite/simulator/file_system/file_system.py b/src/primaite/simulator/file_system/file_system.py index b1688045..41f02270 100644 --- a/src/primaite/simulator/file_system/file_system.py +++ b/src/primaite/simulator/file_system/file_system.py @@ -94,7 +94,7 @@ class FileSystem(SimComponent): :param markdown: Flag indicating if output should be in markdown format. :param full: Flag indicating if to show full files. """ - headers = ["Folder", "Size"] + headers = ["Folder", "Size", "Deleted"] if full: headers[0] = "File Path" table = PrettyTable(headers) @@ -102,12 +102,17 @@ class FileSystem(SimComponent): table.set_style(MARKDOWN) table.align = "l" table.title = f"{self.sys_log.hostname} File System" - for folder in self.folders.values(): + folders = {**self.folders, **self.deleted_folders} + for folder in folders.values(): if not full: - table.add_row([folder.name, folder.size_str]) + table.add_row([folder.name, folder.size_str, folder.deleted]) else: - for file in folder.files.values(): - table.add_row([file.path, file.size_str]) + files = {**folder.files, **folder.deleted_files} + if not files: + table.add_row([folder.name, folder.size_str, folder.deleted]) + else: + for file in files.values(): + table.add_row([file.path, file.size_str, file.deleted]) if full: print(table.get_string(sortby="File Path")) else: @@ -380,6 +385,7 @@ class FileSystem(SimComponent): """ state = super().describe_state() state["folders"] = {folder.name: folder.describe_state() for folder in self.folders.values()} + state["deleted_folders"] = {folder.name: folder.describe_state() for folder in self.deleted_folders.values()} return state def apply_timestep(self, timestep: int) -> None: diff --git a/src/primaite/simulator/file_system/folder.py b/src/primaite/simulator/file_system/folder.py index 67e93e16..f0d55ef8 100644 --- a/src/primaite/simulator/file_system/folder.py +++ b/src/primaite/simulator/file_system/folder.py @@ -76,13 +76,13 @@ class Folder(FileSystemItemABC): :param markdown: Whether to display the table in Markdown format or not. Default is `False`. """ - table = PrettyTable(["File", "Size"]) + table = PrettyTable(["File", "Size", "Deleted"]) if markdown: table.set_style(MARKDOWN) table.align = "l" table.title = f"{self.sys_log.hostname} File System Folder ({self.name})" for file in self.files.values(): - table.add_row([file.name, file.size_str]) + table.add_row([file.name, file.size_str, file.deleted]) print(table.get_string(sortby="File")) @property diff --git a/tests/unit_tests/_primaite/_simulator/_file_system/test_file_actions.py b/tests/unit_tests/_primaite/_simulator/_file_system/test_file_actions.py index f43c6b22..44354325 100644 --- a/tests/unit_tests/_primaite/_simulator/_file_system/test_file_actions.py +++ b/tests/unit_tests/_primaite/_simulator/_file_system/test_file_actions.py @@ -55,7 +55,23 @@ def test_file_repair_request(populated_file_system): def test_file_restore_request(populated_file_system): - pass + """Test that an agent can request that a file can be restored.""" + fs, folder, file = populated_file_system + assert fs.get_file_by_id(folder_uuid=folder.uuid, file_uuid=file.uuid) is not None + + fs.apply_request(request=["delete", "file", folder.uuid, file.uuid]) + assert fs.get_file(folder_name=folder.name, file_name=file.name) is None + assert fs.get_file_by_id(folder_uuid=folder.uuid, file_uuid=file.uuid, include_deleted=True).deleted is True + + fs.apply_request(request=["restore", "file", folder.uuid, file.uuid]) + assert fs.get_file(folder_name=folder.name, file_name=file.name) is not None + assert fs.get_file(folder_name=folder.name, file_name=file.name).deleted is False + + fs.apply_request(request=["file", file.uuid, "corrupt"]) + assert fs.get_file(folder_name=folder.name, file_name=file.name).health_status == FileSystemItemHealthStatus.CORRUPT + + fs.apply_request(request=["restore", "file", folder.uuid, file.uuid]) + assert fs.get_file(folder_name=folder.name, file_name=file.name).health_status == FileSystemItemHealthStatus.GOOD def test_file_corrupt_request(populated_file_system): diff --git a/tests/unit_tests/_primaite/_simulator/_file_system/test_file_system.py b/tests/unit_tests/_primaite/_simulator/_file_system/test_file_system.py index 03c6ad12..86baa1f8 100644 --- a/tests/unit_tests/_primaite/_simulator/_file_system/test_file_system.py +++ b/tests/unit_tests/_primaite/_simulator/_file_system/test_file_system.py @@ -18,6 +18,8 @@ def test_create_folder_and_file(file_system): assert file_system.get_folder("test_folder").get_file("test_file.txt") + file_system.show(full=True) + def test_create_file_no_folder(file_system): """Tests that creating a file without a folder creates a folder and sets that as the file's parent.""" @@ -27,6 +29,8 @@ def test_create_file_no_folder(file_system): assert file_system.get_folder("root").get_file("test_file.txt").file_type == FileType.TXT assert file_system.get_folder("root").get_file("test_file.txt").size == 10 + file_system.show(full=True) + def test_delete_file(file_system): """Tests that a file can be deleted.""" @@ -39,6 +43,8 @@ def test_delete_file(file_system): assert len(file_system.get_folder("root").files) == 0 assert len(file_system.get_folder("root").deleted_files) == 1 + file_system.show(full=True) + def test_delete_non_existent_file(file_system): """Tests deleting a non existent file.""" @@ -56,6 +62,8 @@ def test_delete_non_existent_file(file_system): # The folder should still have 1 file assert len(file_system.get_folder("root").files) == 1 + file_system.show(full=True) + def test_delete_folder(file_system): file_system.create_folder(folder_name="test_folder") @@ -66,6 +74,8 @@ def test_delete_folder(file_system): assert len(file_system.deleted_folders) == 1 + file_system.show(full=True) + def test_create_duplicate_folder(file_system): """Test that creating a duplicate folder throws exception.""" @@ -78,6 +88,8 @@ def test_create_duplicate_folder(file_system): assert len(file_system.folders) is 2 + file_system.show(full=True) + def test_create_duplicate_file(file_system): """Test that creating a duplicate file throws exception.""" @@ -94,6 +106,8 @@ def test_create_duplicate_file(file_system): assert len(file_system.get_folder("test_folder").files) == 1 + file_system.show(full=True) + def test_deleting_a_non_existent_folder(file_system): file_system.create_folder(folder_name="test_folder") @@ -102,6 +116,8 @@ def test_deleting_a_non_existent_folder(file_system): file_system.delete_folder(folder_name="does not exist!") assert len(file_system.folders) == 2 + file_system.show(full=True) + def test_deleting_root_folder_fails(file_system): assert len(file_system.folders) == 1 @@ -109,6 +125,8 @@ def test_deleting_root_folder_fails(file_system): file_system.delete_folder(folder_name="root") assert len(file_system.folders) == 1 + file_system.show(full=True) + def test_move_file(file_system): """Tests the file move function.""" @@ -127,6 +145,8 @@ def test_move_file(file_system): assert len(file_system.get_folder("dst_folder").files) == 1 assert file_system.get_file("dst_folder", "test_file.txt").uuid == original_uuid + file_system.show(full=True) + def test_copy_file(file_system): """Tests the file copy function.""" @@ -145,6 +165,8 @@ def test_copy_file(file_system): assert len(file_system.get_folder("dst_folder").files) == 1 assert file_system.get_file("dst_folder", "test_file.txt").uuid != original_uuid + file_system.show(full=True) + def test_get_file(file_system): """Test that files can be retrieved.""" @@ -162,6 +184,8 @@ def test_get_file(file_system): file_system.delete_folder(folder_name="test_folder") assert file_system.get_file_by_id(file_uuid=file2.uuid, include_deleted=True) is not None + file_system.show(full=True) + @pytest.mark.skip(reason="Skipping until we tackle serialisation") def test_serialisation(file_system): @@ -172,3 +196,5 @@ def test_serialisation(file_system): deserialised_file_sys = FileSystem.model_validate_json(serialised_file_sys) assert file_system.model_dump_json() == deserialised_file_sys.model_dump_json() + + file_system.show(full=True) diff --git a/tests/unit_tests/_primaite/_simulator/_file_system/test_file_system_actions.py b/tests/unit_tests/_primaite/_simulator/_file_system/test_file_system_actions.py index 29642a8d..30c0938e 100644 --- a/tests/unit_tests/_primaite/_simulator/_file_system/test_file_system_actions.py +++ b/tests/unit_tests/_primaite/_simulator/_file_system/test_file_system_actions.py @@ -23,6 +23,8 @@ def test_file_delete_request(populated_file_system): fs.apply_request(request=["delete", "file", folder.uuid, file.uuid]) assert fs.get_file(folder_name=folder.name, file_name=file.name) is None + fs.show(full=True) + def test_folder_delete_request(populated_file_system): """Test that an agent can request a folder deletion.""" @@ -34,87 +36,4 @@ def test_folder_delete_request(populated_file_system): assert fs.get_folder_by_id(folder_uuid=folder.uuid) is None assert fs.get_file_by_id(folder_uuid=folder.uuid, file_uuid=file.uuid) is None - -def test_file_restore_request(populated_file_system): - """Test that an agent can request that a file can be restored.""" - fs, folder, file = populated_file_system - assert fs.get_file_by_id(folder_uuid=folder.uuid, file_uuid=file.uuid) is not None - - fs.apply_request(request=["delete", "file", folder.uuid, file.uuid]) - assert fs.get_file(folder_name=folder.name, file_name=file.name) is None - assert fs.get_file_by_id(folder_uuid=folder.uuid, file_uuid=file.uuid, include_deleted=True).deleted is True - - fs.apply_request(request=["restore", "file", folder.uuid, file.uuid]) - assert fs.get_file(folder_name=folder.name, file_name=file.name) is not None - assert fs.get_file(folder_name=folder.name, file_name=file.name).deleted is False - - fs.apply_request(request=["file", file.uuid, "corrupt"]) - assert fs.get_file(folder_name=folder.name, file_name=file.name).health_status == FileSystemItemHealthStatus.CORRUPT - - fs.apply_request(request=["restore", "file", folder.uuid, file.uuid]) - assert fs.get_file(folder_name=folder.name, file_name=file.name).health_status == FileSystemItemHealthStatus.GOOD - - -def test_folder_restore_request(populated_file_system): - """Test that an agent can request that a folder can be restored.""" - fs, folder, file = populated_file_system - assert fs.get_folder_by_id(folder_uuid=folder.uuid) is not None - assert fs.get_file_by_id(folder_uuid=folder.uuid, file_uuid=file.uuid) is not None - - # delete folder - fs.apply_request(request=["delete", "folder", folder.uuid]) - assert fs.get_folder(folder_name=folder.name) is None - assert fs.get_folder_by_id(folder_uuid=folder.uuid, include_deleted=True).deleted is True - - assert fs.get_file(folder_name=folder.name, file_name=file.name) is None - assert fs.get_file_by_id(folder_uuid=folder.uuid, file_uuid=file.uuid, include_deleted=True).deleted is True - - # restore folder - fs.apply_request(request=["restore", "folder", folder.uuid]) - fs.apply_timestep(timestep=0) - assert fs.get_folder(folder_name=folder.name) is not None - assert ( - fs.get_folder_by_id(folder_uuid=folder.uuid, include_deleted=True).health_status - == FileSystemItemHealthStatus.RESTORING - ) - assert fs.get_folder_by_id(folder_uuid=folder.uuid, include_deleted=True).deleted is False - - assert fs.get_file(folder_name=folder.name, file_name=file.name) is None - assert fs.get_file_by_id(folder_uuid=folder.uuid, file_uuid=file.uuid, include_deleted=True).deleted is True - - fs.apply_timestep(timestep=1) - fs.apply_timestep(timestep=2) - - assert fs.get_file(folder_name=folder.name, file_name=file.name) is not None - assert ( - fs.get_file(folder_name=folder.name, file_name=file.name).health_status - is not FileSystemItemHealthStatus.RESTORING - ) - assert fs.get_file(folder_name=folder.name, file_name=file.name).deleted is False - - assert fs.get_file(folder_name=folder.name, file_name=file.name) is not None - assert fs.get_file_by_id(folder_uuid=folder.uuid, file_uuid=file.uuid, include_deleted=True).deleted is False - - # corrupt folder - fs.apply_request(request=["folder", folder.uuid, "corrupt"]) - assert fs.get_folder(folder_name=folder.name).health_status == FileSystemItemHealthStatus.CORRUPT - assert fs.get_file(folder_name=folder.name, file_name=file.name).health_status == FileSystemItemHealthStatus.CORRUPT - - # restore folder - fs.apply_request(request=["restore", "folder", folder.uuid]) - fs.apply_timestep(timestep=0) - assert fs.get_folder(folder_name=folder.name).health_status == FileSystemItemHealthStatus.RESTORING - assert fs.get_file(folder_name=folder.name, file_name=file.name).health_status == FileSystemItemHealthStatus.CORRUPT - - fs.apply_timestep(timestep=1) - fs.apply_timestep(timestep=2) - - assert fs.get_file(folder_name=folder.name, file_name=file.name) is not None - assert ( - fs.get_file(folder_name=folder.name, file_name=file.name).health_status - is not FileSystemItemHealthStatus.RESTORING - ) - assert fs.get_file(folder_name=folder.name, file_name=file.name).deleted is False - - assert fs.get_file(folder_name=folder.name, file_name=file.name) is not None - assert fs.get_file_by_id(folder_uuid=folder.uuid, file_uuid=file.uuid, include_deleted=True).deleted is False + fs.show(full=True) diff --git a/tests/unit_tests/_primaite/_simulator/_file_system/test_folder_actions.py b/tests/unit_tests/_primaite/_simulator/_file_system/test_folder_actions.py index 9be4d5d1..86db147a 100644 --- a/tests/unit_tests/_primaite/_simulator/_file_system/test_folder_actions.py +++ b/tests/unit_tests/_primaite/_simulator/_file_system/test_folder_actions.py @@ -74,7 +74,68 @@ def test_folder_repair_request(populated_file_system): def test_folder_restore_request(populated_file_system): - pass + """Test that an agent can request that a folder can be restored.""" + fs, folder, file = populated_file_system + assert fs.get_folder_by_id(folder_uuid=folder.uuid) is not None + assert fs.get_file_by_id(folder_uuid=folder.uuid, file_uuid=file.uuid) is not None + + # delete folder + fs.apply_request(request=["delete", "folder", folder.uuid]) + assert fs.get_folder(folder_name=folder.name) is None + assert fs.get_folder_by_id(folder_uuid=folder.uuid, include_deleted=True).deleted is True + + assert fs.get_file(folder_name=folder.name, file_name=file.name) is None + assert fs.get_file_by_id(folder_uuid=folder.uuid, file_uuid=file.uuid, include_deleted=True).deleted is True + + # restore folder + fs.apply_request(request=["restore", "folder", folder.uuid]) + fs.apply_timestep(timestep=0) + assert fs.get_folder(folder_name=folder.name) is not None + assert ( + fs.get_folder_by_id(folder_uuid=folder.uuid, include_deleted=True).health_status + == FileSystemItemHealthStatus.RESTORING + ) + assert fs.get_folder_by_id(folder_uuid=folder.uuid, include_deleted=True).deleted is False + + assert fs.get_file(folder_name=folder.name, file_name=file.name) is None + assert fs.get_file_by_id(folder_uuid=folder.uuid, file_uuid=file.uuid, include_deleted=True).deleted is True + + fs.apply_timestep(timestep=1) + fs.apply_timestep(timestep=2) + + assert fs.get_file(folder_name=folder.name, file_name=file.name) is not None + assert ( + fs.get_file(folder_name=folder.name, file_name=file.name).health_status + is not FileSystemItemHealthStatus.RESTORING + ) + assert fs.get_file(folder_name=folder.name, file_name=file.name).deleted is False + + assert fs.get_file(folder_name=folder.name, file_name=file.name) is not None + assert fs.get_file_by_id(folder_uuid=folder.uuid, file_uuid=file.uuid, include_deleted=True).deleted is False + + # corrupt folder + fs.apply_request(request=["folder", folder.uuid, "corrupt"]) + assert fs.get_folder(folder_name=folder.name).health_status == FileSystemItemHealthStatus.CORRUPT + assert fs.get_file(folder_name=folder.name, file_name=file.name).health_status == FileSystemItemHealthStatus.CORRUPT + + # restore folder + fs.apply_request(request=["restore", "folder", folder.uuid]) + fs.apply_timestep(timestep=0) + assert fs.get_folder(folder_name=folder.name).health_status == FileSystemItemHealthStatus.RESTORING + assert fs.get_file(folder_name=folder.name, file_name=file.name).health_status == FileSystemItemHealthStatus.CORRUPT + + fs.apply_timestep(timestep=1) + fs.apply_timestep(timestep=2) + + assert fs.get_file(folder_name=folder.name, file_name=file.name) is not None + assert ( + fs.get_file(folder_name=folder.name, file_name=file.name).health_status + is not FileSystemItemHealthStatus.RESTORING + ) + assert fs.get_file(folder_name=folder.name, file_name=file.name).deleted is False + + assert fs.get_file(folder_name=folder.name, file_name=file.name) is not None + assert fs.get_file_by_id(folder_uuid=folder.uuid, file_uuid=file.uuid, include_deleted=True).deleted is False def test_folder_corrupt_request(populated_file_system):