Files
breakpilot-compliance/ai-compliance-sdk/internal/ucca/tom_mapper_test.go
Benjamin Admin 38e278ee3c
All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 32s
CI / test-python-backend-compliance (push) Successful in 29s
CI / test-python-document-crawler (push) Successful in 20s
CI / test-python-dsms-gateway (push) Successful in 18s
feat(ucca): Pflichtendatenbank v2 (325 Obligations), Trigger-Engine, TOM-Control-Mapping
- 9 Regulation-JSON-Dateien (DSGVO 80, AI Act 60, NIS2 40, BDSG 30, TTDSG 20, DSA 35, Data Act 25, EU-Maschinen 15, DORA 20)
- Condition-Tree-Engine fuer automatische Pflichtenselektion (all_of/any_of, 80+ Field-Paths)
- Generischer JSONRegulationModule-Loader mit YAML-Fallback
- Bidirektionales TOM-Control-Mapping (291 Obligation→Control, 92 Control→Obligation)
- Gap-Analyse-Engine (Compliance-%, Priority Actions, Domain Breakdown)
- ScopeDecision→UnifiedFacts Bridge fuer Auto-Profiling
- 4 neue API-Endpoints (assess-from-scope, tom-controls, gap-analysis, reverse-lookup)
- Frontend: Auto-Profiling Button, Regulation-Filter Chips, TOM-Panel, Gap-Analyse-View
- 18 Unit Tests (Condition Engine, v2 Loader, TOM Mapper)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 14:51:44 +01:00

176 lines
5.0 KiB
Go

package ucca
import (
"testing"
)
func TestTOMControlLoader(t *testing.T) {
index, err := LoadTOMControls()
if err != nil {
t.Skipf("TOM controls not found: %v", err)
}
if len(index.ByID) == 0 {
t.Error("expected controls indexed by ID")
}
if len(index.ByDomain) == 0 {
t.Error("expected controls indexed by domain")
}
t.Logf("Loaded %d TOM controls across %d domains", len(index.ByID), len(index.ByDomain))
// Check known control
ctrl, ok := index.GetControl("TOM.GOV.01")
if !ok || ctrl == nil {
t.Error("expected TOM.GOV.01 to exist")
} else if ctrl.Title == "" {
t.Error("expected TOM.GOV.01 to have a title")
}
// Check domain
govCtrls := index.GetControlsByDomain("GOV")
if len(govCtrls) == 0 {
t.Error("expected GOV domain to have controls")
}
// Validate known ID
if !index.ValidateControlID("TOM.GOV.01") {
t.Error("TOM.GOV.01 should be valid")
}
if index.ValidateControlID("TOM.FAKE.99") {
t.Error("TOM.FAKE.99 should be invalid")
}
}
func TestTOMObligationMapper_FromObligations(t *testing.T) {
index, err := LoadTOMControls()
if err != nil {
t.Skipf("TOM controls not found: %v", err)
}
// Create test obligations with tom_control_ids
obligations := []V2Obligation{
{
ID: "TEST-OBL-001",
TOMControlIDs: []string{"TOM.GOV.01", "TOM.GOV.02"},
Priority: "kritisch",
},
{
ID: "TEST-OBL-002",
TOMControlIDs: []string{"TOM.GOV.01", "TOM.CRYPTO.01"},
Priority: "hoch",
},
}
mapper := NewTOMObligationMapperFromObligations(index, obligations)
// Check obligation->control
controls := mapper.GetControlsForObligation("TEST-OBL-001")
if len(controls) != 2 {
t.Errorf("expected 2 controls for TEST-OBL-001, got %d", len(controls))
}
// Check control->obligation (reverse)
oblIDs := mapper.GetObligationsForControl("TOM.GOV.01")
if len(oblIDs) != 2 {
t.Errorf("expected 2 obligations for TOM.GOV.01, got %d", len(oblIDs))
}
// Check deduplicated requirements
frameworkObls := make([]Obligation, len(obligations))
for i, o := range obligations {
frameworkObls[i] = Obligation{
ID: o.ID,
Priority: ObligationPriority(o.Priority),
ExternalResources: o.TOMControlIDs,
}
}
reqs := mapper.DeriveControlsFromObligations(frameworkObls)
if len(reqs) == 0 {
t.Error("expected derived control requirements")
}
// GOV.01 should appear once but with 2 obligation references
for _, req := range reqs {
if req.Control != nil && req.Control.ID == "TOM.GOV.01" {
if req.RequiredByCount != 2 {
t.Errorf("expected TOM.GOV.01 required by 2, got %d", req.RequiredByCount)
}
if req.Priority != "kritisch" {
t.Errorf("expected highest priority 'kritisch', got '%s'", req.Priority)
}
return
}
}
t.Error("TOM.GOV.01 not found in derived requirements")
}
func TestTOMGapAnalysis(t *testing.T) {
index, err := LoadTOMControls()
if err != nil {
t.Skipf("TOM controls not found: %v", err)
}
obligations := []V2Obligation{
{ID: "T-001", TOMControlIDs: []string{"TOM.GOV.01"}, Priority: "kritisch"},
{ID: "T-002", TOMControlIDs: []string{"TOM.GOV.01", "TOM.CRYPTO.01"}, Priority: "hoch"},
}
mapper := NewTOMObligationMapperFromObligations(index, obligations)
analyzer := NewTOMGapAnalyzer(mapper, index)
frameworkObls := []Obligation{
{ID: "T-001", Priority: "kritisch", ExternalResources: []string{"TOM.GOV.01"}},
{ID: "T-002", Priority: "hoch", ExternalResources: []string{"TOM.GOV.01", "TOM.CRYPTO.01"}},
}
result := analyzer.Analyze(&GapAnalysisRequest{
Obligations: frameworkObls,
ControlStatusMap: map[string]ControlStatus{
"TOM.GOV.01": ControlImplemented,
"TOM.CRYPTO.01": ControlNotImplemented,
},
})
if result.TotalControls != 2 {
t.Errorf("expected 2 total controls, got %d", result.TotalControls)
}
if result.ImplementedControls != 1 {
t.Errorf("expected 1 implemented, got %d", result.ImplementedControls)
}
if result.MissingControls != 1 {
t.Errorf("expected 1 missing, got %d", result.MissingControls)
}
if result.CompliancePercent != 50 {
t.Errorf("expected 50%% compliance, got %.1f%%", result.CompliancePercent)
}
if len(result.Gaps) != 1 {
t.Errorf("expected 1 gap, got %d", len(result.Gaps))
}
}
func TestTOMGapAnalysis_AllImplemented(t *testing.T) {
index, err := LoadTOMControls()
if err != nil {
t.Skipf("TOM controls not found: %v", err)
}
obligations := []V2Obligation{
{ID: "T-001", TOMControlIDs: []string{"TOM.GOV.01"}, Priority: "hoch"},
}
mapper := NewTOMObligationMapperFromObligations(index, obligations)
analyzer := NewTOMGapAnalyzer(mapper, index)
result := analyzer.Analyze(&GapAnalysisRequest{
Obligations: []Obligation{{ID: "T-001", Priority: "hoch", ExternalResources: []string{"TOM.GOV.01"}}},
ControlStatusMap: map[string]ControlStatus{
"TOM.GOV.01": ControlImplemented,
},
})
if result.CompliancePercent != 100 {
t.Errorf("expected 100%% compliance, got %.1f%%", result.CompliancePercent)
}
if len(result.Gaps) != 0 {
t.Errorf("expected 0 gaps, got %d", len(result.Gaps))
}
}