Skip to content

Commit b74e0ef

Browse files
committed
test: add tests (and fix some bugs)
1 parent 243b35e commit b74e0ef

File tree

5 files changed

+126
-36
lines changed

5 files changed

+126
-36
lines changed

src/opossum_lib/core/services/extract_subtree_impl.py

+13-8
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ def _extract_scan_results(opossum: Opossum, subpath: PurePosixPath) -> ScanResul
5353
kept_attributions = set()
5454
for resource in new_root_resource.all_resources():
5555
kept_attributions |= set(resource.attributions)
56+
kept_attributions |= opossum.scan_results.unassigned_attributions
5657
new_attribution_to_id = {
5758
attribution: id
5859
for (attribution, id) in opossum.scan_results.attribution_to_id.items()
@@ -86,28 +87,32 @@ def _filter_review_results(
8687
update={"input_file_md5_checksum": None}
8788
)
8889

90+
# the paths used as keys for manual_attributions include a leading "/"
8991
absolute_subpath = "/" / subpath
90-
# the paths used as keys for manual_attributions include a leading "/"
91-
new_manual_attributions = {
92-
path: attributions
93-
for (path, attributions) in old_review_results.manual_attributions.items()
94-
if PurePosixPath(path).is_relative_to(absolute_subpath)
95-
}
9692
new_resources_to_attributions = {
9793
path: attributions
9894
for (path, attributions) in old_review_results.resources_to_attributions.items()
9995
if PurePosixPath(path).is_relative_to(absolute_subpath)
10096
}
10197

98+
new_manual_attribution_ids = {
99+
id for ids in new_resources_to_attributions.values() for id in ids
100+
}
101+
new_manual_attributions = {
102+
id: attributions
103+
for (id, attributions) in old_review_results.manual_attributions.items()
104+
if id in new_manual_attribution_ids
105+
}
106+
102107
# since we loaded an Opossum file, every resource has a preexisting ID and thus
103108
# new_scan_results.attribution_to_id contains the ID of each resource
104109
# in new_scan_results
110+
all_external_attribution_ids = set(new_scan_results.attribution_to_id.values())
105111
if old_review_results.resolved_external_attributions:
106-
all_attributions = set(new_scan_results.attribution_to_id.values())
107112
new_resolved_external_attributions = [
108113
attributionID
109114
for attributionID in old_review_results.resolved_external_attributions
110-
if attributionID in all_attributions
115+
if attributionID in all_external_attribution_ids
111116
]
112117
else:
113118
new_resolved_external_attributions = None

tests/core/entities/generators/opossum_provider.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ def opossum(
3434
if generate_review_results is None:
3535
generate_review_results = bool(self.random_int(max=1))
3636
if generate_review_results and not review_results:
37-
review_results = self.review_result_provider.output_file()
37+
review_results = self.review_result_provider.output_file(
38+
scan_results=scan_results
39+
)
3840
return Opossum(
3941
scan_results=scan_results,
4042
review_results=review_results,

tests/input_formats/opossum/entities/generators/generate_outfile_information.py

+61-26
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
from faker.providers.misc import Provider as MiscProvider
1313
from faker.providers.person import Provider as PersonProvider
1414

15+
from opossum_lib.core.entities.scan_results import ScanResults
1516
from opossum_lib.shared.entities.opossum_input_file_model import (
1617
OpossumPackageIdentifierModel,
17-
OpossumPackageModel,
1818
ResourceInFileModel,
1919
)
2020
from opossum_lib.shared.entities.opossum_output_file_model import (
@@ -52,16 +52,36 @@ def output_file(
5252
manual_attributions: dict[str, ManualAttributions] | None = None,
5353
resources_to_attributions: dict[str, list[str]] | None = None,
5454
resolved_external_attributions: list[str] | None = None,
55+
scan_results: ScanResults | None = None,
5556
) -> OpossumOutputFileModel:
5657
if metadata is None:
57-
metadata = self.outfile_metadata()
58+
project_id = scan_results.metadata.project_id if scan_results else None
59+
file_creation_date = (
60+
scan_results.metadata.file_creation_date if scan_results else None
61+
)
62+
metadata = self.outfile_metadata(
63+
project_id=project_id,
64+
file_creation_date=file_creation_date,
65+
)
5866
if manual_attributions is None:
5967
manual_attributions = self.manual_attributions()
6068
if resolved_external_attributions is None:
61-
resolved_external_attributions = self.resolved_external_attributions()
69+
external_attributions_ids = (
70+
list(scan_results.attribution_to_id.values()) if scan_results else None
71+
)
72+
resolved_external_attributions = self.resolved_external_attributions(
73+
external_attributions_ids=external_attributions_ids
74+
)
6275
if resources_to_attributions is None:
76+
all_paths = None
77+
if scan_results:
78+
all_paths = [
79+
str(resource.path)
80+
for resource in scan_results.resources.all_resources()
81+
]
6382
resources_to_attributions = self.resources_to_attributions(
64-
manual_attributions=manual_attributions
83+
manual_attributions=manual_attributions,
84+
all_paths=all_paths,
6585
)
6686
return OpossumOutputFileModel(
6787
metadata=metadata,
@@ -185,32 +205,54 @@ def manual_attribution(
185205
def resolved_external_attributions(
186206
self,
187207
*,
188-
external_attributions: dict[OpossumPackageIdentifierModel, OpossumPackageModel]
189-
| None = None,
208+
external_attributions_ids: list[OpossumPackageIdentifierModel] | None = None,
190209
min_count: int = 1,
191210
max_count: int = 5,
192211
) -> list[str]:
193212
length = self.random_int(min=min_count, max=max_count)
194-
if external_attributions is not None:
195-
length = min(length, len(external_attributions))
196-
ids = list(external_attributions.keys())
197-
return list(self.random_elements(elements=ids, length=length, unique=True))
213+
if external_attributions_ids is not None:
214+
length = min(length, len(external_attributions_ids))
215+
return list(
216+
self.random_elements(
217+
external_attributions_ids, length=length, unique=True
218+
)
219+
)
198220
else:
199221
return [str(self.misc_provider.uuid4()) for _ in range(length)]
200222

223+
def _resources_to_path(
224+
self,
225+
resources: ResourceInFileModel,
226+
) -> list[str]:
227+
paths: list[str] = []
228+
if isinstance(resources, int):
229+
return paths
230+
for path_segment, children in resources.items():
231+
if isinstance(children, int):
232+
paths.append(path_segment)
233+
else:
234+
subpaths = self._resources_to_path(children)
235+
paths.extend(path_segment + "/" + subpath for subpath in subpaths)
236+
return paths
237+
238+
def _ensure_root_prefix(self, path: str) -> str:
239+
if not path.startswith("/"):
240+
return "/" + path
241+
else:
242+
return path
243+
201244
def resources_to_attributions(
202245
self,
203246
*,
204247
resources: ResourceInFileModel | None = None,
205248
manual_attributions: dict[str, ManualAttributions] | None = None,
249+
all_paths: list[str] | None,
206250
min_count: int = 1,
207251
max_count: int = 5,
208252
num_attributions: int = 3,
209253
) -> dict[str, list[str]]:
210254
if manual_attributions is None:
211255
manual_attributions = self.manual_attributions()
212-
if resources is None:
213-
resources = self.file_information_provider.resource_in_file()
214256
if manual_attributions is not None:
215257
attribution_ids = list(manual_attributions.keys())
216258
else:
@@ -219,21 +261,14 @@ def resources_to_attributions(
219261
for _ in range(self.random_int(max=max_count * num_attributions))
220262
]
221263

222-
def resources_to_path(
223-
resources: ResourceInFileModel,
224-
) -> list[str]:
225-
paths: list[str] = []
226-
if isinstance(resources, int):
227-
return paths
228-
for path_segment, children in resources.items():
229-
if isinstance(children, int):
230-
paths.append(path_segment)
231-
else:
232-
subpaths = resources_to_path(children)
233-
paths.extend(path_segment + "/" + subpath for subpath in subpaths)
234-
return paths
264+
all_paths = all_paths or []
265+
if resources:
266+
all_paths.extend(self._resources_to_path(resources))
267+
if not all_paths:
268+
resources = self.file_information_provider.resource_in_file()
269+
all_paths.extend(self._resources_to_path(resources))
270+
all_paths = [self._ensure_root_prefix(path) for path in all_paths]
235271

236-
all_paths = ["/" + path for path in resources_to_path(resources)]
237272
number_of_paths = min(
238273
self.random_int(min=min_count, max=max_count), len(all_paths)
239274
)

tests/setup/opossum_faker_setup.py

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ def __init__(self) -> None:
4040
self.output_file = review_result_provider.output_file
4141
self.outfile_metadata = review_result_provider.outfile_metadata
4242
self.manual_attributions = review_result_provider.manual_attributions
43+
self.manual_attribution = review_result_provider.manual_attribution
4344
self.resources_to_attributions = (
4445
review_result_provider.resources_to_attributions
4546
)

tests/test_cli.py

+48-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from _pytest.logging import LogCaptureFixture
1313
from click.testing import CliRunner, Result
1414

15-
from opossum_lib.cli import generate
15+
from opossum_lib.cli import extract_subtree, generate
1616
from opossum_lib.core.services.write_opossum_file import write_opossum_file
1717
from opossum_lib.shared.constants import (
1818
INPUT_JSON_NAME,
@@ -208,3 +208,50 @@ def test_convert(self, tmp_path: Path) -> None:
208208
)
209209

210210
assert result.exit_code == 0
211+
212+
213+
class TestExtractSubtree:
214+
def _run_extraction(
215+
self,
216+
tmp_path: Path,
217+
subpath: str,
218+
opossumfile: str = "opossum_input.opossum",
219+
outputfile: str = "output.opossum",
220+
) -> Result:
221+
runner = CliRunner()
222+
cmd_line_arguments = [
223+
str(test_data_path / opossumfile),
224+
subpath,
225+
"-o",
226+
str(tmp_path / outputfile),
227+
]
228+
result = runner.invoke(extract_subtree, cmd_line_arguments)
229+
return result
230+
231+
def test_successful_extraction(self, tmp_path: Path) -> None:
232+
result = self._run_extraction(tmp_path, "Frontend/Components")
233+
assert result.exit_code == 0
234+
235+
def test_equivalency_of_subpaths(self, tmp_path: Path) -> None:
236+
result1 = self._run_extraction(
237+
tmp_path, "Frontend/Components", outputfile="out_basic"
238+
)
239+
result2 = self._run_extraction(
240+
tmp_path, "/Frontend/Components", outputfile="out_root"
241+
)
242+
result3 = self._run_extraction(
243+
tmp_path, "Frontend/Components/", outputfile="out_trailing"
244+
)
245+
246+
assert result1.exit_code == 0
247+
assert result2.exit_code == 0
248+
assert result3.exit_code == 0
249+
250+
with open(tmp_path / "out_basic.opossum", "rb") as inp:
251+
file_contents1 = inp.read()
252+
with open(tmp_path / "out_root.opossum", "rb") as inp:
253+
file_contents2 = inp.read()
254+
with open(tmp_path / "out_trailing.opossum", "rb") as inp:
255+
file_contents3 = inp.read()
256+
257+
assert file_contents1 == file_contents2 == file_contents3

0 commit comments

Comments
 (0)