Exemple #1
0
def generate_complex_catalog(stem: str = '') -> cat.Catalog:
    """Generate a complex and deep catalog for testing."""
    group_a = generators.generate_sample_model(cat.Group, True)
    group_a.id = f'{stem}a'
    group_a.controls = generate_control_list(group_a.id, 4)
    group_b = generators.generate_sample_model(cat.Group, True)
    group_b.id = f'{stem}b'
    group_b.controls = generate_control_list(group_b.id, 3)
    group_b.controls[2].controls = generate_control_list(f'{group_b.id}-2', 3)
    group_ba = generators.generate_sample_model(cat.Group, True)
    group_ba.id = f'{stem}ba'
    group_ba.controls = generate_control_list(group_ba.id, 2)
    group_b.groups = [group_ba]

    catalog = generators.generate_sample_model(cat.Catalog, True)
    catalog.controls = generate_control_list(f'{stem}cat', 3)
    catalog.params = generate_param_list(f'{stem}parm', 3)

    test_control = generators.generate_sample_model(cat.Control, False)
    test_control.id = f'{stem}test-1'
    test_control.params = [common.Parameter(id=f'{test_control.id}_prm_1', values=['Default', 'Values'])]
    test_control.parts = [
        common.Part(
            id=f'{test_control.id}_smt',
            name='statement',
            prose='Statement with no parts.  Prose with param value {{ insert: param, test-1_prm_1 }}'
        )
    ]
    catalog.controls.append(test_control)
    catalog.groups = [group_a, group_b]

    return catalog
def test_managed_write(tmp_trestle_dir: pathlib.Path) -> None:
    """Test model write."""
    # generate catalog data and import
    catalog_data = generators.generate_sample_model(cat.Catalog)
    repo = Repository(tmp_trestle_dir)
    managed = repo.import_model(catalog_data, 'imported')

    # generate another catalog data for writing
    catalog_data = generators.generate_sample_model(cat.Catalog)
    success = managed.write(catalog_data)
    assert success
Exemple #3
0
def test_get_all_sample_models() -> None:
    """Test we can get all models which exist."""
    pkgpath = os.path.dirname(oscal.__file__)
    for _, name, _ in pkgutil.iter_modules([pkgpath]):
        __import__(f'trestle.oscal.{name}')
        clsmembers = inspect.getmembers(sys.modules[f'trestle.oscal.{name}'],
                                        inspect.isclass)
        for _, oscal_cls in clsmembers:
            # This removes some enums and other objects.

            if issubclass(oscal_cls, OscalBaseModel):
                gens.generate_sample_model(oscal_cls)
Exemple #4
0
def sample_component_definition():
    """Return a valid ComponentDefinition object with some contents."""
    # one component has no properties - the other has two
    def_comp1: DefinedComponent = gens.generate_sample_model(DefinedComponent)
    def_comp2: DefinedComponent = gens.generate_sample_model(DefinedComponent)
    prop_1 = gens.generate_sample_model(common.Property)
    prop_2 = gens.generate_sample_model(common.Property)
    def_comp2.props = [prop_1, prop_2]
    comp_def: ComponentDefinition = gens.generate_sample_model(
        ComponentDefinition)
    comp_def.components = [def_comp1, def_comp2]
    return comp_def
def test_managed_write_invalid_top_model(
        tmp_trestle_dir: pathlib.Path) -> None:
    """Invalid top level model while writing."""
    # generate catalog data and import
    catalog_data = generators.generate_sample_model(cat.Catalog)
    repo = Repository(tmp_trestle_dir)
    managed = repo.import_model(catalog_data, 'imported')

    # generate another catalog data for writing
    catalog_data = generators.generate_sample_model(oscal.catalog.Group)

    with pytest.raises(TrestleError, match='not a top level model'):
        managed.write(catalog_data)
