def test_get_trestle_project_root(tmp_dir, rand_str): """Test get_trestle_project_root method.""" project_path: pathlib.Path = pathlib.Path.joinpath(tmp_dir, rand_str) sub_path: pathlib.Path = project_path.joinpath('samples2') fs.ensure_directory(sub_path) assert sub_path.exists() and sub_path.is_dir() # create a file sub_path.joinpath('readme.md').touch() # create a data-dir and a file sub_data_dir = pathlib.Path.joinpath(sub_path, 'data') fs.ensure_directory(sub_data_dir) sub_data_dir.joinpath('readme.md').touch() assert fs.get_trestle_project_root(sub_data_dir) is None test_utils.ensure_trestle_config_dir(project_path) assert fs.get_trestle_project_root(sub_data_dir) == project_path assert fs.get_trestle_project_root( sub_data_dir.joinpath('readme.md')) == project_path assert fs.get_trestle_project_root( sub_path.joinpath('readme.md')) == project_path assert fs.get_trestle_project_root(sub_path) == project_path assert fs.get_trestle_project_root(project_path.parent) is None
def test_has_trestle_project_in_path(tmp_dir, rand_str): """Test has_trestle_project_in_path method.""" project_path: pathlib.Path = pathlib.Path.joinpath(tmp_dir, rand_str) sub_path: pathlib.Path = project_path.joinpath('samples2') fs.ensure_directory(sub_path) assert sub_path.exists() and sub_path.is_dir() # create a file sub_path.joinpath('readme.md').touch() # create a data-dir and a file sub_data_dir = pathlib.Path.joinpath(sub_path, 'data') fs.ensure_directory(sub_data_dir) # create a file sub_data_dir.joinpath('readme.md').touch() assert fs.has_trestle_project_in_path(pathlib.Path('/')) is False assert fs.has_trestle_project_in_path(sub_data_dir) is False test_utils.ensure_trestle_config_dir(project_path) assert fs.has_trestle_project_in_path(sub_data_dir) is True assert fs.has_trestle_project_in_path( sub_data_dir.joinpath('readme.md')) is True assert fs.has_trestle_project_in_path( sub_path.joinpath('readme.md')) is True assert fs.has_trestle_project_in_path(sub_path) is True assert fs.has_trestle_project_in_path(project_path.parent) is False
def test_to_origin_dir_path(tmp_dir: pathlib.Path): """Test to origin dir path function.""" # invalid trestle project would error with pytest.raises(AssertionError): trash.to_origin_dir_path(tmp_dir) test_utils.ensure_trestle_config_dir(tmp_dir) trash_dir_path = trash.to_trash_dir_path(tmp_dir) # missing trash path would error with pytest.raises(AssertionError): trash.to_origin_dir_path(trash_dir_path) fs.ensure_directory(tmp_dir / trash.TRESTLE_TRASH_DIR) origin_dir = trash.to_origin_dir_path(trash_dir_path) assert tmp_dir.absolute() == origin_dir.absolute() data_dir = tmp_dir / 'data' trash_dir_path = trash.to_trash_dir_path(data_dir) origin_dir = trash.to_origin_dir_path(trash_dir_path) assert data_dir.absolute() == origin_dir.absolute() # invalid trash path should error with pytest.raises(AssertionError): trash.to_origin_dir_path(data_dir) # trash file path should error tmp_file = tmp_dir / 'temp_file.md' trash_file_path = trash.to_trash_file_path(tmp_file) with pytest.raises(AssertionError): trash.to_origin_dir_path(trash_file_path)
def test_trash_store_dir(tmp_dir: pathlib.Path): """Test moving whole directory to trash.""" test_utils.ensure_trestle_config_dir(tmp_dir) # trash whole directory data_dir: pathlib.Path = tmp_dir / 'data' fs.ensure_directory(data_dir) readme_file: pathlib.Path = data_dir / 'readme.md' readme_file.touch() # trash with deleting original assert not trash.to_trash_dir_path(data_dir).exists() assert not trash.to_trash_file_path(readme_file).exists() trash.store_dir(data_dir, True) assert data_dir.exists() is False assert readme_file.exists() is False assert trash.to_trash_dir_path(data_dir).exists() assert trash.to_trash_file_path(readme_file).exists() # trash without deleting original fs.ensure_directory(data_dir) readme_file.touch() trash.store_dir(data_dir, False) assert data_dir.exists() assert readme_file.exists() assert trash.to_trash_dir_path(data_dir).exists() assert trash.to_trash_file_path(readme_file).exists()
def test_target_dups(tmp_dir): """Test model validation.""" content_type = FileContentType.YAML models_dir_name = test_utils.TARGET_DEFS_DIR model_ref = ostarget.TargetDefinition test_utils.ensure_trestle_config_dir(tmp_dir) file_ext = FileContentType.to_file_extension(content_type) models_full_path = tmp_dir / models_dir_name / 'my_test_model' model_alias = utils.classname_to_alias(model_ref.__name__, 'json') model_def_file = models_full_path / f'{model_alias}{file_ext}' fs.ensure_directory(models_full_path) shutil.copyfile('tests/data/yaml/good_target.yaml', model_def_file) testcmd = f'trestle validate -f {model_def_file} -m duplicates -i uuid' with patch.object(sys, 'argv', testcmd.split()): with pytest.raises(SystemExit) as pytest_wrapped_e: cli.run() assert pytest_wrapped_e.type == SystemExit assert pytest_wrapped_e.value.code is None shutil.copyfile('tests/data/yaml/bad_target_dup_uuid.yaml', model_def_file) testcmd = f'trestle validate -f {model_def_file} -m duplicates -i uuid' with patch.object(sys, 'argv', testcmd.split()): with pytest.raises(TrestleValidationError) as pytest_wrapped_e: cli.run() assert pytest_wrapped_e.type == TrestleValidationError
def test_ensure_directory(tmpdir): """Test ensure_directory function.""" # Happy path fs.ensure_directory(tmpdir) # Unhappy path with pytest.raises(AssertionError): fs.ensure_directory(__file__)
def test_remove_path_file(tmp_dir: pathlib.Path): """Test remove path with content clear option.""" tmp_data_dir = tmp_dir.joinpath('data') tmp_data_file = tmp_data_dir.joinpath('readme.md') fs.ensure_directory(tmp_data_dir) # not a valid trestle project should error in constructor with pytest.raises(TrestleError): rpa = RemovePathAction(tmp_data_file) # create trestle project test_utils.ensure_trestle_config_dir(tmp_dir) rpa = RemovePathAction(tmp_data_file) # missing file should error with pytest.raises(FileNotFoundError): rpa.execute() # write some content in the file file_pos = 0 dummy_data = 'DUMMY DATA' with open(tmp_data_file, 'a+') as fp: fp.write(dummy_data) file_pos = fp.tell() assert file_pos >= 0 # remove file tmp_data_file_trash = trash.to_trash_file_path(tmp_data_file) assert tmp_data_file_trash.exists() is False rpa.execute() tmp_data_file_trash.exists() assert tmp_data_file.exists() is False # rollback file rpa.rollback() tmp_data_file_trash.exists() tmp_data_file.exists() with open(tmp_data_file, 'a+') as fp: assert file_pos == fp.tell() # remove dir rpa = RemovePathAction(tmp_data_dir) tmp_data_trash = trash.to_trash_dir_path(tmp_data_dir) tmp_data_file_trash = trash.to_trash_file_path(tmp_data_file) if tmp_data_trash.exists(): tmp_data_trash.rmdir() rpa.execute() assert tmp_data_trash.exists() assert tmp_data_file_trash.exists() assert tmp_data_file.exists() is False assert tmp_data_dir.exists() is False # rollback dir rpa.rollback() assert tmp_data_trash.exists() is False assert tmp_data_file_trash.exists() is False assert tmp_data_file.exists() assert tmp_data_dir.exists()
def tmp_dir(rand_str) -> pathlib.Path: """Return a path for a tmp directory.""" tmp_dir = pathlib.Path.joinpath(test_utils.BASE_TMP_DIR, rand_str) assert tmp_dir.parent == test_utils.BASE_TMP_DIR fs.ensure_directory(tmp_dir) yield tmp_dir # tear down test_utils.clean_tmp_dir(tmp_dir)
def test_split_run_failure(tmp_dir, sample_target_def: ostarget.TargetDefinition): """Test split run failure.""" # prepare trestle project dir with the file target_def_dir: pathlib.Path = tmp_dir / 'target-definitions' / 'mytarget' target_def_file: pathlib.Path = target_def_dir / 'target-definition.yaml' fs.ensure_directory(target_def_dir) sample_target_def.oscal_write(target_def_file) invalid_file = target_def_dir / 'invalid.file' invalid_file.touch() cwd = os.getcwd() os.chdir(target_def_dir) # not a trestle project testargs = [ 'trestle', 'split', '-f', 'target-definition.yaml', '-e', 'target-definition.metadata, target-definition.targets.*' ] with patch.object(sys, 'argv', testargs): with pytest.raises(TrestleError): Trestle().run() # create trestle project test_utils.ensure_trestle_config_dir(tmp_dir) # no file specified testargs = [ 'trestle', 'split', '-e', 'target-definition.metadata, target-definition.targets.*' ] with patch.object(sys, 'argv', testargs): with pytest.raises(TrestleError): Trestle().run() # check with missing file testargs = [ 'trestle', 'split', '-f', 'missing.yaml', '-e', 'target-definition.metadata, target-definition.targets.*' ] with patch.object(sys, 'argv', testargs): with pytest.raises(TrestleError): Trestle().run() # check with incorrect file type testargs = [ 'trestle', 'split', '-f', invalid_file.name, '-e', 'target-definition.metadata, target-definition.targets.*' ] with patch.object(sys, 'argv', testargs): with pytest.raises(TrestleError): Trestle().run() os.chdir(cwd)
def test_to_trash_path(tmp_dir: pathlib.Path): """Test to trash path function.""" data_dir: pathlib.Path = tmp_dir / 'data' fs.ensure_directory(data_dir) readme_file: pathlib.Path = data_dir / 'readme.md' readme_file.touch() test_utils.ensure_trestle_config_dir(tmp_dir) assert trash.to_trash_file_path(readme_file) == trash.to_trash_path(readme_file) assert trash.to_trash_dir_path(readme_file.parent) == trash.to_trash_path(readme_file.parent)
def test_to_origin_file_path(tmp_dir: pathlib.Path): """Test to origin file path function.""" test_utils.ensure_trestle_config_dir(tmp_dir) fs.ensure_directory(tmp_dir / trash.TRESTLE_TRASH_DIR) tmp_file = tmp_dir / 'temp_file.md' trash_file_path = trash.to_trash_file_path(tmp_file) origin_file_path = trash.to_origin_file_path(trash_file_path) assert tmp_file.absolute() == origin_file_path.absolute() with pytest.raises(AssertionError): trash.to_origin_file_path(tmp_file)
def test_to_origin_path(tmp_dir: pathlib.Path): """Test to origin path function.""" test_utils.ensure_trestle_config_dir(tmp_dir) fs.ensure_directory(tmp_dir / trash.TRESTLE_TRASH_DIR) tmp_file = tmp_dir / 'temp_file.md' trash_file_path = trash.to_trash_file_path(tmp_file) origin_file_path = trash.to_origin_path(trash_file_path) assert tmp_file.absolute() == origin_file_path.absolute() data_dir = tmp_dir / 'data' trash_dir_path = trash.to_trash_dir_path(data_dir) origin_dir = trash.to_origin_path(trash_dir_path) assert data_dir.absolute() == origin_dir.absolute()
def test_get_trash_root(tmp_dir: pathlib.Path): """Test get trash root function.""" assert trash.get_trash_root(pathlib.Path('')) is None readme_file: pathlib.Path = tmp_dir / 'data/readme.md' assert trash.get_trash_root(readme_file) is None test_utils.ensure_trestle_config_dir(tmp_dir) trash_root = tmp_dir / trash.TRESTLE_TRASH_DIR fs.ensure_directory(trash_root) trash_file_path = trash.to_trash_file_path(readme_file) found_root = trash.get_trash_root(trash_file_path) assert trash_root.absolute() == found_root.absolute()
def prepare_trestle_project_dir( tmp_dir, content_type: FileContentType, model_obj: OscalBaseModel, models_dir_name: str ): """Prepare a temp directory with an example OSCAL model.""" ensure_trestle_config_dir(tmp_dir) model_alias = utils.classname_to_alias(model_obj.__class__.__name__, 'json') file_ext = FileContentType.to_file_extension(content_type) models_full_path = tmp_dir / models_dir_name / 'my_test_model' model_def_file = models_full_path / f'{model_alias}{file_ext}' fs.ensure_directory(models_full_path) model_obj.oscal_write(model_def_file) return models_full_path, model_def_file
def test_trash_recover_file(tmp_dir): """Test recover trashed file.""" test_utils.ensure_trestle_config_dir(tmp_dir) data_dir: pathlib.Path = tmp_dir / 'data' fs.ensure_directory(data_dir) readme_file: pathlib.Path = data_dir / 'readme.md' readme_file.touch() trash.store_file(readme_file, True) assert data_dir.exists() assert readme_file.exists() is False trash.recover_file(readme_file) assert data_dir.exists() assert readme_file.exists()
def test_to_trash_file_path(tmp_dir: pathlib.Path): """Test to_trash_file_path method.""" tmp_file: pathlib.Path = tmp_dir / 'tmp_file.md' tmp_file.touch() data_dir: pathlib.Path = tmp_dir / 'data' fs.ensure_directory(data_dir) readme_file: pathlib.Path = data_dir / 'readme.md' readme_file.touch() with pytest.raises(AssertionError): trash.to_trash_file_path(readme_file) test_utils.ensure_trestle_config_dir(tmp_dir) assert trash.to_trash_file_path(tmp_file) is not None assert trash.to_trash_file_path(tmp_file).parent == trash.to_trash_dir_path(tmp_dir) assert trash.to_trash_file_path(readme_file).parent.name == f'data{trash.TRESTLE_TRASH_DIR_EXT}'
def test_to_trash_dir_path(tmp_dir: pathlib.Path): """Test to_trash_dir_path method.""" tmp_file: pathlib.Path = tmp_dir / 'tmp_file.md' tmp_file.touch() data_dir: pathlib.Path = tmp_dir / 'data' fs.ensure_directory(data_dir) readme_file: pathlib.Path = data_dir / 'readme.md' readme_file.touch() with pytest.raises(AssertionError): trash.to_trash_file_path(readme_file) test_utils.ensure_trestle_config_dir(tmp_dir) # trestle root will use the trash root assert trash.to_trash_dir_path(tmp_dir).name == pathlib.Path(trash.TRESTLE_TRASH_DIR).name assert trash.to_trash_dir_path(tmp_dir).parent.name == pathlib.Path(trash.TRESTLE_TRASH_DIR).parent.name # any directory under trestle rool will have the trash as the parent assert trash.to_trash_dir_path(data_dir).parent.name == pathlib.Path(trash.TRESTLE_TRASH_DIR).name
def test_trash_store(tmp_dir): """Test trash store function.""" test_utils.ensure_trestle_config_dir(tmp_dir) data_dir: pathlib.Path = tmp_dir / 'data' fs.ensure_directory(data_dir) readme_file: pathlib.Path = data_dir / 'readme.md' readme_file.touch() # trash using common trash method trash.store(readme_file, True) assert readme_file.exists() is False assert data_dir.exists() assert trash.to_trash_dir_path(data_dir).exists() assert trash.to_trash_file_path(readme_file).exists() # trash whole directory fs.ensure_directory(data_dir) readme_file.touch() trash.store(data_dir, True) assert data_dir.exists() is False assert readme_file.exists() is False assert trash.to_trash_dir_path(data_dir).exists() assert trash.to_trash_file_path(readme_file).exists()
def test_clean_project_sub_path(tmp_dir, rand_str): """Test clean_project_sub_path method.""" project_path: pathlib.Path = pathlib.Path.joinpath(tmp_dir, rand_str) sub_path: pathlib.Path = project_path.joinpath('samples') fs.ensure_directory(sub_path) assert sub_path.exists() and sub_path.is_dir() # create a file sub_path.joinpath('readme.md').touch() # create a data-dir and a file sub_data_dir = pathlib.Path.joinpath(sub_path, 'data') sub_data_dir_file = sub_data_dir.joinpath('readme.md') fs.ensure_directory(sub_data_dir) # create a file sub_data_dir_file.touch() try: # not having .trestle directory at the project root or tmp_dir should fail fs.clean_project_sub_path(sub_path) except TrestleError: pass test_utils.ensure_trestle_config_dir(project_path) fs.clean_project_sub_path(sub_data_dir_file) assert not sub_data_dir_file.exists() # create the file again with open(sub_data_dir_file, 'w+'): pass # clean the sub_path in the trestle project fs.clean_project_sub_path(sub_path) assert not sub_path.exists()
def prepare_target_def_file(): test_utils.ensure_trestle_config_dir(tmp_dir) fs.ensure_directory(target_def_dir) sample_target_def.oscal_write(target_def_file)
def ensure_trestle_config_dir(sub_dir: pathlib.Path): """Ensure that the sub_dir has trestle config dir.""" trestle_dir = pathlib.Path.joinpath(sub_dir, const.TRESTLE_CONFIG_DIR) fs.ensure_directory(trestle_dir)
def test_parse_element_arg(tmp_dir): """Unit test parse a single element arg.""" with pytest.raises(TrestleError): cmd_utils.parse_element_arg('target-definition', False) with pytest.raises(TrestleError): cmd_utils.parse_element_arg('*.target', False) with pytest.raises(TrestleError): cmd_utils.parse_element_arg('*.*', False) with pytest.raises(TrestleError): cmd_utils.parse_element_arg('*', False) with pytest.raises(TrestleError): cmd_utils.parse_element_arg('target-definition.targets.*.*', False) element_arg = 'catalog.groups.*' expected_paths: List[ElementPath] = prepare_expected_element_paths( ['catalog.groups.*']) element_paths: List[ElementPath] = cmd_utils.parse_element_arg( element_arg, False) assert expected_paths == element_paths # contextual path test_utils.ensure_trestle_config_dir(tmp_dir) catalog_split_dir = tmp_dir / 'catalogs/nist800-53/catalog' fs.ensure_directory(catalog_split_dir) cur_dir = pathlib.Path.cwd() os.chdir(catalog_split_dir) element_arg = 'groups.*' expected_paths: List[ElementPath] = prepare_expected_element_paths( ['groups.*']) element_paths: List[ElementPath] = cmd_utils.parse_element_arg( element_arg, True) assert expected_paths == element_paths os.chdir(cur_dir) element_arg = 'catalog.metadata.parties.*' expected_paths: List[ElementPath] = prepare_expected_element_paths( ['catalog.metadata', 'metadata.parties.*']) element_paths: List[ElementPath] = cmd_utils.parse_element_arg( element_arg, False) assert expected_paths == element_paths element_arg = 'target-definition.targets' expected_paths: List[ElementPath] = prepare_expected_element_paths( ['target-definition.targets']) element_paths: List[ElementPath] = cmd_utils.parse_element_arg( element_arg, False) assert expected_paths == element_paths element_arg = 'target-definition.targets.*' expected_paths: List[ElementPath] = prepare_expected_element_paths( ['target-definition.targets.*']) element_paths: List[ElementPath] = cmd_utils.parse_element_arg( element_arg, False) assert expected_paths == element_paths element_arg = 'catalog.groups.*.controls.*.controls.*' p1 = ElementPath('catalog.groups.*') p2 = ElementPath('group.controls.*', parent_path=p1) p3 = ElementPath('control.controls.*', parent_path=p2) expected_paths: List[ElementPath] = [p1, p2, p3] element_paths: List[ElementPath] = cmd_utils.parse_element_arg( element_arg, False) assert expected_paths == element_paths element_arg = 'catalog.groups.*.controls' p1 = ElementPath('catalog.groups.*') p2 = ElementPath('group.controls', parent_path=p1) expected_paths: List[ElementPath] = [p1, p2] element_paths: List[ElementPath] = cmd_utils.parse_element_arg( element_arg, False) assert expected_paths == element_paths element_arg = 'target-definition.targets.*.target-control-implementations' p1 = ElementPath('target-definition.targets.*') p2 = ElementPath('target.target-control-implementations', parent_path=p1) expected_paths: List[ElementPath] = [p1, p2] element_paths: List[ElementPath] = cmd_utils.parse_element_arg( element_arg, False) assert expected_paths == element_paths element_arg = 'target-definition.targets.*.target-control-implementations.*' p1 = ElementPath('target-definition.targets.*') p2 = ElementPath('target.target-control-implementations.*', parent_path=p1) expected_paths: List[ElementPath] = [p1, p2] element_paths: List[ElementPath] = cmd_utils.parse_element_arg( element_arg, False) assert expected_paths == element_paths # use contextual path for parsing path test_utils.ensure_trestle_config_dir(tmp_dir) target_def_dir: pathlib.Path = tmp_dir / 'target-definitions/mytarget/' fs.ensure_directory(target_def_dir) cur_dir = pathlib.Path.cwd() os.chdir(target_def_dir) element_arg = 'metadata.parties.*' expected_paths: List[ElementPath] = prepare_expected_element_paths( ['metadata.parties.*']) element_paths: List[ElementPath] = cmd_utils.parse_element_arg( element_arg, True) assert expected_paths == element_paths os.chdir(cur_dir)