243 lines
8.6 KiB
Python
243 lines
8.6 KiB
Python
from __future__ import annotations
|
|
|
|
import unittest
|
|
|
|
from govoplan_core.core.configuration_packages import (
|
|
ConfigurationModuleRequirement,
|
|
ConfigurationPackageEvidence,
|
|
ConfigurationPackageManifest,
|
|
ConfigurationPackageParent,
|
|
ConfigurationPreflightContext,
|
|
ConfigurationProviderExpectation,
|
|
dry_run_configuration_package,
|
|
validate_configuration_package_derivation,
|
|
)
|
|
|
|
|
|
def _evidence(*kinds: str) -> tuple[ConfigurationPackageEvidence, ...]:
|
|
return tuple(
|
|
ConfigurationPackageEvidence(
|
|
kind=kind, # type: ignore[arg-type]
|
|
reference=f"evidence/{kind}.json",
|
|
summary=f"Evidence for {kind}.",
|
|
checksum=f"sha256:{'a' * 64}",
|
|
)
|
|
for kind in kinds
|
|
)
|
|
|
|
|
|
class ConfigurationPackageArchitectureTests(unittest.TestCase):
|
|
def test_legacy_package_defaults_to_product_and_round_trips(self) -> None:
|
|
package = ConfigurationPackageManifest.from_mapping(
|
|
{"package_id": "example", "name": "Example", "version": "1.0.0"}
|
|
)
|
|
|
|
self.assertEqual(package.package_class, "product")
|
|
self.assertEqual(
|
|
ConfigurationPackageManifest.from_mapping(package.to_dict()),
|
|
package,
|
|
)
|
|
|
|
def test_reference_package_requires_operational_evidence(self) -> None:
|
|
with self.assertRaisesRegex(ValueError, "accessibility"):
|
|
ConfigurationPackageManifest(
|
|
package_id="reference.example",
|
|
name="Example reference",
|
|
version="1.0.0",
|
|
package_class="reference",
|
|
evidence=_evidence("target_test", "recovery"),
|
|
)
|
|
|
|
def test_reference_evidence_requires_content_checksums(self) -> None:
|
|
with self.assertRaisesRegex(ValueError, "without checksums"):
|
|
ConfigurationPackageManifest(
|
|
package_id="reference.unbound",
|
|
name="Unbound reference",
|
|
version="1.0.0",
|
|
package_class="reference",
|
|
evidence=tuple(
|
|
ConfigurationPackageEvidence(
|
|
kind=kind, # type: ignore[arg-type]
|
|
reference=f"evidence/{kind}.json",
|
|
summary=f"{kind} evidence.",
|
|
checksum=(
|
|
None
|
|
if kind == "target_test"
|
|
else f"sha256:{'b' * 64}"
|
|
),
|
|
)
|
|
for kind in (
|
|
"target_test",
|
|
"recovery",
|
|
"security",
|
|
"operations",
|
|
"accessibility",
|
|
"privacy",
|
|
"documentation",
|
|
)
|
|
),
|
|
)
|
|
|
|
def test_integration_package_preflight_checks_provider_contract_and_health(self) -> None:
|
|
package = ConfigurationPackageManifest(
|
|
package_id="integration.example",
|
|
name="Example integration",
|
|
version="1.0.0",
|
|
package_class="integration",
|
|
evidence=_evidence(
|
|
"target_test", "recovery", "operations", "documentation"
|
|
),
|
|
provider_expectations=(
|
|
ConfigurationProviderExpectation(
|
|
provider_id="connectors.example",
|
|
authority_mode="external_mirror",
|
|
minimum_maturity="read",
|
|
),
|
|
),
|
|
)
|
|
|
|
healthy = dry_run_configuration_package(
|
|
package,
|
|
(),
|
|
ConfigurationPreflightContext(
|
|
external_provider_declarations={
|
|
"connectors.example": {
|
|
"authority_modes": ["external_mirror"],
|
|
"maturity": "synchronize",
|
|
}
|
|
},
|
|
external_provider_states={
|
|
"connectors.example": {"health": "healthy"}
|
|
},
|
|
),
|
|
)
|
|
unhealthy = dry_run_configuration_package(
|
|
package,
|
|
(),
|
|
ConfigurationPreflightContext(
|
|
external_provider_declarations={
|
|
"connectors.example": {
|
|
"authority_modes": ["external_authoritative"],
|
|
"maturity": "discover",
|
|
}
|
|
},
|
|
external_provider_states={
|
|
"connectors.example": {"health": "error"}
|
|
},
|
|
),
|
|
)
|
|
|
|
self.assertFalse(
|
|
any(item.severity == "blocker" for item in healthy.diagnostics)
|
|
)
|
|
self.assertEqual(
|
|
{
|
|
"external_provider_authority_mode_unsupported",
|
|
"external_provider_maturity_insufficient",
|
|
"external_provider_unhealthy",
|
|
},
|
|
{item.code for item in unhealthy.diagnostics},
|
|
)
|
|
|
|
def test_provider_preflight_selects_the_requested_runtime_binding(self) -> None:
|
|
package = ConfigurationPackageManifest(
|
|
package_id="integration.calendar",
|
|
name="Calendar integration",
|
|
version="1.0.0",
|
|
package_class="integration",
|
|
evidence=_evidence(
|
|
"target_test", "recovery", "operations", "documentation"
|
|
),
|
|
provider_expectations=(
|
|
ConfigurationProviderExpectation(
|
|
provider_id="calendar.caldav_sync",
|
|
authority_mode="governed_sync",
|
|
minimum_maturity="synchronize",
|
|
binding_ref="calendar:sync-source:required",
|
|
freshness_expectation="current",
|
|
recovery_expectation="ready",
|
|
),
|
|
),
|
|
)
|
|
context = ConfigurationPreflightContext(
|
|
external_provider_declarations={
|
|
"calendar.caldav_sync": {
|
|
"authority_modes": ["governed_sync"],
|
|
"maturity": "synchronize",
|
|
"behavior": {},
|
|
}
|
|
},
|
|
external_provider_states={
|
|
"calendar.caldav_sync": {
|
|
"health": "warning",
|
|
"bindings": [
|
|
{
|
|
"binding_ref": "calendar:sync-source:other",
|
|
"authority_mode": "governed_sync",
|
|
"health": "error",
|
|
"freshness": "stale",
|
|
"recovery": "attention",
|
|
},
|
|
{
|
|
"binding_ref": "calendar:sync-source:required",
|
|
"authority_mode": "governed_sync",
|
|
"health": "healthy",
|
|
"freshness": "current",
|
|
"recovery": "ready",
|
|
},
|
|
],
|
|
}
|
|
},
|
|
)
|
|
|
|
result = dry_run_configuration_package(package, (), context)
|
|
|
|
self.assertFalse(
|
|
any(item.severity == "blocker" for item in result.diagnostics)
|
|
)
|
|
|
|
def test_derived_package_may_tighten_but_not_remove_parent_constraints(self) -> None:
|
|
parent = ConfigurationPackageManifest(
|
|
package_id="product.base",
|
|
name="Base",
|
|
version="1.0.0",
|
|
required_modules=(
|
|
ConfigurationModuleRequirement("connectors", "1.0.0"),
|
|
),
|
|
required_capabilities=("connectors.profiles",),
|
|
provider_expectations=(
|
|
ConfigurationProviderExpectation(
|
|
provider_id="connectors.example",
|
|
authority_mode="external_mirror",
|
|
minimum_maturity="read",
|
|
),
|
|
),
|
|
)
|
|
child = ConfigurationPackageManifest(
|
|
package_id="sector.example",
|
|
name="Sector example",
|
|
version="1.0.0",
|
|
package_class="sector",
|
|
parents=(
|
|
ConfigurationPackageParent("product.base", "1.0.0"),
|
|
),
|
|
evidence=_evidence("documentation"),
|
|
)
|
|
|
|
codes = {
|
|
item.code
|
|
for item in validate_configuration_package_derivation(child, parent)
|
|
}
|
|
self.assertEqual(
|
|
{
|
|
"package_parent_module_constraint_loosened",
|
|
"package_parent_capability_constraint_loosened",
|
|
"package_parent_provider_constraint_removed",
|
|
},
|
|
codes,
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|