def test_validate_dup_uuids(
        sample_component_definition: ComponentDefinition) -> None:
    """Test validation of comp def with duplicate uuids."""
    args = argparse.Namespace(mode=const.VAL_MODE_ALL)
    validator = validator_factory.get(args)

    # confirm the comp_def is valid
    assert validator.model_is_valid(sample_component_definition)

    # force two components to have same uuid and confirm invalid
    sample_component_definition.components[
        1].uuid = sample_component_definition.components[0].uuid
    assert not validator.model_is_valid(sample_component_definition)

    # restore uuid to unique value and confirm it is valid again
    sample_component_definition.components[1].uuid = str(uuid4())
    assert validator.model_is_valid(sample_component_definition)

    # add a control implementation to one of the components and confirm valid
    control_imp: ControlImplementation = generate_sample_model(
        ControlImplementation)
    sample_component_definition.components[1].control_implementations = [
        control_imp
    ]
    assert validator.model_is_valid(sample_component_definition)

    # force the control implementation to have same uuid as the first component and confirm invalid
    sample_component_definition.components[1].control_implementations[
        0].uuid = sample_component_definition.components[0].uuid
    assert not validator.model_is_valid(sample_component_definition)
def test_control_with_components() -> None:
    """Test loading and parsing of implementated reqs with components."""
    control_path = pathlib.Path(
        'tests/data/author/controls/control_with_components.md').resolve()
    comp_prose_dict, _ = ControlIOReader.read_all_implementation_prose_and_header(
        control_path)
    assert len(comp_prose_dict.keys()) == 3
    assert len(comp_prose_dict['This System'].keys()) == 3
    assert len(comp_prose_dict['Trestle Component'].keys()) == 1
    assert len(comp_prose_dict['Fancy Thing'].keys()) == 2
    assert comp_prose_dict['Fancy Thing']['a.'] == [
        'Text for fancy thing component'
    ]

    # need to build the needed components so they can be referenced
    comp_dict = {}
    for comp_name in comp_prose_dict.keys():
        comp = gens.generate_sample_model(ossp.SystemComponent)
        comp.title = comp_name
        comp_dict[comp_name] = comp

    # confirm that the header content was inserted into the props of the imp_req
    imp_req = ControlIOReader.read_implemented_requirement(
        control_path, comp_dict)
    assert len(imp_req.props) == 12
    assert len(imp_req.statements) == 3
    assert len(imp_req.statements[0].by_components) == 3
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'
Exemple #9
0
def sample_catalog_rich_controls():
    """Return a catalog with controls in groups and in the catalog itself."""
    catalog_obj = gens.generate_sample_model(cat.Catalog)

    param_0 = common.Parameter(
        id='param_0', values=[common.ParameterValue(__root__='param_0_val')])
    param_1 = common.Parameter(
        id='param_1', values=[common.ParameterValue(__root__='param_1_val')])
    control_a = cat.Control(id='control_a',
                            title='this is control a',
                            params=[param_0, param_1])
    control_b = cat.Control(id='control_b', title='this is control b')
    group = cat.Group(id='xy',
                      title='The xy control group',
                      controls=[control_a, control_b])
    catalog_obj.groups = [group]

    part = common.Part(id='cpart', name='name.c.part')
    control_c = cat.Control(id='control_c',
                            title='this is control c',
                            parts=[part])

    control_d = cat.Control(id='control_d', title='this is control d')
    control_d1 = cat.Control(id='control_d1', title='this is control d1')
    control_d.controls = [control_d1]

    catalog_obj.controls = [control_c, control_d]
    return catalog_obj
def test_managed_oscal(tmp_trestle_dir: pathlib.Path) -> None:
    """Test creating Managed OSCAL object."""
    # generate catalog data and import
    catalog_data = generators.generate_sample_model(cat.Catalog)
    repo = Repository(tmp_trestle_dir)
    managed = repo.import_model(catalog_data, 'imported')
    assert managed.model_dir == tmp_trestle_dir / 'catalogs' / 'imported'
def test_validate(tmp_trestle_dir: pathlib.Path) -> None:
    """Test validate model."""
    # create a model
    catalog_data = generators.generate_sample_model(cat.Catalog)
    repo = Repository(tmp_trestle_dir)
    repo.import_model(catalog_data, 'imported')
    success = repo.validate_model(cat.Catalog, 'imported')
    assert success
