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
22 func TestPaths(t *testing.T) {
23 var r Runtime
24 inst, _ := r.Compile("", `
25 #Foo: a: b: 1
26 "#Foo": c: d: 2
27 _foo: b: 5
28 a: 3
29 b: [4, 5, 6]
30 c: "#Foo": 7
31 map: [string]: int
32 list: [...int]
33
34 // Issue 2060
35 let X = {a: b: 0}
36 x: y: X.a
37 `)
38 testCases := []struct {
39 path Path
40 out string
41 str string
42 err bool
43 }{{
44 path: MakePath(Str("list"), AnyIndex),
45 out: "int",
46 str: "list.[_]",
47 }, {
48
49 path: MakePath(Def("#Foo"), Str("a"), Str("b")),
50 out: "1",
51 str: "#Foo.a.b",
52 }, {
53 path: ParsePath(`#Foo.a.b`),
54 out: "1",
55 str: "#Foo.a.b",
56 }, {
57 path: ParsePath(`"#Foo".c.d`),
58 out: "2",
59 str: `"#Foo".c.d`,
60 }, {
61
62 path: MakePath(Def("Foo"), Str("a"), Str("b")),
63 out: "1",
64 str: "#Foo.a.b",
65 }, {
66 path: MakePath(Str("b"), Index(2)),
67 out: "6",
68 str: "b[2]",
69 }, {
70 path: MakePath(Str("c"), Str("#Foo")),
71 out: "7",
72 str: `c."#Foo"`,
73 }, {
74 path: MakePath(Hid("_foo", "_"), Str("b")),
75 out: "5",
76 str: `_foo.b`,
77 }, {
78 path: ParsePath("#Foo.a.b"),
79 str: "#Foo.a.b",
80 out: "1",
81 }, {
82 path: ParsePath("#Foo.a.c"),
83 str: "#Foo.a.c",
84 out: `_|_ // field not found: c`,
85 }, {
86 path: ParsePath(`b[2]`),
87 str: `b[2]`,
88 out: "6",
89 }, {
90 path: ParsePath(`c."#Foo"`),
91 str: `c."#Foo"`,
92 out: "7",
93 }, {
94 path: ParsePath("foo._foo"),
95 str: "_|_",
96 err: true,
97 out: `_|_ // invalid path: hidden label _foo not allowed`,
98 }, {
99 path: ParsePath(`c."#Foo`),
100 str: "_|_",
101 err: true,
102 out: `_|_ // string literal not terminated`,
103 }, {
104 path: ParsePath(`b[a]`),
105 str: "_|_",
106 err: true,
107 out: `_|_ // non-constant expression a`,
108 }, {
109 path: ParsePath(`b['1']`),
110 str: "_|_",
111 err: true,
112 out: `_|_ // invalid string index '1'`,
113 }, {
114 path: ParsePath(`b[3T]`),
115 str: "_|_",
116 err: true,
117 out: `_|_ // int label out of range (3000000000000 not >=0 and <= 268435454)`,
118 }, {
119 path: ParsePath(`b[3.3]`),
120 str: "_|_",
121 err: true,
122 out: `_|_ // invalid literal 3.3`,
123 }, {
124 path: MakePath(Str("map"), AnyString),
125 out: "int",
126 str: "map.[_]",
127 }, {
128 path: MakePath(Str("list"), AnyIndex),
129 out: "int",
130 str: "list.[_]",
131 }, {
132 path: ParsePath("x.y"),
133 out: "{\n\tb: 0\n}",
134 str: "x.y",
135 }, {
136 path: ParsePath("x.y.b"),
137 out: "0",
138 str: "x.y.b",
139 }}
140
141 v := inst.Value()
142 for _, tc := range testCases {
143 t.Run(tc.str, func(t *testing.T) {
144 if gotErr := tc.path.Err() != nil; gotErr != tc.err {
145 t.Errorf("error: got %v; want %v", gotErr, tc.err)
146 }
147
148 w := v.LookupPath(tc.path)
149
150 if got := fmt.Sprint(w); got != tc.out {
151 t.Errorf("Value: got %v; want %v", got, tc.out)
152 }
153
154 if got := tc.path.String(); got != tc.str {
155 t.Errorf("String: got %v; want %v", got, tc.str)
156 }
157
158 if w.Err() != nil {
159 return
160 }
161
162 if got := w.Path().String(); got != tc.str {
163 t.Errorf("Path: got %v; want %v", got, tc.str)
164 }
165 })
166 }
167 }
168
169 var selectorTests = []struct {
170 sel Selector
171 stype SelectorType
172 string string
173 unquoted string
174 index int
175 isHidden bool
176 isConstraint bool
177 isDefinition bool
178 isString bool
179 pkgPath string
180 }{{
181 sel: Str("foo"),
182 stype: StringLabel,
183 string: "foo",
184 unquoted: "foo",
185 isString: true,
186 }, {
187 sel: Str("_foo"),
188 stype: StringLabel,
189 string: `"_foo"`,
190 unquoted: "_foo",
191 isString: true,
192 }, {
193 sel: Str(`a "b`),
194 stype: StringLabel,
195 string: `"a \"b"`,
196 unquoted: `a "b`,
197 isString: true,
198 }, {
199 sel: Index(5),
200 stype: IndexLabel,
201 string: "5",
202 index: 5,
203 }, {
204 sel: Def("foo"),
205 stype: DefinitionLabel,
206 string: "#foo",
207 isDefinition: true,
208 }, {
209 sel: Str("foo").Optional(),
210 stype: StringLabel | OptionalConstraint,
211 string: "foo?",
212 unquoted: "foo",
213 isString: true,
214 isConstraint: true,
215 }, {
216 sel: Str("foo").Required(),
217 stype: StringLabel | RequiredConstraint,
218 string: "foo!",
219 unquoted: "foo",
220 isString: true,
221 isConstraint: true,
222 }, {
223 sel: Def("foo").Required().Optional(),
224 stype: DefinitionLabel | OptionalConstraint,
225 string: "#foo?",
226 isDefinition: true,
227 isConstraint: true,
228 }, {
229 sel: Def("foo").Optional().Required(),
230 stype: DefinitionLabel | RequiredConstraint,
231 string: "#foo!",
232 isDefinition: true,
233 isConstraint: true,
234 }, {
235 sel: AnyString,
236 stype: StringLabel | PatternConstraint,
237 string: "[_]",
238 isConstraint: true,
239 }, {
240 sel: AnyIndex,
241 stype: IndexLabel | PatternConstraint,
242 string: "[_]",
243 isConstraint: true,
244 }, {
245 sel: Hid("_foo", "example.com"),
246 stype: HiddenLabel,
247 string: "_foo",
248 isHidden: true,
249 pkgPath: "example.com",
250 }, {
251 sel: Hid("_#foo", "example.com"),
252 stype: HiddenDefinitionLabel,
253 string: "_#foo",
254 isHidden: true,
255 isDefinition: true,
256 pkgPath: "example.com",
257 }}
258
259 func TestSelector(t *testing.T) {
260 for _, tc := range selectorTests {
261 t.Run(tc.sel.String(), func(t *testing.T) {
262 sel := tc.sel
263 if got, want := sel.Type(), tc.stype; got != want {
264 t.Errorf("unexpected type; got %v want %v", got, want)
265 }
266 if got, want := sel.String(), tc.string; got != want {
267 t.Errorf("unexpected sel.String result; got %q want %q", got, want)
268 }
269 if tc.unquoted == "" {
270 checkPanic(t, "Selector.Unquoted invoked on non-string label", func() {
271 sel.Unquoted()
272 })
273 } else {
274 if got, want := sel.Unquoted(), tc.unquoted; got != want {
275 t.Errorf("unexpected sel.Unquoted result; got %q want %q", got, want)
276 }
277 }
278 if sel.Type() != IndexLabel {
279 checkPanic(t, "Index called on non-index selector", func() {
280 sel.Index()
281 })
282 } else {
283 if got, want := sel.Index(), tc.index; got != want {
284 t.Errorf("unexpected sel.Index result; got %v want %v", got, want)
285 }
286 }
287 if got, want := sel.Type().IsHidden(), tc.isHidden; got != want {
288 t.Errorf("unexpected sel.IsHidden result; got %v want %v", got, want)
289 }
290 if got, want := sel.IsConstraint(), tc.isConstraint; got != want {
291 t.Errorf("unexpected sel.IsOptional result; got %v want %v", got, want)
292 }
293 if got, want := sel.IsString(), tc.isString; got != want {
294 t.Errorf("unexpected sel.IsString result; got %v want %v", got, want)
295 }
296 if got, want := sel.IsDefinition(), tc.isDefinition; got != want {
297 t.Errorf("unexpected sel.IsDefinition result; got %v want %v", got, want)
298 }
299 if got, want := sel.PkgPath(), tc.pkgPath; got != want {
300 t.Errorf("unexpected sel.PkgPath result; got %v want %v", got, want)
301 }
302 })
303 }
304 }
305
306 func TestSelectorTypeString(t *testing.T) {
307 if got, want := InvalidSelectorType.String(), "NoLabels"; got != want {
308 t.Errorf("unexpected SelectorType.String result; got %q want %q", got, want)
309 }
310 if got, want := PatternConstraint.String(), "PatternConstraint"; got != want {
311 t.Errorf("unexpected SelectorType.String result; got %q want %q", got, want)
312 }
313 if got, want := (StringLabel | OptionalConstraint).String(), "StringLabel|OptionalConstraint"; got != want {
314 t.Errorf("unexpected SelectorType.String result; got %q want %q", got, want)
315 }
316 if got, want := SelectorType(255).String(), "StringLabel|IndexLabel|DefinitionLabel|HiddenLabel|HiddenDefinitionLabel|OptionalConstraint|RequiredConstraint|PatternConstraint"; got != want {
317 t.Errorf("unexpected SelectorType.String result; got %q want %q", got, want)
318 }
319 }
320
321 func checkPanic(t *testing.T, wantPanicStr string, f func()) {
322 gotPanicStr := ""
323 func() {
324 defer func() {
325 e := recover()
326 if e == nil {
327 t.Errorf("function did not panic")
328 return
329 }
330 gotPanicStr = fmt.Sprint(e)
331 }()
332 f()
333 }()
334 if got, want := gotPanicStr, wantPanicStr; got != want {
335 t.Errorf("unexpected panic message; got %q want %q", got, want)
336 }
337 }
338
View as plain text