forked from mattbaird/jsonpatch
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjsonpatch_entity_set_test.go
More file actions
204 lines (188 loc) · 9.69 KB
/
Copy pathjsonpatch_entity_set_test.go
File metadata and controls
204 lines (188 loc) · 9.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
package jsonpatch
import (
"testing"
"github.com/stretchr/testify/assert"
)
var simpleObjEntitySet = `{"a":100, "t":[{"k":1, "v":1},{"k":2, "v":2}]}`
var simpleObjAddEntitySetItem = `{"t":[{"k":3, "v":3}]}`
var simpleObjModifyEntitySetItem = `{"t":[{"k":2, "v":3}]}`
var simpleObjAddDuplicateEntitySetItem = `{"t":[{"k":2, "v":2}]}`
var simpleObjAddMultipleDuplicateAndFailedItems = `{"t":[{"k":1, "v":1},{"k":2, "v":2},{"k":3, "v":3},{"k":4, "v":4}]}`
var simpleObjEntitySetRemoveItem = `{"a":100, "t":[{"k":1, "v":1}]}`
var complexNextedEntitySet = `{
"a":100,
"t":[
{"k":1,
"v":[
{"nk":11, "c":"x", "d":[1,2], "e":"f"},
{"nk":22, "c":"y", "d":[3,4], "e":"f"}
]
},
{"k":2,
"v":[
{"nk":33, "c":"z", "d":[5,6], "e":"f"}
]
}
]}`
var complexNextedEntitySetModifyItem = `{
"t":[
{"k":2,
"v":[
{"nk":33, "c":"zz", "d":[7,8]}
]
}
]}`
var entitySetTestCollections = Collections{
EntitySets: EntitySets{
Path("$.t"): Key("k"),
Path("$.t[*].v"): Key("nk"),
},
Arrays: []Path{}, // No arrays in this test, only sets
}
func TestCreatePatch_AddItemToEntitySet_InEnsureExistsMode_GeneratesAddOperation(t *testing.T) {
patch, err := CreatePatch([]byte(simpleObjEntitySet), []byte(simpleObjAddEntitySetItem), entitySetTestCollections, nil, PatchStrategyEnsureExists)
assert.NoError(t, err)
assert.Equal(t, 1, len(patch), "they should be equal")
change := patch[0]
assert.Equal(t, "add", change.Operation, "they should be equal")
assert.Equal(t, "/t/2", change.Path, "they should be equal")
var expected = map[string]any{"k": float64(3), "v": float64(3)}
assert.Equal(t, expected, change.Value, "they should be equal")
}
func TestCreatePatch_AddItemToEntitySet_InExactMatchMode_GeneratesAddOperation(t *testing.T) {
patch, err := CreatePatch([]byte(simpleObjEntitySet), []byte(simpleObjAddEntitySetItem), entitySetTestCollections, nil, PatchStrategyExactMatch)
assert.NoError(t, err)
assert.Equal(t, 3, len(patch), "they should be equal")
change := patch[0]
assert.Equal(t, "remove", change.Operation, "they should be equal")
assert.Equal(t, "/t/1", change.Path, "they should be equal")
change = patch[1]
assert.Equal(t, "remove", change.Operation, "they should be equal")
assert.Equal(t, "/t/0", change.Path, "they should be equal")
change = patch[2]
assert.Equal(t, "add", change.Operation, "they should be equal")
assert.Equal(t, "/t/0", change.Path, "they should be equal")
var expected = map[string]any{"k": float64(3), "v": float64(3)}
assert.Equal(t, expected, change.Value, "they should be equal")
}
func TestCreatePatch_ModifyItemInEntitySet_InEnsureExistsMode_GeneratesReplaceOperation(t *testing.T) {
patch, err := CreatePatch([]byte(simpleObjEntitySet), []byte(simpleObjModifyEntitySetItem), entitySetTestCollections, nil, PatchStrategyEnsureExists)
assert.NoError(t, err)
assert.Equal(t, 1, len(patch), "they should be equal")
change := patch[0]
assert.Equal(t, "replace", change.Operation, "they should be equal")
assert.Equal(t, "/t/1/v", change.Path, "they should be equal")
var expected float64 = 3
assert.Equal(t, expected, change.Value, "they should be equal")
}
func TestCreatePatch_RemoveItemFromEntitySet_InExactMatchExistsMode_GeneratesRemoveOperation(t *testing.T) {
patch, err := CreatePatch([]byte(simpleObjEntitySet), []byte(simpleObjEntitySetRemoveItem), entitySetTestCollections, nil, PatchStrategyExactMatch)
assert.NoError(t, err)
assert.Equal(t, 1, len(patch), "they should be equal")
change := patch[0]
assert.Equal(t, "remove", change.Operation, "they should be equal")
assert.Equal(t, "/t/1", change.Path, "they should be equal")
}
func TestCreatePatch_ModifyItemInEntitySet_InExactMatchMode_GeneratesARemoveAndAReplaceOperation(t *testing.T) {
patch, err := CreatePatch([]byte(simpleObjEntitySet), []byte(simpleObjModifyEntitySetItem), entitySetTestCollections, nil, PatchStrategyExactMatch)
assert.NoError(t, err)
assert.Equal(t, 2, len(patch), "they should be equal")
change := patch[0]
assert.Equal(t, "remove", change.Operation, "they should be equal")
assert.Equal(t, "/t/0", change.Path, "they should be equal")
change = patch[1]
assert.Equal(t, "replace", change.Operation, "they should be equal")
assert.Equal(t, "/t/1/v", change.Path, "they should be equal")
var expected float64 = 3
assert.Equal(t, expected, change.Value, "they should be equal")
}
func TestCreatePatch_AddDuplicateItemToEntitySet_InEnsureExistsMode_GeneratesNoOperations(t *testing.T) {
patch, err := CreatePatch([]byte(simpleObjEntitySet), []byte(simpleObjAddDuplicateEntitySetItem), entitySetTestCollections, nil, PatchStrategyEnsureExists)
assert.NoError(t, err)
assert.Equal(t, 0, len(patch), "they should be equal")
}
func TestCreatePatch_AddDuplicateItemToEntitySet_InExactMatchMode_GeneratesARemoveOperation(t *testing.T) {
patch, err := CreatePatch([]byte(simpleObjEntitySet), []byte(simpleObjAddDuplicateEntitySetItem), entitySetTestCollections, nil, PatchStrategyExactMatch)
assert.NoError(t, err)
assert.Equal(t, 1, len(patch), "they should be equal")
change := patch[0]
assert.Equal(t, "remove", change.Operation, "they should be equal")
assert.Equal(t, "/t/0", change.Path, "they should be equal")
}
func TestCreatePatch_ModifyItemInComplexNestedEntitySet_InEnsureExistsMode_GeneratesReplaceOperation(t *testing.T) {
patch, err := CreatePatch([]byte(complexNextedEntitySet), []byte(complexNextedEntitySetModifyItem), entitySetTestCollections, nil, PatchStrategyEnsureExists)
assert.NoError(t, err)
assert.Equal(t, 3, len(patch), "they should be equal")
change := patch[0]
assert.Equal(t, "replace", change.Operation, "they should be equal")
assert.Equal(t, "/t/1/v/0/c", change.Path, "they should be equal")
assert.Equal(t, "zz", change.Value, "they should be equal")
change = patch[1]
assert.Equal(t, "add", change.Operation, "they should be equal")
assert.Equal(t, "/t/1/v/0/d/2", change.Path, "they should be equal")
assert.Equal(t, float64(7), change.Value, "they should be equal")
change = patch[2]
assert.Equal(t, "add", change.Operation, "they should be equal")
assert.Equal(t, "add", change.Operation, "they should be equal")
assert.Equal(t, "/t/1/v/0/d/3", change.Path, "they should be equal")
assert.Equal(t, float64(8), change.Value, "they should be equal")
}
func TestCreatePatch_ModifyItemInComplexNestedEntitySet_InExactMatchMode_GeneratesReplaceOperation(t *testing.T) {
patch, err := CreatePatch([]byte(complexNextedEntitySet), []byte(complexNextedEntitySetModifyItem), entitySetTestCollections, nil, PatchStrategyExactMatch)
assert.NoError(t, err)
assert.Equal(t, 6, len(patch), "they should be equal")
change := patch[0]
assert.Equal(t, "remove", change.Operation, "they should be equal")
assert.Equal(t, "/t/0", change.Path, "they should be equal")
change = patch[1]
assert.Equal(t, "replace", change.Operation, "they should be equal")
assert.Equal(t, "/t/1/v/0/c", change.Path, "they should be equal")
assert.Equal(t, "zz", change.Value, "they should be equal")
change = patch[2]
assert.Equal(t, "remove", change.Operation, "they should be equal")
assert.Equal(t, "/t/1/v/0/d/1", change.Path, "they should be equal")
change = patch[3]
assert.Equal(t, "remove", change.Operation, "they should be equal")
assert.Equal(t, "/t/1/v/0/d/0", change.Path, "they should be equal")
change = patch[4]
assert.Equal(t, "add", change.Operation, "they should be equal")
assert.Equal(t, "/t/1/v/0/d/0", change.Path, "they should be equal")
assert.Equal(t, float64(7), change.Value, "they should be equal")
change = patch[5]
assert.Equal(t, "add", change.Operation, "they should be equal")
assert.Equal(t, "/t/1/v/0/d/1", change.Path, "they should be equal")
assert.Equal(t, float64(8), change.Value, "they should be equal")
}
func TestCreatePatch_AddMultipleDuplicateAndFailedItemsToEntitySet_InEnsureExistsMode_GeneratesNoOperations(t *testing.T) {
patch, err := CreatePatch([]byte(simpleObjEntitySet), []byte(simpleObjAddMultipleDuplicateAndFailedItems), entitySetTestCollections, nil, PatchStrategyEnsureExists)
assert.NoError(t, err)
assert.Equal(t, 2, len(patch), "they should be equal")
change := patch[0]
assert.Equal(t, "add", change.Operation, "they should be equal")
assert.Equal(t, "/t/2", change.Path, "they should be equal")
var expected = map[string]any{"k": float64(3), "v": float64(3)}
assert.Equal(t, expected, change.Value, "they should be equal")
change = patch[1]
assert.Equal(t, "add", change.Operation, "they should be equal")
assert.Equal(t, "/t/3", change.Path, "they should be equal")
var expected2 = map[string]any{"k": float64(4), "v": float64(4)}
assert.Equal(t, expected2, change.Value, "they should be equal")
}
// Regression test for the case where an EntitySet collection is populated on
// the document (actual) side but the field is entirely absent on the patch
// (desired) side. ExactMatch should produce remove ops for every element so
// the diff round-trip clears the collection. Previously CreatePatch returned
// zero ops, silently swallowing the drift — observed as the formae e2e tests
// `TestSoftReconcile`/`TestHardReconcile`/`TestSimulateApply` failing to
// reject an apply after an out-of-band tag was added to an IAM Role whose
// IaC declared no `tags` field.
func TestCreatePatch_EntitySetAbsentOnDesiredSide_InExactMatchMode_GeneratesRemoveOperation(t *testing.T) {
document := `{"a":100, "t":[{"k":1, "v":1}]}`
desired := `{"a":100}`
patch, err := CreatePatch([]byte(document), []byte(desired), entitySetTestCollections, nil, PatchStrategyExactMatch)
assert.NoError(t, err)
assert.Equal(t, 1, len(patch), "expected one remove op for the absent EntitySet")
change := patch[0]
assert.Equal(t, "remove", change.Operation, "operation should be remove")
assert.Equal(t, "/t", change.Path, "path should be the EntitySet root")
}