1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package subsume
16
17 import (
18 "regexp"
19 "strconv"
20 "strings"
21 "testing"
22
23 "cuelang.org/go/cue/parser"
24 "cuelang.org/go/internal/core/adt"
25 "cuelang.org/go/internal/core/compile"
26 "cuelang.org/go/internal/core/eval"
27 "cuelang.org/go/internal/core/runtime"
28 )
29
30 const (
31 subNone = iota
32 subFinal
33 subNoOptional
34 subSchema
35 subDefaults
36 )
37
38 func TestValues(t *testing.T) {
39
40
41 type subsumeTest struct {
42
43 subsumes bool
44 in string
45 mode int
46 }
47 testCases := []subsumeTest{
48
49 0: {subsumes: true, in: `a: _, b: _ `},
50 1: {subsumes: true, in: `a: _, b: null `},
51 2: {subsumes: true, in: `a: _, b: int `},
52 3: {subsumes: true, in: `a: _, b: 1 `},
53 4: {subsumes: true, in: `a: _, b: float `},
54 5: {subsumes: true, in: `a: _, b: "s" `},
55 6: {subsumes: true, in: `a: _, b: {} `},
56 7: {subsumes: true, in: `a: _, b: []`},
57 8: {subsumes: true, in: `a: _, b: _|_ `},
58
59
60 9: {subsumes: false, in: `a: null, b: _`},
61 10: {subsumes: false, in: `a: int, b: _`},
62 11: {subsumes: false, in: `a: 1, b: _`},
63 12: {subsumes: false, in: `a: float, b: _`},
64 13: {subsumes: false, in: `a: "s", b: _`},
65 14: {subsumes: false, in: `a: {}, b: _`},
66 15: {subsumes: false, in: `a: [], b: _`},
67 16: {subsumes: false, in: `a: _|_ , b: _`},
68
69
70 17: {subsumes: false, in: `a: _|_, b: null `},
71 18: {subsumes: false, in: `a: _|_, b: int `},
72 19: {subsumes: false, in: `a: _|_, b: 1 `},
73 20: {subsumes: false, in: `a: _|_, b: float `},
74 21: {subsumes: false, in: `a: _|_, b: "s" `},
75 22: {subsumes: false, in: `a: _|_, b: {} `},
76 23: {subsumes: false, in: `a: _|_, b: [] `},
77 24: {subsumes: true, in: ` a: _|_, b: _|_ `},
78
79
80 25: {subsumes: true, in: `a: null, b: _|_`},
81 26: {subsumes: true, in: `a: int, b: _|_`},
82 27: {subsumes: true, in: `a: 1, b: _|_`},
83 28: {subsumes: true, in: `a: float, b: _|_`},
84 29: {subsumes: true, in: `a: "s", b: _|_`},
85 30: {subsumes: true, in: `a: {}, b: _|_`},
86 31: {subsumes: true, in: `a: [], b: _|_`},
87 32: {subsumes: true, in: `a: true, b: _|_`},
88 33: {subsumes: true, in: `a: _|_, b: _|_`},
89
90
91 34: {subsumes: true, in: ` a: null, b: null `},
92 35: {subsumes: false, in: `a: null, b: 1 `},
93 36: {subsumes: false, in: `a: 1, b: null `},
94
95 37: {subsumes: true, in: ` a: true, b: true `},
96 38: {subsumes: false, in: `a: true, b: false `},
97
98 39: {subsumes: true, in: ` a: "a", b: "a" `},
99 40: {subsumes: false, in: `a: "a", b: "b" `},
100 41: {subsumes: true, in: ` a: string, b: "a" `},
101 42: {subsumes: false, in: `a: "a", b: string `},
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 43: {subsumes: true, in: `a: 1, b: 1 `},
129 44: {subsumes: true, in: `a: 1.0, b: 1.0 `},
130 45: {subsumes: true, in: `a: 3.0, b: 3.0 `},
131 46: {subsumes: false, in: `a: 1.0, b: 1 `},
132 47: {subsumes: false, in: `a: 1, b: 1.0 `},
133 48: {subsumes: false, in: `a: 3, b: 3.0`},
134 49: {subsumes: true, in: `a: int, b: 1`},
135 50: {subsumes: true, in: `a: int, b: int & 1`},
136 51: {subsumes: true, in: `a: float, b: 1.0`},
137 52: {subsumes: false, in: `a: float, b: 1`},
138 53: {subsumes: false, in: `a: int, b: 1.0`},
139 54: {subsumes: true, in: `a: int, b: int`},
140 55: {subsumes: true, in: `a: number, b: int`},
141
142
143 64: {subsumes: true, in: `a: {}, b: {}`},
144 65: {subsumes: true, in: `a: {}, b: {a: 1}`},
145 66: {subsumes: true, in: `a: {a:1}, b: {a:1, b:1}`},
146 67: {subsumes: true, in: `a: {s: { a:1} }, b: { s: { a:1, b:2 }}`},
147 68: {subsumes: true, in: `a: {}, b: {}`},
148
149
150 69: {subsumes: true, in: `a: {}, b: {} & c, c: {}`},
151
152 70: {subsumes: false, in: `a: {a:1}, b: {}`},
153 71: {subsumes: false, in: `a: {a:1, b:1}, b: {a:1}`},
154 72: {subsumes: false, in: `a: {s: { a:1} }, b: { s: {}}`},
155
156 84: {subsumes: true, in: `a: 1 | 2, b: 2 | 1`},
157 85: {subsumes: true, in: `a: 1 | 2, b: 1 | 2`},
158
159 86: {subsumes: true, in: `a: number, b: 2 | 1`},
160 87: {subsumes: true, in: `a: number, b: 2 | 1`},
161 88: {subsumes: false, in: `a: int, b: 1 | 2 | 3.1`},
162
163 89: {subsumes: true, in: `a: float | number, b: 1 | 2 | 3.1`},
164
165 90: {subsumes: false, in: `a: int, b: 1 | 2 | 3.1`},
166 91: {subsumes: true, in: `a: 1 | 2, b: 1`},
167 92: {subsumes: true, in: `a: 1 | 2, b: 2`},
168 93: {subsumes: false, in: `a: 1 | 2, b: 3`},
169
170
171
172
173 150: {subsumes: false, in: `a: number | *1, b: number | *2`},
174 151: {subsumes: true, in: `a: number | *2, b: number | *2`},
175 152: {subsumes: true, in: `a: int | *float, b: int | *2.0`},
176 153: {subsumes: false, in: `a: int | *2, b: int | *2.0`},
177 154: {subsumes: true, in: `a: number | *2 | *3, b: number | *2`},
178 155: {subsumes: true, in: `a: number, b: number | *2`},
179
180
181 170: {subsumes: true, in: `a: >=2, b: >=2`},
182 171: {subsumes: true, in: `a: >=1, b: >=2`},
183 172: {subsumes: true, in: `a: >0, b: >=2`},
184 173: {subsumes: true, in: `a: >1, b: >1`},
185 174: {subsumes: true, in: `a: >=1, b: >1`},
186 175: {subsumes: false, in: `a: >1, b: >=1`},
187 176: {subsumes: true, in: `a: >=1, b: >=1`},
188 177: {subsumes: true, in: `a: <1, b: <1`},
189 178: {subsumes: true, in: `a: <=1, b: <1`},
190 179: {subsumes: false, in: `a: <1, b: <=1`},
191 180: {subsumes: true, in: `a: <=1, b: <=1`},
192
193 181: {subsumes: true, in: `a: !=1, b: !=1`},
194 182: {subsumes: false, in: `a: !=1, b: !=2`},
195
196 183: {subsumes: false, in: `a: !=1, b: <=1`},
197 184: {subsumes: true, in: `a: !=1, b: <1`},
198 185: {subsumes: false, in: `a: !=1, b: >=1`},
199 186: {subsumes: true, in: `a: !=1, b: <1`},
200
201 187: {subsumes: true, in: `a: !=1, b: <=0`},
202 188: {subsumes: true, in: `a: !=1, b: >=2`},
203 189: {subsumes: true, in: `a: !=1, b: >1`},
204
205 195: {subsumes: false, in: `a: >=2, b: !=2`},
206 196: {subsumes: false, in: `a: >2, b: !=2`},
207 197: {subsumes: false, in: `a: <2, b: !=2`},
208 198: {subsumes: false, in: `a: <=2, b: !=2`},
209
210 200: {subsumes: true, in: `a: =~"foo", b: =~"foo"`},
211 201: {subsumes: false, in: `a: =~"foo", b: =~"bar"`},
212 202: {subsumes: false, in: `a: =~"foo1", b: =~"foo"`},
213
214 203: {subsumes: true, in: `a: !~"foo", b: !~"foo"`},
215 204: {subsumes: false, in: `a: !~"foo", b: !~"bar"`},
216 205: {subsumes: false, in: `a: !~"foo", b: !~"foo1"`},
217
218
219
220 210: {subsumes: false, in: `a: =~"foo", b: =~"foo1"`},
221 211: {subsumes: false, in: `a: !~"foo1", b: !~"foo"`},
222
223 220: {subsumes: true, in: `a: <5, b: 4`},
224 221: {subsumes: false, in: `a: <5, b: 5`},
225 222: {subsumes: true, in: `a: <=5, b: 5`},
226 223: {subsumes: false, in: `a: <=5.0, b: 5.00000001`},
227 224: {subsumes: true, in: `a: >5, b: 6`},
228 225: {subsumes: false, in: `a: >5, b: 5`},
229 226: {subsumes: true, in: `a: >=5, b: 5`},
230 227: {subsumes: false, in: `a: >=5, b: 4`},
231 228: {subsumes: true, in: `a: !=5, b: 6`},
232 229: {subsumes: false, in: `a: !=5, b: 5`},
233 230: {subsumes: false, in: `a: !=5.0, b: 5.0`},
234 231: {subsumes: false, in: `a: !=5.0, b: 5`},
235
236 250: {subsumes: true, in: `a: =~ #"^\d{3}$"#, b: "123"`},
237 251: {subsumes: false, in: `a: =~ #"^\d{3}$"#, b: "1234"`},
238 252: {subsumes: true, in: `a: !~ #"^\d{3}$"#, b: "1234"`},
239 253: {subsumes: false, in: `a: !~ #"^\d{3}$"#, b: "123"`},
240
241
242 300: {subsumes: true, in: `a: >0, b: >=2 & <=100`},
243 301: {subsumes: false, in: `a: >0, b: >=0 & <=100`},
244
245 310: {subsumes: true, in: `a: >=0 & <=100, b: 10`},
246 311: {subsumes: true, in: `a: >=0 & <=100, b: >=0 & <=100`},
247 312: {subsumes: false, in: `a: !=2 & !=4, b: >3`},
248 313: {subsumes: true, in: `a: !=2 & !=4, b: >5`},
249
250 314: {subsumes: false, in: `a: >=0 & <=100, b: >=0 & <=150`},
251 315: {subsumes: true, in: `a: >=0 & <=150, b: >=0 & <=100`},
252
253
254 330: {subsumes: true, in: `a: >5, b: >10 | 8`},
255 331: {subsumes: false, in: `a: >8, b: >10 | 8`},
256
257
258
259
260
261
262
263
264
265 400: {subsumes: false, in: `a: {foo: 1}, b: {}`},
266 401: {subsumes: false, in: `a: {foo?: 1}, b: {}`},
267 402: {subsumes: true, in: `a: {}, b: {foo: 1}`},
268 403: {subsumes: true, in: `a: {}, b: {foo?: 1}`},
269
270 404: {subsumes: true, in: `a: {foo: 1}, b: {foo: 1}`},
271 405: {subsumes: true, in: `a: {foo?: 1}, b: {foo: 1}`},
272 406: {subsumes: true, in: `a: {foo?: 1}, b: {foo?: 1}`},
273 407: {subsumes: false, in: `a: {foo: 1}, b: {foo?: 1}`},
274
275 408: {subsumes: false, in: `a: {foo: 1}, b: {foo: 2}`},
276 409: {subsumes: false, in: `a: {foo?: 1}, b: {foo: 2}`},
277 410: {subsumes: false, in: `a: {foo?: 1}, b: {foo?: 2}`},
278 411: {subsumes: false, in: `a: {foo: 1}, b: {foo?: 2}`},
279
280 412: {subsumes: true, in: `a: {foo: number}, b: {foo: 2}`},
281 413: {subsumes: true, in: `a: {foo?: number}, b: {foo: 2}`},
282 414: {subsumes: true, in: `a: {foo?: number}, b: {foo?: 2}`},
283 415: {subsumes: false, in: `a: {foo: number}, b: {foo?: 2}`},
284
285 416: {subsumes: false, in: `a: {foo: 1}, b: {foo: number}`},
286 417: {subsumes: false, in: `a: {foo?: 1}, b: {foo: number}`},
287 418: {subsumes: false, in: `a: {foo?: 1}, b: {foo?: number}`},
288 419: {subsumes: false, in: `a: {foo: 1}, b: {foo?: number}`},
289
290
291
292
293
294 420: {subsumes: true, in: `a: {foo?: _}, b: {}`},
295
296 430: {subsumes: false, in: `a: {[_]: 4}, b: {[_]: int}`},
297
298 431: {subsumes: false, in: `a: {[_]: int}, b: {[_]: 2}`},
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316 460: {subsumes: true, in: `a: {1, #foo: number}, b: {1, #foo: 1}`},
317 461: {subsumes: true, in: `a: {1, #foo?: number}, b: {1, #foo: 1}`},
318 462: {subsumes: true, in: `a: {1, #foo?: number}, b: {1, #foo?: 1}`},
319 463: {subsumes: false, in: `a: {1, #foo: number}, b: {1, #foo?: 1}`},
320
321 464: {subsumes: true, in: `a: {int, #foo: number}, b: {1, #foo: 1}`},
322 465: {subsumes: false, in: `a: {int, #foo: 1}, b: {1, #foo: number}`},
323 466: {subsumes: false, in: `a: {1, #foo: number}, b: {int, #foo: 1}`},
324 467: {subsumes: false, in: `a: {1, #foo: 1}, b: {int, #foo: number}`},
325
326
327 506: {subsumes: true, in: `a: [], b: [] `},
328 507: {subsumes: true, in: `a: [1], b: [1] `},
329 508: {subsumes: false, in: `a: [1], b: [2] `},
330 509: {subsumes: false, in: `a: [1], b: [2, 3] `},
331 510: {subsumes: true, in: `a: [{b: string}], b: [{b: "foo"}] `},
332 511: {subsumes: true, in: `a: [...{b: string}], b: [{b: "foo"}] `},
333 512: {subsumes: false, in: `a: [{b: "foo"}], b: [{b: string}] `},
334 513: {subsumes: false, in: `a: [{b: string}], b: [{b: "foo"}, ...{b: "foo"}] `},
335 520: {subsumes: false, in: `a: [_, int, ...], b: [int, string, ...string] `},
336
337
338 600: {subsumes: false, in: `a: close({}), b: {a: 1}`},
339 601: {subsumes: false, in: `a: close({a: 1}), b: {a: 1}`},
340 602: {subsumes: false, in: `a: close({a: 1, b: 1}), b: {a: 1}`},
341 603: {subsumes: false, in: `a: {a: 1}, b: close({})`},
342 604: {subsumes: true, in: `a: {a: 1}, b: close({a: 1})`},
343 605: {subsumes: true, in: `a: {a: 1}, b: close({a: 1, b: 1})`},
344 606: {subsumes: true, in: `a: close({b?: 1}), b: close({b: 1})`},
345 607: {subsumes: false, in: `a: close({b: 1}), b: close({b?: 1})`},
346 608: {subsumes: true, in: `a: {}, b: close({})`},
347 609: {subsumes: true, in: `a: {}, b: close({foo?: 1})`},
348 610: {subsumes: true, in: `a: {foo?:1}, b: close({})`},
349
350
351 611: {subsumes: false, in: `a: close({foo?:1}), b: close({bar?: 1})`},
352 612: {subsumes: true, in: `a: {foo?:1}, b: close({bar?: 1})`},
353 613: {subsumes: true, in: `a: {foo?:1}, b: close({bar: 1})`},
354
355
356 630: {subsumes: false, in: `a: {#a: 1}, b: {a: 1}`},
357 631: {subsumes: false, in: `a: {a: 1}, b: {#a: 1}`},
358
359
360 700: {subsumes: true, in: `a: [string]: 1, b: {foo: 1}`, mode: subFinal},
361 701: {subsumes: true, in: `a: [string]: int, b: {foo: 1}`, mode: subFinal},
362 702: {subsumes: true, in: `a: {["foo"]: int}, b: {foo: 1}`, mode: subFinal},
363 703: {subsumes: false, in: `a: close({["foo"]: 1}), b: {bar: 1}`, mode: subFinal},
364 704: {subsumes: false, in: `a: {foo: 1}, b: {foo?: 1}`, mode: subFinal},
365 705: {subsumes: true, in: `a: close({}), b: {foo?: 1}`, mode: subFinal},
366 706: {subsumes: true, in: `a: close({}), b: close({foo?: 1})`, mode: subFinal},
367 707: {subsumes: true, in: `a: {}, b: close({})`, mode: subFinal},
368 708: {subsumes: false, in: `a: {[string]: 1}, b: {foo: 2}`, mode: subFinal},
369 709: {subsumes: true, in: `a: {}, b: close({foo?: 1})`, mode: subFinal},
370 710: {subsumes: false, in: `a: {foo: [...string]}, b: {}`, mode: subFinal},
371
372
373 800: {subsumes: true, in: `a: close({}), b: {foo: 1}`, mode: subSchema},
374
375
376 804: {subsumes: false, in: `a: {foo: 1}, b: {foo?: 1}`, mode: subSchema},
377 805: {subsumes: true, in: `a: close({}), b: {foo?: 1}`, mode: subSchema},
378 806: {subsumes: true, in: `a: close({}), b: close({foo?: 1})`, mode: subSchema},
379 807: {subsumes: true, in: `a: {}, b: close({})`, mode: subSchema},
380 808: {subsumes: false, in: `a: {[string]: 1}, b: {foo: 2}`, mode: subSchema},
381 809: {subsumes: true, in: `a: {}, b: close({foo?: 1})`, mode: subSchema},
382
383
384 950: {subsumes: true, in: `a: [], b: []`},
385 951: {subsumes: true, in: `a: [...], b: []`},
386 952: {subsumes: true, in: `a: [...], b: [...]`},
387 953: {subsumes: false, in: `a: [], b: [...]`},
388
389 954: {subsumes: true, in: `a: [2], b: [2]`},
390 955: {subsumes: true, in: `a: [int], b: [2]`},
391 956: {subsumes: false, in: `a: [2], b: [int]`},
392 957: {subsumes: true, in: `a: [int], b: [int]`},
393
394 958: {subsumes: true, in: `a: [...2], b: [2]`},
395 959: {subsumes: true, in: `a: [...int], b: [2]`},
396 960: {subsumes: false, in: `a: [...2], b: [int]`},
397 961: {subsumes: true, in: `a: [...int], b: [int]`},
398
399 962: {subsumes: false, in: `a: [2], b: [...2]`},
400 963: {subsumes: false, in: `a: [int], b: [...2]`},
401 964: {subsumes: false, in: `a: [2], b: [...int]`},
402 965: {subsumes: false, in: `a: [int], b: [...int]`},
403
404 966: {subsumes: false, in: `a: [...int], b: ["foo"]`},
405 967: {subsumes: false, in: `a: ["foo"], b: [...int]`},
406
407
408
409
410
411 970: {subsumes: true, in: `a: [], b: [...int]`, mode: subDefaults},
412 971: {subsumes: true, in: `a: [2], b: [2, ...int]`, mode: subDefaults},
413
414
415 980: {subsumes: true, in: `a: [], b: [...int]`, mode: subFinal},
416 981: {subsumes: true, in: `a: [2], b: [2, ...int]`, mode: subFinal},
417 }
418
419 re := regexp.MustCompile(`a: (.*).*b: ([^\n]*)`)
420 for i, tc := range testCases {
421 if tc.in == "" {
422 continue
423 }
424 m := re.FindStringSubmatch(strings.Join(strings.Split(tc.in, "\n"), ""))
425 const cutset = "\n ,"
426 key := strings.Trim(m[1], cutset) + " ⊑ " + strings.Trim(m[2], cutset)
427
428 r := runtime.New()
429
430 t.Run(strconv.Itoa(i)+"/"+key, func(t *testing.T) {
431
432 file, err := parser.ParseFile("subsume", tc.in)
433 if err != nil {
434 t.Fatal(err)
435 }
436
437 root, errs := compile.Files(nil, r, "", file)
438 if errs != nil {
439 t.Fatal(errs)
440 }
441
442 ctx := eval.NewContext(r, root)
443 root.Finalize(ctx)
444
445
446 var a, b adt.Value
447 for _, arc := range root.Arcs {
448 switch arc.Label {
449 case ctx.StringLabel("a"):
450 a = arc
451 case ctx.StringLabel("b"):
452 b = arc
453 }
454 }
455
456 switch tc.mode {
457 case subNone:
458 err = Value(ctx, a, b)
459 case subSchema:
460 err = API.Value(ctx, a, b)
461
462
463
464 case subDefaults:
465 p := Profile{Defaults: true}
466 err = p.Value(ctx, a, b)
467 case subFinal:
468 err = Final.Value(ctx, a, b)
469 }
470 got := err == nil
471
472 if got != tc.subsumes {
473 t.Errorf("got %v; want %v (%v vs %v)", got, tc.subsumes, a.Kind(), b.Kind())
474 }
475 })
476 }
477 }
478
View as plain text