package training import ( "testing" ) func TestChunkControls_EmptySlice(t *testing.T) { chunks := chunkControls(nil, 20) if len(chunks) != 0 { t.Errorf("expected 0 chunks, got %d", len(chunks)) } } func TestChunkControls_SingleChunk(t *testing.T) { controls := make([]CanonicalControlSummary, 5) for i := range controls { controls[i].ControlID = "CTRL-" + string(rune('A'+i)) } chunks := chunkControls(controls, 20) if len(chunks) != 1 { t.Errorf("expected 1 chunk, got %d", len(chunks)) } if len(chunks[0]) != 5 { t.Errorf("expected 5 controls in chunk, got %d", len(chunks[0])) } } func TestChunkControls_MultipleChunks(t *testing.T) { controls := make([]CanonicalControlSummary, 25) for i := range controls { controls[i].ControlID = "CTRL-" + string(rune('A'+i%26)) } chunks := chunkControls(controls, 10) if len(chunks) != 3 { t.Errorf("expected 3 chunks, got %d", len(chunks)) } if len(chunks[0]) != 10 { t.Errorf("expected 10 in first chunk, got %d", len(chunks[0])) } if len(chunks[2]) != 5 { t.Errorf("expected 5 in last chunk, got %d", len(chunks[2])) } } func TestChunkControls_ExactMultiple(t *testing.T) { controls := make([]CanonicalControlSummary, 20) chunks := chunkControls(controls, 10) if len(chunks) != 2 { t.Errorf("expected 2 chunks, got %d", len(chunks)) } } func TestBlockGenerator_DeriveRoles_EnterpriseAudience(t *testing.T) { bg := &BlockGenerator{} controls := []CanonicalControlSummary{ {ControlID: "AUTH-001", Category: "authentication", TargetAudience: "enterprise"}, } roles := bg.deriveRoles(controls, "enterprise") // Should include enterprise mapping roles roleSet := map[string]bool{} for _, r := range roles { roleSet[r] = true } // Enterprise maps to R1, R4, R5, R6, R7, R9 if !roleSet[RoleR1] { t.Error("expected R1 for enterprise audience") } if !roleSet[RoleR9] { t.Error("expected R9 for enterprise audience") } } func TestBlockGenerator_DeriveRoles_AuthorityAudience(t *testing.T) { bg := &BlockGenerator{} controls := []CanonicalControlSummary{ {ControlID: "GOV-001", Category: "governance", TargetAudience: "authority"}, } roles := bg.deriveRoles(controls, "authority") roleSet := map[string]bool{} for _, r := range roles { roleSet[r] = true } // Authority maps to R10 if !roleSet[RoleR10] { t.Error("expected R10 for authority audience") } } func TestBlockGenerator_DeriveRoles_NoFilter(t *testing.T) { bg := &BlockGenerator{} controls := []CanonicalControlSummary{ {ControlID: "ENC-001", Category: "encryption", TargetAudience: "provider"}, } roles := bg.deriveRoles(controls, "") roleSet := map[string]bool{} for _, r := range roles { roleSet[r] = true } // Without audience filter, should use per-control audience + category // encryption → R2, R8 // provider → R2, R8 if !roleSet[RoleR2] { t.Error("expected R2 from encryption category + provider audience") } if !roleSet[RoleR8] { t.Error("expected R8 from encryption category + provider audience") } } func TestBlockGenerator_DeriveRoles_DefaultToR9(t *testing.T) { bg := &BlockGenerator{} controls := []CanonicalControlSummary{ {ControlID: "UNK-001", Category: "", TargetAudience: ""}, } roles := bg.deriveRoles(controls, "") if len(roles) != 1 || roles[0] != RoleR9 { t.Errorf("expected [R9] default, got %v", roles) } } func TestBlockGenerator_ExtractControlIDs(t *testing.T) { bg := &BlockGenerator{} controls := []CanonicalControlSummary{ {ControlID: "AUTH-001"}, {ControlID: "AUTH-002"}, {ControlID: "ENC-010"}, } ids := bg.extractControlIDs(controls) if len(ids) != 3 { t.Errorf("expected 3 IDs, got %d", len(ids)) } if ids[0] != "AUTH-001" || ids[1] != "AUTH-002" || ids[2] != "ENC-010" { t.Errorf("unexpected IDs: %v", ids) } } func TestBlockGenerator_BuildModuleTitle_SinglePart(t *testing.T) { bg := &BlockGenerator{} config := &TrainingBlockConfig{Name: "Authentifizierung"} controls := []CanonicalControlSummary{{ControlID: "AUTH-001"}} title := bg.buildModuleTitle(config, controls, 1, 1) if title != "Authentifizierung" { t.Errorf("expected 'Authentifizierung', got '%s'", title) } } func TestBlockGenerator_BuildModuleTitle_MultiPart(t *testing.T) { bg := &BlockGenerator{} config := &TrainingBlockConfig{Name: "Authentifizierung"} controls := []CanonicalControlSummary{{ControlID: "AUTH-001"}} title := bg.buildModuleTitle(config, controls, 2, 3) expected := "Authentifizierung (Teil 2/3)" if title != expected { t.Errorf("expected '%s', got '%s'", expected, title) } } func TestNilIfEmpty(t *testing.T) { tests := []struct { input string expected bool // true = nil result }{ {"", true}, {" ", true}, {"value", false}, {" value ", false}, } for _, tt := range tests { result := nilIfEmpty(tt.input) if tt.expected && result != nil { t.Errorf("nilIfEmpty(%q) = %v, expected nil", tt.input, *result) } if !tt.expected && result == nil { t.Errorf("nilIfEmpty(%q) = nil, expected non-nil", tt.input) } } } func TestTargetAudienceRoleMapping_AllKeys(t *testing.T) { expectedKeys := []string{"enterprise", "authority", "provider", "all"} for _, key := range expectedKeys { roles, ok := TargetAudienceRoleMapping[key] if !ok { t.Errorf("missing key '%s' in TargetAudienceRoleMapping", key) } if len(roles) == 0 { t.Errorf("empty roles for key '%s'", key) } } } func TestCategoryRoleMapping_HasEntries(t *testing.T) { if len(CategoryRoleMapping) == 0 { t.Error("CategoryRoleMapping is empty") } // Verify some expected entries if _, ok := CategoryRoleMapping["encryption"]; !ok { t.Error("missing 'encryption' in CategoryRoleMapping") } if _, ok := CategoryRoleMapping["authentication"]; !ok { t.Error("missing 'authentication' in CategoryRoleMapping") } if _, ok := CategoryRoleMapping["data_protection"]; !ok { t.Error("missing 'data_protection' in CategoryRoleMapping") } }