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 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 generate_control_list(label: str, count: int) -> List[cat.Control]: """Generate a list of controls with indexed names.""" controls: List[cat.Control] = [] for ii in range(count): control = generators.generate_sample_model(cat.Control, True) control.id = f'{label}-{ii + 1}' control.params[0].id = f'{control.id}.param' sub_part = common.Part( id=f'{control.id}_smt.a', name='item', props=[common.Property(name='label', value='a.')], prose=f'Prose for item a. of control {control.id}' ) control.parts = [ common.Part( id=f'{control.id}_smt', name='statement', prose=f'Prose for the statement part of control {control.id}', parts=[sub_part] ), ] controls.append(control) return controls
def test_control_failures(tmp_path: pathlib.Path) -> None: """Test various failure modes.""" part = common.Part(name='foo') assert ControlIOWriter.get_label(part) == '' assert ControlIOReader._strip_to_make_ncname('1a@foo') == 'afoo' with pytest.raises(TrestleError): ControlIOReader._strip_to_make_ncname('1@') with pytest.raises(TrestleError): ControlIOReader._indent('') with pytest.raises(TrestleError): ControlIOReader._indent(' foo')
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
This is a fancy control and should be used with care. """ @pytest.mark.parametrize('sections', [True, False]) @pytest.mark.parametrize('control_prose', [True, False]) @pytest.mark.parametrize('case', [case_1, case_2, case_3]) @pytest.mark.parametrize('additional_content', [True, False]) def test_read_write_controls(sections, control_prose, case, additional_content, tmp_path: pathlib.Path, keep_cwd: pathlib.Path) -> None: """Test read and write of controls via markdown.""" dummy_title = 'dummy title' control = cat.Control(id='ac-1', title=dummy_title) statement_part = common.Part(id='ac-1_smt', name='statement') prop = common.Property(name='label', value='a') part_a = common.Part(id='ac-1_smt.a', name='item', prose='a prose', props=[prop]) prop.value = 'b' part_b = common.Part(id='ac-1_smt.b', name='item', prose='b prose', props=[prop]) prop.value = '1' part_b1 = common.Part(id='ac-1_smt.b.1', name='item', prose='b.1 prose', props=[prop])