216 lines
5.6 KiB
Go
216 lines
5.6 KiB
Go
package rules
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
)
|
|
|
|
func TestUnmarshalRule(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
json string
|
|
wantErr bool
|
|
check func(t *testing.T, rule Rule)
|
|
}{
|
|
{
|
|
name: "mimetype rule",
|
|
json: `{"mimetype": "text/html", "extractors": [{"key": "obelisk"}]}`,
|
|
wantErr: false,
|
|
check: func(t *testing.T, rule Rule) {
|
|
mr, ok := rule.(*MimetypeRule)
|
|
if !ok {
|
|
t.Fatalf("expected MimetypeRule, got %T", rule)
|
|
}
|
|
if mr.Mimetype != "text/html" {
|
|
t.Errorf("Mimetype = %q, want %q", mr.Mimetype, "text/html")
|
|
}
|
|
if len(mr.Archivers) != 1 || mr.Archivers[0].Key != "obelisk" {
|
|
t.Errorf("Archivers = %v, want [{key: obelisk}]", mr.Archivers)
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "hostname rule",
|
|
json: `{"hostname": "example.com", "extractors": [{"key": "direct_download"}]}`,
|
|
wantErr: false,
|
|
check: func(t *testing.T, rule Rule) {
|
|
hr, ok := rule.(*HostnameRule)
|
|
if !ok {
|
|
t.Fatalf("expected HostnameRule, got %T", rule)
|
|
}
|
|
if hr.Hostname != "example.com" {
|
|
t.Errorf("Hostname = %q, want %q", hr.Hostname, "example.com")
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "and rule",
|
|
json: `{"and": [{"mimetype": "text/html"}, {"hostname": "example.com"}], "extractors": [{"key": "obelisk"}]}`,
|
|
wantErr: false,
|
|
check: func(t *testing.T, rule Rule) {
|
|
ar, ok := rule.(*AndRule)
|
|
if !ok {
|
|
t.Fatalf("expected AndRule, got %T", rule)
|
|
}
|
|
if len(ar.Rules) != 2 {
|
|
t.Errorf("Rules length = %d, want 2", len(ar.Rules))
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "or rule",
|
|
json: `{"or": [{"mimetype": "text/html"}, {"hostname": "example.com"}], "extractors": [{"key": "obelisk"}]}`,
|
|
wantErr: false,
|
|
check: func(t *testing.T, rule Rule) {
|
|
or, ok := rule.(*OrRule)
|
|
if !ok {
|
|
t.Fatalf("expected OrRule, got %T", rule)
|
|
}
|
|
if len(or.Rules) != 2 {
|
|
t.Errorf("Rules length = %d, want 2", len(or.Rules))
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "nested and/or rules",
|
|
json: `{"and": [{"or": [{"mimetype": "text/html"}, {"mimetype": "application/json"}]}, {"hostname": "example.com"}], "extractors": [{"key": "obelisk"}]}`,
|
|
wantErr: false,
|
|
check: func(t *testing.T, rule Rule) {
|
|
ar, ok := rule.(*AndRule)
|
|
if !ok {
|
|
t.Fatalf("expected AndRule, got %T", rule)
|
|
}
|
|
if len(ar.Rules) != 2 {
|
|
t.Errorf("Rules length = %d, want 2", len(ar.Rules))
|
|
}
|
|
or, ok := ar.Rules[0].(*OrRule)
|
|
if !ok {
|
|
t.Fatalf("expected first child to be OrRule, got %T", ar.Rules[0])
|
|
}
|
|
if len(or.Rules) != 2 {
|
|
t.Errorf("OrRule children length = %d, want 2", len(or.Rules))
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "invalid rule - no type field",
|
|
json: `{"extractors": [{"key": "obelisk"}]}`,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "invalid json",
|
|
json: `{invalid json}`,
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
rule, err := UnmarshalRule([]byte(tt.json))
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("UnmarshalRule() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
if tt.wantErr {
|
|
return
|
|
}
|
|
if rule == nil {
|
|
t.Fatal("UnmarshalRule() returned nil rule")
|
|
}
|
|
if tt.check != nil {
|
|
tt.check(t, rule)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUnmarshalRuleConfig(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
json string
|
|
wantErr bool
|
|
check func(t *testing.T, config *RuleConfig)
|
|
}{
|
|
{
|
|
name: "valid config",
|
|
json: `{"rules": [{"mimetype": "text/html", "extractors": [{"key": "obelisk"}]}], "default_extractors": [{"key": "direct_download"}]}`,
|
|
wantErr: false,
|
|
check: func(t *testing.T, config *RuleConfig) {
|
|
if len(config.Rules) != 1 {
|
|
t.Errorf("Rules length = %d, want 1", len(config.Rules))
|
|
}
|
|
if len(config.DefaultArchivers) != 1 || config.DefaultArchivers[0].Key != "direct_download" {
|
|
t.Errorf("DefaultArchivers = %v, want [{key: direct_download}]", config.DefaultArchivers)
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "empty rules",
|
|
json: `{"rules": [], "default_extractors": [{"key": "obelisk"}]}`,
|
|
wantErr: false,
|
|
check: func(t *testing.T, config *RuleConfig) {
|
|
if len(config.Rules) != 0 {
|
|
t.Errorf("Rules length = %d, want 0", len(config.Rules))
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "invalid json",
|
|
json: `{invalid json}`,
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
config, err := UnmarshalRuleConfig([]byte(tt.json))
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("UnmarshalRuleConfig() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
if tt.wantErr {
|
|
return
|
|
}
|
|
if config == nil {
|
|
t.Fatal("UnmarshalRuleConfig() returned nil config")
|
|
}
|
|
if tt.check != nil {
|
|
tt.check(t, config)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUnmarshalRule_RoundTrip(t *testing.T) {
|
|
// Test that we can marshal and unmarshal rules correctly
|
|
original := &MimetypeRule{
|
|
Mimetype: "application/*",
|
|
Archivers: []ArchiverConfig{
|
|
{Key: "direct_download", Config: map[string]any{"timeout": "5m"}},
|
|
},
|
|
}
|
|
|
|
// Marshal
|
|
data, err := json.Marshal(original)
|
|
if err != nil {
|
|
t.Fatalf("Marshal() error = %v", err)
|
|
}
|
|
|
|
// Unmarshal
|
|
unmarshaled, err := UnmarshalRule(data)
|
|
if err != nil {
|
|
t.Fatalf("UnmarshalRule() error = %v", err)
|
|
}
|
|
|
|
// Check
|
|
mr, ok := unmarshaled.(*MimetypeRule)
|
|
if !ok {
|
|
t.Fatalf("expected MimetypeRule, got %T", unmarshaled)
|
|
}
|
|
if mr.Mimetype != original.Mimetype {
|
|
t.Errorf("Mimetype = %q, want %q", mr.Mimetype, original.Mimetype)
|
|
}
|
|
if len(mr.Archivers) != len(original.Archivers) {
|
|
t.Errorf("Archivers length = %d, want %d", len(mr.Archivers), len(original.Archivers))
|
|
}
|
|
}
|