def test_get(tmp_trestle_dir: pathlib.Path) -> None:
    """Test get model."""
    # create a model
    catalog_data = generators.generate_sample_model(cat.Catalog)
    repo = Repository(tmp_trestle_dir)
    repo.import_model(catalog_data, 'imported')
    managed_oscal = repo.get_model(cat.Catalog, 'imported')
    assert managed_oscal._model_name == 'imported'
def test_managed_validate(tmp_trestle_dir: pathlib.Path) -> None:
    """Test model validate."""
    # generate catalog data and import
    catalog_data = generators.generate_sample_model(cat.Catalog)
    repo = Repository(tmp_trestle_dir)
    managed = repo.import_model(catalog_data, 'imported')
    success = managed.validate()
    assert success
def test_import_invalid_top_model(tmp_trestle_dir: pathlib.Path) -> None:
    """Invalid top model."""
    # try to import Metadata
    metadata = generators.generate_sample_model(oscal.common.Metadata)

    repo = Repository(tmp_trestle_dir)
    with pytest.raises(TrestleError, match='not a top level model'):
        repo.import_model(metadata, 'imported')
def test_managed_read(tmp_trestle_dir: pathlib.Path) -> None:
    """Test model read."""
    # generate catalog data and import
    catalog_data = generators.generate_sample_model(cat.Catalog)
    repo = Repository(tmp_trestle_dir)
    managed = repo.import_model(catalog_data, 'imported')
    model = managed.read()
    assert model.uuid == catalog_data.uuid
Exemple #16
0
    def create_object(cls, model_alias: str, object_type: Type[TLO],
                      args: argparse.Namespace) -> int:
        """Create a top level OSCAL object within the trestle directory, leveraging functionality in add."""
        log.set_log_level_from_args(args)
        trestle_root = fs.get_trestle_project_root(Path.cwd())
        if not trestle_root:
            logger.error(
                f'Current working directory {Path.cwd()} is not with a trestle project.'
            )
            return 1
        plural_path: str
        # Cater to POAM
        if model_alias[-1] == 's':
            plural_path = model_alias
        else:
            plural_path = model_alias + 's'

        desired_model_dir = trestle_root / plural_path / args.name

        desired_model_path = desired_model_dir / (model_alias + '.' +
                                                  args.extension)

        if desired_model_path.exists():
            logger.error(
                f'OSCAL file to be created here: {desired_model_path} exists.')
            logger.error('Aborting trestle create.')
            return 1

        # Create sample model.
        sample_model = generators.generate_sample_model(object_type)
        # Presuming top level level model not sure how to do the typing for this.
        sample_model.metadata.title = f'Generic {model_alias} created by trestle.'  # type: ignore
        sample_model.metadata.last_modified = datetime.now().astimezone()
        sample_model.metadata.oscal_version = trestle.oscal.OSCAL_VERSION
        sample_model.metadata.version = '0.0.0'

        top_element = Element(sample_model, model_alias)

        create_action = CreatePathAction(desired_model_path.absolute(), True)
        write_action = WriteFileAction(
            desired_model_path.absolute(), top_element,
            FileContentType.to_content_type(desired_model_path.suffix))

        # create a plan to write the directory and file.
        try:
            create_plan = Plan()
            create_plan.add_action(create_action)
            create_plan.add_action(write_action)
            create_plan.simulate()
            create_plan.execute()
            return 0
        except Exception as e:
            logger.error(
                'Unknown error executing trestle create operations. Rolling back.'
            )
            logger.debug(e)
            return 1
def test_delete(tmp_trestle_dir: pathlib.Path) -> None:
    """Test delete model."""
    # create a model
    catalog_data = generators.generate_sample_model(cat.Catalog)
    repo = Repository(tmp_trestle_dir)
    repo.import_model(catalog_data, 'imported')
    # created model is 'dist' folder also
    repo.assemble_model(cat.Catalog, 'imported')
    success = repo.delete_model(cat.Catalog, 'imported')
    assert success
