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

186 lines
4.9 KiB
Go

package rules
import (
"context"
"testing"
)
func TestEngine_Evaluate(t *testing.T) {
tests := []struct {
name string
config *RuleConfig
metadata *URLMetadata
wantErr bool
check func(t *testing.T, extractors []ArchiverConfig)
}{
{
name: "first rule matches",
config: &RuleConfig{
Rules: []Rule{
&MimetypeRule{Mimetype: "text/html", Archivers: []ArchiverConfig{{Key: "obelisk"}}},
&MimetypeRule{Mimetype: "application/pdf", Archivers: []ArchiverConfig{{Key: "direct_download"}}},
},
DefaultArchivers: []ArchiverConfig{{Key: "direct_download"}},
},
metadata: &URLMetadata{
MimeType: "text/html",
},
wantErr: false,
check: func(t *testing.T, extractors []ArchiverConfig) {
if len(extractors) != 1 || extractors[0].Key != "obelisk" {
t.Errorf("Archivers = %v, want [{key: obelisk}]", extractors)
}
},
},
{
name: "second rule matches",
config: &RuleConfig{
Rules: []Rule{
&MimetypeRule{Mimetype: "text/html", Archivers: []ArchiverConfig{{Key: "obelisk"}}},
&MimetypeRule{Mimetype: "application/pdf", Archivers: []ArchiverConfig{{Key: "direct_download"}}},
},
DefaultArchivers: []ArchiverConfig{{Key: "direct_download"}},
},
metadata: &URLMetadata{
MimeType: "application/pdf",
},
wantErr: false,
check: func(t *testing.T, extractors []ArchiverConfig) {
if len(extractors) != 1 || extractors[0].Key != "direct_download" {
t.Errorf("Archivers = %v, want [{key: direct_download}]", extractors)
}
},
},
{
name: "no rules match - use default",
config: &RuleConfig{
Rules: []Rule{
&MimetypeRule{Mimetype: "text/html", Archivers: []ArchiverConfig{{Key: "obelisk"}}},
},
DefaultArchivers: []ArchiverConfig{{Key: "direct_download"}},
},
metadata: &URLMetadata{
MimeType: "application/pdf",
},
wantErr: false,
check: func(t *testing.T, extractors []ArchiverConfig) {
if len(extractors) != 1 || extractors[0].Key != "direct_download" {
t.Errorf("Archivers = %v, want [{key: direct_download}]", extractors)
}
},
},
{
name: "empty extractors from rule",
config: &RuleConfig{
Rules: []Rule{
&MimetypeRule{Mimetype: "text/html", Archivers: []ArchiverConfig{}},
},
DefaultArchivers: []ArchiverConfig{{Key: "direct_download"}},
},
metadata: &URLMetadata{
MimeType: "text/html",
},
wantErr: false,
check: func(t *testing.T, extractors []ArchiverConfig) {
if len(extractors) != 0 {
t.Errorf("Archivers = %v, want []", extractors)
}
},
},
{
name: "no default extractor",
config: &RuleConfig{
Rules: []Rule{
&MimetypeRule{Mimetype: "text/html", Archivers: []ArchiverConfig{{Key: "obelisk"}}},
},
DefaultArchivers: []ArchiverConfig{},
},
metadata: &URLMetadata{
MimeType: "application/pdf",
},
wantErr: true,
},
{
name: "invalid rule in config",
config: &RuleConfig{
Rules: []Rule{
&MimetypeRule{Mimetype: "", Archivers: []ArchiverConfig{{Key: "obelisk"}}}, // Invalid
},
DefaultArchivers: []ArchiverConfig{{Key: "direct_download"}},
},
metadata: &URLMetadata{
MimeType: "text/html",
},
wantErr: true,
},
{
name: "nil config",
config: nil,
metadata: &URLMetadata{MimeType: "text/html"},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
engine := NewEngine(tt.config)
ctx := context.Background()
extractors, err := engine.Evaluate(ctx, tt.metadata)
if (err != nil) != tt.wantErr {
t.Errorf("Evaluate() error = %v, wantErr %v", err, tt.wantErr)
return
}
if tt.wantErr {
return
}
if tt.check != nil {
tt.check(t, extractors)
}
})
}
}
func TestEngine_Evaluate_ComplexRules(t *testing.T) {
// Test with AND rule
andRule := &AndRule{
Rules: []Rule{
&MimetypeRule{Mimetype: "text/html", Archivers: []ArchiverConfig{}},
&HostnameRule{Hostname: "example.com", Archivers: []ArchiverConfig{}},
},
Archivers: []ArchiverConfig{{Key: "obelisk"}},
}
config := &RuleConfig{
Rules: []Rule{andRule},
DefaultArchivers: []ArchiverConfig{{Key: "direct_download"}},
}
engine := NewEngine(config)
ctx := context.Background()
// Should match
metadata := &URLMetadata{
MimeType: "text/html",
Domain: "example.com",
}
extractors, err := engine.Evaluate(ctx, metadata)
if err != nil {
t.Fatalf("Evaluate() error = %v", err)
}
if len(extractors) != 1 || extractors[0].Key != "obelisk" {
t.Errorf("Archivers = %v, want [{key: obelisk}]", extractors)
}
// Should not match (hostname doesn't match)
metadata2 := &URLMetadata{
MimeType: "text/html",
Domain: "other.com",
}
extractors2, err := engine.Evaluate(ctx, metadata2)
if err != nil {
t.Fatalf("Evaluate() error = %v", err)
}
if len(extractors2) != 1 || extractors2[0].Key != "direct_download" {
t.Errorf("Archivers = %v, want [{key: direct_download}]", extractors2)
}
}