package ckconfig import ( "reflect" "strings" "testing" "go.yaml.in/yaml/v4" ) func TestDecodeSafeSnapshotPreservesYAMLTypes(t *testing.T) { tests := []struct { name string text string kind yaml.Kind tag string value string }{ {name: "null", text: "null\n", kind: yaml.ScalarNode, tag: "!!null", value: "null"}, {name: "boolean", text: "true\n", kind: yaml.ScalarNode, tag: "!!bool", value: "true"}, {name: "large integer", text: "9007199254740993\n", kind: yaml.ScalarNode, tag: "!!int", value: "9007199254740993"}, {name: "numeric string", text: "'123'\n", kind: yaml.ScalarNode, tag: "!!str", value: "123"}, {name: "boolean-like string", text: "'false'\n", kind: yaml.ScalarNode, tag: "!!str", value: "false"}, {name: "empty mapping", text: "{}\n", kind: yaml.MappingNode, tag: "!!map"}, {name: "empty sequence", text: "[]\n", kind: yaml.SequenceNode, tag: "!!seq"}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { node, err := decodeSafeSnapshot(test.text) if err != nil { t.Fatal(err) } if node.Kind != test.kind || node.Tag != test.tag || node.Value != test.value { t.Fatalf("node kind/tag/value = %v/%q/%q, want %v/%q/%q", node.Kind, node.Tag, node.Value, test.kind, test.tag, test.value) } }) } nested, err := decodeSafeSnapshot("items:\n - name: example\n enabled: false\n") if err != nil { t.Fatal(err) } if nested.Kind != yaml.MappingNode || nested.Content[1].Kind != yaml.SequenceNode || nested.Content[1].Content[0].Content[3].Tag != "!!bool" { t.Fatalf("nested collection/scalar tags were not preserved: %#v", nested) } } func TestDecodeJSONPointerPreservesSemanticTokens(t *testing.T) { tests := []struct { pointer string want []string }{ {pointer: "", want: nil}, {pointer: "/", want: []string{""}}, {pointer: "/parent/child", want: []string{"parent", "child"}}, {pointer: "/0/../a.b/50%", want: []string{"0", "..", "a.b", "50%"}}, {pointer: "/a~1b/c~0d", want: []string{"a/b", "c~d"}}, {pointer: "/~01", want: []string{"~1"}}, } for _, test := range tests { got, err := decodeJSONPointer(test.pointer) if err != nil { t.Fatalf("decode %q: %v", test.pointer, err) } if !reflect.DeepEqual(got, test.want) { t.Errorf("decode %q = %#v, want %#v", test.pointer, got, test.want) } } for _, pointer := range []string{"missing-leading-slash", "/bad~", "/bad~2escape"} { if _, err := decodeJSONPointer(pointer); err == nil { t.Errorf("decode %q unexpectedly succeeded", pointer) } } } func TestPlaceYAMLValueBuildsOrderedSemanticMappings(t *testing.T) { var placer yamlValuePlacer category := &yaml.Node{Kind: yaml.MappingNode, Tag: "!!map"} paths := [][]string{ {"parent", "0", "dot.name", "50%"}, {"parent", "second"}, {"a/b", "~1"}, {""}, } for index, path := range paths { value := &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!str", Value: string(rune('a' + index))} updated, err := placer.placeValue(category, path, value) if err != nil { t.Fatalf("place %q: %v", pointerFromTokens(path), err) } category = updated } if len(category.Content) != 6 || category.Content[0].Value != "parent" || category.Content[2].Value != "a/b" || category.Content[4].Value != "" { t.Fatalf("mapping insertion order or empty key = %#v", category.Content) } parent := category.Content[1] if parent.Kind != yaml.MappingNode || len(parent.Content) != 4 || parent.Content[0].Value != "0" || parent.Content[2].Value != "second" { t.Fatalf("nested shared ancestor/order = %#v", parent) } numeric := parent.Content[1] dotted := numeric.Content[1] if numeric.Kind != yaml.MappingNode || numeric.Content[0].Value != "dot.name" || dotted.Kind != yaml.MappingNode || dotted.Content[0].Value != "50%" { t.Fatalf("semantic tokens were changed: numeric=%#v dotted=%#v", numeric, dotted) } if category.Content[1].Content[0].Tag != "!!str" || category.Content[2].Tag != "!!str" || category.Content[4].Tag != "!!str" { t.Fatal("mapping keys are not explicitly tagged as YAML strings") } } func TestPlaceYAMLValueHandlesRootAndEmptyKey(t *testing.T) { var placer yamlValuePlacer category := &yaml.Node{Kind: yaml.MappingNode, Tag: "!!map"} root := &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!null", Value: "null"} updated, err := placer.placeValue(category, nil, root) if err != nil || updated != root { t.Fatalf("root placement = %#v, %v", updated, err) } category = &yaml.Node{Kind: yaml.MappingNode, Tag: "!!map"} value := &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!str", Value: "empty-key"} updated, err = placer.placeValue(category, []string{""}, value) if err != nil { t.Fatal(err) } if updated != category || len(category.Content) != 2 || category.Content[0].Value != "" || category.Content[0].Tag != "!!str" || category.Content[1] != value { t.Fatalf("slash path placement = %#v", category) } } func TestPlaceYAMLValueRejectsIncompatibleAncestors(t *testing.T) { var placer yamlValuePlacer category := &yaml.Node{Kind: yaml.MappingNode, Tag: "!!map", Content: []*yaml.Node{ stringKey("parent"), {Kind: yaml.ScalarNode, Tag: "!!str", Value: "leaf"}, }} _, err := placer.placeValue(category, []string{"parent", "child"}, &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!null", Value: "null"}) if err == nil || !strings.Contains(err.Error(), "/parent/child") || !strings.Contains(err.Error(), "/parent") { t.Fatalf("incompatible ancestor error = %v", err) } } func TestDecodeSafeSnapshotRejectsMalformedYAML(t *testing.T) { if _, err := decodeSafeSnapshot("value: [unterminated\n"); err == nil { t.Fatal("malformed snapshot unexpectedly decoded") } }