|
1 | 1 | package typed |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "fmt" |
4 | 5 | "testing" |
5 | 6 |
|
6 | 7 | "sigs.k8s.io/structured-merge-diff/v2/fieldpath" |
7 | | - "sigs.k8s.io/structured-merge-diff/v2/schema" |
8 | 8 | "sigs.k8s.io/structured-merge-diff/v2/value" |
9 | 9 | ) |
10 | 10 |
|
11 | | -func TestRemoveShallowRemovesParents(t *testing.T) { |
| 11 | +func TestRemove(t *testing.T) { |
12 | 12 |
|
13 | | - test, err := value.FromJSON([]byte(` |
14 | | - { |
15 | | - "removeMap": { |
16 | | - "child": "value" |
| 13 | + var cases = []struct { |
| 14 | + object YAMLObject |
| 15 | + remove *fieldpath.Set |
| 16 | + deep bool |
| 17 | + expect YAMLObject |
| 18 | + }{ |
| 19 | + { |
| 20 | + object: `{}`, |
| 21 | + remove: fieldpath.NewSet(fieldpath.MakePathOrDie("a")), |
| 22 | + deep: true, |
| 23 | + expect: ``, |
17 | 24 | }, |
18 | | - "removeList": [ |
19 | | - {"child": "value"} |
20 | | - ], |
21 | | - "keep": "value", |
22 | | - "keepMap": { |
23 | | - "child": "value" |
| 25 | + { |
| 26 | + object: `{"a": "value"}`, |
| 27 | + remove: fieldpath.NewSet(fieldpath.MakePathOrDie("a")), |
| 28 | + deep: true, |
| 29 | + expect: `null`, |
24 | 30 | }, |
25 | | - "keepList": [ |
26 | | - {"child": "value"} |
27 | | - ] |
28 | | - }`)) |
29 | | - if err != nil { |
30 | | - t.Fatal(err) |
31 | | - } |
32 | | - |
33 | | - remove := fieldpath.NewSet( |
34 | | - fieldpath.MakePathOrDie("removeMap"), |
35 | | - fieldpath.MakePathOrDie("removeList"), |
36 | | - ) |
37 | | - |
38 | | - str := schema.String |
39 | | - |
40 | | - atom := schema.Atom{ |
41 | | - Map: &schema.Map{ |
42 | | - Fields: []schema.StructField{ |
43 | | - { |
44 | | - Name: "removeMap", |
45 | | - Type: schema.TypeRef{ |
46 | | - Inlined: schema.Atom{Map: &schema.Map{ |
47 | | - Fields: []schema.StructField{ |
48 | | - {Name: "child", Type: schema.TypeRef{Inlined: schema.Atom{Scalar: &str}}}}}, |
49 | | - }, |
50 | | - }, |
51 | | - }, |
52 | | - { |
53 | | - Name: "removeList", |
54 | | - Type: schema.TypeRef{ |
55 | | - Inlined: schema.Atom{ |
56 | | - List: &schema.List{ |
57 | | - ElementRelationship: schema.Separable, |
58 | | - ElementType: schema.TypeRef{ |
59 | | - Inlined: schema.Atom{Map: &schema.Map{ |
60 | | - Fields: []schema.StructField{ |
61 | | - {Name: "child", Type: schema.TypeRef{Inlined: schema.Atom{Scalar: &str}}}}}, |
62 | | - }, |
63 | | - }, |
64 | | - }, |
65 | | - }, |
66 | | - }, |
67 | | - }, |
68 | | - { |
69 | | - Name: "keep", |
70 | | - Type: schema.TypeRef{ |
71 | | - Inlined: schema.Atom{ |
72 | | - Scalar: &str, |
73 | | - }, |
74 | | - }, |
75 | | - }, |
76 | | - { |
77 | | - Name: "keepMap", |
78 | | - Type: schema.TypeRef{ |
79 | | - Inlined: schema.Atom{Map: &schema.Map{ |
80 | | - Fields: []schema.StructField{ |
81 | | - {Name: "child", Type: schema.TypeRef{Inlined: schema.Atom{Scalar: &str}}}}}, |
82 | | - }, |
83 | | - }, |
84 | | - }, |
85 | | - { |
86 | | - Name: "keepList", |
87 | | - Type: schema.TypeRef{ |
88 | | - Inlined: schema.Atom{ |
89 | | - List: &schema.List{ |
90 | | - ElementRelationship: schema.Separable, |
91 | | - ElementType: schema.TypeRef{ |
92 | | - Inlined: schema.Atom{Map: &schema.Map{ |
93 | | - Fields: []schema.StructField{ |
94 | | - {Name: "child", Type: schema.TypeRef{Inlined: schema.Atom{Scalar: &str}}}}}, |
95 | | - }, |
96 | | - }, |
97 | | - }, |
98 | | - }, |
99 | | - }, |
100 | | - }, |
101 | | - }, |
| 31 | + { |
| 32 | + object: `{"a": "value", "b": "value"}`, |
| 33 | + remove: fieldpath.NewSet(fieldpath.MakePathOrDie("a")), |
| 34 | + deep: true, |
| 35 | + expect: `{"b": "value"}`, |
102 | 36 | }, |
103 | | - } |
104 | | - |
105 | | - typeDef := schema.TypeDef{ |
106 | | - Name: "test", |
107 | | - Atom: atom, |
108 | | - } |
109 | | - |
110 | | - typeRef := schema.TypeRef{ |
111 | | - Inlined: atom, |
112 | | - } |
113 | | - |
114 | | - schema := &schema.Schema{ |
115 | | - Types: []schema.TypeDef{ |
116 | | - typeDef, |
| 37 | + { |
| 38 | + object: `{"a": "value", "b": {}}`, |
| 39 | + remove: fieldpath.NewSet(fieldpath.MakePathOrDie("a")), |
| 40 | + deep: true, |
| 41 | + expect: `{"b": {}}`, |
| 42 | + }, |
| 43 | + { |
| 44 | + object: `{"a": "value", "b": {"c":"value"}}`, |
| 45 | + remove: fieldpath.NewSet(fieldpath.MakePathOrDie("b")), |
| 46 | + deep: true, |
| 47 | + expect: `{"a": "value"}`, |
| 48 | + }, |
| 49 | + { |
| 50 | + object: `{"a": "value", "b":{"c":"value"}}`, |
| 51 | + remove: fieldpath.NewSet(fieldpath.MakePathOrDie("b")), |
| 52 | + deep: false, |
| 53 | + // TODO: this seems to behave differently with a non deduced schema: {"a": "value", "b":{"c":"value"}} which is the reason for this PR |
| 54 | + expect: `{"a": "value"}`, |
| 55 | + }, |
| 56 | + { |
| 57 | + object: `{"a": "value", "b": {"c":"value"}}`, |
| 58 | + remove: fieldpath.NewSet(fieldpath.MakePathOrDie("b", "c")), |
| 59 | + deep: true, |
| 60 | + // TODO: is a null result expected (insted of a {}) |
| 61 | + expect: `{"a": "value", "b": null}`, |
| 62 | + }, |
| 63 | + { |
| 64 | + object: `{"a": "value", "b": []}`, |
| 65 | + remove: fieldpath.NewSet(fieldpath.MakePathOrDie("b")), |
| 66 | + deep: true, |
| 67 | + expect: `{"a": "value"}`, |
| 68 | + }, |
| 69 | + { |
| 70 | + object: `{"a": "value", "b": ["c"]}`, |
| 71 | + remove: fieldpath.NewSet(fieldpath.MakePathOrDie("b", "c")), |
| 72 | + deep: true, |
| 73 | + expect: `{"a": "value", "b": null}`, |
| 74 | + }, |
| 75 | + { |
| 76 | + object: `{"a": "value", "b": ["c", "d"]}`, |
| 77 | + remove: fieldpath.NewSet(fieldpath.MakePathOrDie("b", "c")), |
| 78 | + deep: true, |
| 79 | + // TODO: is this expected? |
| 80 | + expect: `{"a": "value", "b": null}`, |
| 81 | + }, |
| 82 | + { |
| 83 | + object: `{"a": "value", "b": [{"c": "value"}, {"d": "value"}]}`, |
| 84 | + remove: fieldpath.NewSet(fieldpath.MakePathOrDie("b", "c")), |
| 85 | + deep: true, |
| 86 | + // TODO: is this expected? |
| 87 | + expect: `{"a": "value", "b": null}`, |
| 88 | + }, |
| 89 | + { |
| 90 | + object: `{"a": "value", "b": {"c":"value", "d":{"e":"value"}}}`, |
| 91 | + remove: fieldpath.NewSet(fieldpath.MakePathOrDie("b", "d")), |
| 92 | + deep: true, |
| 93 | + expect: `{"a": "value", "b": {"c":"value"}}`, |
| 94 | + }, |
| 95 | + { |
| 96 | + object: `{"a": "value", "b": {"c":"value", "d": {"e":"value"}}}`, |
| 97 | + remove: fieldpath.NewSet(fieldpath.MakePathOrDie("b", "d", "e")), |
| 98 | + deep: true, |
| 99 | + expect: `{"a": "value", "b": {"c":"value", "d": null}}`, |
117 | 100 | }, |
118 | 101 | } |
119 | 102 |
|
120 | | - tv := TypedValue{ |
121 | | - value: test, |
122 | | - typeRef: typeRef, |
123 | | - schema: schema, |
124 | | - } |
| 103 | + for i, c := range cases { |
| 104 | + c := c |
| 105 | + t.Run(fmt.Sprintf("case-%d", i), func(t *testing.T) { |
| 106 | + t.Parallel() |
125 | 107 |
|
126 | | - result := tv.RemoveItems(remove) |
| 108 | + obj, err := DeducedParseableType.FromYAML(c.object) |
| 109 | + if err != nil { |
| 110 | + t.Fatalf("unable to parse/validate object: %v\n%v", err, c.object) |
| 111 | + } |
127 | 112 |
|
128 | | - expect, err := value.FromJSON([]byte(`{"keep": "value", "keepMap": {"child": "value"}, "keepList": [{"child": "value"}], "removeMap": {"child":"value"}, "removeList": [{"child": "value"}]}`)) |
129 | | - if err != nil { |
130 | | - t.Fatal(err) |
131 | | - } |
132 | | - if !value.Equals(result.AsValue(), expect) { |
133 | | - t.Fatalf("unexpected result after remove:\ngot: %v\nexp: %v", test.String(), expect.String()) |
134 | | - } |
| 113 | + expectTyped, err := DeducedParseableType.FromYAML(c.expect) |
| 114 | + if err != nil { |
| 115 | + t.Fatalf("unable to parse/validate expected object: %v\n%v", err, c.expect) |
| 116 | + } |
| 117 | + expect := expectTyped.AsValue() |
135 | 118 |
|
136 | | - result = tv.RemoveDeep(remove) |
| 119 | + var result value.Value |
| 120 | + if c.deep { |
| 121 | + result = obj.RemoveDeep(c.remove).AsValue() |
| 122 | + } else { |
| 123 | + result = obj.RemoveItems(c.remove).AsValue() |
| 124 | + } |
137 | 125 |
|
138 | | - expect, err = value.FromJSON([]byte(`{"keep": "value", "keepMap": {"child": "value"}, "keepList": [{"child": "value"}]}`)) |
139 | | - if err != nil { |
140 | | - t.Fatal(err) |
141 | | - } |
142 | | - if !value.Equals(result.AsValue(), expect) { |
143 | | - t.Fatalf("unexpected result after remove:\ngot: %v\nexp: %v", value.ToString(test), value.ToString(expect)) |
| 126 | + if !value.Equals(result, expect) { |
| 127 | + t.Fatalf("unexpected result after remove:\ngot: %v\nexp: %v", |
| 128 | + value.ToString(result), value.ToString(expect), |
| 129 | + ) |
| 130 | + } |
| 131 | + }) |
144 | 132 | } |
145 | 133 | } |
0 commit comments