- Relocated and standardized tests for clean_release subsystem into __tests__ sub-packages. - Implemented missing unit tests for preparation_service, audit_service, and stages. - Enhanced API contract tests for candidate preparation and compliance reporting. - Updated 023-clean-repo-enterprise coverage matrix with final verification results. - Fixed relative import issues and model validation mismatches during test migration.
150 lines
5.6 KiB
Python
150 lines
5.6 KiB
Python
# [DEF:__tests__/test_clean_release:Module]
|
|
# @RELATION: VERIFIES -> ../clean_release.py
|
|
# @PURPOSE: Contract testing for Clean Release models
|
|
# [/DEF:__tests__/test_clean_release:Module]
|
|
|
|
import pytest
|
|
from datetime import datetime
|
|
from pydantic import ValidationError
|
|
from src.models.clean_release import (
|
|
ReleaseCandidate,
|
|
ReleaseCandidateStatus,
|
|
ProfileType,
|
|
CleanProfilePolicy,
|
|
DistributionManifest,
|
|
ManifestItem,
|
|
ManifestSummary,
|
|
ClassificationType,
|
|
ComplianceCheckRun,
|
|
CheckFinalStatus,
|
|
CheckStageResult,
|
|
CheckStageName,
|
|
CheckStageStatus,
|
|
ComplianceReport,
|
|
ExecutionMode
|
|
)
|
|
|
|
# @TEST_FIXTURE: valid_enterprise_candidate
|
|
@pytest.fixture
|
|
def valid_candidate_data():
|
|
return {
|
|
"candidate_id": "RC-001",
|
|
"version": "1.0.0",
|
|
"profile": ProfileType.ENTERPRISE_CLEAN,
|
|
"created_at": datetime.now(),
|
|
"created_by": "admin",
|
|
"source_snapshot_ref": "v1.0.0-snapshot"
|
|
}
|
|
|
|
def test_release_candidate_valid(valid_candidate_data):
|
|
rc = ReleaseCandidate(**valid_candidate_data)
|
|
assert rc.candidate_id == "RC-001"
|
|
assert rc.status == ReleaseCandidateStatus.DRAFT
|
|
|
|
def test_release_candidate_empty_id(valid_candidate_data):
|
|
valid_candidate_data["candidate_id"] = " "
|
|
with pytest.raises(ValueError, match="candidate_id must be non-empty"):
|
|
ReleaseCandidate(**valid_candidate_data)
|
|
|
|
# @TEST_FIXTURE: valid_enterprise_policy
|
|
@pytest.fixture
|
|
def valid_policy_data():
|
|
return {
|
|
"policy_id": "POL-001",
|
|
"policy_version": "1",
|
|
"active": True,
|
|
"prohibited_artifact_categories": ["test-data"],
|
|
"required_system_categories": ["core"],
|
|
"internal_source_registry_ref": "REG-1",
|
|
"effective_from": datetime.now(),
|
|
"profile": ProfileType.ENTERPRISE_CLEAN
|
|
}
|
|
|
|
# @TEST_INVARIANT: policy_purity
|
|
def test_enterprise_policy_valid(valid_policy_data):
|
|
policy = CleanProfilePolicy(**valid_policy_data)
|
|
assert policy.external_source_forbidden is True
|
|
|
|
# @TEST_EDGE: enterprise_policy_missing_prohibited
|
|
def test_enterprise_policy_missing_prohibited(valid_policy_data):
|
|
valid_policy_data["prohibited_artifact_categories"] = []
|
|
with pytest.raises(ValueError, match="enterprise-clean policy requires prohibited_artifact_categories"):
|
|
CleanProfilePolicy(**valid_policy_data)
|
|
|
|
# @TEST_EDGE: enterprise_policy_external_allowed
|
|
def test_enterprise_policy_external_allowed(valid_policy_data):
|
|
valid_policy_data["external_source_forbidden"] = False
|
|
with pytest.raises(ValueError, match="enterprise-clean policy requires external_source_forbidden=true"):
|
|
CleanProfilePolicy(**valid_policy_data)
|
|
|
|
# @TEST_INVARIANT: manifest_consistency
|
|
# @TEST_EDGE: manifest_count_mismatch
|
|
def test_manifest_count_mismatch():
|
|
summary = ManifestSummary(included_count=1, excluded_count=0, prohibited_detected_count=0)
|
|
item = ManifestItem(path="p", category="c", classification=ClassificationType.ALLOWED, reason="r")
|
|
|
|
# Valid
|
|
DistributionManifest(
|
|
manifest_id="m1", candidate_id="rc1", policy_id="p1",
|
|
generated_at=datetime.now(), generated_by="u", items=[item],
|
|
summary=summary, deterministic_hash="h"
|
|
)
|
|
|
|
# Invalid count
|
|
summary.included_count = 2
|
|
with pytest.raises(ValueError, match="manifest summary counts must match items size"):
|
|
DistributionManifest(
|
|
manifest_id="m1", candidate_id="rc1", policy_id="p1",
|
|
generated_at=datetime.now(), generated_by="u", items=[item],
|
|
summary=summary, deterministic_hash="h"
|
|
)
|
|
|
|
# @TEST_INVARIANT: run_integrity
|
|
# @TEST_EDGE: compliant_run_stage_fail
|
|
def test_compliant_run_validation():
|
|
base_run = {
|
|
"check_run_id": "run1",
|
|
"candidate_id": "rc1",
|
|
"policy_id": "p1",
|
|
"started_at": datetime.now(),
|
|
"triggered_by": "u",
|
|
"execution_mode": ExecutionMode.TUI,
|
|
"final_status": CheckFinalStatus.COMPLIANT,
|
|
"checks": [
|
|
CheckStageResult(stage=CheckStageName.DATA_PURITY, status=CheckStageStatus.PASS),
|
|
CheckStageResult(stage=CheckStageName.INTERNAL_SOURCES_ONLY, status=CheckStageStatus.PASS),
|
|
CheckStageResult(stage=CheckStageName.NO_EXTERNAL_ENDPOINTS, status=CheckStageStatus.PASS),
|
|
CheckStageResult(stage=CheckStageName.MANIFEST_CONSISTENCY, status=CheckStageStatus.PASS),
|
|
]
|
|
}
|
|
# Valid
|
|
ComplianceCheckRun(**base_run)
|
|
|
|
# One stage fails -> cannot be COMPLIANT
|
|
base_run["checks"][0].status = CheckStageStatus.FAIL
|
|
with pytest.raises(ValueError, match="compliant run requires PASS on all mandatory stages"):
|
|
ComplianceCheckRun(**base_run)
|
|
|
|
# Missing stage -> cannot be COMPLIANT
|
|
base_run["checks"] = base_run["checks"][1:]
|
|
with pytest.raises(ValueError, match="compliant run requires all mandatory stages"):
|
|
ComplianceCheckRun(**base_run)
|
|
|
|
def test_report_validation():
|
|
# Valid blocked report
|
|
ComplianceReport(
|
|
report_id="rep1", check_run_id="run1", candidate_id="rc1",
|
|
generated_at=datetime.now(), final_status=CheckFinalStatus.BLOCKED,
|
|
operator_summary="Blocked", structured_payload_ref="ref",
|
|
violations_count=2, blocking_violations_count=2
|
|
)
|
|
|
|
# BLOCKED with 0 blocking violations
|
|
with pytest.raises(ValueError, match="blocked report requires blocking violations"):
|
|
ComplianceReport(
|
|
report_id="rep1", check_run_id="run1", candidate_id="rc1",
|
|
generated_at=datetime.now(), final_status=CheckFinalStatus.BLOCKED,
|
|
operator_summary="Blocked", structured_payload_ref="ref",
|
|
violations_count=2, blocking_violations_count=0
|
|
)
|