1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package cue
16
17 import (
18 "fmt"
19 "testing"
20
21 "cuelang.org/go/cue/errors"
22 )
23
24 func TestAttributes(t *testing.T) {
25 const config = `
26 a: {
27 a: 0 @foo(a,b,c=1)
28 b: 1 @bar(a,b,c,d=1) @foo(a,,d=1)
29 }
30 b: {
31 @embed(foo)
32 3
33 } @field(foo)
34
35 c1: {} @step(1)
36 if true {
37 c2: { @step(2a) } @step(2b)
38 @step(2c)
39 }
40 c3: {} @step(3)
41 if false {
42 c4: { @step(4a) } @step(4b)
43 @step(4c)
44 }
45 `
46
47 testCases := []struct {
48 flags AttrKind
49 path string
50 out string
51 }{{
52 flags: FieldAttr,
53 path: "a.a",
54 out: "[@foo(a,b,c=1)]",
55 }, {
56 flags: FieldAttr,
57 path: "a.b",
58 out: "[@bar(a,b,c,d=1) @foo(a,,d=1)]",
59 }, {
60 flags: DeclAttr,
61 path: "b",
62 out: "[@embed(foo)]",
63 }, {
64 flags: FieldAttr,
65 path: "b",
66 out: "[@field(foo)]",
67 }, {
68 flags: ValueAttr,
69 path: "b",
70 out: "[@field(foo) @embed(foo)]",
71 }, {
72 flags: ValueAttr,
73 path: "c1",
74 out: "[@step(1)]",
75 }, {
76 flags: DeclAttr,
77 path: "c2",
78 out: "[@step(2a)]",
79 }, {
80 flags: FieldAttr,
81 path: "c2",
82 out: "[@step(2b)]",
83 }, {
84 flags: DeclAttr,
85 path: "",
86 out: "[@step(2c)]",
87 }, {
88 flags: ValueAttr | FieldAttr,
89 path: "c3",
90 out: "[@step(3)]",
91 }, {
92 flags: ValueAttr | FieldAttr,
93 path: "c4",
94 out: "[]",
95 }}
96 for _, tc := range testCases {
97 t.Run(tc.path, func(t *testing.T) {
98 v := getInstance(t, config).Value().LookupPath(ParsePath(tc.path))
99 a := v.Attributes(tc.flags)
100 got := fmt.Sprint(a)
101 if got != tc.out {
102 t.Errorf("got %v; want %v", got, tc.out)
103 }
104
105 })
106 }
107 }
108
109 func TestAttributeErr(t *testing.T) {
110 const config = `
111 a: {
112 a: 0 @foo(a,b,c=1)
113 b: 1 @bar(a,b,c,d=1) @foo(a,,d=1)
114 }
115 `
116 testCases := []struct {
117 path string
118 attr string
119 err error
120 }{{
121 path: "a",
122 attr: "foo",
123 err: nil,
124 }, {
125 path: "a",
126 attr: "bar",
127 err: errors.New(`attribute "bar" does not exist`),
128 }, {
129 path: "xx",
130 attr: "bar",
131 err: errors.New(`attribute "bar" does not exist`),
132 }, {
133 path: "e",
134 attr: "bar",
135 err: errors.New(`attribute "bar" does not exist`),
136 }}
137 for _, tc := range testCases {
138 t.Run(tc.path+"-"+tc.attr, func(t *testing.T) {
139 v := getInstance(t, config).Value().Lookup("a", tc.path)
140 a := v.Attribute(tc.attr)
141 err := a.Err()
142 if !cmpError(err, tc.err) {
143 t.Errorf("got %v; want %v", err, tc.err)
144 }
145 })
146 }
147 }
148
149 func TestAttributeName(t *testing.T) {
150 const config = `
151 a: 0 @foo(a,b,c=1) @bar()
152 `
153 v := getInstance(t, config).Value().Lookup("a")
154 a := v.Attribute("foo")
155 if got, want := a.Name(), "foo"; got != want {
156 t.Errorf("got %v; want %v", got, want)
157 }
158 }
159
160 func TestAttributeString(t *testing.T) {
161 const config = `
162 a: {
163 a: 0 @foo(a,b,c=1)
164 b: 1 @bar(a,b,c,d=1) @foo(a,,d=1,e="x y","f g")
165 }
166 `
167 testCases := []struct {
168 path string
169 attr string
170 pos int
171 str string
172 err error
173 }{{
174 path: "a",
175 attr: "foo",
176 pos: 0,
177 str: "a",
178 }, {
179 path: "a",
180 attr: "foo",
181 pos: 2,
182 str: "c=1",
183 }, {
184 path: "b",
185 attr: "bar",
186 pos: 3,
187 str: "d=1",
188 }, {
189 path: "b",
190 attr: "foo",
191 pos: 3,
192 str: `e="x y"`,
193 }, {
194 path: "b",
195 attr: "foo",
196 pos: 4,
197 str: `f g`,
198 }, {
199 path: "e",
200 attr: "bar",
201 err: errors.New(`attribute "bar" does not exist`),
202 }, {
203 path: "b",
204 attr: "foo",
205 pos: 5,
206 err: errors.New("field does not exist"),
207 }}
208 for _, tc := range testCases {
209 t.Run(fmt.Sprintf("%s.%s:%d", tc.path, tc.attr, tc.pos), func(t *testing.T) {
210 v := getInstance(t, config).Value().Lookup("a", tc.path)
211 a := v.Attribute(tc.attr)
212 got, err := a.String(tc.pos)
213 if !cmpError(err, tc.err) {
214 t.Errorf("err: got %v; want %v", err, tc.err)
215 }
216 if got != tc.str {
217 t.Errorf("str: got %v; want %v", got, tc.str)
218 }
219 })
220 }
221 }
222
223 func TestAttributeArg(t *testing.T) {
224 const config = `
225 a: 1 @foo(a,,d=1,e="x y","f g", with spaces , s= spaces in value )
226 `
227 testCases := []struct {
228 pos int
229 key string
230 val string
231 raw string
232 }{{
233 pos: 0,
234 key: "a",
235 val: "",
236 raw: "a",
237 }, {
238 pos: 1,
239 key: "",
240 val: "",
241 raw: "",
242 }, {
243 pos: 2,
244 key: "d",
245 val: "1",
246 raw: "d=1",
247 }, {
248 pos: 3,
249 key: "e",
250 val: "x y",
251 raw: `e="x y"`,
252 }, {
253 pos: 4,
254 key: "f g",
255 val: "",
256 raw: `"f g"`,
257 }, {
258 pos: 5,
259 key: "with spaces",
260 val: "",
261 raw: " with spaces ",
262 }, {
263 pos: 6,
264 key: "s",
265 val: "spaces in value",
266 raw: " s= spaces in value ",
267 }}
268 for _, tc := range testCases {
269 t.Run(fmt.Sprintf("%d", tc.pos), func(t *testing.T) {
270 v := getInstance(t, config).Value().Lookup("a")
271 a := v.Attribute("foo")
272 key, val := a.Arg(tc.pos)
273 raw := a.RawArg(tc.pos)
274 if got, want := key, tc.key; got != want {
275 t.Errorf("unexpected key; got %q want %q", got, want)
276 }
277 if got, want := val, tc.val; got != want {
278 t.Errorf("unexpected value; got %q want %q", got, want)
279 }
280 if got, want := raw, tc.raw; got != want {
281 t.Errorf("unexpected raw value; got %q want %q", got, want)
282 }
283 })
284 }
285 }
286
287 func TestAttributeInt(t *testing.T) {
288 const config = `
289 a: {
290 a: 0 @foo(1,3,c=1)
291 b: 1 @bar(a,-4,c,d=1) @foo(a,,d=1)
292 }
293 `
294 testCases := []struct {
295 path string
296 attr string
297 pos int
298 val int64
299 err error
300 }{{
301 path: "a",
302 attr: "foo",
303 pos: 0,
304 val: 1,
305 }, {
306 path: "b",
307 attr: "bar",
308 pos: 1,
309 val: -4,
310 }, {
311 path: "e",
312 attr: "bar",
313 err: errors.New(`attribute "bar" does not exist`),
314 }, {
315 path: "b",
316 attr: "foo",
317 pos: 4,
318 err: errors.New("field does not exist"),
319 }, {
320 path: "a",
321 attr: "foo",
322 pos: 2,
323 err: errors.New(`strconv.ParseInt: parsing "c=1": invalid syntax`),
324 }}
325 for _, tc := range testCases {
326 t.Run(fmt.Sprintf("%s.%s:%d", tc.path, tc.attr, tc.pos), func(t *testing.T) {
327 v := getInstance(t, config).Value().Lookup("a", tc.path)
328 a := v.Attribute(tc.attr)
329 got, err := a.Int(tc.pos)
330 if !cmpError(err, tc.err) {
331 t.Errorf("err: got %v; want %v", err, tc.err)
332 }
333 if got != tc.val {
334 t.Errorf("val: got %v; want %v", got, tc.val)
335 }
336 })
337 }
338 }
339
340 func TestAttributeFlag(t *testing.T) {
341 const config = `
342 a: {
343 a: 0 @foo(a,b,c=1)
344 b: 1 @bar(a,b,c,d=1) @foo(a,,d=1)
345 }
346 `
347 testCases := []struct {
348 path string
349 attr string
350 pos int
351 flag string
352 val bool
353 err error
354 }{{
355 path: "a",
356 attr: "foo",
357 pos: 0,
358 flag: "a",
359 val: true,
360 }, {
361 path: "b",
362 attr: "bar",
363 pos: 1,
364 flag: "a",
365 val: false,
366 }, {
367 path: "b",
368 attr: "bar",
369 pos: 0,
370 flag: "c",
371 val: true,
372 }, {
373 path: "e",
374 attr: "bar",
375 err: errors.New(`attribute "bar" does not exist`),
376 }, {
377 path: "b",
378 attr: "foo",
379 pos: 4,
380 err: errors.New("field does not exist"),
381 }}
382 for _, tc := range testCases {
383 t.Run(fmt.Sprintf("%s.%s:%d", tc.path, tc.attr, tc.pos), func(t *testing.T) {
384 v := getInstance(t, config).Value().Lookup("a", tc.path)
385 a := v.Attribute(tc.attr)
386 got, err := a.Flag(tc.pos, tc.flag)
387 if !cmpError(err, tc.err) {
388 t.Errorf("err: got %v; want %v", err, tc.err)
389 }
390 if got != tc.val {
391 t.Errorf("val: got %v; want %v", got, tc.val)
392 }
393 })
394 }
395 }
396
397 func TestAttributeLookup(t *testing.T) {
398 const config = `
399 a: {
400 a: 0 @foo(a,b,c=1)
401 b: 1 @bar(a,b,e =-5,d=1) @foo(a,,d=1)
402 }
403 `
404 testCases := []struct {
405 path string
406 attr string
407 pos int
408 key string
409 val string
410 err error
411 }{{
412 path: "a",
413 attr: "foo",
414 pos: 0,
415 key: "c",
416 val: "1",
417 }, {
418 path: "b",
419 attr: "bar",
420 pos: 1,
421 key: "a",
422 val: "",
423 }, {
424 path: "b",
425 attr: "bar",
426 pos: 0,
427 key: "e",
428 val: "-5",
429 }, {
430 path: "b",
431 attr: "bar",
432 pos: 0,
433 key: "d",
434 val: "1",
435 }, {
436 path: "b",
437 attr: "foo",
438 pos: 2,
439 key: "d",
440 val: "1",
441 }, {
442 path: "b",
443 attr: "foo",
444 pos: 2,
445 key: "f",
446 val: "",
447 }, {
448 path: "e",
449 attr: "bar",
450 err: errors.New(`attribute "bar" does not exist`),
451 }, {
452 path: "b",
453 attr: "foo",
454 pos: 4,
455 err: errors.New("field does not exist"),
456 }}
457 for _, tc := range testCases {
458 t.Run(fmt.Sprintf("%s.%s:%d", tc.path, tc.attr, tc.pos), func(t *testing.T) {
459 v := getInstance(t, config).Value().Lookup("a", tc.path)
460 a := v.Attribute(tc.attr)
461 got, _, err := a.Lookup(tc.pos, tc.key)
462 if !cmpError(err, tc.err) {
463 t.Errorf("err: got %v; want %v", err, tc.err)
464 }
465 if got != tc.val {
466 t.Errorf("val: got %v; want %v", got, tc.val)
467 }
468 })
469 }
470 }
471
View as plain text