def test_instance_no_header(testdata_dir: pathlib.Path, tmp_trestle_dir: pathlib.Path, monkeypatch: MonkeyPatch) -> None: """Test behaviour when validating instance with no header.""" task_template_folder = tmp_trestle_dir / '.trestle/author/test_task/' test_template_folder = testdata_dir / 'author/headers/good_templates' test_instances_folder = testdata_dir / 'author/headers/empty_headers' task_instance_folder = tmp_trestle_dir / 'test_task' shutil.copytree(test_template_folder, task_template_folder) # copy all files shutil.copytree(test_instances_folder, task_instance_folder) command_string_validate_content = 'trestle author headers validate -tn test_task' monkeypatch.setattr(sys, 'argv', command_string_validate_content.split()) rc = Trestle().run() assert rc == 3 command_string_validate_content = 'trestle author headers validate -tn test_task -tv 0.0.1' monkeypatch.setattr(sys, 'argv', command_string_validate_content.split()) rc = Trestle().run() assert rc == 3 command_string_validate_content = 'trestle author headers validate -tv 0.0.1' monkeypatch.setattr(sys, 'argv', command_string_validate_content.split()) rc = Trestle().run() assert rc == 1
def test_run_failure_plan_execute(tmp_path: pathlib.Path, sample_catalog_minimal: Catalog, monkeypatch: MonkeyPatch, caplog: pytest.LogCaptureFixture): """Test failure plan execute() in _run on RemoveCmd.""" # Plant this specific logged error for failing execution in mock_execute: logged_error = 'fail_execute' def mock_execute(*args, **kwargs): raise err.TrestleError(logged_error) # Create a temporary file as a valid arg for trestle remove: content_type = FileContentType.JSON catalog_def_dir, catalog_def_file = test_utils.prepare_trestle_project_dir( tmp_path, content_type, sample_catalog_minimal, test_utils.CATALOGS_DIR) monkeypatch.chdir(tmp_path) # Add remarks here, so it is a valid removal target, testargs = [ 'trestle', 'create', '-f', str(catalog_def_file), '-e', 'catalog.metadata.remarks' ] monkeypatch.setattr(sys, 'argv', testargs) Trestle().run() # .. then attempt to remove it here, but mocking a failed execute: testargs = [ 'trestle', 'remove', '-f', str(catalog_def_file), '-e', 'catalog.metadata.remarks' ] monkeypatch.setattr(Plan, 'execute', mock_execute) monkeypatch.setattr(sys, 'argv', testargs) caplog.clear() rc = Trestle().run() assert rc > 0
def test_broken_args(tmp_trestle_dir: pathlib.Path) -> None: """Test behaviour on broken arguments.""" # must be done using sys patching. testargs_root = ['trestle', 'create'] with mock.patch.object(sys, 'argv', testargs_root): with pytest.raises(SystemExit) as pytest_wrapped_e: Trestle().run() assert pytest_wrapped_e.type == SystemExit assert pytest_wrapped_e.value.code > 0 testargs = testargs_root + ['catalog'] # missing command with mock.patch.object(sys, 'argv', testargs): with pytest.raises(SystemExit) as pytest_wrapped_e: Trestle().run() assert pytest_wrapped_e.type == SystemExit assert pytest_wrapped_e.value.code > 0 # missing mandatory args testargs = testargs + ['-x', 'json'] with mock.patch.object(sys, 'argv', testargs): with pytest.raises(SystemExit) as pytest_wrapped_e: Trestle().run() assert pytest_wrapped_e.type == SystemExit assert pytest_wrapped_e.value.code > 0 testargs = testargs + ['-n', 'name'] # correct behavior with mock.patch.object(sys, 'argv', testargs): rc = Trestle().run() assert rc == 0 # correct behavior testargs[2] = 'bad_name' with mock.patch.object(sys, 'argv', testargs): with pytest.raises(SystemExit) as pytest_wrapped_e: Trestle().run() assert pytest_wrapped_e.type == SystemExit assert pytest_wrapped_e.value.code > 0
def test_broken_args(tmp_trestle_dir: pathlib.Path, monkeypatch: MonkeyPatch) -> None: """Test behaviour on broken arguments.""" # must be done using sys patching. testargs_root = ['trestle', 'create', '-t'] monkeypatch.setattr(sys, 'argv', testargs_root) with pytest.raises(SystemExit) as pytest_wrapped_e: Trestle().run() assert pytest_wrapped_e.type == SystemExit assert pytest_wrapped_e.value.code > 0 testargs = testargs_root + ['catalog'] # missing command monkeypatch.setattr(sys, 'argv', testargs) rc = Trestle().run() assert rc > 0 # missing mandatory args testargs = testargs + ['-x', 'json'] monkeypatch.setattr(sys, 'argv', testargs) rc = Trestle().run() assert rc > 0 testargs = testargs + ['-o', 'output'] # correct behavior monkeypatch.setattr(sys, 'argv', testargs) rc = Trestle().run() assert rc == 0 # correct behavior testargs[3] = 'bad_name' monkeypatch.setattr(sys, 'argv', testargs) with pytest.raises(SystemExit) as pytest_wrapped_e: Trestle().run() assert pytest_wrapped_e.type == SystemExit assert pytest_wrapped_e.value.code > 0
def test_run_failure_nonexistent_element(tmp_path: pathlib.Path, sample_catalog_minimal: Catalog, monkeypatch: MonkeyPatch): """Test failure of _run on RemoveCmd in specifying nonexistent element for removal.""" # Create a temporary catalog file with responsible-parties content_type = FileContentType.JSON catalog_def_dir, catalog_def_file = test_utils.prepare_trestle_project_dir( tmp_path, content_type, sample_catalog_minimal, test_utils.CATALOGS_DIR) # 1. self.remove() fails -- Should happen if wildcard is given, or nonexistent element. testargs = [ 'trestle', 'remove', '-f', str(catalog_def_file), '-e', 'catalog.blah' ] monkeypatch.setattr(sys, 'argv', testargs) exitcode = Trestle().run() assert exitcode == 5 # 2. Corrupt json file source_file_path = pathlib.Path.joinpath(test_utils.JSON_TEST_DATA_PATH, 'bad_simple.json') shutil.copyfile(source_file_path, catalog_def_file) testargs = [ 'trestle', 'remove', '-f', str(catalog_def_file), '-e', 'catalog.metadata.roles' ] monkeypatch.setattr(sys, 'argv', testargs) exitcode = Trestle().run() assert exitcode == 5
def test_href_failures(tmp_path: pathlib.Path, keep_cwd: pathlib.Path, simplified_nist_profile: profile.Profile, monkeypatch: MonkeyPatch) -> None: """Test href failure modes.""" # prepare trestle project dir with the file models_path, profile_path = test_utils.prepare_trestle_project_dir( tmp_path, FileContentType.JSON, simplified_nist_profile, test_utils.PROFILES_DIR) cmd_string = 'trestle href -n my_test_model -hr foobar' # not in trestle project so fail monkeypatch.setattr(sys, 'argv', cmd_string.split()) rc = Trestle().run() assert rc == 5 os.chdir(models_path) cmd_string = 'trestle href -n my_test_model -hr foobar -i 2' # add extra import to the profile and ask for import number 2 simplified_nist_profile.imports.append(simplified_nist_profile.imports[0]) simplified_nist_profile.oscal_write(profile_path) monkeypatch.setattr(sys, 'argv', cmd_string.split()) rc = Trestle().run() assert rc == 1
def test_href_cmd(tmp_path: pathlib.Path, keep_cwd: pathlib.Path, simplified_nist_profile: profile.Profile, monkeypatch: MonkeyPatch) -> None: """Test basic cmd invocation of href.""" # prepare trestle project dir with the file models_path, profile_path = test_utils.prepare_trestle_project_dir( tmp_path, FileContentType.JSON, simplified_nist_profile, test_utils.PROFILES_DIR) os.chdir(models_path) # just list the hrefs cmd_string = 'trestle href -n my_test_model' monkeypatch.setattr(sys, 'argv', cmd_string.split()) rc = Trestle().run() assert rc == 0 orig_href = simplified_nist_profile.imports[0].href new_href = 'trestle://catalogs/my_catalog/catalog.json' cmd_string = f'trestle href -n my_test_model -hr {new_href}' monkeypatch.setattr(sys, 'argv', cmd_string.split()) rc = Trestle().run() assert rc == 0 # confirm new href is correct new_profile: profile.Profile = profile.Profile.oscal_read(profile_path) assert new_profile.imports[0].href == new_href # restore orig href to confirm models are otherwise equivalent # only thing different should be last-modified new_profile.imports[0].href = orig_href assert test_utils.models_are_equivalent(new_profile, simplified_nist_profile)
def test_assemble_catalog_all( testdata_dir: pathlib.Path, tmp_trestle_dir: pathlib.Path, monkeypatch: MonkeyPatch ) -> None: """Test assembling all catalogs in trestle dir.""" shutil.rmtree(pathlib.Path('dist')) catalogs_dir = tmp_trestle_dir / 'catalogs' my_names = ['mycatalog1', 'mycatalog2', 'mycatalog3'] for my_name in my_names: test_data_source = testdata_dir / 'split_merge/step4_split_groups_array/catalogs/mycatalog' shutil.copytree(test_data_source, catalogs_dir / my_name) testargs = ['trestle', 'assemble', 'catalog', '-t', '-x', 'json'] monkeypatch.setattr(sys, 'argv', testargs) rc = Trestle().run() assert rc == 0 # Read assembled model for my_name in my_names: _, _, expected_model = ModelUtils.load_distributed(catalogs_dir / f'{my_name}/catalog.json', tmp_trestle_dir) actual_model = Catalog.oscal_read(pathlib.Path(f'dist/catalogs/{my_name}.json')) assert actual_model == expected_model testargs = ['trestle', 'assemble', 'profile', '-t', '-x', 'json'] # Tests should pass on empty set of directories. monkeypatch.setattr(sys, 'argv', testargs) rc = Trestle().run() assert rc == 0
def test_catalog_assemble_failures(tmp_trestle_dir: pathlib.Path, monkeypatch: MonkeyPatch) -> None: """Test failurs of catalog assemble.""" test_args = 'trestle author catalog-assemble -m foo -o my_md'.split() monkeypatch.setattr(sys, 'argv', test_args) assert Trestle().run() == 1 (tmp_trestle_dir / 'foo').mkdir() monkeypatch.setattr(sys, 'argv', test_args) assert Trestle().run() == 1
def test_run_failure(keep_cwd: pathlib.Path, monkeypatch: MonkeyPatch) -> None: """Test failure of _run for AddCmd.""" testargs = ['trestle', 'create', '-e', 'catalog.metadata.roles'] monkeypatch.setattr(sys, 'argv', testargs) rc = Trestle().run() assert rc > 0 testargs = ['trestle', 'create', '-f', './catalog.json'] monkeypatch.setattr(sys, 'argv', testargs) rc = Trestle().run() assert rc > 0
def test_split_run_failure( tmp_path: pathlib.Path, sample_target_def: ostarget.TargetDefinition) -> None: """Test split run failure.""" # prepare trestle project dir with the file target_def_dir: pathlib.Path = tmp_path / 'target-definitions' / 'mytarget' target_def_file: pathlib.Path = target_def_dir / 'target-definition.yaml' target_def_dir.mkdir(exist_ok=True, parents=True) 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_path) # no file specified testargs = [ 'trestle', 'split', '-e', 'target-definition.metadata, target-definition.targets.*' ] with patch.object(sys, 'argv', testargs): rc = Trestle().run() assert rc > 0 # check with missing file testargs = [ 'trestle', 'split', '-f', 'missing.yaml', '-e', 'target-definition.metadata, target-definition.targets.*' ] with patch.object(sys, 'argv', testargs): rc = Trestle().run() assert rc > 0 # 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_run_failure(): """Test failure of _run for AddCmd.""" testargs = ['trestle', 'add', '-e', 'catalog.metadata.roles'] with patch.object(sys, 'argv', testargs): with pytest.raises(err.TrestleError): Trestle().run() testargs = ['trestle', 'add', '-f', './catalog.json'] with patch.object(sys, 'argv', testargs): with pytest.raises(err.TrestleError): Trestle().run()
def test_e2e(task_name: str, template_path: pathlib.Path, content_path: pathlib.Path, global_: bool, setup_rc: int, template_validate_rc: int, validate_rc: int, testdata_dir: pathlib.Path, tmp_trestle_dir: pathlib.Path, monkeypatch: MonkeyPatch) -> None: """Run an E2E workflow with a number of test criteria.""" command_string_setup = 'trestle author headers setup' command_string_create_sample = 'trestle author headers create-sample' command_string_validate_template = 'trestle author headers template-validate' command_string_validate_content = 'trestle author headers validate -r' template_target_loc: pathlib.Path if task_name: tn_string = f' -tn {task_name}' command_string_setup += tn_string command_string_create_sample += tn_string command_string_validate_template += tn_string command_string_validate_content += tn_string template_target_loc = tmp_trestle_dir / '.trestle' / 'author' / task_name / START_TEMPLATE_VERSION else: task_name = 'placeholder' if global_: global_str = ' --global' command_string_setup += global_str command_string_create_sample += global_str command_string_validate_template += global_str command_string_validate_content += global_str template_target_loc = tmp_trestle_dir / '.trestle' / 'author' / '__global__' / START_TEMPLATE_VERSION test_content_loc = tmp_trestle_dir / task_name / f'{uuid4()}' monkeypatch.setattr(sys, 'argv', command_string_setup.split()) rc = Trestle().run() assert rc == setup_rc if setup_rc > 0: return shutil.rmtree(str(template_target_loc)) shutil.copytree(str(testdata_dir / template_path), str(template_target_loc)) monkeypatch.setattr(sys, 'argv', command_string_validate_template.split()) rc = Trestle().run() assert rc == template_validate_rc if template_validate_rc > 0: return # Create sample - should always work if we are here. monkeypatch.setattr(sys, 'argv', command_string_create_sample.split()) rc = Trestle().run() assert rc == 0 shutil.copytree(str(testdata_dir / content_path), str(test_content_loc)) monkeypatch.setattr(sys, 'argv', command_string_validate_content.split()) rc = Trestle().run() assert rc == validate_rc
def test_run(tmp_path: pathlib.Path, sample_catalog_missing_roles, monkeypatch: MonkeyPatch): """Test _run for RemoveCmd.""" # 1. Test trestle remove for one element. # expected catalog after remove of Responsible-Party file_path = pathlib.Path.joinpath( test_utils.JSON_TEST_DATA_PATH, 'minimal_catalog_no_responsible-parties.json') expected_catalog_no_rp = Catalog.oscal_read(file_path) content_type = FileContentType.JSON # Create a temporary file with responsible-parties to be removed. catalog_def_dir, catalog_def_file = test_utils.prepare_trestle_project_dir( tmp_path, content_type, sample_catalog_missing_roles, test_utils.CATALOGS_DIR) testargs = [ 'trestle', 'remove', '-tr', str(tmp_path), '-f', str(catalog_def_file), '-e', 'catalog.metadata.responsible-parties' ] monkeypatch.setattr(sys, 'argv', testargs) assert Trestle().run() == 0 actual_catalog = Catalog.oscal_read(catalog_def_file) assert expected_catalog_no_rp == actual_catalog # 2. Test trestle remove for multiple comma-separated elements. # minimal catalog with Roles and Resposibile-Parties. file_path = pathlib.Path.joinpath(test_utils.JSON_TEST_DATA_PATH, 'minimal_catalog_roles.json') catalog_with_roles_responsible_parties = Catalog.oscal_read(file_path) # Create a temporary file with Roles and Responsible-Parties to be removed. catalog_def_dir, catalog_def_file_2 = test_utils.prepare_trestle_project_dir( tmp_path, content_type, catalog_with_roles_responsible_parties, test_utils.CATALOGS_DIR) testargs = [ 'trestle', 'remove', '-tr', str(tmp_path), '-f', str(catalog_def_file_2), '-e', 'catalog.metadata.responsible-parties,catalog.metadata.roles' ] monkeypatch.setattr(sys, 'argv', testargs) assert Trestle().run() == 0 actual_catalog = Catalog.oscal_read(catalog_def_file_2) assert expected_catalog_no_rp == actual_catalog
def test_split_run_failures( keep_cwd: pathlib.Path, tmp_path: pathlib.Path, sample_nist_component_def: component.ComponentDefinition, monkeypatch: MonkeyPatch) -> None: """Test split run failure.""" # prepare trestle project dir with the file component_def_dir: pathlib.Path = tmp_path / 'component-definitions' / 'mytarget' component_def_file: pathlib.Path = component_def_dir / 'component-definition.yaml' component_def_dir.mkdir(exist_ok=True, parents=True) sample_nist_component_def.oscal_write(component_def_file) invalid_file = component_def_dir / 'invalid.file' invalid_file.touch() os.chdir(component_def_dir) # not a trestle project testargs = [ 'trestle', 'split', '-tr', str(tmp_path), '-f', 'component-definition.yaml', '-e', 'component-definition.metadata, component-definition.components.*' ] monkeypatch.setattr(sys, 'argv', testargs) with pytest.raises(SystemExit) as wrapped_error: trestle.cli.run() assert wrapped_error.value.code == 1 # create trestle project test_utils.ensure_trestle_config_dir(tmp_path) # no file specified and garbage element testargs = ['trestle', 'split', '-e', 'foo.bar'] monkeypatch.setattr(sys, 'argv', testargs) rc = Trestle().run() assert rc > 0 # check with missing file testargs = [ 'trestle', 'split', '-f', 'missing.yaml', '-e', 'component-definition.metadata, component-definition.components.*' ] monkeypatch.setattr(sys, 'argv', testargs) rc = Trestle().run() assert rc > 0 # check with incorrect file type testargs = [ 'trestle', 'split', '-f', invalid_file.name, '-e', 'component-definition.metadata, component-definition.components.*' ] monkeypatch.setattr(sys, 'argv', testargs) rc = Trestle().run() assert rc == 1
def test_run_failure(): """Test failure of _run for AddCmd.""" testargs = ['trestle', 'add', '-e', 'catalog.metadata.roles'] with patch.object(sys, 'argv', testargs): with pytest.raises(SystemExit) as e: Trestle().run() assert e.type == SystemExit assert e.value.code == 2 testargs = ['trestle', 'add', '-f', './catalog.json'] with patch.object(sys, 'argv', testargs): with pytest.raises(SystemExit) as e: Trestle().run() assert e.type == SystemExit assert e.value.code == 2
def create_trestle_project_with_model( top_dir: pathlib.Path, model_obj: OscalBaseModel, model_name: str, monkeypatch: MonkeyPatch ) -> pathlib.Path: """Create initialized trestle project and import the model into it.""" cur_dir = pathlib.Path.cwd() # create subdirectory for trestle project trestle_root = top_dir / 'my_trestle' trestle_root.mkdir() os.chdir(trestle_root) try: testargs = ['trestle', 'init'] monkeypatch.setattr(sys, 'argv', testargs) assert Trestle().run() == 0 # place model object in top directory outside trestle project # so it can be imported tmp_model_path = top_dir / (model_name + '.json') model_obj.oscal_write(tmp_model_path) i = ImportCmd() args = argparse.Namespace( trestle_root=trestle_root, file=str(tmp_model_path), output=model_name, verbose=0, regenerate=False ) assert i._run(args) == 0 except Exception as e: raise TrestleError(f'Error creating trestle project with model: {e}') finally: os.chdir(cur_dir) return trestle_root
def test_import_profile_with_optional_added(tmp_trestle_dir: pathlib.Path, monkeypatch: MonkeyPatch) -> None: """Create profile, add modify to it, and import.""" rand_str = ''.join(random.choice(string.ascii_letters) for x in range(16)) profile_file = f'{tmp_trestle_dir.parent}/{rand_str}.json' # create generic profile profile_data = generators.generate_sample_model( trestle.oscal.profile.Profile) # create special parameter and add it to profile set_parameter = SetParameter(param_id='my_param', depends_on='my_depends') modify = Modify(set_parameters=[set_parameter]) profile_data.modify = modify # write it to place outside trestle directory profile_data.oscal_write(pathlib.Path(profile_file)) # now do actual import into trestle directory with name 'imported' test_args = f'trestle import -f {profile_file} -o imported'.split() monkeypatch.setattr(sys, 'argv', test_args) rc = Trestle().run() assert rc == 0 # then do a direct read of it and confirm our parameter is there profile_path = tmp_trestle_dir / 'profiles/imported/profile.json' profile: Profile = Profile.oscal_read(profile_path) params = profile.modify.set_parameters assert params assert len(params) == 1 assert params[0].param_id == 'my_param' assert params[0].depends_on == 'my_depends'
def test_validation_unhappy(name, mode, parent, status, tmp_trestle_dir: pathlib.Path, monkeypatch: MonkeyPatch) -> None: """Test failure modes of validation.""" (tmp_trestle_dir / test_utils.CATALOGS_DIR / 'my_test_model').mkdir( exist_ok=True, parents=True) (tmp_trestle_dir / test_utils.CATALOGS_DIR / 'my_test_model2').mkdir( exist_ok=True, parents=True) shutil.copyfile( test_data_dir / 'json/minimal_catalog_bad_oscal_version.json', tmp_trestle_dir / test_utils.CATALOGS_DIR / 'my_test_model/catalog.json') shutil.copyfile( test_data_dir / 'json/minimal_catalog.json', tmp_trestle_dir / test_utils.CATALOGS_DIR / 'my_test_model2/catalog.json') model_def_file = tmp_trestle_dir / test_utils.CATALOGS_DIR / ( 'my_test_model/catalog.json') if mode == '-f': if not parent: testcmd = f'trestle validate {mode} {model_def_file}' else: testcmd = f'trestle validate {mode} {model_def_file.parent}' elif mode == '-n': testcmd = f'trestle validate -t catalog -n {name}' elif mode == '-x': testcmd = f'trestle validate -t catalog -n {name}' else: testcmd = 'trestle validate -a' monkeypatch.setattr(sys, 'argv', testcmd.split()) rc = Trestle().run() assert rc == status
def test_abort_safely_on_missing_directory(tmp_trestle_dir: pathlib.Path, monkeypatch: MonkeyPatch) -> None: """Test that validation fails cleanly on a missing directory.""" task_name = 'tester' command_string_setup = f'trestle author headers setup -tn {task_name}' command_string_validate_content = f'trestle author headers validate -tn {task_name} -r' task_dir = tmp_trestle_dir / task_name monkeypatch.setattr(sys, 'argv', command_string_setup.split()) rc = Trestle().run() assert rc == 0 shutil.rmtree(str(task_dir)) monkeypatch.setattr(sys, 'argv', command_string_validate_content.split()) rc = Trestle().run() assert rc > 0
def test_assemble_not_trestle_root(testdata_dir: pathlib.Path, tmp_trestle_dir: pathlib.Path) -> None: """Test execution of assemble from a folder that is not trestle root.""" os.chdir(pathlib.Path.cwd() / 'catalogs') testargs = ['trestle', 'assemble', 'catalog', '-n', 'mycatalog', '-x', 'json'] with mock.patch.object(sys, 'argv', testargs): rc = Trestle().run() assert rc == 1
def test_cli(sample_file: str, element_path: str, rc: int, testdata_dir: pathlib.Path, monkeypatch: MonkeyPatch) -> None: """Test the CLI directly.""" full_path = testdata_dir / sample_file command_str = f'trestle partial-object-validate -f {str(full_path)} -e {element_path}' monkeypatch.setattr(sys, 'argv', command_str.split()) cli_rc = Trestle().run() assert rc == cli_rc
def test_run_failure_switches(tmp_path, sample_catalog_minimal): """Test failure of _run on bad switches for RemoveCmd.""" # 1. Missing --file argument. testargs = ['trestle', 'remove', '-e', 'catalog.metadata.roles'] with patch.object(sys, 'argv', testargs): with pytest.raises(SystemExit) as e: Trestle().run() assert e.type == SystemExit assert e.value.code == 2 # 2. Missing --element argument. testargs = ['trestle', 'remove', '-f', './catalog.json'] with patch.object(sys, 'argv', testargs): with pytest.raises(SystemExit) as e: Trestle().run() assert e.type == SystemExit assert e.value.code == 2
def test_assemble_not_trestle_project(tmp_empty_cwd: pathlib.Path) -> None: """Test failure if not trestle project.""" testargs = [ 'trestle', 'assemble', 'catalog', '-n', 'mycatalog', '-x', 'json' ] with mock.patch.object(sys, 'argv', testargs): rc = Trestle().run() assert rc == 1
def test_run_and_missing_model(tmp_trestle_dir: pathlib.Path) -> None: """Test _run and test it fails without top level model file.""" testargs_root = ['trestle', 'assemble'] for subcommand in subcommand_list: test_args = testargs_root + [subcommand] + ['-n', f'my_{subcommand}'] + ['-x', 'json'] with mock.patch.object(sys, 'argv', test_args): rc = Trestle().run() assert rc != 0
def test_for_failure_on_multiple_element_paths( testdata_dir: pathlib.Path, monkeypatch: MonkeyPatch) -> None: """Test whether a bad element string correctly errors.""" element_str = "'catalogs,profile'" full_path = testdata_dir / 'json/minimal_catalog.json' command_str = f'trestle partial-object-validate -f {str(full_path)} -e {element_str}' monkeypatch.setattr(sys, 'argv', command_str.split()) rc = Trestle().run() assert rc > 0
def test_missing_file(tmp_path: pathlib.Path, monkeypatch: MonkeyPatch) -> None: """Test what happens when a file is missing.""" fake_catalog_path = tmp_path / 'catalog.json' element_str = 'catalog' command_str = f'trestle partial-object-validate -f {str(fake_catalog_path)} -e {element_str}' monkeypatch.setattr(sys, 'argv', command_str.split()) rc = Trestle().run() assert rc == 1
def test_run_failure_switches(tmp_path: pathlib.Path, monkeypatch: MonkeyPatch): """Test failure of _run on bad switches for RemoveCmd.""" # 1. Missing --file argument. testargs = ['trestle', 'remove', '-e', 'catalog.metadata.roles'] monkeypatch.setattr(sys, 'argv', testargs) with pytest.raises(SystemExit) as e: Trestle().run() assert e.type == SystemExit assert e.value.code == 2 # 2. Missing --element argument. testargs = ['trestle', 'remove', '-f', './catalog.json'] monkeypatch.setattr(sys, 'argv', testargs) with pytest.raises(SystemExit) as e: Trestle().run() assert e.type == SystemExit assert e.value.code == 2
def test_create_cmd(tmp_trestle_dir: pathlib.Path) -> None: """Happy path test at the cli level.""" # Test testargs_root = ['trestle', 'create'] for subcommand in subcommand_list: test_args = testargs_root + [subcommand] + ['-n', f'random_named_{subcommand}'] with mock.patch.object(sys, 'argv', test_args): rc = Trestle().run() assert rc == 0
def test_catalog_generate_failures(tmp_trestle_dir: pathlib.Path, monkeypatch: MonkeyPatch) -> None: """Test failures of author catalog.""" # disallowed output name test_args = 'trestle author catalog-generate -n foo -o profiles'.split() monkeypatch.setattr(sys, 'argv', test_args) assert Trestle().run() == 1 # catalog doesn't exist test_args = 'trestle author catalog-generate -n foo -o my_md'.split() monkeypatch.setattr(sys, 'argv', test_args) assert Trestle().run() == 1 # bad yaml bad_yaml_path = str(test_utils.YAML_TEST_DATA_PATH / 'bad_simple.yaml') test_args = f'trestle author catalog-generate -n foo -o my_md -y {bad_yaml_path}'.split( ) monkeypatch.setattr(sys, 'argv', test_args) assert Trestle().run() == 1