blob: 775c7c34b279891f53a8d02ca70e449bd2d20b1d [file] [log] [blame]
Marcel van Lohuizen31cd2b72019-11-09 17:08:49 +01001// Copyright 2019 CUE Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package diff
16
17import (
18 "bytes"
19 "testing"
20
21 "cuelang.org/go/cue"
22)
23
24func TestDiff(t *testing.T) {
25 testCases := []struct {
Marcel van Lohuizen29e9d002020-04-03 12:03:53 +020026 name string
27 x, y string
28 kind Kind
29 diff string
30 profile *Profile
Marcel van Lohuizen31cd2b72019-11-09 17:08:49 +010031 }{{
32 name: "identity struct",
33 x: `{
34 a: {
35 b: 1
36 c: 2
37 }
38 l: {
39 d: 1
40 }
41 }`,
42 y: `{
43 a: {
44 c: 2
45 b: 1
46 }
47 l: {
48 d: 1
49 }
50 }`,
51 }, {
52 name: "identity list",
53 x: `[1, 2, 3]`,
54 y: `[1, 2, 3]`,
55 }, {
56 name: "identity value",
57 x: `"foo"`,
58 y: `"foo"`,
59 }, {
60 name: "modified value",
61 x: `"foo"`,
62 y: `"bar"`,
63 kind: Modified,
64 }, {
65 name: "basics",
66 x: `{
67 a: int
68 b: 2
69 s: 4
70 d: 1
71 }
72 `,
73 y: `
74 {
75 a: string
76 c: 3
77 s: 4
78 d: int
79 }
80 `,
81 kind: Modified,
82 diff: ` {
83- a: int
84+ a: string
85- b: 2
86 s: 4
87- d: 1
88+ d: int
89+ c: 3
90 }
91`,
92 }, {
93 name: "basics 2",
94 x: `{
95 ls: [2, 3, 4]
96 "foo-bar": 2
97 s: 4
98 lm1: [2, 3, 5]
99 lm2: [6]
100 }
101 `,
102 y: `
103 {
104 ls: [2, 3, 4]
105 "foo-bar": 3
106 s: 4
107 lm1: [2, 3, 4, 6]
108 lm2: []
109 la: [2, 3, 4]
110 }
111 `,
112 kind: Modified,
113 diff: ` {
114 ls: [2, 3, 4]
115- "foo-bar": 2
116+ "foo-bar": 3
117 s: 4
118 lm1: [
119 2,
120 3,
121- 5,
122+ 4,
123+ 6,
124 ]
125 lm2: [
126- 6,
127 ]
128+ la: [2, 3, 4]
129 }
130`,
131 }, {
132 name: "interupted run 1",
133 x: `{
134 a: 1
135 b: 2
136 c: 3
137 d: 4
138 e: 10
139 f: 6
140 g: 7
141 h: 8
142 i: 9
143 j: 10
144}
145`,
146 y: `
147{
148 a: 1
149 b: 2
150 c: 3
151 d: 4
152 e: 5
153 f: 6
154 g: 7
155 h: 8
156 i: 9
157 j: 10
158}
159`,
160 kind: Modified,
161 diff: ` {
162 ... // 2 identical elements
163 c: 3
164 d: 4
165- e: 10
166+ e: 5
167 f: 6
168 g: 7
169 ... // 3 identical elements
170 }
171`,
172 }, {
173 name: "interupted run 2",
174 x: `{
175 a: -1
176 b: 2
177 c: 3
178 d: 4
179 e: 5
180 f: 6
181 g: 7
182 h: 8
183 i: 9
184 j: -10
185 }`,
186 y: `{
187 a: 1
188 b: 2
189 c: 3
190 d: 4
191 e: 5
192 f: 6
193 g: 7
194 h: 8
195 i: 9
196 j: 10
197 }
198 `,
199 kind: Modified,
200 diff: ` {
201- a: -1
202+ a: 1
203 b: 2
204 c: 3
205 ... // 4 identical elements
206 h: 8
207 i: 9
208- j: -10
209+ j: 10
210 }
211`,
212 }, {
213 name: "recursion",
214 x: `{
215 s: {
216 a: 1
217 b: 3
218 d: 4
219 }
220 l: [
221 [3, 4]
222 ]
223 }`,
224 y: `{
225 s: {
226 a: 2
227 b: 3
228 c: 4
229 }
230 l: [
231 [3, 5, 6]
232 ]
233 }
234 `,
235 kind: Modified,
236 diff: ` {
237 s: {
238- a: 1
239+ a: 2
240 b: 3
241- d: 4
242+ c: 4
243 }
244 l: [
245 [
246 3,
247- 4,
248+ 5,
249+ 6,
250 ]
251 ]
252 }
253`,
254 }, {
255 name: "optional and definitions",
256 x: `{
257 s :: {
258 a :: 1
259 b: 2
260 }
261 o?: 3
262 od? :: 1
263 oc?: 5
264}`,
265 y: `{
266 s :: {
267 a: 2
268 b :: 2
269 }
270 o?: 4
271 od :: 1
272 oc? :: 5
273}
274`,
275 kind: Modified,
276 diff: ` {
277 s :: {
278- a :: 1
279+ a: 2
280- b: 2
281+ b :: 2
282 }
283- o?: 3
284+ o?: 4
285- od? :: 1
286+ od :: 1
287- oc?: 5
288+ oc? :: 5
289 }
290`,
Marcel van Lohuizen5c3a17b2020-02-12 21:25:52 +0100291 }, {
Marcel van Lohuizen56c994d2020-04-21 16:20:36 +0200292 name: "bulk optional",
293 x: `{[_]: x: "hello"}
Marcel van Lohuizen5c3a17b2020-02-12 21:25:52 +0100294
295a: x: "hello"
296 `,
297 y: `[_]: x: "hello"
298
299 `,
300 kind: Modified,
301 diff: ` {
302- a: {
303- x: "hello"
304- }
305 }
306`,
Marcel van Lohuizen29e9d002020-04-03 12:03:53 +0200307 }, {
308 x: `
309 Directory :: {
310 {
311 // Directory from another directory (e.g. subdirectory)
312 from: Directory
313 } | {
314 // Reference to remote directory
315 ref: string
316 } | {
317 // Use a local directory
318 local: string
319 }
320 path: string | *"/"
321 }
322 `,
323 y: `
324 Directory :: {
325 {
326 // Directory from another directory (e.g. subdirectory)
327 from: Directory
328 } | {
329 // Reference to remote directory
330 ref: string
331 } | {
332 // Use a local directory
333 local: string
334 }
335 path: string | *"/"
336 }
337 `,
338 profile: Final,
339 }, {
340 x: `
341 Directory :: {
342 {
343 // Directory from another directory (e.g. subdirectory)
344 from: Directory
345 } | {
346 // Reference to remote directory
347 ref: string
348 } | {
349 // Use a local directory
350 local: string
351 }
352 path: string | *"/"
353 }
354 `,
355 y: `
356 Directory :: {
357 {
358 // Directory from another directory (e.g. subdirectory)
359 from: Directory
360 } | {
361 // Reference to remote directory
362 ref: string
363 } | {
364 // Use a local directory
365 local: string
366 }
367 path: string | *"/"
368 }
369 `,
Marcel van Lohuizen31cd2b72019-11-09 17:08:49 +0100370 }}
371 for _, tc := range testCases {
372 t.Run(tc.name, func(t *testing.T) {
373 var r cue.Runtime
374 x, err := r.Compile("x", tc.x)
375 if err != nil {
376 t.Fatal(err)
377 }
378 y, err := r.Compile("y", tc.y)
379 if err != nil {
380 t.Fatal(err)
381 }
Marcel van Lohuizen29e9d002020-04-03 12:03:53 +0200382 p := tc.profile
383 if p == nil {
384 p = Schema
385 }
386 kind, script := p.Diff(x.Value(), y.Value())
Marcel van Lohuizen31cd2b72019-11-09 17:08:49 +0100387 if kind != tc.kind {
388 t.Fatalf("got %d; want %d", kind, tc.kind)
389 }
390 if script != nil {
391 w := &bytes.Buffer{}
392 err = Print(w, script)
393 if err != nil {
394 t.Fatal(err)
395 }
396 if got := w.String(); got != tc.diff {
Marcel van Lohuizen5c3a17b2020-02-12 21:25:52 +0100397 t.Errorf("\ngot\n%s;\nwant\n%s", got, tc.diff)
Marcel van Lohuizen31cd2b72019-11-09 17:08:49 +0100398 }
399 }
400 })
401 }
402}
403
404func TestX(t *testing.T) {
405 t.Skip()
406
407 tc := struct {
408 x, y string
409 kind Kind
410 diff string
411 }{
412 x: `{
413 }
414 `,
415 y: `
416 {
417 }
418 `,
419 kind: Modified,
420 diff: ``,
421 }
422 var r cue.Runtime
423 x, err := r.Compile("x", tc.x)
424 if err != nil {
425 t.Fatal(err)
426 }
427 y, err := r.Compile("y", tc.y)
428 if err != nil {
429 t.Fatal(err)
430 }
431 kind, script := Diff(x.Value(), y.Value())
432 if kind != tc.kind {
433 t.Fatalf("got %d; want %d", kind, tc.kind)
434 }
435 w := &bytes.Buffer{}
436 err = Print(w, script)
437 if err != nil {
438 t.Fatal(err)
439 }
440 if got := w.String(); got != tc.diff {
441 t.Errorf("got\n%s;\nwant\n%s", got, tc.diff)
442 }
443}