package engine import ( "bytes" "reflect" "strings" "testing" "gitea.maximumdirect.net/eric/ConfigKit/internal/document" ) func TestSequenceHistoryReplaysAppendAtAssignedIndexes(t *testing.T) { policy := sequencePolicy{identityFields: map[string]string{"/records": "id", "/other": "id"}} first := parseCompositionDocument(t, "source-1", "records: [{id: a, value: first}]\nother: [{id: x}]\n") second := parseCompositionDocument(t, "source-2", "records: [{id: b, value: second}]\nother: [{id: y}]\n") composed, diagnostics := composeDocumentsWithPolicy(policy, first, second) if len(diagnostics) != 0 { t.Fatalf("compose diagnostics = %#v", diagnostics) } for applicationIndex, application := range composed.applications { for path, want := range map[string]int{"/records": 1, "/other": 1} { sequence, present := documentAtPath(application.value, mustParsePath(t, path)) if !present || sequence.Kind != document.Sequence || len(sequence.Sequence) != want { t.Errorf("application %d retained %s = %#v, %v; want one source fragment item", applicationIndex, path, sequence, present) } } } working := parseCompositionDocument(t, "defaults", "records: [{id: default}]\nother: [{id: default}]\n") index := new(mappingIndex) for _, application := range composed.applications { applyHistoryApplication(&working, application, index) } for path, want := range map[string][]string{ "/records": {"a", "b"}, "/other": {"x", "y"}, } { sequence, present := documentAtPath(working, mustParsePath(t, path)) if !present || sequence.Kind != document.Sequence || len(sequence.Sequence) != len(want) { t.Fatalf("replayed %s = %#v", path, sequence) } for itemIndex, id := range want { field := sequence.Sequence[itemIndex].Mapping[0].Value.Text if field != id { t.Errorf("replayed %s[%d].id = %q, want %q", path, itemIndex, field, id) } } } application := composed.applications[1] cloned := cloneHistoryApplications(composed.applications) cloned[1].sequences[0].path.segments[0].key = "mutated" if composed.applications[1].sequences[0].path.String() != "/records" { t.Fatal("cloned sequence history path aliases its source") } addedPath := Keys("records").Index(1).Key("value") if operation, relevant := applicationOperationPath(application, addedPath, nil); !relevant || operation.String() != addedPath.String() { t.Fatalf("appended value operation = %s, %v", operation.String(), relevant) } if _, relevant := applicationOperationPath(application, Keys("records").Index(0).Key("value"), nil); relevant { t.Fatal("later contribution was reported as changing an earlier record") } origin := historyApplicationOrigin(application, addedPath, nil) if len(origin.Locations) != 1 || origin.Locations[0].SourceID != "source-2" { t.Fatalf("appended value origin = %#v", origin) } overlay := historyApplication{ layer: LayerOverlay, value: parseCompositionDocument(t, "overlay", "records: []\n"), } applyHistoryApplication(&working, overlay, index) replaced, present := documentAtPath(working, Keys("records")) if !present || replaced.Kind != document.Sequence || len(replaced.Sequence) != 0 { t.Fatalf("ordinary later list replacement = %#v, %v", replaced, present) } } func TestSequenceHistoryPreservesTierReplacementAndEmptyLists(t *testing.T) { policy := sequencePolicy{identityFields: map[string]string{"/records": "id", "/independent": "id"}} first, diagnostics := composeDocumentsWithPolicy(policy, parseCompositionDocument(t, "underlay-1a", "records: [{id: shared}]\nindependent: [{id: x}]\n"), parseCompositionDocument(t, "underlay-1b", "records: [{id: lower}]\n"), ) if len(diagnostics) != 0 { t.Fatalf("first tier diagnostics = %#v", diagnostics) } for index := range first.applications { first.applications[index].layer = LayerUnderlay } second, diagnostics := composeDocumentsWithPolicy(policy, parseCompositionDocument(t, "underlay-2", "records: [{id: shared}]\nindependent: []\n"), ) if len(diagnostics) != 0 { t.Fatalf("second tier diagnostics = %#v", diagnostics) } main, diagnostics := composeDocumentsWithPolicy(policy, parseCompositionDocument(t, "main", "records: []\n"), ) if len(diagnostics) != 0 { t.Fatalf("main diagnostics = %#v", diagnostics) } assembly := newAssemblyAccumulator(first) if diagnostics := assembly.applyOverlay(second.root, second.origins, second.applications, LayerUnderlay); len(diagnostics) != 0 { t.Fatalf("second tier handoff diagnostics = %#v", diagnostics) } if diagnostics := assembly.applyOverlay(main.root, main.origins, main.applications, LayerBase); len(diagnostics) != 0 { t.Fatalf("main handoff diagnostics = %#v", diagnostics) } if len(assembly.current.applications) != 4 { t.Fatalf("retained source applications = %d, want 4", len(assembly.current.applications)) } working := parseCompositionDocument(t, "defaults", "records: [{id: default}]\nindependent: [{id: default}]\n") index := new(mappingIndex) for _, application := range assembly.current.applications { applyHistoryApplication(&working, application, index) } for path, want := range map[string][]string{ "/records": nil, "/independent": nil, } { sequence, present := documentAtPath(working, mustParsePath(t, path)) if !present || sequence.Kind != document.Sequence || len(sequence.Sequence) != len(want) { t.Errorf("replayed replacement %s = %#v, want an explicit empty sequence", path, sequence) } } // The same identity may appear in separate tiers, while each tier still // retains its individual source applications for explanation replay. if got := []Layer{assembly.current.applications[0].layer, assembly.current.applications[1].layer, assembly.current.applications[2].layer, assembly.current.applications[3].layer}; !reflect.DeepEqual(got, []Layer{LayerUnderlay, LayerUnderlay, LayerUnderlay, LayerBase}) { t.Fatalf("application layers = %#v", got) } } func TestHistoryMergeSupportsSemanticIndexedPrefixes(t *testing.T) { root := parseCompositionDocument(t, "base", "records: [{id: one, helper: {value: old}}]\n") application := historyApplication{ path: Keys("records").Index(0).Key("helper"), value: parseCompositionDocument(t, "helper", "value: new\n"), } applyHistoryApplication(&root, application, new(mappingIndex)) value, present := documentAtPath(root, Keys("records").Index(0).Key("helper").Key("value")) if !present || value.Text != "new" { t.Fatalf("indexed helper replay = %#v, %v", value, present) } } func TestProjectedSequenceHistoryAgreesAcrossMetadataAndExplanation(t *testing.T) { policy := sequencePolicy{identityFields: map[string]string{"/records": "id"}} composed, diagnostics := composeDocumentsWithPolicy(policy, parseCompositionDocument(t, "first", "records: [{id: first, token: public}]"), parseCompositionDocument(t, "second", "records: [{id: second, token: private}]"), ) if len(diagnostics) != 0 { t.Fatalf("compose diagnostics = %#v", diagnostics) } path := Keys("records").Index(1).Key("token") var metadata Metadata finalizeMetadataPaths(&metadata, composed.root, composed.applications) if !metadata.hasHistoricalPath(path) { t.Fatalf("projected metadata omitted shifted path %s: %#v", path, metadata.historicalPaths) } inspection := &Inspection{ metadata: metadata, baseline: &document.Node{Kind: document.Mapping}, input: composed.root, final: composed.root, applications: composed.applications, } inspection.secrets = classifySecretPaths(nil, func(candidate Path) bool { return reflect.DeepEqual(candidate, path) }, metadata, composed.root, composed.applications) explanation, ok := inspection.Explain(path) if !ok || !explanation.Effective.Redacted { t.Fatalf("shifted explanation = %#v, %v", explanation, ok) } var foundSecondOrigin bool for _, change := range explanation.History { for _, location := range change.Origin.Locations { foundSecondOrigin = foundSecondOrigin || location.SourceID == "second" } } if !foundSecondOrigin { t.Fatalf("shifted history lost second source attribution: %#v", explanation.History) } var rendered bytes.Buffer if err := inspection.WriteExplanation(&rendered, path); err != nil { t.Fatal(err) } if !strings.Contains(rendered.String(), `path: "/records/1/token"`) || strings.Contains(rendered.String(), "private") { t.Fatalf("shifted explanation rendering is incomplete or unsafe: %s", rendered.String()) } } func TestReplacedProjectedSensitiveRecordRemainsRedacted(t *testing.T) { policy := sequencePolicy{identityFields: map[string]string{"/records": "id"}} composed, diagnostics := composeDocumentsWithPolicy(policy, parseCompositionDocument(t, "first", "records: [{id: first, token: public}]"), parseCompositionDocument(t, "second", "records: [{id: second, token: PRIVATE-RECORD-CANARY}]"), ) if len(diagnostics) != 0 { t.Fatalf("compose diagnostics = %#v", diagnostics) } applications := append([]historyApplication(nil), composed.applications...) applications = append(applications, historyApplication{ layer: LayerOverlay, value: parseCompositionDocument(t, "replacement", "records: [{id: replacement, token: visible}]"), }) final := applications[len(applications)-1].value path := Keys("records").Index(1).Key("token") var metadata Metadata finalizeMetadataPaths(&metadata, final, applications) inspection := &Inspection{ metadata: metadata, baseline: &document.Node{Kind: document.Mapping}, input: final, final: final, applications: applications, } inspection.secrets = classifySecretPaths(nil, func(candidate Path) bool { return reflect.DeepEqual(candidate, path) }, metadata, final, applications) explanation, ok := inspection.Explain(path) if !ok || explanation.Effective.Present { t.Fatalf("replaced shifted record explanation = %#v, %v", explanation, ok) } var rendered bytes.Buffer if err := inspection.WriteExplanation(&rendered, path); err != nil { t.Fatal(err) } if strings.Contains(rendered.String(), "PRIVATE-RECORD-CANARY") || !strings.Contains(rendered.String(), "[REDACTED]") { t.Fatalf("replaced sensitive history leaked or was not redacted: %s", rendered.String()) } } func mustParsePath(t *testing.T, value string) Path { t.Helper() path, err := ParsePath(value) if err != nil { t.Fatal(err) } return path }