73 lines
2.7 KiB
Python
73 lines
2.7 KiB
Python
from __future__ import annotations
|
|
|
|
import importlib.util
|
|
import pathlib
|
|
import unittest
|
|
|
|
|
|
MODULE_PATH = pathlib.Path(__file__).with_name("validate.py")
|
|
SPEC = importlib.util.spec_from_file_location("tenancy_posture_validate", MODULE_PATH)
|
|
assert SPEC and SPEC.loader
|
|
VALIDATE = importlib.util.module_from_spec(SPEC)
|
|
SPEC.loader.exec_module(VALIDATE)
|
|
|
|
|
|
def declaration() -> dict:
|
|
reasons = {axis: "floor explained" for axis in VALIDATE.AXES}
|
|
return {
|
|
"schema_version": "0.1",
|
|
"framework": "netkingdom-tenancy-posture",
|
|
"service": "example",
|
|
"role": "test",
|
|
"tenancy": {
|
|
"current": {"I": 1, "A": 1, "E": 0, "P": 0, "R": 1, "V": 0},
|
|
"target": {"I": 1, "A": 1, "E": 0, "P": 0, "R": 1, "V": 0},
|
|
"reviewed": "2026-08-17",
|
|
"review_due": "2027-02-17",
|
|
"service_class": "interactive",
|
|
"reason": reasons,
|
|
},
|
|
}
|
|
|
|
|
|
class SemanticValidationTests(unittest.TestCase):
|
|
def validate(self, document: dict) -> list[str]:
|
|
return VALIDATE.validate_semantics(document, pathlib.Path("tenancy.yaml"))
|
|
|
|
def test_floor_vector_with_reasons_is_valid(self) -> None:
|
|
self.assertEqual([], self.validate(declaration()))
|
|
|
|
def test_level_above_floor_requires_exact_evidence_key(self) -> None:
|
|
document = declaration()
|
|
document["tenancy"]["current"]["A"] = 2
|
|
self.assertIn("current A2 has no evidence entry", self.validate(document)[0])
|
|
document["evidence"] = {"A2": "docs/evidence/authorization.md"}
|
|
self.assertEqual([], self.validate(document))
|
|
|
|
def test_implemented_level_must_be_above_current(self) -> None:
|
|
document = declaration()
|
|
document["tenancy"]["implemented"] = {"E": 0}
|
|
self.assertIn("implemented E0 must be above current E0", self.validate(document)[0])
|
|
|
|
def test_provider_available_cannot_exceed_maximum(self) -> None:
|
|
document = declaration()
|
|
document["provider"] = {"axes": {"V": {"available": 2, "maximum": 1}}}
|
|
self.assertIn("provider V available 2 exceeds maximum 1", self.validate(document)[0])
|
|
|
|
def test_review_due_cannot_precede_review(self) -> None:
|
|
document = declaration()
|
|
document["tenancy"]["review_due"] = "2026-08-16"
|
|
self.assertIn("review_due precedes reviewed", self.validate(document)[0])
|
|
|
|
def test_service_names_are_unique(self) -> None:
|
|
entry = declaration()
|
|
document = {
|
|
"schema_version": "0.1",
|
|
"framework": "netkingdom-tenancy-posture",
|
|
"services": [entry, entry],
|
|
}
|
|
self.assertIn("service names must be unique", self.validate(document)[0])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|