def test_generate_sample_model() -> None:
    """Test utils method generate_sample_model."""
    # Create the expected catalog first
    expected_ctlg_dict = {
        'uuid': 'ea784488-49a1-4ee5-9830-38058c7c10a4',
        'metadata': {
            'title': 'REPLACE_ME',
            'last-modified': '2020-10-21T06:52:10.387+00:00',
            'version': 'REPLACE_ME',
            'oscal-version': oscal.OSCAL_VERSION
        }
    }
    expected_ctlg = catalog.Catalog(**expected_ctlg_dict)

    actual_ctlg = gens.generate_sample_model(catalog.Catalog)

    # Check if uuid is valid, then change to uuid of expected catalog, as newly generated
    # uuids will always be different
    assert is_valid_uuid(actual_ctlg.uuid)
    actual_ctlg.uuid = expected_ctlg.uuid
    # Check if last-modified datetime is of type datetime, and then equate in actual and expected
    assert type(actual_ctlg.metadata) is common.Metadata
    actual_ctlg.metadata.last_modified = expected_ctlg.metadata.last_modified
    # Check that expected generated catalog is now same a actual catalog
    assert expected_ctlg == actual_ctlg

    # Test list type models
    expected_role = common.Role(**{'id': 'REPLACE_ME', 'title': 'REPLACE_ME'})
    list_role = gens.generate_sample_model(List[common.Role])
    assert type(list_role) is list
    actual_role = list_role[0]
    assert expected_role == actual_role

    # Test dict type models
    if False:
        party_uuid = common.PartyUuid(__root__=const.SAMPLE_UUID_STR)
        expected_rp = {'role_id': 'REPLACE_ME', 'party-uuids': [party_uuid]}
        expected_rp = common.ResponsibleParty(**expected_rp)
        expected_rp_dict = {'REPLACE_ME': expected_rp}
        actual_rp_dict = gens.generate_sample_model(
            Dict[str, common.ResponsibleParty])
        assert type(actual_rp_dict) is dict
        assert expected_rp_dict == actual_rp_dict
def test_managed_file_not_exist(tmp_trestle_dir: pathlib.Path) -> None:
    """Test model file does not exist while creating a Managed OSCAL object."""
    # generate catalog data and import
    catalog_data = generators.generate_sample_model(cat.Catalog)
    repo = Repository(tmp_trestle_dir)
    managed = repo.import_model(catalog_data, 'imported')

    # delete file
    managed.filepath.unlink()
    with pytest.raises(TrestleError, match=r'Model file .* does not exist'):
        ManagedOSCAL(tmp_trestle_dir, cat.Catalog, 'imported')
def test_assemble(tmp_trestle_dir: pathlib.Path) -> None:
    """Test assemble model."""
    # create a model
    catalog_data = generators.generate_sample_model(cat.Catalog)
    repo = Repository(tmp_trestle_dir)
    repo.import_model(catalog_data, 'imported')
    success = repo.assemble_model(cat.Catalog, 'imported')
    assert success
    dist_model_path = pathlib.Path(tmp_trestle_dir, 'dist', 'catalogs',
                                   'imported.json')
    assert dist_model_path.exists()
def test_import_model_exists(tmp_trestle_dir: pathlib.Path) -> None:
    """Model already exists."""
    # Generate sample catalog model
    catalog_data = generators.generate_sample_model(cat.Catalog)

    repo = Repository(tmp_trestle_dir)
    managed_oscal = repo.import_model(catalog_data, 'imported')
    assert managed_oscal.filepath.exists()

    with pytest.raises(TrestleError, match=r'OSCAL file .* exists'):
        repo.import_model(catalog_data, 'imported')
def test_import(tmp_trestle_dir: pathlib.Path) -> None:
    """Test import."""
    # Generate sample catalog model
    catalog_data = generators.generate_sample_model(cat.Catalog)

    repo = Repository(tmp_trestle_dir)
    managed_oscal = repo.import_model(catalog_data, 'imported')
    assert managed_oscal._root_dir == tmp_trestle_dir
    assert managed_oscal._model_name == 'imported'
    assert managed_oscal._model_type == catalog_data.__class__
    assert managed_oscal.filepath.exists()
