hako/internal/archival/rules/engine_stop_test.go
2026-01-12 19:35:18 +01:00

128 lines
3.2 KiB
Go

package rules
import (
"context"
"testing"
)
func TestEngine_StopsAfterFirstMatch(t *testing.T) {
// Create a config with multiple rules
config := &RuleConfig{
Rules: []Rule{
// First rule: matches text/html and returns obelisk
&MimetypeRule{
Mimetype: "text/html",
Archivers: []ArchiverConfig{
{Key: "obelisk"},
},
},
// Second rule: matches application/* and returns direct_download
// This should NEVER be evaluated if first rule matches
&MimetypeRule{
Mimetype: "application/*",
Archivers: []ArchiverConfig{
{Key: "direct_download"},
},
},
},
DefaultArchivers: []ArchiverConfig{{Key: "obelisk"}},
}
engine := NewEngine(config)
ctx := context.Background()
// Test with text/html - should match first rule and stop
metadata := &URLMetadata{
MimeType: "text/html",
Domain: "example.com",
}
extractors, err := engine.Evaluate(ctx, metadata)
if err != nil {
t.Fatalf("Evaluate() error = %v", err)
}
// Should only return obelisk (from first rule), NOT direct_download
if len(extractors) != 1 {
t.Errorf("Expected 1 extractor, got %d", len(extractors))
}
if extractors[0].Key != "obelisk" {
t.Errorf("Expected extractor 'obelisk', got '%s'", extractors[0].Key)
}
}
func TestEngine_StopsAfterFirstMatch_WithEmptyArchivers(t *testing.T) {
// Test that engine stops even when first rule returns empty extractors
config := &RuleConfig{
Rules: []Rule{
// First rule: matches and returns empty extractors (skip archiving)
&HostnameRule{
Hostname: "example.com",
Archivers: []ArchiverConfig{}, // Empty = skip
},
// Second rule: should never be evaluated
&MimetypeRule{
Mimetype: "text/html",
Archivers: []ArchiverConfig{
{Key: "obelisk"},
},
},
},
DefaultArchivers: []ArchiverConfig{{Key: "obelisk"}},
}
engine := NewEngine(config)
ctx := context.Background()
metadata := &URLMetadata{
MimeType: "text/html",
Domain: "example.com", // Matches first rule
}
extractors, err := engine.Evaluate(ctx, metadata)
if err != nil {
t.Fatalf("Evaluate() error = %v", err)
}
// Should return empty extractors (skip archiving), NOT obelisk from second rule
if len(extractors) != 0 {
t.Errorf("Expected 0 extractors (skip archiving), got %d: %v", len(extractors), extractors)
}
}
func TestEngine_MultipleArchiversInSingleRule(t *testing.T) {
// Test that a single rule can return multiple extractors
config := &RuleConfig{
Rules: []Rule{
&MimetypeRule{
Mimetype: "text/html",
Archivers: []ArchiverConfig{
{Key: "obelisk"},
{Key: "direct_download"}, // Multiple extractors in one rule
},
},
},
DefaultArchivers: []ArchiverConfig{{Key: "obelisk"}},
}
engine := NewEngine(config)
ctx := context.Background()
metadata := &URLMetadata{
MimeType: "text/html",
Domain: "example.com",
}
extractors, err := engine.Evaluate(ctx, metadata)
if err != nil {
t.Fatalf("Evaluate() error = %v", err)
}
// Should return both extractors from the single rule
if len(extractors) != 2 {
t.Errorf("Expected 2 extractors, got %d", len(extractors))
}
if extractors[0].Key != "obelisk" || extractors[1].Key != "direct_download" {
t.Errorf("Expected [obelisk, direct_download], got %v", extractors)
}
}