From d81b3f62823b1961d4473fbd8fb4f5d17de0902b Mon Sep 17 00:00:00 2001 From: Simon Davy Date: Mon, 16 Oct 2023 17:13:57 +0100 Subject: [PATCH] Add very basic json validation. --- sacro/models.py | 17 +++++++++++++++++ tests/test_models.py | 24 ++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/sacro/models.py b/sacro/models.py index 87132bd..6384ae0 100644 --- a/sacro/models.py +++ b/sacro/models.py @@ -20,6 +20,9 @@ def load_from_path(path): class ACROOutputs(dict): """An ACRO json output file""" + class InvalidFile(Exception): + pass + path: Path version: str = None config: dict = field(default_factory=dict) @@ -30,6 +33,20 @@ def __post_init__(self): if config_path.exists(): self.config = json.loads(config_path.read_text()) + # super basic structural validation + try: + assert "version" in self.raw_metadata + assert "results" in self.raw_metadata + assert len(self.raw_metadata["results"]) > 0 + for result in self.raw_metadata["results"].values(): + assert "files" in result + assert len(result["files"]) > 0 + for filedata in result["files"]: + assert "name" in filedata + + except AssertionError as exc: + raise self.InvalidFile(f"{self.path} is not a valid ACRO json file: {exc}") + self.version = self.raw_metadata["version"] self.update(self.raw_metadata["results"]) self.annotate() diff --git a/tests/test_models.py b/tests/test_models.py index f957a2c..1135fbd 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,3 +1,10 @@ +import json + +import pytest + +from sacro import models + + def test_outputs_annotation(test_outputs): assert test_outputs.version == "0.4.0" for metadata in test_outputs.values(): @@ -30,3 +37,20 @@ def test_outputs_annotation_checksum_failed(test_outputs): assert test_outputs[first_output]["files"][0]["checksum"] == "bad checksum" assert test_outputs[first_output]["files"][0]["checksum_valid"] is False + + +@pytest.mark.parametrize( + "data", + [ + {}, + {"version": "1"}, + {"version": "1", "results": {}}, + {"version": "1", "results": {"name": {"files": []}}}, + {"version": "1", "results": {"name": {"notfiles": "foo"}}}, + ], +) +def test_validation(data, tmp_path): + bad_json = tmp_path / "bad.json" + bad_json.write_text(json.dumps(data)) + with pytest.raises(models.ACROOutputs.InvalidFile): + models.ACROOutputs(bad_json)