def test_generate_sample_model():
    """Test utils method generate_sample_model."""
    # Create the expected catalog first
    expected_ctlg_dict = {
        'uuid': 'ea784488-49a1-4ee5-9830-38058c7c10a4',
        'metadata': {
            'title': 'REPLACE_ME',
            'last-modified': '2020-10-21T06:52:10.387+00:00',
            'version': 'REPLACE_ME',
            'oscal-version': 'REPLACE_ME'
        }
    }
    expected_ctlg = catalog.Catalog(**expected_ctlg_dict)

    actual_ctlg = gens.generate_sample_model(catalog.Catalog)

    # Check if uuid is valid, then change to uuid of expected catalog, as newly generated
    # uuids will always be different
    assert is_valid_uuid(actual_ctlg.uuid)
    actual_ctlg.uuid = expected_ctlg.uuid
    # Check if last-modified datetime is of type datetime, and then equate in actual and expected
    assert type(actual_ctlg.metadata.last_modified) is catalog.LastModified
    actual_ctlg.metadata.last_modified = expected_ctlg.metadata.last_modified
    # Check that expected generated catalog is now same a actual catalog
    assert expected_ctlg == actual_ctlg

    # Test list type models
    expected_role = catalog.Role(**{'id': 'REPLACE_ME', 'title': 'REPLACE_ME'})
    list_role = gens.generate_sample_model(typing.List[catalog.Role])
    assert type(list_role) is list
    actual_role = list_role[0]
    assert expected_role == actual_role

    # Test dict type models
    expected_rp = {'party-uuids': ['00000000-0000-4000-8000-000000000000']}
    expected_rp = catalog.ResponsibleParty(**expected_rp)
    expected_rp_dict = {'REPLACE_ME': expected_rp}
    actual_rp_dict = gens.generate_sample_model(
        typing.Dict[str, catalog.ResponsibleParty])
    assert type(actual_rp_dict) is dict
    assert expected_rp_dict == actual_rp_dict
Exemple #24
0
def generate_param_list(label: str, count: int) -> List[cat.Control]:
    """Generate a list of params with indexed names."""
    params: List[common.Parameter] = []
    for ii in range(count):
        param = generators.generate_sample_model(common.Parameter, True)
        param.id = f'{label}-{ii + 1}'
        param.label = f'label-{param.id}'
        param.props[0].name = f'name-{param.id}'
        param.props[0].value = f'value-{param.id}'
        param.guidelines[0].prose = f'prose-{param.id}'
        params.append(param)
    return params
Exemple #25
0
def test_import_non_top_level_element(tmp_trestle_dir: pathlib.Path) -> None:
    """Test for expected fail to import non-top level element, e.g., groups."""
    # Input file, catalog:
    rand_str = ''.join(random.choice(string.ascii_letters) for x in range(16))
    groups_file = f'{tmp_trestle_dir.parent}/{rand_str}.json'
    groups_data = generators.generate_sample_model(trestle.oscal.catalog.Group)
    groups_data.oscal_write(pathlib.Path(groups_file))
    args = argparse.Namespace(file=groups_file,
                              output='imported',
                              verbose=True)
    i = importcmd.ImportCmd()
    rc = i._run(args)
    assert rc == 1
def test_list(tmp_trestle_dir: pathlib.Path) -> None:
    """Test list models."""
    # 1. Empty list
    repo = Repository(tmp_trestle_dir)
    model_list = repo.list_models(cat.Catalog)
    assert len(model_list) == 0

    # model exists
    catalog_data = generators.generate_sample_model(cat.Catalog)
    repo.import_model(catalog_data, 'imported')
    model_list = repo.list_models(cat.Catalog)
    assert len(model_list) == 1
    assert 'imported' in model_list
