Skip to content

Commit

Permalink
fix: improve bad property error message by including csv row number (#…
Browse files Browse the repository at this point in the history
…1466)

* fix: improve bad property error message by including csv row number

Signed-off-by: Lou DeGenaro <lou.degenaro@gmail.com>

* fix: handle empty ProfileSource correctly

Signed-off-by: Lou DeGenaro <lou.degenaro@gmail.com>

* fix sonar code smells

Signed-off-by: Lou DeGenaro <lou.degenaro@gmail.com>

* fix sonar code smell

Signed-off-by: Lou DeGenaro <lou.degenaro@gmail.com>

---------

Signed-off-by: Lou DeGenaro <lou.degenaro@gmail.com>
  • Loading branch information
degenaro committed Oct 24, 2023
1 parent 5289f51 commit ab97beb
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 15 deletions.
66 changes: 66 additions & 0 deletions tests/trestle/tasks/csv_to_oscal_cd_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1138,3 +1138,69 @@ def test_execute_validation(tmp_path: pathlib.Path) -> None:
assert component.props[2].name == 'Check_Description'
assert component.props[2].value == 'validation-check-description'
assert len(component.control_implementations) == 0


def test_row_property_builder(tmp_path):
"""Test row property builder."""
# valid
prop = csv_to_oscal_cd.row_property_builder(
row=0,
name='name',
value='value',
ns='https://www.ibm.com',
class_='class',
remarks='remarks',
)
assert prop
# missing name
try:
prop = csv_to_oscal_cd.row_property_builder(
row=0,
name=None,
value='value',
ns='https://www.ibm.com',
class_='class',
remarks='remarks',
)
raise AssertionError('missing name OK?')
except Exception:
assert prop
# missing value
try:
prop = csv_to_oscal_cd.row_property_builder(
row=0,
name='name',
value=None,
ns='https://www.ibm.com',
class_='class',
remarks='remarks',
)
raise AssertionError('missing value OK?')
except Exception:
assert prop
# invalid ns
try:
prop = csv_to_oscal_cd.row_property_builder(
row=0,
name='name',
value='value',
ns='foobar',
class_='class',
remarks='remarks',
)
raise AssertionError('invalid ns OK?')
except Exception:
assert prop
# invalid class
try:
prop = csv_to_oscal_cd.row_property_builder(
row=0,
name='name',
value='value',
ns='https://www.ibm.com',
class_='\n',
remarks='remarks',
)
raise AssertionError('invalid class OK?')
except Exception:
assert prop
86 changes: 71 additions & 15 deletions trestle/tasks/csv_to_oscal_cd.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,65 @@ def derive_part_id(control_mapping: str) -> str:
return rval


def etype(target: str) -> str:
"""Get etype."""
if target:
return 'invalid'
else:
return 'missing'


def row_property_builder(row: int, name: str, value, ns: str, class_: str, remarks: str) -> Property:
"""Row property builder."""
# name
try:
Property(
name=name,
value='value',
)
except Exception:
text = f'property for row: {row} name: {name} is {etype(name)}'
raise RuntimeError(text)
# value
try:
Property(
name=name,
value=value,
)
except Exception:
text = f'property for row: {row} value: {value} is {etype(value)}'
raise RuntimeError(text)
# ns
try:
Property(
name=name,
value=value,
ns=ns,
)
except Exception:
text = f'property for row: {row} ns: {ns} is {etype(ns)}'
raise RuntimeError(text)
# class
try:
Property(
name=name,
value=value,
class_=class_,
)
except Exception:
text = f'property for row: {row} class: {class_} is {etype(class_)}'
raise RuntimeError(text)
# prop
prop = Property(
name=name,
value=value,
ns=ns,
class_=class_,
remarks=remarks,
)
return prop


class CsvToOscalComponentDefinition(TaskBase):
"""
Task to create OSCAL ComponentDefinition json.
Expand Down Expand Up @@ -911,18 +970,15 @@ def __init__(self, row_number: int, rule_set: str) -> None:
def add_prop(self, name: str, value: str, ns: str, class_: str) -> None:
"""Add prop."""
if value is not None and len(value):
try:
prop = Property(
name=name,
value=value,
ns=ns,
class_=class_,
remarks=self._rule_set,
)
self._props[name] = prop
except Exception:
text = f'Invalid property name: {name} value: {value} remarks: {self._rule_set}'
raise RuntimeError(text)
prop = row_property_builder(
row=self._row_number,
name=name,
value=value,
ns=ns,
class_=class_,
remarks=self._rule_set,
)
self._props[name] = prop

def get_props(self) -> List[Property]:
"""Get props."""
Expand Down Expand Up @@ -1438,8 +1494,6 @@ def __init__(self, csv_path: pathlib.Path) -> None:
self._csv_controls_map = {}
self._csv_profile_list = []
for row_num, row in self.row_generator():
if self._is_no_control(row):
continue
self._check_row_minimum_requirements(row_num, row)
component_title = self.get_row_value(row, f'{COMPONENT_TITLE}')
component_type = self.get_row_value(row, f'{COMPONENT_TYPE}')
Expand All @@ -1454,7 +1508,7 @@ def __init__(self, csv_path: pathlib.Path) -> None:
logger.debug(f'csv-rules: {key} {self._csv_rules_map[key][0]}')
# set parameters, by component
source = self.get_row_value(row, PROFILE_SOURCE)
if source not in self._csv_profile_list:
if source and source not in self._csv_profile_list:
self._csv_profile_list.append(source)
description = self.get_row_value(row, PROFILE_DESCRIPTION)
param_id = self.get_row_value(row, PARAMETER_ID)
Expand Down Expand Up @@ -1489,6 +1543,8 @@ def row_generator(self) -> Generator[Union[int, Iterator[List[str]]], None, None
index += 1
if index < 3:
continue
if self._is_no_control(row):
continue
logger.debug(f'row_gen: {index} {row}')
yield index, row

Expand Down

0 comments on commit ab97beb

Please sign in to comment.