Files
wyndham-ARR/tests/test_arr_ingestion_contracts.py
2026-07-29 16:38:05 +08:00

193 lines
6.5 KiB
Python

from __future__ import annotations
import copy
import unittest
from arr_ingestion.contracts import DeliveryEnvelope, IngestionError
SHA_A = "a" * 64
SHA_B = "b" * 64
SHA_C = "c" * 64
SHA_D = "d" * 64
SHA_E = "e" * 64
def artifact(
object_key: str,
original_filename: str,
sha256: str,
byte_size: int,
mime_type: str,
) -> dict[str, object]:
return {
"object_key": object_key,
"original_filename": original_filename,
"sha256": sha256,
"byte_size": byte_size,
"mime_type": mime_type,
}
def success_envelope() -> dict[str, object]:
return {
"delivery_schema_version": "1.0",
"delivery_id": "delivery-001",
"job_id": "job-001",
"attempt_no": 1,
"status": "success",
"processor_version": "3.0.0",
"rule_set_sha256": SHA_A,
"result_schema_version": "3.0",
"business_date": "2026-07-27",
"artifacts": {
"source_xml": artifact(
"arr/jobs/job-001/input/source.xml",
"source.xml",
SHA_A,
100,
"application/xml",
),
"daily_report": artifact(
"arr/jobs/job-001/output/7.27.xlsx",
"7.27.xlsx",
SHA_B,
200,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
),
"result_json": artifact(
"arr/jobs/job-001/output/result.json",
"result.json",
SHA_C,
300,
"application/json",
),
"structured_result_json": artifact(
"arr/jobs/job-001/output/structured-result.json",
"structured-result.json",
SHA_D,
400,
"application/json",
),
"exception_report": None,
},
}
def failure_envelope() -> dict[str, object]:
payload = success_envelope()
payload["status"] = "failed"
payload["business_date"] = None
artifacts = payload["artifacts"]
assert isinstance(artifacts, dict)
artifacts["daily_report"] = None
artifacts["exception_report"] = artifact(
"arr/jobs/job-001/output/exception.xlsx",
"exception.xlsx",
SHA_E,
500,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
)
return payload
class DeliveryEnvelopeTests(unittest.TestCase):
def test_success_contract_is_strict_and_typed(self):
envelope = DeliveryEnvelope.from_dict(success_envelope())
self.assertEqual(envelope.job_id, "job-001")
self.assertEqual(envelope.attempt_no, 1)
self.assertEqual(envelope.business_date.isoformat(), "2026-07-27")
self.assertEqual(envelope.artifacts["source_xml"].file_kind, "opera_xml")
self.assertIsNone(envelope.artifacts["exception_report"])
def test_failed_contract_requires_exception_and_forbids_daily(self):
envelope = DeliveryEnvelope.from_dict(failure_envelope())
self.assertEqual(envelope.status, "failed")
self.assertIsNone(envelope.business_date)
self.assertIsNone(envelope.artifacts["daily_report"])
self.assertIsNotNone(envelope.artifacts["exception_report"])
missing_exception = failure_envelope()
artifacts = missing_exception["artifacts"]
assert isinstance(artifacts, dict)
artifacts["exception_report"] = None
with self.assertRaisesRegex(IngestionError, "failed delivery"):
DeliveryEnvelope.from_dict(missing_exception)
def test_extra_fields_and_monthly_artifacts_are_rejected(self):
extra = success_envelope()
extra["message"] = "not allowed"
with self.assertRaisesRegex(IngestionError, "field set"):
DeliveryEnvelope.from_dict(extra)
monthly = success_envelope()
artifacts = monthly["artifacts"]
assert isinstance(artifacts, dict)
artifacts["monthly_report"] = artifact(
"arr/jobs/job-001/output/monthly.xlsx",
"monthly.xlsx",
SHA_E,
500,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
)
with self.assertRaisesRegex(IngestionError, "artifact field set"):
DeliveryEnvelope.from_dict(monthly)
def test_object_keys_and_filenames_cannot_escape_or_impersonate_roles(self):
invalid_keys = (
"/absolute/source.xml",
"../source.xml",
"arr/jobs/../source.xml",
"arr\\jobs\\source.xml",
"arr//jobs/source.xml",
)
for invalid in invalid_keys:
payload = success_envelope()
artifacts = payload["artifacts"]
assert isinstance(artifacts, dict)
source = artifacts["source_xml"]
assert isinstance(source, dict)
source["object_key"] = invalid
with self.subTest(object_key=invalid):
with self.assertRaises(IngestionError):
DeliveryEnvelope.from_dict(payload)
bad_filename = success_envelope()
artifacts = bad_filename["artifacts"]
assert isinstance(artifacts, dict)
daily = artifacts["daily_report"]
assert isinstance(daily, dict)
daily["original_filename"] = "../7.27.xlsx"
with self.assertRaises(IngestionError):
DeliveryEnvelope.from_dict(bad_filename)
bad_mime = success_envelope()
artifacts = bad_mime["artifacts"]
assert isinstance(artifacts, dict)
source = artifacts["source_xml"]
assert isinstance(source, dict)
source["mime_type"] = "text/plain"
with self.assertRaisesRegex(IngestionError, "source_xml metadata"):
DeliveryEnvelope.from_dict(bad_mime)
def test_contract_rejects_bad_versions_hashes_dates_and_identifiers(self):
mutations = (
("delivery_schema_version", "2.0"),
("delivery_id", "contains spaces"),
("attempt_no", 0),
("processor_version", ""),
("rule_set_sha256", "not-a-hash"),
("result_schema_version", "2.0"),
("business_date", "2026-02-30"),
)
for field, value in mutations:
payload = copy.deepcopy(success_envelope())
payload[field] = value
with self.subTest(field=field):
with self.assertRaises(IngestionError):
DeliveryEnvelope.from_dict(payload)
if __name__ == "__main__":
unittest.main(verbosity=2)