diff --git a/fossology/report.py b/fossology/report.py index 10f55d9..3217d51 100644 --- a/fossology/report.py +++ b/fossology/report.py @@ -53,8 +53,23 @@ def generate_report( response = self.session.get(f"{self.api}/report", headers=headers) if response.status_code == 201: - report_id = re.search("[0-9]*$", response.json()["message"]) - return report_id[0] # type: ignore + message = None + try: + message = response.json()["message"] + match = re.search(r"[0-9]+$", message) + except (ValueError, KeyError, TypeError) as exc: + description = ( + f"Report generation for upload {upload.uploadname} succeeded " + f"but response could not be parsed: {exc}" + ) + raise FossologyApiError(description, response) from exc + if match is None: + description = ( + f"Report generation for upload {upload.uploadname} succeeded " + f"but report ID could not be parsed from response message: {message!r}" + ) + raise FossologyApiError(description, response) + return int(match[0]) elif response.status_code == 403: description = f"Report generation for upload {upload.id} not authorized" diff --git a/tests/test_report.py b/tests/test_report.py index b3a25ad..97e21d3 100644 --- a/tests/test_report.py +++ b/tests/test_report.py @@ -47,6 +47,88 @@ def test_generate_report(foss: Fossology, upload: Upload): Path(report_path / report_name).unlink() +@responses.activate +def test_generate_report_unparseable_message( + foss_server: str, foss: Fossology, upload: Upload +): + responses.add( + responses.GET, + f"{foss_server}/api/v1/report", + status=201, + json={"code": 201, "message": "Report has been queued."}, + ) + with pytest.raises(FossologyApiError) as excinfo: + foss.generate_report(upload) + assert "report ID could not be parsed" in str(excinfo.value) + + +@responses.activate +def test_generate_report_malformed_response_body( + foss_server: str, foss: Fossology, upload: Upload +): + responses.add( + responses.GET, + f"{foss_server}/api/v1/report", + status=201, + body="Internal Server Error", + content_type="text/html", + ) + with pytest.raises(FossologyApiError) as excinfo: + foss.generate_report(upload) + assert "response could not be parsed" in str(excinfo.value) + + +@responses.activate +def test_generate_report_missing_message_key( + foss_server: str, foss: Fossology, upload: Upload +): + responses.add( + responses.GET, + f"{foss_server}/api/v1/report", + status=201, + json={"code": 201, "type": "INFO"}, + ) + with pytest.raises(FossologyApiError) as excinfo: + foss.generate_report(upload) + assert "response could not be parsed" in str(excinfo.value) + + +@responses.activate +def test_generate_report_non_string_message( + foss_server: str, foss: Fossology, upload: Upload +): + responses.add( + responses.GET, + f"{foss_server}/api/v1/report", + status=201, + json={"code": 201, "message": 42}, + ) + with pytest.raises(FossologyApiError) as excinfo: + foss.generate_report(upload) + assert "response could not be parsed" in str(excinfo.value) + + +@responses.activate +def test_generate_report_returns_int( + foss_server: str, foss: Fossology, upload: Upload +): + responses.add( + responses.GET, + f"{foss_server}/api/v1/report", + status=201, + json={ + "code": 201, + "message": ( + "Report will be generated in the back ground, " + "report id is 42" + ), + }, + ) + report_id = foss.generate_report(upload) + assert report_id == 42 + assert isinstance(report_id, int) + + @responses.activate def test_report_error(foss_server: str, foss: Fossology, upload: Upload): responses.add(