github.com/solo-io/cue@v0.4.7/internal/diff/diff_test.go (about) 1 // 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 15 package diff 16 17 import ( 18 "bytes" 19 "testing" 20 21 "github.com/solo-io/cue/cue" 22 ) 23 24 func TestDiff(t *testing.T) { 25 testCases := []struct { 26 name string 27 x, y string 28 kind Kind 29 diff string 30 profile *Profile 31 }{{ 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 diff: `- "foo", 65 + "bar", 66 `, 67 }, { 68 name: "basics", 69 x: `{ 70 a: int 71 b: 2 72 s: 4 73 d: 1 74 e: null 75 } 76 `, 77 y: ` 78 { 79 a: string 80 c: 3 81 s: 4 82 d: int 83 e: null 84 } 85 `, 86 kind: Modified, 87 diff: ` { 88 - a: int 89 + a: string 90 - b: 2 91 + c: 3 92 s: 4 93 - d: 1 94 + d: int 95 e: null 96 } 97 `, 98 }, { 99 name: "basics 2", 100 x: `{ 101 ls: [2, 3, 4] 102 "foo-bar": 2 103 s: 4 104 lm1: [2, 3, 5] 105 lm2: [6] 106 } 107 `, 108 y: ` 109 { 110 ls: [2, 3, 4] 111 "foo-bar": 3 112 s: 4 113 lm1: [2, 3, 4, 6] 114 lm2: [] 115 la: [2, 3, 4] 116 } 117 `, 118 kind: Modified, 119 diff: ` { 120 ls: [2, 3, 4] 121 - "foo-bar": 2 122 + "foo-bar": 3 123 s: 4 124 lm1: [ 125 2, 126 3, 127 - 5, 128 + 4, 129 + 6, 130 ] 131 lm2: [ 132 - 6, 133 ] 134 + la: [2, 3, 4] 135 } 136 `, 137 }, { 138 name: "interupted run 1", 139 x: `{ 140 a: 1 141 b: 2 142 c: 3 143 d: 4 144 e: 10 145 f: 6 146 g: 7 147 h: 8 148 i: 9 149 j: 10 150 } 151 `, 152 y: ` 153 { 154 a: 1 155 b: 2 156 c: 3 157 d: 4 158 e: 5 159 f: 6 160 g: 7 161 h: 8 162 i: 9 163 j: 10 164 } 165 `, 166 kind: Modified, 167 diff: ` { 168 ... // 2 identical elements 169 c: 3 170 d: 4 171 - e: 10 172 + e: 5 173 f: 6 174 g: 7 175 ... // 3 identical elements 176 } 177 `, 178 }, { 179 name: "interupted run 2", 180 x: `{ 181 a: -1 182 b: 2 183 c: 3 184 d: 4 185 e: 5 186 f: 6 187 g: 7 188 h: 8 189 i: 9 190 j: -10 191 }`, 192 y: `{ 193 a: 1 194 b: 2 195 c: 3 196 d: 4 197 e: 5 198 f: 6 199 g: 7 200 h: 8 201 i: 9 202 j: 10 203 } 204 `, 205 kind: Modified, 206 diff: ` { 207 - a: -1 208 + a: 1 209 b: 2 210 c: 3 211 ... // 4 identical elements 212 h: 8 213 i: 9 214 - j: -10 215 + j: 10 216 } 217 `, 218 }, { 219 name: "recursion", 220 x: `{ 221 s: { 222 a: 1 223 b: 3 224 d: 4 225 } 226 l: [ 227 [3, 4] 228 ] 229 }`, 230 y: `{ 231 s: { 232 a: 2 233 b: 3 234 c: 4 235 } 236 l: [ 237 [3, 5, 6] 238 ] 239 } 240 `, 241 kind: Modified, 242 diff: ` { 243 s: { 244 - a: 1 245 + a: 2 246 b: 3 247 - d: 4 248 + c: 4 249 } 250 l: [ 251 [ 252 3, 253 - 4, 254 + 5, 255 + 6, 256 ] 257 ] 258 } 259 `, 260 }, { 261 name: "optional and definitions", 262 x: `{ 263 #s: { 264 #a: 1 265 b: 2 266 } 267 o?: 3 268 #od?: 1 269 oc?: 5 270 }`, 271 y: `{ 272 #s: { 273 a: 2 274 #b: 2 275 } 276 o?: 4 277 #od: 1 278 #oc?: 5 279 } 280 `, 281 kind: Modified, 282 diff: ` { 283 #s: { 284 - #a: 1 285 - b: 2 286 + a: 2 287 + #b: 2 288 } 289 - o?: 3 290 + o?: 4 291 - #od?: 1 292 + #od: 1 293 - oc?: 5 294 + #oc?: 5 295 } 296 `, 297 }, { 298 name: "bulk optional", 299 x: `{[_]: x: "hello"} 300 301 a: x: "hello" 302 `, 303 y: `[_]: x: "hello" 304 305 `, 306 kind: Modified, 307 diff: ` { 308 - a: { 309 - x: "hello" 310 - } 311 } 312 `, 313 }, { 314 x: ` 315 #Directory: { 316 { 317 // Directory from another directory (e.g. subdirectory) 318 from: #Directory 319 } | { 320 // Reference to remote directory 321 ref: string 322 } | { 323 // Use a local directory 324 local: string 325 } 326 path: string | *"/" 327 } 328 `, 329 y: ` 330 #Directory: { 331 { 332 // Directory from another directory (e.g. subdirectory) 333 from: #Directory 334 } | { 335 // Reference to remote directory 336 ref: string 337 } | { 338 // Use a local directory 339 local: string 340 } 341 path: string | *"/" 342 } 343 `, 344 profile: Final, 345 }, { 346 x: ` 347 #Directory: { 348 { 349 // Directory from another directory (e.g. subdirectory) 350 from: #Directory 351 } | { 352 // Reference to remote directory 353 ref: string 354 } | { 355 // Use a local directory 356 local: string 357 } 358 path: string | *"/" 359 } 360 `, 361 y: ` 362 #Directory: { 363 { 364 // Directory from another directory (e.g. subdirectory) 365 from: #Directory 366 } | { 367 // Reference to remote directory 368 ref: string 369 } | { 370 // Use a local directory 371 local: string 372 } 373 path: string | *"/" 374 } 375 `, 376 }} 377 for _, tc := range testCases { 378 t.Run(tc.name, func(t *testing.T) { 379 var r cue.Runtime 380 x, err := r.Compile("x", tc.x) 381 if err != nil { 382 t.Fatal(err) 383 } 384 y, err := r.Compile("y", tc.y) 385 if err != nil { 386 t.Fatal(err) 387 } 388 p := tc.profile 389 if p == nil { 390 p = Schema 391 } 392 kind, script := p.Diff(x.Value(), y.Value()) 393 if kind != tc.kind { 394 t.Fatalf("got %d; want %d", kind, tc.kind) 395 } 396 if script != nil { 397 w := &bytes.Buffer{} 398 err = Print(w, script) 399 if err != nil { 400 t.Fatal(err) 401 } 402 if got := w.String(); got != tc.diff { 403 t.Errorf("\ngot\n%s;\nwant\n%s", got, tc.diff) 404 } 405 } 406 }) 407 } 408 } 409 410 func TestX(t *testing.T) { 411 t.Skip() 412 413 tc := struct { 414 x, y string 415 kind Kind 416 diff string 417 }{ 418 x: `{ 419 } 420 `, 421 y: ` 422 { 423 } 424 `, 425 kind: Modified, 426 diff: ``, 427 } 428 var r cue.Runtime 429 x, err := r.Compile("x", tc.x) 430 if err != nil { 431 t.Fatal(err) 432 } 433 y, err := r.Compile("y", tc.y) 434 if err != nil { 435 t.Fatal(err) 436 } 437 kind, script := Diff(x.Value(), y.Value()) 438 if kind != tc.kind { 439 t.Fatalf("got %d; want %d", kind, tc.kind) 440 } 441 w := &bytes.Buffer{} 442 err = Print(w, script) 443 if err != nil { 444 t.Fatal(err) 445 } 446 if got := w.String(); got != tc.diff { 447 t.Errorf("got\n%s;\nwant\n%s", got, tc.diff) 448 } 449 }