Files
breakpilot-compliance/ai-compliance-sdk/internal/ucca/license_policy_test.go
Benjamin Boenisch 4435e7ea0a Initial commit: breakpilot-compliance - Compliance SDK Platform
Services: Admin-Compliance, Backend-Compliance,
AI-Compliance-SDK, Consent-SDK, Developer-Portal,
PCA-Platform, DSMS

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 23:47:28 +01:00

941 lines
24 KiB
Go

package ucca
import (
"testing"
)
// =============================================================================
// License Policy Engine Tests
// =============================================================================
func TestNewLicensePolicyEngine(t *testing.T) {
engine := NewLicensePolicyEngine()
if engine == nil {
t.Fatal("Expected non-nil engine")
}
}
// =============================================================================
// Basic Evaluation Tests
// =============================================================================
func TestLicensePolicyEngine_NoLicensedContent(t *testing.T) {
engine := NewLicensePolicyEngine()
facts := &LicensedContentFacts{
Present: false,
}
result := engine.Evaluate(facts)
if result.EffectiveMode != "UNRESTRICTED" {
t.Errorf("Expected UNRESTRICTED mode for no licensed content, got %s", result.EffectiveMode)
}
if !result.Allowed {
t.Error("Expected allowed=true for no licensed content")
}
if !result.OutputRestrictions.AllowQuotes {
t.Error("Expected AllowQuotes=true for no licensed content")
}
if !result.OutputRestrictions.AllowCopy {
t.Error("Expected AllowCopy=true for no licensed content")
}
if !result.OutputRestrictions.AllowExport {
t.Error("Expected AllowExport=true for no licensed content")
}
}
// =============================================================================
// Operation Mode Tests
// =============================================================================
func TestLicensePolicyEngine_LinkOnlyMode(t *testing.T) {
engine := NewLicensePolicyEngine()
facts := &LicensedContentFacts{
Present: true,
Publisher: "VDI",
LicenseType: "SINGLE_WORKSTATION",
AIUsePermitted: "UNKNOWN",
OperationMode: "LINK_ONLY",
}
result := engine.Evaluate(facts)
if result.EffectiveMode != "LINK_ONLY" {
t.Errorf("Expected LINK_ONLY mode, got %s", result.EffectiveMode)
}
if !result.Allowed {
t.Error("Expected allowed=true for LINK_ONLY mode")
}
if result.RiskScore != 0 {
t.Errorf("Expected risk score 0 for LINK_ONLY, got %d", result.RiskScore)
}
if result.OutputRestrictions.AllowQuotes {
t.Error("Expected AllowQuotes=false for LINK_ONLY")
}
if result.OutputRestrictions.AllowCopy {
t.Error("Expected AllowCopy=false for LINK_ONLY")
}
}
func TestLicensePolicyEngine_NotesOnlyMode(t *testing.T) {
engine := NewLicensePolicyEngine()
facts := &LicensedContentFacts{
Present: true,
Publisher: "ISO",
LicenseType: "NETWORK_INTRANET",
AIUsePermitted: "NO",
OperationMode: "NOTES_ONLY",
}
result := engine.Evaluate(facts)
if result.EffectiveMode != "NOTES_ONLY" {
t.Errorf("Expected NOTES_ONLY mode, got %s", result.EffectiveMode)
}
if !result.Allowed {
t.Error("Expected allowed=true for NOTES_ONLY mode")
}
if result.RiskScore != 10 {
t.Errorf("Expected risk score 10 for NOTES_ONLY, got %d", result.RiskScore)
}
// Notes can be copied (they are customer's own)
if !result.OutputRestrictions.AllowCopy {
t.Error("Expected AllowCopy=true for NOTES_ONLY")
}
}
func TestLicensePolicyEngine_NotesOnlyMode_UnknownLicense(t *testing.T) {
engine := NewLicensePolicyEngine()
facts := &LicensedContentFacts{
Present: true,
Publisher: "VDE",
LicenseType: "UNKNOWN",
AIUsePermitted: "UNKNOWN",
OperationMode: "NOTES_ONLY",
}
result := engine.Evaluate(facts)
// Should have escalation level E2
if result.EscalationLevel != "E2" {
t.Errorf("Expected escalation level E2 for unknown license, got %s", result.EscalationLevel)
}
// Should have GAP_LICENSE_UNKNOWN gap
hasGap := false
for _, gap := range result.Gaps {
if gap.ID == "GAP_LICENSE_UNKNOWN" {
hasGap = true
break
}
}
if !hasGap {
t.Error("Expected GAP_LICENSE_UNKNOWN gap for unknown license")
}
}
func TestLicensePolicyEngine_ExcerptOnlyMode_WithAIPermission(t *testing.T) {
engine := NewLicensePolicyEngine()
facts := &LicensedContentFacts{
Present: true,
Publisher: "ISO",
LicenseType: "NETWORK_INTRANET",
AIUsePermitted: "YES",
OperationMode: "EXCERPT_ONLY",
}
result := engine.Evaluate(facts)
if result.EffectiveMode != "EXCERPT_ONLY" {
t.Errorf("Expected EXCERPT_ONLY mode, got %s", result.EffectiveMode)
}
if !result.Allowed {
t.Error("Expected allowed=true for EXCERPT_ONLY with AI permission")
}
// Short quotes should be allowed
if !result.OutputRestrictions.AllowQuotes {
t.Error("Expected AllowQuotes=true for EXCERPT_ONLY with AI permission")
}
// But limited to 150 chars
if result.OutputRestrictions.MaxQuoteLength != 150 {
t.Errorf("Expected MaxQuoteLength=150, got %d", result.OutputRestrictions.MaxQuoteLength)
}
}
func TestLicensePolicyEngine_ExcerptOnlyMode_WithoutAIPermission(t *testing.T) {
engine := NewLicensePolicyEngine()
facts := &LicensedContentFacts{
Present: true,
Publisher: "ISO",
LicenseType: "NETWORK_INTRANET",
AIUsePermitted: "NO",
OperationMode: "EXCERPT_ONLY",
}
result := engine.Evaluate(facts)
// Should be downgraded to NOTES_ONLY
if result.EffectiveMode != "NOTES_ONLY" {
t.Errorf("Expected NOTES_ONLY mode (downgraded), got %s", result.EffectiveMode)
}
// Should have GAP_AI_USE_NOT_PERMITTED
hasGap := false
for _, gap := range result.Gaps {
if gap.ID == "GAP_AI_USE_NOT_PERMITTED" {
hasGap = true
break
}
}
if !hasGap {
t.Error("Expected GAP_AI_USE_NOT_PERMITTED gap")
}
}
func TestLicensePolicyEngine_FulltextRAGMode_Allowed(t *testing.T) {
engine := NewLicensePolicyEngine()
facts := &LicensedContentFacts{
Present: true,
Publisher: "VDI",
LicenseType: "AI_LICENSE",
AIUsePermitted: "YES",
ProofUploaded: true,
OperationMode: "FULLTEXT_RAG",
}
result := engine.Evaluate(facts)
if result.EffectiveMode != "FULLTEXT_RAG" {
t.Errorf("Expected FULLTEXT_RAG mode, got %s", result.EffectiveMode)
}
if !result.Allowed {
t.Error("Expected allowed=true for FULLTEXT_RAG with proof")
}
if result.StopLine != nil {
t.Error("Expected no stop line for allowed FULLTEXT_RAG")
}
// Quotes allowed but limited
if !result.OutputRestrictions.AllowQuotes {
t.Error("Expected AllowQuotes=true for FULLTEXT_RAG")
}
if result.OutputRestrictions.MaxQuoteLength != 500 {
t.Errorf("Expected MaxQuoteLength=500, got %d", result.OutputRestrictions.MaxQuoteLength)
}
}
func TestLicensePolicyEngine_FulltextRAGMode_Blocked_NoProof(t *testing.T) {
engine := NewLicensePolicyEngine()
facts := &LicensedContentFacts{
Present: true,
Publisher: "VDI",
LicenseType: "NETWORK_INTRANET",
AIUsePermitted: "YES",
ProofUploaded: false, // No proof!
OperationMode: "FULLTEXT_RAG",
}
result := engine.Evaluate(facts)
// Should be blocked and downgraded to LINK_ONLY
if result.Allowed {
t.Error("Expected allowed=false for FULLTEXT_RAG without proof")
}
if result.EffectiveMode != "LINK_ONLY" {
t.Errorf("Expected LINK_ONLY mode (downgraded), got %s", result.EffectiveMode)
}
// Should have stop line
if result.StopLine == nil {
t.Fatal("Expected stop line for blocked FULLTEXT_RAG")
}
if result.StopLine.ID != "STOP_FULLTEXT_WITHOUT_PROOF" {
t.Errorf("Expected stop line STOP_FULLTEXT_WITHOUT_PROOF, got %s", result.StopLine.ID)
}
// Should have GAP_FULLTEXT_WITHOUT_PROOF
hasGap := false
for _, gap := range result.Gaps {
if gap.ID == "GAP_FULLTEXT_WITHOUT_PROOF" {
hasGap = true
if gap.Severity != "BLOCK" {
t.Error("Expected gap severity BLOCK")
}
break
}
}
if !hasGap {
t.Error("Expected GAP_FULLTEXT_WITHOUT_PROOF gap")
}
if result.EscalationLevel != "E3" {
t.Errorf("Expected escalation level E3, got %s", result.EscalationLevel)
}
}
func TestLicensePolicyEngine_TrainingMode_Blocked(t *testing.T) {
engine := NewLicensePolicyEngine()
facts := &LicensedContentFacts{
Present: true,
Publisher: "DIN_MEDIA",
LicenseType: "NETWORK_INTRANET",
AIUsePermitted: "NO",
ProofUploaded: false,
OperationMode: "TRAINING",
}
result := engine.Evaluate(facts)
if result.Allowed {
t.Error("Expected allowed=false for TRAINING without AI license")
}
if result.EffectiveMode != "LINK_ONLY" {
t.Errorf("Expected LINK_ONLY mode (downgraded), got %s", result.EffectiveMode)
}
// Should have stop line
if result.StopLine == nil {
t.Fatal("Expected stop line for blocked TRAINING")
}
if result.EscalationLevel != "E3" {
t.Errorf("Expected escalation level E3, got %s", result.EscalationLevel)
}
}
func TestLicensePolicyEngine_TrainingMode_Allowed(t *testing.T) {
engine := NewLicensePolicyEngine()
facts := &LicensedContentFacts{
Present: true,
Publisher: "VDI",
LicenseType: "AI_LICENSE",
AIUsePermitted: "YES",
ProofUploaded: true,
OperationMode: "TRAINING",
}
result := engine.Evaluate(facts)
if result.EffectiveMode != "TRAINING" {
t.Errorf("Expected TRAINING mode, got %s", result.EffectiveMode)
}
if !result.Allowed {
t.Error("Expected allowed=true for TRAINING with AI_LICENSE")
}
// Still requires E3 review
if result.EscalationLevel != "E3" {
t.Errorf("Expected escalation level E3 even for allowed training, got %s", result.EscalationLevel)
}
}
// =============================================================================
// Publisher-Specific Tests (DIN Media)
// =============================================================================
func TestLicensePolicyEngine_DINMedia_FulltextBlocked(t *testing.T) {
engine := NewLicensePolicyEngine()
facts := &LicensedContentFacts{
Present: true,
Publisher: "DIN_MEDIA",
LicenseType: "SINGLE_WORKSTATION",
AIUsePermitted: "NO",
ProofUploaded: false,
OperationMode: "FULLTEXT_RAG",
}
result := engine.Evaluate(facts)
if result.Allowed {
t.Error("Expected allowed=false for DIN_MEDIA FULLTEXT_RAG without AI permission")
}
// Should have DIN-specific stop line
if result.StopLine == nil {
t.Fatal("Expected stop line for DIN_MEDIA")
}
if result.StopLine.ID != "STOP_DIN_FULLTEXT_AI_NOT_ALLOWED" {
t.Errorf("Expected stop line STOP_DIN_FULLTEXT_AI_NOT_ALLOWED, got %s", result.StopLine.ID)
}
// Should have CTRL-NO-CRAWLING-DIN control
hasControl := false
for _, ctrl := range result.RequiredControls {
if ctrl.ID == "CTRL-NO-CRAWLING-DIN" {
hasControl = true
break
}
}
if !hasControl {
t.Error("Expected CTRL-NO-CRAWLING-DIN control for DIN_MEDIA")
}
}
func TestLicensePolicyEngine_DINMedia_LinkOnlyAllowed(t *testing.T) {
engine := NewLicensePolicyEngine()
facts := &LicensedContentFacts{
Present: true,
Publisher: "DIN_MEDIA",
LicenseType: "SINGLE_WORKSTATION",
AIUsePermitted: "NO",
OperationMode: "LINK_ONLY",
}
result := engine.Evaluate(facts)
if !result.Allowed {
t.Error("Expected allowed=true for DIN_MEDIA LINK_ONLY")
}
if result.EffectiveMode != "LINK_ONLY" {
t.Errorf("Expected LINK_ONLY mode, got %s", result.EffectiveMode)
}
// Should have no stop line for LINK_ONLY
if result.StopLine != nil {
t.Error("Expected no stop line for DIN_MEDIA LINK_ONLY")
}
}
func TestLicensePolicyEngine_DINMedia_NotesOnlyAllowed(t *testing.T) {
engine := NewLicensePolicyEngine()
facts := &LicensedContentFacts{
Present: true,
Publisher: "DIN_MEDIA",
LicenseType: "NETWORK_INTRANET",
AIUsePermitted: "NO",
OperationMode: "NOTES_ONLY",
}
result := engine.Evaluate(facts)
if !result.Allowed {
t.Error("Expected allowed=true for DIN_MEDIA NOTES_ONLY")
}
if result.EffectiveMode != "NOTES_ONLY" {
t.Errorf("Expected NOTES_ONLY mode, got %s", result.EffectiveMode)
}
}
// =============================================================================
// Distribution Scope Tests
// =============================================================================
func TestLicensePolicyEngine_DistributionScopeMismatch(t *testing.T) {
engine := NewLicensePolicyEngine()
facts := &LicensedContentFacts{
Present: true,
Publisher: "ISO",
LicenseType: "SINGLE_WORKSTATION",
AIUsePermitted: "NO",
OperationMode: "LINK_ONLY",
DistributionScope: "COMPANY_INTERNAL",
}
result := engine.Evaluate(facts)
// Should have GAP_DISTRIBUTION_SCOPE_MISMATCH
hasGap := false
for _, gap := range result.Gaps {
if gap.ID == "GAP_DISTRIBUTION_SCOPE_MISMATCH" {
hasGap = true
break
}
}
if !hasGap {
t.Error("Expected GAP_DISTRIBUTION_SCOPE_MISMATCH for single workstation with company distribution")
}
if result.EscalationLevel != "E3" {
t.Errorf("Expected escalation level E3, got %s", result.EscalationLevel)
}
}
func TestLicensePolicyEngine_NetworkLicenseExternalDistribution(t *testing.T) {
engine := NewLicensePolicyEngine()
facts := &LicensedContentFacts{
Present: true,
Publisher: "VDI",
LicenseType: "NETWORK_INTRANET",
AIUsePermitted: "YES",
ProofUploaded: true,
OperationMode: "NOTES_ONLY",
DistributionScope: "EXTERNAL_CUSTOMERS",
}
result := engine.Evaluate(facts)
// Should have GAP_DISTRIBUTION_SCOPE_EXTERNAL
hasGap := false
for _, gap := range result.Gaps {
if gap.ID == "GAP_DISTRIBUTION_SCOPE_EXTERNAL" {
hasGap = true
break
}
}
if !hasGap {
t.Error("Expected GAP_DISTRIBUTION_SCOPE_EXTERNAL for network license with external distribution")
}
}
// =============================================================================
// Helper Function Tests
// =============================================================================
func TestLicensePolicyEngine_CanIngestFulltext(t *testing.T) {
engine := NewLicensePolicyEngine()
tests := []struct {
name string
facts *LicensedContentFacts
expected bool
}{
{
name: "No licensed content",
facts: &LicensedContentFacts{
Present: false,
},
expected: true,
},
{
name: "LINK_ONLY mode",
facts: &LicensedContentFacts{
Present: true,
OperationMode: "LINK_ONLY",
},
expected: false,
},
{
name: "NOTES_ONLY mode",
facts: &LicensedContentFacts{
Present: true,
OperationMode: "NOTES_ONLY",
},
expected: false,
},
{
name: "FULLTEXT_RAG with proof",
facts: &LicensedContentFacts{
Present: true,
OperationMode: "FULLTEXT_RAG",
AIUsePermitted: "YES",
ProofUploaded: true,
},
expected: true,
},
{
name: "FULLTEXT_RAG without proof",
facts: &LicensedContentFacts{
Present: true,
OperationMode: "FULLTEXT_RAG",
AIUsePermitted: "YES",
ProofUploaded: false,
},
expected: false,
},
{
name: "TRAINING with AI_LICENSE",
facts: &LicensedContentFacts{
Present: true,
OperationMode: "TRAINING",
AIUsePermitted: "YES",
ProofUploaded: true,
LicenseType: "AI_LICENSE",
},
expected: true,
},
{
name: "TRAINING without AI_LICENSE",
facts: &LicensedContentFacts{
Present: true,
OperationMode: "TRAINING",
AIUsePermitted: "YES",
ProofUploaded: true,
LicenseType: "NETWORK_INTRANET",
},
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := engine.CanIngestFulltext(tt.facts)
if result != tt.expected {
t.Errorf("Expected %v, got %v", tt.expected, result)
}
})
}
}
func TestLicensePolicyEngine_CanIngestNotes(t *testing.T) {
engine := NewLicensePolicyEngine()
tests := []struct {
name string
facts *LicensedContentFacts
expected bool
}{
{
name: "No licensed content",
facts: &LicensedContentFacts{
Present: false,
},
expected: true,
},
{
name: "LINK_ONLY mode",
facts: &LicensedContentFacts{
Present: true,
OperationMode: "LINK_ONLY",
},
expected: false,
},
{
name: "NOTES_ONLY mode",
facts: &LicensedContentFacts{
Present: true,
OperationMode: "NOTES_ONLY",
},
expected: true,
},
{
name: "EXCERPT_ONLY mode",
facts: &LicensedContentFacts{
Present: true,
OperationMode: "EXCERPT_ONLY",
},
expected: true,
},
{
name: "FULLTEXT_RAG mode",
facts: &LicensedContentFacts{
Present: true,
OperationMode: "FULLTEXT_RAG",
},
expected: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := engine.CanIngestNotes(tt.facts)
if result != tt.expected {
t.Errorf("Expected %v, got %v", tt.expected, result)
}
})
}
}
func TestLicensePolicyEngine_GetEffectiveMode(t *testing.T) {
engine := NewLicensePolicyEngine()
// Test downgrade scenario
facts := &LicensedContentFacts{
Present: true,
Publisher: "DIN_MEDIA",
LicenseType: "SINGLE_WORKSTATION",
AIUsePermitted: "NO",
OperationMode: "FULLTEXT_RAG",
}
effectiveMode := engine.GetEffectiveMode(facts)
if effectiveMode != "LINK_ONLY" {
t.Errorf("Expected effective mode LINK_ONLY (downgraded), got %s", effectiveMode)
}
}
func TestLicensePolicyEngine_DecideIngest(t *testing.T) {
engine := NewLicensePolicyEngine()
facts := &LicensedContentFacts{
Present: true,
Publisher: "VDI",
LicenseType: "AI_LICENSE",
AIUsePermitted: "YES",
ProofUploaded: true,
OperationMode: "FULLTEXT_RAG",
}
decision := engine.DecideIngest(facts)
if !decision.AllowMetadata {
t.Error("Expected AllowMetadata=true")
}
if !decision.AllowNotes {
t.Error("Expected AllowNotes=true")
}
if !decision.AllowFulltext {
t.Error("Expected AllowFulltext=true for FULLTEXT_RAG with proof")
}
if decision.EffectiveMode != "FULLTEXT_RAG" {
t.Errorf("Expected EffectiveMode=FULLTEXT_RAG, got %s", decision.EffectiveMode)
}
}
// =============================================================================
// Audit Entry Tests
// =============================================================================
func TestLicensePolicyEngine_FormatAuditEntry(t *testing.T) {
engine := NewLicensePolicyEngine()
facts := &LicensedContentFacts{
Present: true,
Publisher: "DIN_MEDIA",
LicenseType: "SINGLE_WORKSTATION",
AIUsePermitted: "NO",
OperationMode: "FULLTEXT_RAG",
}
result := engine.Evaluate(facts)
entry := engine.FormatAuditEntry("tenant-123", "doc-456", facts, result)
if entry.TenantID != "tenant-123" {
t.Errorf("Expected TenantID=tenant-123, got %s", entry.TenantID)
}
if entry.DocumentID != "doc-456" {
t.Errorf("Expected DocumentID=doc-456, got %s", entry.DocumentID)
}
if entry.Decision != "DENY" {
t.Errorf("Expected Decision=DENY, got %s", entry.Decision)
}
if entry.StopLineID == "" {
t.Error("Expected StopLineID to be set for denied request")
}
}
func TestLicensePolicyEngine_FormatAuditEntry_Downgrade(t *testing.T) {
engine := NewLicensePolicyEngine()
facts := &LicensedContentFacts{
Present: true,
Publisher: "ISO",
LicenseType: "NETWORK_INTRANET",
AIUsePermitted: "NO",
OperationMode: "EXCERPT_ONLY",
}
result := engine.Evaluate(facts)
entry := engine.FormatAuditEntry("tenant-123", "doc-456", facts, result)
if entry.Decision != "DOWNGRADE" {
t.Errorf("Expected Decision=DOWNGRADE, got %s", entry.Decision)
}
if entry.EffectiveMode != "NOTES_ONLY" {
t.Errorf("Expected EffectiveMode=NOTES_ONLY, got %s", entry.EffectiveMode)
}
}
// =============================================================================
// Human Readable Summary Tests
// =============================================================================
func TestLicensePolicyEngine_FormatHumanReadableSummary(t *testing.T) {
engine := NewLicensePolicyEngine()
facts := &LicensedContentFacts{
Present: true,
Publisher: "DIN_MEDIA",
LicenseType: "SINGLE_WORKSTATION",
AIUsePermitted: "NO",
OperationMode: "FULLTEXT_RAG",
}
result := engine.Evaluate(facts)
summary := engine.FormatHumanReadableSummary(result)
// Should contain key elements
if !stringContains(summary, "BLOCKIERT") {
t.Error("Summary should contain 'BLOCKIERT'")
}
if !stringContains(summary, "LINK_ONLY") {
t.Error("Summary should contain 'LINK_ONLY'")
}
if !stringContains(summary, "STOP-LINE") {
t.Error("Summary should contain '!!! STOP-LINE !!!'")
}
if !stringContains(summary, "DIN Media") {
t.Error("Summary should mention DIN Media")
}
}
// =============================================================================
// Determinism Tests
// =============================================================================
func TestLicensePolicyEngine_Determinism(t *testing.T) {
engine := NewLicensePolicyEngine()
facts := &LicensedContentFacts{
Present: true,
Publisher: "DIN_MEDIA",
LicenseType: "NETWORK_INTRANET",
AIUsePermitted: "NO",
ProofUploaded: false,
OperationMode: "FULLTEXT_RAG",
DistributionScope: "COMPANY_INTERNAL",
}
// Run evaluation 10 times and ensure identical results
firstResult := engine.Evaluate(facts)
for i := 0; i < 10; i++ {
result := engine.Evaluate(facts)
if result.Allowed != firstResult.Allowed {
t.Errorf("Run %d: Allowed mismatch: %v vs %v", i, result.Allowed, firstResult.Allowed)
}
if result.EffectiveMode != firstResult.EffectiveMode {
t.Errorf("Run %d: EffectiveMode mismatch: %s vs %s", i, result.EffectiveMode, firstResult.EffectiveMode)
}
if result.RiskScore != firstResult.RiskScore {
t.Errorf("Run %d: RiskScore mismatch: %d vs %d", i, result.RiskScore, firstResult.RiskScore)
}
if len(result.Gaps) != len(firstResult.Gaps) {
t.Errorf("Run %d: Gaps count mismatch: %d vs %d", i, len(result.Gaps), len(firstResult.Gaps))
}
}
}
// =============================================================================
// Edge Case Tests
// =============================================================================
func TestLicensePolicyEngine_UnknownOperationMode(t *testing.T) {
engine := NewLicensePolicyEngine()
facts := &LicensedContentFacts{
Present: true,
Publisher: "ISO",
OperationMode: "INVALID_MODE",
}
result := engine.Evaluate(facts)
// Should default to LINK_ONLY
if result.EffectiveMode != "LINK_ONLY" {
t.Errorf("Expected default to LINK_ONLY for unknown mode, got %s", result.EffectiveMode)
}
if !result.Allowed {
t.Error("Expected allowed=true for fallback to LINK_ONLY")
}
}
func TestLicensePolicyEngine_EmptyFacts(t *testing.T) {
engine := NewLicensePolicyEngine()
facts := &LicensedContentFacts{}
result := engine.Evaluate(facts)
// Empty facts = no licensed content
if result.EffectiveMode != "UNRESTRICTED" {
t.Errorf("Expected UNRESTRICTED for empty facts, got %s", result.EffectiveMode)
}
}
// =============================================================================
// Risk Score Tests
// =============================================================================
func TestLicensePolicyEngine_RiskScores(t *testing.T) {
engine := NewLicensePolicyEngine()
tests := []struct {
name string
mode string
expectedMin int
expectedMax int
}{
{"LINK_ONLY", "LINK_ONLY", 0, 0},
{"NOTES_ONLY", "NOTES_ONLY", 10, 30},
{"EXCERPT_ONLY", "EXCERPT_ONLY", 30, 50},
{"FULLTEXT_RAG", "FULLTEXT_RAG", 60, 90},
{"TRAINING", "TRAINING", 80, 100},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
facts := &LicensedContentFacts{
Present: true,
Publisher: "VDI",
LicenseType: "AI_LICENSE",
AIUsePermitted: "YES",
ProofUploaded: true,
OperationMode: tt.mode,
}
result := engine.Evaluate(facts)
if result.RiskScore < tt.expectedMin || result.RiskScore > tt.expectedMax {
t.Errorf("Expected risk score in range [%d, %d], got %d",
tt.expectedMin, tt.expectedMax, result.RiskScore)
}
})
}
}
// Helper function
func stringContains(s, substr string) bool {
return len(s) >= len(substr) && (s == substr || len(s) > 0 && stringContainsHelper(s, substr))
}
func stringContainsHelper(s, substr string) bool {
for i := 0; i <= len(s)-len(substr); i++ {
if s[i:i+len(substr)] == substr {
return true
}
}
return false
}