- Add RecordRule.UnmarshalYAML so a misconfigured folder_fields fails when the .zddc is parsed, not as a 500 on the first record write. A negative parent-distance is now rejected with a message naming the field. Mirrors FieldCode.UnmarshalYAML's raw-alias pattern. - Memoize anchored field-code pattern regexes in a package-level sync.Map (compileFieldPattern), used by both the unmarshal-time validation and FieldCode.Validate — replacing the per-call regexp.Compile that the old comment flagged as cache-if-it-shows-up. Tests: negative distance rejected (standalone + nested in a records: map), valid distance round-trips, pattern field code matches anchored. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
67 lines
2.4 KiB
Go
67 lines
2.4 KiB
Go
package zddc
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
// TestRecordRule_RejectsNegativeFolderDistance — a folder_fields entry
|
|
// with a negative parent-distance must fail at .zddc parse time (via
|
|
// RecordRule.UnmarshalYAML), not surface as a 500 on the first record
|
|
// write.
|
|
func TestRecordRule_RejectsNegativeFolderDistance(t *testing.T) {
|
|
src := "folder_fields:\n originator: -1\nfilename_format: \"{originator}-{sequence}\"\n"
|
|
var rr RecordRule
|
|
err := yaml.Unmarshal([]byte(src), &rr)
|
|
if err == nil {
|
|
t.Fatal("expected error for negative folder_fields distance, got nil")
|
|
}
|
|
if !strings.Contains(err.Error(), "folder_fields") || !strings.Contains(err.Error(), "originator") {
|
|
t.Errorf("error should name folder_fields + the field: %v", err)
|
|
}
|
|
}
|
|
|
|
// TestRecordRule_AcceptsValidFolderFields — a non-negative distance
|
|
// unmarshals and round-trips.
|
|
func TestRecordRule_AcceptsValidFolderFields(t *testing.T) {
|
|
src := "folder_fields:\n originator: 1\nfilename_format: \"{originator}-{sequence}\"\n"
|
|
var rr RecordRule
|
|
if err := yaml.Unmarshal([]byte(src), &rr); err != nil {
|
|
t.Fatalf("valid folder_fields should unmarshal: %v", err)
|
|
}
|
|
if rr.FolderFields["originator"] != 1 {
|
|
t.Errorf("folder_fields[originator]=%d want 1", rr.FolderFields["originator"])
|
|
}
|
|
}
|
|
|
|
// TestRecordRule_NegativeDistanceInRecordsMap — the same rejection
|
|
// applies when the rule is nested in a records: map (the real cascade
|
|
// shape: map[string]RecordRule decodes each value via UnmarshalYAML).
|
|
func TestRecordRule_NegativeDistanceInRecordsMap(t *testing.T) {
|
|
src := "\"*.yaml\":\n folder_fields:\n originator: -2\n"
|
|
var rules map[string]RecordRule
|
|
if err := yaml.Unmarshal([]byte(src), &rules); err == nil {
|
|
t.Fatal("expected error for negative distance in records map, got nil")
|
|
}
|
|
}
|
|
|
|
// TestFieldCode_PatternValidate — pattern field codes match values
|
|
// against the anchored regex (exercises the compiled-pattern cache).
|
|
func TestFieldCode_PatternValidate(t *testing.T) {
|
|
src := "kind: pattern\npattern: \"[0-9]{4}\"\n"
|
|
var fc FieldCode
|
|
if err := yaml.Unmarshal([]byte(src), &fc); err != nil {
|
|
t.Fatalf("unmarshal: %v", err)
|
|
}
|
|
if err := fc.Validate("0042"); err != nil {
|
|
t.Errorf("0042 should match [0-9]{4}: %v", err)
|
|
}
|
|
if err := fc.Validate("42"); err == nil {
|
|
t.Error("42 should NOT match [0-9]{4} (anchored, 4 digits)")
|
|
}
|
|
if err := fc.Validate("0042x"); err == nil {
|
|
t.Error("0042x should NOT match (anchored)")
|
|
}
|
|
}
|