Files
ConfigKit/internal/engine/diff_snapshot_test.go

341 lines
13 KiB
Go

package engine
import (
"testing"
"gitea.maximumdirect.net/eric/ConfigKit/internal/document"
)
func TestPreparePairedDiffSnapshotRedactsAlignedMappingFromEitherSide(t *testing.T) {
left := parseCompositionDocument(t, "left", "credential: alpha\npublic: before\n")
right := parseCompositionDocument(t, "right", "credential: bravo\npublic: after\n")
sensitivity := newDiffSensitivity(map[string]bool{"/credential": true}, nil)
paired, supported := preparePairedDiffSnapshot(left, right, Path{}, sensitivity)
if !supported {
t.Fatal("compatible mappings were not supported")
}
if !paired.leftRedacted || !paired.rightRedacted {
t.Fatalf("redacted flags = %v, %v; want true on both sides", paired.leftRedacted, paired.rightRedacted)
}
assertDiffStringNode(t, mappingValue(t, paired.left, "credential"), "[REDACTED]")
assertDiffStringNode(t, mappingValue(t, paired.right, "credential"), "[REDACTED]")
assertDiffStringNode(t, mappingValue(t, paired.left, "public"), "before")
assertDiffStringNode(t, mappingValue(t, paired.right, "public"), "after")
assertDiffStringNode(t, mappingValue(t, left, "credential"), "alpha")
assertDiffStringNode(t, mappingValue(t, right, "credential"), "bravo")
if paired.left == left || paired.right == right || &paired.left.Mapping[0] == &left.Mapping[0] {
t.Fatal("safe mapping containers or entries share mutable storage with retained trees")
}
}
func TestPreparePairedDiffSnapshotPreservesSequencePositionsAndLengths(t *testing.T) {
left := parseCompositionDocument(t, "left", "items: [left-public, hidden, old-tail]\n")
right := parseCompositionDocument(t, "right", "items: [right-public, hidden, old-tail, extra]\n")
sensitivity := newDiffSensitivity(nil, map[string]bool{"/items/1": true})
paired, supported := preparePairedDiffSnapshot(
mappingValue(t, left, "items"), mappingValue(t, right, "items"), Keys("items"), sensitivity,
)
if !supported {
t.Fatal("compatible sequences were not supported")
}
if !paired.leftRedacted || !paired.rightRedacted {
t.Fatalf("redacted flags = %v, %v; want true on both sides", paired.leftRedacted, paired.rightRedacted)
}
if len(paired.left.Sequence) != 3 || len(paired.right.Sequence) != 4 {
t.Fatalf("sequence lengths = %d, %d; want 3, 4", len(paired.left.Sequence), len(paired.right.Sequence))
}
assertDiffStringNode(t, paired.left.Sequence[0], "left-public")
assertDiffStringNode(t, paired.right.Sequence[0], "right-public")
assertDiffStringNode(t, paired.left.Sequence[1], "[REDACTED]")
assertDiffStringNode(t, paired.right.Sequence[1], "[REDACTED]")
assertDiffStringNode(t, paired.right.Sequence[3], "extra")
assertDiffStringNode(t, mappingValue(t, left, "items").Sequence[1], "hidden")
if &paired.left.Sequence[0] == &mappingValue(t, left, "items").Sequence[0] {
t.Fatal("safe sequence shares mutable storage with retained tree")
}
}
func TestPreparePairedDiffSnapshotMasksSensitiveDescendantsOfAbsentSubtrees(t *testing.T) {
tests := []struct {
name string
left, right string
absentSide string
}{
{
name: "removed subtree",
left: "removed: {token: old-secret, public: retained}\n",
right: "other: value\n",
absentSide: "right",
},
{
name: "added subtree",
left: "other: value\n",
right: "added: {token: new-secret, public: retained}\n",
absentSide: "left",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
left := parseCompositionDocument(t, "left", test.left)
right := parseCompositionDocument(t, "right", test.right)
paired, supported := preparePairedDiffSnapshot(
mappingValueIfPresent(left, "removed", "added"),
mappingValueIfPresent(right, "removed", "added"),
Keys("subtree"),
newDiffSensitivity(map[string]bool{"/subtree/token": true}, nil),
)
if !supported {
t.Fatal("compatible subtree and absence were not supported")
}
if test.absentSide == "left" {
if paired.left != nil || paired.leftRedacted || !paired.rightRedacted {
t.Fatalf("paired absence/redaction = %#v", paired)
}
assertDiffStringNode(t, mappingValue(t, paired.right, "token"), "[REDACTED]")
assertDiffStringNode(t, mappingValue(t, paired.right, "public"), "retained")
} else {
if paired.right != nil || paired.rightRedacted || !paired.leftRedacted {
t.Fatalf("paired absence/redaction = %#v", paired)
}
assertDiffStringNode(t, mappingValue(t, paired.left, "token"), "[REDACTED]")
assertDiffStringNode(t, mappingValue(t, paired.left, "public"), "retained")
}
})
}
}
func TestPreparePairedDiffSnapshotMasksSelectedRootAndContainer(t *testing.T) {
tests := []struct {
name string
left, right *document.Node
path Path
selector string
}{
{
name: "root",
left: parseCompositionDocument(t, "left", "token: old\n"),
right: parseCompositionDocument(t, "right", "token: new\n"),
path: Path{},
selector: "",
},
{
name: "container",
left: parseCompositionDocument(t, "left", "group: {public: old}\n"),
right: parseCompositionDocument(t, "right", "group: {public: new}\n"),
path: Keys("group"),
selector: "/group",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
paired, supported := preparePairedDiffSnapshot(
test.left, test.right, test.path,
newDiffSensitivity(map[string]bool{test.selector: true}, nil),
)
if !supported {
t.Fatal("selected nodes were not supported")
}
if !paired.leftRedacted || !paired.rightRedacted {
t.Fatalf("redacted flags = %v, %v; want true on both sides", paired.leftRedacted, paired.rightRedacted)
}
assertDiffStringNode(t, paired.left, "[REDACTED]")
assertDiffStringNode(t, paired.right, "[REDACTED]")
})
}
}
func TestPreparePairedDiffSnapshotDoesNotInterpretMarkerLookingInput(t *testing.T) {
left := parseCompositionDocument(t, "left", "label: '[REDACTED]'\n")
right := parseCompositionDocument(t, "right", "label: '[REDACTED]'\n")
paired, supported := preparePairedDiffSnapshot(
mappingValue(t, left, "label"), mappingValue(t, right, "label"), Keys("label"),
newDiffSensitivity(nil, nil),
)
if !supported {
t.Fatal("ordinary scalar values were not supported")
}
if paired.leftRedacted || paired.rightRedacted {
t.Fatalf("redacted flags = %v, %v; want false", paired.leftRedacted, paired.rightRedacted)
}
if paired.left != mappingValue(t, left, "label") || paired.right != mappingValue(t, right, "label") {
t.Fatal("unselected scalar nodes should remain borrowed immutable nodes")
}
assertDiffStringNode(t, paired.left, "[REDACTED]")
assertDiffStringNode(t, paired.right, "[REDACTED]")
}
func TestPreparePairedDiffSnapshotMasksSensitiveStructuralReplacements(t *testing.T) {
tests := []struct {
name string
left, right string
path Path
selector string
}{
{
name: "mapping to scalar",
left: "changed: {token: old-secret, public: old}\n",
right: "changed: new-scalar\n",
path: Keys("changed"),
selector: "/changed/token",
},
{
name: "scalar to mapping",
left: "changed: old-scalar\n",
right: "changed: {token: new-secret, public: new}\n",
path: Keys("changed"),
selector: "/changed/token",
},
{
name: "mapping to sequence with numeric paths",
left: "changed: {'0': {token: old-secret}}\n",
right: "changed: [{token: new-secret}]\n",
path: Keys("changed"),
selector: "/changed/0/token",
},
{
name: "sequence to mapping with numeric paths",
left: "changed: [{token: old-secret}]\n",
right: "changed: {'0': {token: new-secret}}\n",
path: Keys("changed"),
selector: "/changed/0/token",
},
{
name: "null to container",
left: "changed: null\n",
right: "changed: {token: new-secret}\n",
path: Keys("changed"),
selector: "/changed/token",
},
{
name: "container to null",
left: "changed: {token: old-secret}\n",
right: "changed: null\n",
path: Keys("changed"),
selector: "/changed/token",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
leftRoot := parseCompositionDocument(t, "left", test.left)
rightRoot := parseCompositionDocument(t, "right", test.right)
left := mappingValue(t, leftRoot, test.path.segments[0].key)
right := mappingValue(t, rightRoot, test.path.segments[0].key)
paired, supported := preparePairedDiffSnapshot(
left, right, test.path, newDiffSensitivity(nil, map[string]bool{test.selector: true}),
)
assertWholeRegionFallback(t, paired, supported, left, right)
})
}
}
func TestPreparePairedDiffSnapshotMasksOriginalRegionForNestedSequenceMismatch(t *testing.T) {
leftRoot := parseCompositionDocument(t, "left", "items: [{branch: {token: old-secret, public: old}}]\n")
rightRoot := parseCompositionDocument(t, "right", "items: [{branch: new-scalar}]\n")
left := mappingValue(t, leftRoot, "items")
right := mappingValue(t, rightRoot, "items")
paired, supported := preparePairedDiffSnapshot(
left, right, Keys("items"), newDiffSensitivity(nil, map[string]bool{"/items/0/branch/token": true}),
)
assertWholeRegionFallback(t, paired, supported, left, right)
}
func TestPreparePairedDiffSnapshotUsesHistoricalDescendantClassification(t *testing.T) {
leftRoot := parseCompositionDocument(t, "left", "changed: before\n")
rightRoot := parseCompositionDocument(t, "right", "changed: after\n")
left := mappingValue(t, leftRoot, "changed")
right := mappingValue(t, rightRoot, "changed")
paired, supported := preparePairedDiffSnapshot(
left, right, Keys("changed"), newDiffSensitivity(map[string]bool{"/changed/removed/secret": true}, nil),
)
assertWholeRegionFallback(t, paired, supported, left, right)
}
func TestPreparePairedDiffSnapshotFallbackPreservesAbsentReportedSide(t *testing.T) {
right := parseCompositionDocument(t, "right", "branch: scalar\n")
paired, supported := preparePairedDiffSnapshot(
nil, right, Keys("added"), newDiffSensitivity(nil, map[string]bool{"/added/branch/secret": true}),
)
if !supported || paired.left != nil || paired.leftRedacted || !paired.rightRedacted {
t.Fatalf("fallback presence/redaction = %#v, supported=%v", paired, supported)
}
assertDiffStringNode(t, paired.right, "[REDACTED]")
}
func TestPreparePairedDiffSnapshotPreservesPublicReplacementBesideSensitiveSibling(t *testing.T) {
left := parseCompositionDocument(t, "left", "child: before\n")
right := &document.Node{Kind: document.String, Text: "after"}
paired, supported := preparePairedDiffSnapshot(
mappingValue(t, left, "child"), right, Keys("public"),
newDiffSensitivity(nil, map[string]bool{"/private/token": true}),
)
if !supported || paired.left != mappingValue(t, left, "child") || paired.right != right || paired.leftRedacted || paired.rightRedacted {
t.Fatalf("unrelated classification changed public replacement: %#v, supported=%v", paired, supported)
}
}
func TestPreparePairedDiffSnapshotTargetsRedactionAcrossAbsence(t *testing.T) {
left := parseCompositionDocument(t, "left", "items: []\n")
right := parseCompositionDocument(t, "right", "items: [{token: new-secret, public: visible}]\n")
leftItems := mappingValue(t, left, "items")
rightItems := mappingValue(t, right, "items")
paired, supported := preparePairedDiffSnapshot(
leftItems, rightItems, Keys("items"), newDiffSensitivity(nil, map[string]bool{"/items/0/token": true}),
)
if !supported || paired.left == nil || paired.right == nil || paired.leftRedacted || !paired.rightRedacted {
t.Fatalf("targeted sequence redaction = %#v, supported=%v", paired, supported)
}
if len(paired.left.Sequence) != 0 || len(paired.right.Sequence) != 1 {
t.Fatalf("sequence lengths = %d, %d; want 0, 1", len(paired.left.Sequence), len(paired.right.Sequence))
}
assertDiffStringNode(t, mappingValue(t, paired.right.Sequence[0], "token"), "[REDACTED]")
assertDiffStringNode(t, mappingValue(t, paired.right.Sequence[0], "public"), "visible")
}
func assertWholeRegionFallback(t *testing.T, paired pairedDiffSnapshot, supported bool, left, right *document.Node) {
t.Helper()
if !supported {
t.Fatal("sensitive incompatible shape was not handled")
}
if !paired.hiddenChanged {
t.Fatal("fallback for a changed reported region did not mark hidden change")
}
if (left == nil) != (paired.left == nil) || (right == nil) != (paired.right == nil) {
t.Fatalf("fallback changed root presence: %#v", paired)
}
if left != nil {
assertDiffStringNode(t, paired.left, "[REDACTED]")
if !paired.leftRedacted {
t.Fatal("present left region was not marked redacted")
}
}
if right != nil {
assertDiffStringNode(t, paired.right, "[REDACTED]")
if !paired.rightRedacted {
t.Fatal("present right region was not marked redacted")
}
}
}
func mappingValueIfPresent(node *document.Node, keys ...string) *document.Node {
if node == nil {
return nil
}
for _, key := range keys {
for _, entry := range node.Mapping {
if entry.Key == key {
return entry.Value
}
}
}
return nil
}
func assertDiffStringNode(t *testing.T, node *document.Node, want string) {
t.Helper()
if node == nil || node.Kind != document.String || node.Text != want {
t.Fatalf("node = %#v, want string %q", node, want)
}
}