def test_profile_resolver_merge(sample_catalog_rich_controls: cat.Catalog) -> None:
    """Test profile resolver merge."""
    profile = gens.generate_sample_model(prof.Profile)
    method = prof.Method.merge
    combine = prof.Combine(method=method)
    profile.merge = prof.Merge(combine=combine)
    merge = Merge(profile)

    # merge into empty catalog
    merged = gens.generate_sample_model(cat.Catalog)
    new_merged = merge._merge_catalog(merged, sample_catalog_rich_controls)
    catalog_interface = CatalogInterface(new_merged)
    assert catalog_interface.get_count_of_controls_in_catalog(True) == 5

    # add part to first control and merge, then make sure it is there
    part = com.Part(name='foo', title='added part')
    control_id = sample_catalog_rich_controls.controls[0].id
    cat_with_added_part = copy.deepcopy(sample_catalog_rich_controls)
    cat_with_added_part.controls[0].parts.append(part)
    final_merged = merge._merge_catalog(sample_catalog_rich_controls, cat_with_added_part)
    catalog_interface = CatalogInterface(final_merged)
    assert catalog_interface.get_count_of_controls_in_catalog(True) == 5
    assert catalog_interface.get_control(control_id).parts[-1].name == 'foo'

    # add part to first control and merge but with use-first.  The part should not be there at end.
    method = prof.Method.use_first
    combine = prof.Combine(method=method)
    profile.merge = prof.Merge(combine=combine)
    merge = Merge(profile)
    final_merged = merge._merge_catalog(sample_catalog_rich_controls, cat_with_added_part)
    catalog_interface = CatalogInterface(final_merged)
    assert catalog_interface.get_count_of_controls_in_catalog(True) == 5
    assert len(catalog_interface.get_control(control_id).parts) == 1

    # now force a merge with keep
    profile.merge = None
    merge_keep = Merge(profile)
    merged_keep = merge_keep._merge_catalog(new_merged, sample_catalog_rich_controls)
    assert CatalogInterface(merged_keep).get_count_of_controls_in_catalog(True) == 10
Exemple #28
0
def test_import_run(tmp_trestle_dir: pathlib.Path) -> None:
    """Test successful _run() on valid and invalid."""
    rand_str = ''.join(random.choice(string.ascii_letters) for x in range(16))
    catalog_file = f'{tmp_trestle_dir.parent}/{rand_str}.json'
    catalog_data = generators.generate_sample_model(
        trestle.oscal.catalog.Catalog)
    catalog_data.oscal_write(pathlib.Path(catalog_file))
    i = importcmd.ImportCmd()
    args = argparse.Namespace(file=catalog_file,
                              output='imported',
                              verbose=True)
    rc = i._run(args)
    assert rc == 0
def test_import_root_key_found(tmp_trestle_dir: pathlib.Path) -> None:
    """Test root key is found."""
    rand_str = ''.join(random.choice(string.ascii_letters) for x in range(16))
    catalog_file = f'{tmp_trestle_dir.parent}/{rand_str}.json'
    catalog_data = generators.generate_sample_model(Catalog)
    catalog_data.oscal_write(pathlib.Path(catalog_file))
    args = argparse.Namespace(trestle_root=tmp_trestle_dir,
                              file=catalog_file,
                              output='catalog',
                              verbose=1,
                              regenerate=False)
    i = importcmd.ImportCmd()
    rc = i._run(args)
    assert rc == 0
Exemple #30
0
def test_import_cmd(tmp_trestle_dir: pathlib.Path) -> None:
    """Happy path test at the cli level."""
    # 1. Input file, profile:
    rand_str = ''.join(random.choice(string.ascii_letters) for x in range(16))
    profile_file = f'{tmp_trestle_dir.parent}/{rand_str}.json'
    profile_data = generators.generate_sample_model(
        trestle.oscal.profile.Profile)
    profile_data.oscal_write(pathlib.Path(profile_file))
    # 2. Input file, target:
    rand_str = ''.join(random.choice(string.ascii_letters) for x in range(16))
    target_file = f'{tmp_trestle_dir.parent}/{rand_str}.json'
    target_data = generators.generate_sample_model(
        trestle.oscal.target.TargetDefinition)
    target_data.oscal_write(pathlib.Path(target_file))
    # Test 1
    test_args = f'trestle import -f {profile_file} -o imported'.split()
    with patch.object(sys, 'argv', test_args):
        rc = Trestle().run()
        assert rc == 0
    # Test 2
    test_args = f'trestle import -f {target_file} -o imported'.split()
    with patch.object(sys, 'argv', test_args):
        rc = Trestle().run()
        assert rc == 0