xref: /aosp_15_r20/build/blueprint/proptools/unpack_test.go (revision 1fa6dee971e1612fa5cc0aa5ca2d35a22e2c34a3)
1*1fa6dee9SAndroid Build Coastguard Worker// Copyright 2014 Google Inc. All rights reserved.
2*1fa6dee9SAndroid Build Coastguard Worker//
3*1fa6dee9SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*1fa6dee9SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*1fa6dee9SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*1fa6dee9SAndroid Build Coastguard Worker//
7*1fa6dee9SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*1fa6dee9SAndroid Build Coastguard Worker//
9*1fa6dee9SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*1fa6dee9SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*1fa6dee9SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*1fa6dee9SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*1fa6dee9SAndroid Build Coastguard Worker// limitations under the License.
14*1fa6dee9SAndroid Build Coastguard Worker
15*1fa6dee9SAndroid Build Coastguard Workerpackage proptools
16*1fa6dee9SAndroid Build Coastguard Worker
17*1fa6dee9SAndroid Build Coastguard Workerimport (
18*1fa6dee9SAndroid Build Coastguard Worker	"bytes"
19*1fa6dee9SAndroid Build Coastguard Worker	"reflect"
20*1fa6dee9SAndroid Build Coastguard Worker	"testing"
21*1fa6dee9SAndroid Build Coastguard Worker	"text/scanner"
22*1fa6dee9SAndroid Build Coastguard Worker
23*1fa6dee9SAndroid Build Coastguard Worker	"github.com/google/blueprint/parser"
24*1fa6dee9SAndroid Build Coastguard Worker)
25*1fa6dee9SAndroid Build Coastguard Worker
26*1fa6dee9SAndroid Build Coastguard Workervar validUnpackTestCases = []struct {
27*1fa6dee9SAndroid Build Coastguard Worker	name   string
28*1fa6dee9SAndroid Build Coastguard Worker	input  string
29*1fa6dee9SAndroid Build Coastguard Worker	output []interface{}
30*1fa6dee9SAndroid Build Coastguard Worker	empty  []interface{}
31*1fa6dee9SAndroid Build Coastguard Worker	errs   []error
32*1fa6dee9SAndroid Build Coastguard Worker}{
33*1fa6dee9SAndroid Build Coastguard Worker	{
34*1fa6dee9SAndroid Build Coastguard Worker		name: "blank and unset",
35*1fa6dee9SAndroid Build Coastguard Worker		input: `
36*1fa6dee9SAndroid Build Coastguard Worker			m {
37*1fa6dee9SAndroid Build Coastguard Worker				s: "abc",
38*1fa6dee9SAndroid Build Coastguard Worker				blank: "",
39*1fa6dee9SAndroid Build Coastguard Worker			}
40*1fa6dee9SAndroid Build Coastguard Worker		`,
41*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
42*1fa6dee9SAndroid Build Coastguard Worker			&struct {
43*1fa6dee9SAndroid Build Coastguard Worker				S     *string
44*1fa6dee9SAndroid Build Coastguard Worker				Blank *string
45*1fa6dee9SAndroid Build Coastguard Worker				Unset *string
46*1fa6dee9SAndroid Build Coastguard Worker			}{
47*1fa6dee9SAndroid Build Coastguard Worker				S:     StringPtr("abc"),
48*1fa6dee9SAndroid Build Coastguard Worker				Blank: StringPtr(""),
49*1fa6dee9SAndroid Build Coastguard Worker				Unset: nil,
50*1fa6dee9SAndroid Build Coastguard Worker			},
51*1fa6dee9SAndroid Build Coastguard Worker		},
52*1fa6dee9SAndroid Build Coastguard Worker	},
53*1fa6dee9SAndroid Build Coastguard Worker
54*1fa6dee9SAndroid Build Coastguard Worker	{
55*1fa6dee9SAndroid Build Coastguard Worker		name: "string",
56*1fa6dee9SAndroid Build Coastguard Worker		input: `
57*1fa6dee9SAndroid Build Coastguard Worker			m {
58*1fa6dee9SAndroid Build Coastguard Worker				s: "abc",
59*1fa6dee9SAndroid Build Coastguard Worker			}
60*1fa6dee9SAndroid Build Coastguard Worker		`,
61*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
62*1fa6dee9SAndroid Build Coastguard Worker			&struct {
63*1fa6dee9SAndroid Build Coastguard Worker				S string
64*1fa6dee9SAndroid Build Coastguard Worker			}{
65*1fa6dee9SAndroid Build Coastguard Worker				S: "abc",
66*1fa6dee9SAndroid Build Coastguard Worker			},
67*1fa6dee9SAndroid Build Coastguard Worker		},
68*1fa6dee9SAndroid Build Coastguard Worker	},
69*1fa6dee9SAndroid Build Coastguard Worker
70*1fa6dee9SAndroid Build Coastguard Worker	{
71*1fa6dee9SAndroid Build Coastguard Worker		name: "bool",
72*1fa6dee9SAndroid Build Coastguard Worker		input: `
73*1fa6dee9SAndroid Build Coastguard Worker			m {
74*1fa6dee9SAndroid Build Coastguard Worker				isGood: true,
75*1fa6dee9SAndroid Build Coastguard Worker			}
76*1fa6dee9SAndroid Build Coastguard Worker		`,
77*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
78*1fa6dee9SAndroid Build Coastguard Worker			&struct {
79*1fa6dee9SAndroid Build Coastguard Worker				IsGood bool
80*1fa6dee9SAndroid Build Coastguard Worker			}{
81*1fa6dee9SAndroid Build Coastguard Worker				IsGood: true,
82*1fa6dee9SAndroid Build Coastguard Worker			},
83*1fa6dee9SAndroid Build Coastguard Worker		},
84*1fa6dee9SAndroid Build Coastguard Worker	},
85*1fa6dee9SAndroid Build Coastguard Worker
86*1fa6dee9SAndroid Build Coastguard Worker	{
87*1fa6dee9SAndroid Build Coastguard Worker		name: "boolptr",
88*1fa6dee9SAndroid Build Coastguard Worker		input: `
89*1fa6dee9SAndroid Build Coastguard Worker			m {
90*1fa6dee9SAndroid Build Coastguard Worker				isGood: true,
91*1fa6dee9SAndroid Build Coastguard Worker				isBad: false,
92*1fa6dee9SAndroid Build Coastguard Worker			}
93*1fa6dee9SAndroid Build Coastguard Worker		`,
94*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
95*1fa6dee9SAndroid Build Coastguard Worker			&struct {
96*1fa6dee9SAndroid Build Coastguard Worker				IsGood *bool
97*1fa6dee9SAndroid Build Coastguard Worker				IsBad  *bool
98*1fa6dee9SAndroid Build Coastguard Worker				IsUgly *bool
99*1fa6dee9SAndroid Build Coastguard Worker			}{
100*1fa6dee9SAndroid Build Coastguard Worker				IsGood: BoolPtr(true),
101*1fa6dee9SAndroid Build Coastguard Worker				IsBad:  BoolPtr(false),
102*1fa6dee9SAndroid Build Coastguard Worker				IsUgly: nil,
103*1fa6dee9SAndroid Build Coastguard Worker			},
104*1fa6dee9SAndroid Build Coastguard Worker		},
105*1fa6dee9SAndroid Build Coastguard Worker	},
106*1fa6dee9SAndroid Build Coastguard Worker
107*1fa6dee9SAndroid Build Coastguard Worker	{
108*1fa6dee9SAndroid Build Coastguard Worker		name: "slice",
109*1fa6dee9SAndroid Build Coastguard Worker		input: `
110*1fa6dee9SAndroid Build Coastguard Worker			m {
111*1fa6dee9SAndroid Build Coastguard Worker				stuff: ["asdf", "jkl;", "qwert",
112*1fa6dee9SAndroid Build Coastguard Worker					"uiop", "bnm,"],
113*1fa6dee9SAndroid Build Coastguard Worker				empty: []
114*1fa6dee9SAndroid Build Coastguard Worker			}
115*1fa6dee9SAndroid Build Coastguard Worker		`,
116*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
117*1fa6dee9SAndroid Build Coastguard Worker			&struct {
118*1fa6dee9SAndroid Build Coastguard Worker				Stuff     []string
119*1fa6dee9SAndroid Build Coastguard Worker				Empty     []string
120*1fa6dee9SAndroid Build Coastguard Worker				Nil       []string
121*1fa6dee9SAndroid Build Coastguard Worker				NonString []struct{ S string } `blueprint:"mutated"`
122*1fa6dee9SAndroid Build Coastguard Worker			}{
123*1fa6dee9SAndroid Build Coastguard Worker				Stuff:     []string{"asdf", "jkl;", "qwert", "uiop", "bnm,"},
124*1fa6dee9SAndroid Build Coastguard Worker				Empty:     []string{},
125*1fa6dee9SAndroid Build Coastguard Worker				Nil:       nil,
126*1fa6dee9SAndroid Build Coastguard Worker				NonString: nil,
127*1fa6dee9SAndroid Build Coastguard Worker			},
128*1fa6dee9SAndroid Build Coastguard Worker		},
129*1fa6dee9SAndroid Build Coastguard Worker	},
130*1fa6dee9SAndroid Build Coastguard Worker
131*1fa6dee9SAndroid Build Coastguard Worker	{
132*1fa6dee9SAndroid Build Coastguard Worker		name: "double nested",
133*1fa6dee9SAndroid Build Coastguard Worker		input: `
134*1fa6dee9SAndroid Build Coastguard Worker			m {
135*1fa6dee9SAndroid Build Coastguard Worker				nested: {
136*1fa6dee9SAndroid Build Coastguard Worker					nested: {
137*1fa6dee9SAndroid Build Coastguard Worker						s: "abc",
138*1fa6dee9SAndroid Build Coastguard Worker					},
139*1fa6dee9SAndroid Build Coastguard Worker				},
140*1fa6dee9SAndroid Build Coastguard Worker			}
141*1fa6dee9SAndroid Build Coastguard Worker		`,
142*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
143*1fa6dee9SAndroid Build Coastguard Worker			&struct {
144*1fa6dee9SAndroid Build Coastguard Worker				Nested struct {
145*1fa6dee9SAndroid Build Coastguard Worker					Nested struct {
146*1fa6dee9SAndroid Build Coastguard Worker						S string
147*1fa6dee9SAndroid Build Coastguard Worker					}
148*1fa6dee9SAndroid Build Coastguard Worker				}
149*1fa6dee9SAndroid Build Coastguard Worker			}{
150*1fa6dee9SAndroid Build Coastguard Worker				Nested: struct{ Nested struct{ S string } }{
151*1fa6dee9SAndroid Build Coastguard Worker					Nested: struct{ S string }{
152*1fa6dee9SAndroid Build Coastguard Worker						S: "abc",
153*1fa6dee9SAndroid Build Coastguard Worker					},
154*1fa6dee9SAndroid Build Coastguard Worker				},
155*1fa6dee9SAndroid Build Coastguard Worker			},
156*1fa6dee9SAndroid Build Coastguard Worker		},
157*1fa6dee9SAndroid Build Coastguard Worker	},
158*1fa6dee9SAndroid Build Coastguard Worker
159*1fa6dee9SAndroid Build Coastguard Worker	{
160*1fa6dee9SAndroid Build Coastguard Worker		name: "nested",
161*1fa6dee9SAndroid Build Coastguard Worker		input: `
162*1fa6dee9SAndroid Build Coastguard Worker			m {
163*1fa6dee9SAndroid Build Coastguard Worker				nested: {
164*1fa6dee9SAndroid Build Coastguard Worker					s: "abc",
165*1fa6dee9SAndroid Build Coastguard Worker				}
166*1fa6dee9SAndroid Build Coastguard Worker			}
167*1fa6dee9SAndroid Build Coastguard Worker		`,
168*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
169*1fa6dee9SAndroid Build Coastguard Worker			&struct {
170*1fa6dee9SAndroid Build Coastguard Worker				Nested struct {
171*1fa6dee9SAndroid Build Coastguard Worker					S string
172*1fa6dee9SAndroid Build Coastguard Worker				}
173*1fa6dee9SAndroid Build Coastguard Worker			}{
174*1fa6dee9SAndroid Build Coastguard Worker				Nested: struct{ S string }{
175*1fa6dee9SAndroid Build Coastguard Worker					S: "abc",
176*1fa6dee9SAndroid Build Coastguard Worker				},
177*1fa6dee9SAndroid Build Coastguard Worker			},
178*1fa6dee9SAndroid Build Coastguard Worker		},
179*1fa6dee9SAndroid Build Coastguard Worker	},
180*1fa6dee9SAndroid Build Coastguard Worker
181*1fa6dee9SAndroid Build Coastguard Worker	{
182*1fa6dee9SAndroid Build Coastguard Worker		name: "nested interface",
183*1fa6dee9SAndroid Build Coastguard Worker		input: `
184*1fa6dee9SAndroid Build Coastguard Worker			m {
185*1fa6dee9SAndroid Build Coastguard Worker				nested: {
186*1fa6dee9SAndroid Build Coastguard Worker					s: "def",
187*1fa6dee9SAndroid Build Coastguard Worker				}
188*1fa6dee9SAndroid Build Coastguard Worker			}
189*1fa6dee9SAndroid Build Coastguard Worker		`,
190*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
191*1fa6dee9SAndroid Build Coastguard Worker			&struct {
192*1fa6dee9SAndroid Build Coastguard Worker				Nested interface{}
193*1fa6dee9SAndroid Build Coastguard Worker			}{
194*1fa6dee9SAndroid Build Coastguard Worker				Nested: &struct{ S string }{
195*1fa6dee9SAndroid Build Coastguard Worker					S: "def",
196*1fa6dee9SAndroid Build Coastguard Worker				},
197*1fa6dee9SAndroid Build Coastguard Worker			},
198*1fa6dee9SAndroid Build Coastguard Worker		},
199*1fa6dee9SAndroid Build Coastguard Worker	},
200*1fa6dee9SAndroid Build Coastguard Worker
201*1fa6dee9SAndroid Build Coastguard Worker	{
202*1fa6dee9SAndroid Build Coastguard Worker		name: "mixed",
203*1fa6dee9SAndroid Build Coastguard Worker		input: `
204*1fa6dee9SAndroid Build Coastguard Worker			m {
205*1fa6dee9SAndroid Build Coastguard Worker				nested: {
206*1fa6dee9SAndroid Build Coastguard Worker					foo: "abc",
207*1fa6dee9SAndroid Build Coastguard Worker				},
208*1fa6dee9SAndroid Build Coastguard Worker				bar: false,
209*1fa6dee9SAndroid Build Coastguard Worker				baz: ["def", "ghi"],
210*1fa6dee9SAndroid Build Coastguard Worker			}
211*1fa6dee9SAndroid Build Coastguard Worker		`,
212*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
213*1fa6dee9SAndroid Build Coastguard Worker			&struct {
214*1fa6dee9SAndroid Build Coastguard Worker				Nested struct {
215*1fa6dee9SAndroid Build Coastguard Worker					Foo string
216*1fa6dee9SAndroid Build Coastguard Worker				}
217*1fa6dee9SAndroid Build Coastguard Worker				Bar bool
218*1fa6dee9SAndroid Build Coastguard Worker				Baz []string
219*1fa6dee9SAndroid Build Coastguard Worker			}{
220*1fa6dee9SAndroid Build Coastguard Worker				Nested: struct{ Foo string }{
221*1fa6dee9SAndroid Build Coastguard Worker					Foo: "abc",
222*1fa6dee9SAndroid Build Coastguard Worker				},
223*1fa6dee9SAndroid Build Coastguard Worker				Bar: false,
224*1fa6dee9SAndroid Build Coastguard Worker				Baz: []string{"def", "ghi"},
225*1fa6dee9SAndroid Build Coastguard Worker			},
226*1fa6dee9SAndroid Build Coastguard Worker		},
227*1fa6dee9SAndroid Build Coastguard Worker	},
228*1fa6dee9SAndroid Build Coastguard Worker
229*1fa6dee9SAndroid Build Coastguard Worker	{
230*1fa6dee9SAndroid Build Coastguard Worker		name: "filter",
231*1fa6dee9SAndroid Build Coastguard Worker		input: `
232*1fa6dee9SAndroid Build Coastguard Worker			m {
233*1fa6dee9SAndroid Build Coastguard Worker				nested: {
234*1fa6dee9SAndroid Build Coastguard Worker					foo: "abc",
235*1fa6dee9SAndroid Build Coastguard Worker				},
236*1fa6dee9SAndroid Build Coastguard Worker				bar: false,
237*1fa6dee9SAndroid Build Coastguard Worker				baz: ["def", "ghi"],
238*1fa6dee9SAndroid Build Coastguard Worker			}
239*1fa6dee9SAndroid Build Coastguard Worker		`,
240*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
241*1fa6dee9SAndroid Build Coastguard Worker			&struct {
242*1fa6dee9SAndroid Build Coastguard Worker				Nested struct {
243*1fa6dee9SAndroid Build Coastguard Worker					Foo string `allowNested:"true"`
244*1fa6dee9SAndroid Build Coastguard Worker				} `blueprint:"filter(allowNested:\"true\")"`
245*1fa6dee9SAndroid Build Coastguard Worker				Bar bool
246*1fa6dee9SAndroid Build Coastguard Worker				Baz []string
247*1fa6dee9SAndroid Build Coastguard Worker			}{
248*1fa6dee9SAndroid Build Coastguard Worker				Nested: struct {
249*1fa6dee9SAndroid Build Coastguard Worker					Foo string `allowNested:"true"`
250*1fa6dee9SAndroid Build Coastguard Worker				}{
251*1fa6dee9SAndroid Build Coastguard Worker					Foo: "abc",
252*1fa6dee9SAndroid Build Coastguard Worker				},
253*1fa6dee9SAndroid Build Coastguard Worker				Bar: false,
254*1fa6dee9SAndroid Build Coastguard Worker				Baz: []string{"def", "ghi"},
255*1fa6dee9SAndroid Build Coastguard Worker			},
256*1fa6dee9SAndroid Build Coastguard Worker		},
257*1fa6dee9SAndroid Build Coastguard Worker	},
258*1fa6dee9SAndroid Build Coastguard Worker
259*1fa6dee9SAndroid Build Coastguard Worker	// List of maps
260*1fa6dee9SAndroid Build Coastguard Worker	{
261*1fa6dee9SAndroid Build Coastguard Worker		name: "list of structs",
262*1fa6dee9SAndroid Build Coastguard Worker		input: `
263*1fa6dee9SAndroid Build Coastguard Worker			m {
264*1fa6dee9SAndroid Build Coastguard Worker				mapslist: [
265*1fa6dee9SAndroid Build Coastguard Worker					{
266*1fa6dee9SAndroid Build Coastguard Worker						foo: "abc",
267*1fa6dee9SAndroid Build Coastguard Worker						bar: true,
268*1fa6dee9SAndroid Build Coastguard Worker					},
269*1fa6dee9SAndroid Build Coastguard Worker					{
270*1fa6dee9SAndroid Build Coastguard Worker						foo: "def",
271*1fa6dee9SAndroid Build Coastguard Worker						bar: false,
272*1fa6dee9SAndroid Build Coastguard Worker					}
273*1fa6dee9SAndroid Build Coastguard Worker				],
274*1fa6dee9SAndroid Build Coastguard Worker			}
275*1fa6dee9SAndroid Build Coastguard Worker		`,
276*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
277*1fa6dee9SAndroid Build Coastguard Worker			&struct {
278*1fa6dee9SAndroid Build Coastguard Worker				Mapslist []struct {
279*1fa6dee9SAndroid Build Coastguard Worker					Foo string
280*1fa6dee9SAndroid Build Coastguard Worker					Bar bool
281*1fa6dee9SAndroid Build Coastguard Worker				}
282*1fa6dee9SAndroid Build Coastguard Worker			}{
283*1fa6dee9SAndroid Build Coastguard Worker				Mapslist: []struct {
284*1fa6dee9SAndroid Build Coastguard Worker					Foo string
285*1fa6dee9SAndroid Build Coastguard Worker					Bar bool
286*1fa6dee9SAndroid Build Coastguard Worker				}{
287*1fa6dee9SAndroid Build Coastguard Worker					{Foo: "abc", Bar: true},
288*1fa6dee9SAndroid Build Coastguard Worker					{Foo: "def", Bar: false},
289*1fa6dee9SAndroid Build Coastguard Worker				},
290*1fa6dee9SAndroid Build Coastguard Worker			},
291*1fa6dee9SAndroid Build Coastguard Worker		},
292*1fa6dee9SAndroid Build Coastguard Worker	},
293*1fa6dee9SAndroid Build Coastguard Worker
294*1fa6dee9SAndroid Build Coastguard Worker	// List of pointers to structs
295*1fa6dee9SAndroid Build Coastguard Worker	{
296*1fa6dee9SAndroid Build Coastguard Worker		name: "list of pointers to structs",
297*1fa6dee9SAndroid Build Coastguard Worker		input: `
298*1fa6dee9SAndroid Build Coastguard Worker			m {
299*1fa6dee9SAndroid Build Coastguard Worker				mapslist: [
300*1fa6dee9SAndroid Build Coastguard Worker					{
301*1fa6dee9SAndroid Build Coastguard Worker						foo: "abc",
302*1fa6dee9SAndroid Build Coastguard Worker						bar: true,
303*1fa6dee9SAndroid Build Coastguard Worker					},
304*1fa6dee9SAndroid Build Coastguard Worker					{
305*1fa6dee9SAndroid Build Coastguard Worker						foo: "def",
306*1fa6dee9SAndroid Build Coastguard Worker						bar: false,
307*1fa6dee9SAndroid Build Coastguard Worker					}
308*1fa6dee9SAndroid Build Coastguard Worker				],
309*1fa6dee9SAndroid Build Coastguard Worker			}
310*1fa6dee9SAndroid Build Coastguard Worker		`,
311*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
312*1fa6dee9SAndroid Build Coastguard Worker			&struct {
313*1fa6dee9SAndroid Build Coastguard Worker				Mapslist []*struct {
314*1fa6dee9SAndroid Build Coastguard Worker					Foo string
315*1fa6dee9SAndroid Build Coastguard Worker					Bar bool
316*1fa6dee9SAndroid Build Coastguard Worker				}
317*1fa6dee9SAndroid Build Coastguard Worker			}{
318*1fa6dee9SAndroid Build Coastguard Worker				Mapslist: []*struct {
319*1fa6dee9SAndroid Build Coastguard Worker					Foo string
320*1fa6dee9SAndroid Build Coastguard Worker					Bar bool
321*1fa6dee9SAndroid Build Coastguard Worker				}{
322*1fa6dee9SAndroid Build Coastguard Worker					{Foo: "abc", Bar: true},
323*1fa6dee9SAndroid Build Coastguard Worker					{Foo: "def", Bar: false},
324*1fa6dee9SAndroid Build Coastguard Worker				},
325*1fa6dee9SAndroid Build Coastguard Worker			},
326*1fa6dee9SAndroid Build Coastguard Worker		},
327*1fa6dee9SAndroid Build Coastguard Worker	},
328*1fa6dee9SAndroid Build Coastguard Worker
329*1fa6dee9SAndroid Build Coastguard Worker	// List of lists
330*1fa6dee9SAndroid Build Coastguard Worker	{
331*1fa6dee9SAndroid Build Coastguard Worker		name: "list of lists",
332*1fa6dee9SAndroid Build Coastguard Worker		input: `
333*1fa6dee9SAndroid Build Coastguard Worker			m {
334*1fa6dee9SAndroid Build Coastguard Worker				listoflists: [
335*1fa6dee9SAndroid Build Coastguard Worker					["abc",],
336*1fa6dee9SAndroid Build Coastguard Worker					["def",],
337*1fa6dee9SAndroid Build Coastguard Worker				],
338*1fa6dee9SAndroid Build Coastguard Worker			}
339*1fa6dee9SAndroid Build Coastguard Worker		`,
340*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
341*1fa6dee9SAndroid Build Coastguard Worker			&struct {
342*1fa6dee9SAndroid Build Coastguard Worker				Listoflists [][]string
343*1fa6dee9SAndroid Build Coastguard Worker			}{
344*1fa6dee9SAndroid Build Coastguard Worker				Listoflists: [][]string{
345*1fa6dee9SAndroid Build Coastguard Worker					[]string{"abc"},
346*1fa6dee9SAndroid Build Coastguard Worker					[]string{"def"},
347*1fa6dee9SAndroid Build Coastguard Worker				},
348*1fa6dee9SAndroid Build Coastguard Worker			},
349*1fa6dee9SAndroid Build Coastguard Worker		},
350*1fa6dee9SAndroid Build Coastguard Worker	},
351*1fa6dee9SAndroid Build Coastguard Worker
352*1fa6dee9SAndroid Build Coastguard Worker	// Multilevel
353*1fa6dee9SAndroid Build Coastguard Worker	{
354*1fa6dee9SAndroid Build Coastguard Worker		name: "multilevel",
355*1fa6dee9SAndroid Build Coastguard Worker		input: `
356*1fa6dee9SAndroid Build Coastguard Worker			m {
357*1fa6dee9SAndroid Build Coastguard Worker				name: "mymodule",
358*1fa6dee9SAndroid Build Coastguard Worker				flag: true,
359*1fa6dee9SAndroid Build Coastguard Worker				settings: ["foo1", "foo2", "foo3",],
360*1fa6dee9SAndroid Build Coastguard Worker				perarch: {
361*1fa6dee9SAndroid Build Coastguard Worker					arm: "32",
362*1fa6dee9SAndroid Build Coastguard Worker					arm64: "64",
363*1fa6dee9SAndroid Build Coastguard Worker				},
364*1fa6dee9SAndroid Build Coastguard Worker				configvars: [
365*1fa6dee9SAndroid Build Coastguard Worker					{ var: "var1", values: ["1.1", "1.2", ], },
366*1fa6dee9SAndroid Build Coastguard Worker					{ var: "var2", values: ["2.1", ], },
367*1fa6dee9SAndroid Build Coastguard Worker				],
368*1fa6dee9SAndroid Build Coastguard Worker            }
369*1fa6dee9SAndroid Build Coastguard Worker        `,
370*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
371*1fa6dee9SAndroid Build Coastguard Worker			&struct {
372*1fa6dee9SAndroid Build Coastguard Worker				Name     string
373*1fa6dee9SAndroid Build Coastguard Worker				Flag     bool
374*1fa6dee9SAndroid Build Coastguard Worker				Settings []string
375*1fa6dee9SAndroid Build Coastguard Worker				Perarch  *struct {
376*1fa6dee9SAndroid Build Coastguard Worker					Arm   string
377*1fa6dee9SAndroid Build Coastguard Worker					Arm64 string
378*1fa6dee9SAndroid Build Coastguard Worker				}
379*1fa6dee9SAndroid Build Coastguard Worker				Configvars []struct {
380*1fa6dee9SAndroid Build Coastguard Worker					Var    string
381*1fa6dee9SAndroid Build Coastguard Worker					Values []string
382*1fa6dee9SAndroid Build Coastguard Worker				}
383*1fa6dee9SAndroid Build Coastguard Worker			}{
384*1fa6dee9SAndroid Build Coastguard Worker				Name:     "mymodule",
385*1fa6dee9SAndroid Build Coastguard Worker				Flag:     true,
386*1fa6dee9SAndroid Build Coastguard Worker				Settings: []string{"foo1", "foo2", "foo3"},
387*1fa6dee9SAndroid Build Coastguard Worker				Perarch: &struct {
388*1fa6dee9SAndroid Build Coastguard Worker					Arm   string
389*1fa6dee9SAndroid Build Coastguard Worker					Arm64 string
390*1fa6dee9SAndroid Build Coastguard Worker				}{Arm: "32", Arm64: "64"},
391*1fa6dee9SAndroid Build Coastguard Worker				Configvars: []struct {
392*1fa6dee9SAndroid Build Coastguard Worker					Var    string
393*1fa6dee9SAndroid Build Coastguard Worker					Values []string
394*1fa6dee9SAndroid Build Coastguard Worker				}{
395*1fa6dee9SAndroid Build Coastguard Worker					{Var: "var1", Values: []string{"1.1", "1.2"}},
396*1fa6dee9SAndroid Build Coastguard Worker					{Var: "var2", Values: []string{"2.1"}},
397*1fa6dee9SAndroid Build Coastguard Worker				},
398*1fa6dee9SAndroid Build Coastguard Worker			},
399*1fa6dee9SAndroid Build Coastguard Worker		},
400*1fa6dee9SAndroid Build Coastguard Worker	},
401*1fa6dee9SAndroid Build Coastguard Worker	// Anonymous struct
402*1fa6dee9SAndroid Build Coastguard Worker	{
403*1fa6dee9SAndroid Build Coastguard Worker		name: "embedded struct",
404*1fa6dee9SAndroid Build Coastguard Worker		input: `
405*1fa6dee9SAndroid Build Coastguard Worker			m {
406*1fa6dee9SAndroid Build Coastguard Worker				s: "abc",
407*1fa6dee9SAndroid Build Coastguard Worker				nested: {
408*1fa6dee9SAndroid Build Coastguard Worker					s: "def",
409*1fa6dee9SAndroid Build Coastguard Worker				},
410*1fa6dee9SAndroid Build Coastguard Worker			}
411*1fa6dee9SAndroid Build Coastguard Worker		`,
412*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
413*1fa6dee9SAndroid Build Coastguard Worker			&struct {
414*1fa6dee9SAndroid Build Coastguard Worker				EmbeddedStruct
415*1fa6dee9SAndroid Build Coastguard Worker				Nested struct {
416*1fa6dee9SAndroid Build Coastguard Worker					EmbeddedStruct
417*1fa6dee9SAndroid Build Coastguard Worker				}
418*1fa6dee9SAndroid Build Coastguard Worker			}{
419*1fa6dee9SAndroid Build Coastguard Worker				EmbeddedStruct: EmbeddedStruct{
420*1fa6dee9SAndroid Build Coastguard Worker					S: "abc",
421*1fa6dee9SAndroid Build Coastguard Worker				},
422*1fa6dee9SAndroid Build Coastguard Worker				Nested: struct {
423*1fa6dee9SAndroid Build Coastguard Worker					EmbeddedStruct
424*1fa6dee9SAndroid Build Coastguard Worker				}{
425*1fa6dee9SAndroid Build Coastguard Worker					EmbeddedStruct: EmbeddedStruct{
426*1fa6dee9SAndroid Build Coastguard Worker						S: "def",
427*1fa6dee9SAndroid Build Coastguard Worker					},
428*1fa6dee9SAndroid Build Coastguard Worker				},
429*1fa6dee9SAndroid Build Coastguard Worker			},
430*1fa6dee9SAndroid Build Coastguard Worker		},
431*1fa6dee9SAndroid Build Coastguard Worker	},
432*1fa6dee9SAndroid Build Coastguard Worker
433*1fa6dee9SAndroid Build Coastguard Worker	// Anonymous interface
434*1fa6dee9SAndroid Build Coastguard Worker	{
435*1fa6dee9SAndroid Build Coastguard Worker		name: "embedded interface",
436*1fa6dee9SAndroid Build Coastguard Worker		input: `
437*1fa6dee9SAndroid Build Coastguard Worker			m {
438*1fa6dee9SAndroid Build Coastguard Worker				s: "abc",
439*1fa6dee9SAndroid Build Coastguard Worker				nested: {
440*1fa6dee9SAndroid Build Coastguard Worker					s: "def",
441*1fa6dee9SAndroid Build Coastguard Worker				},
442*1fa6dee9SAndroid Build Coastguard Worker			}
443*1fa6dee9SAndroid Build Coastguard Worker		`,
444*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
445*1fa6dee9SAndroid Build Coastguard Worker			&struct {
446*1fa6dee9SAndroid Build Coastguard Worker				EmbeddedInterface
447*1fa6dee9SAndroid Build Coastguard Worker				Nested struct {
448*1fa6dee9SAndroid Build Coastguard Worker					EmbeddedInterface
449*1fa6dee9SAndroid Build Coastguard Worker				}
450*1fa6dee9SAndroid Build Coastguard Worker			}{
451*1fa6dee9SAndroid Build Coastguard Worker				EmbeddedInterface: &struct{ S string }{
452*1fa6dee9SAndroid Build Coastguard Worker					S: "abc",
453*1fa6dee9SAndroid Build Coastguard Worker				},
454*1fa6dee9SAndroid Build Coastguard Worker				Nested: struct {
455*1fa6dee9SAndroid Build Coastguard Worker					EmbeddedInterface
456*1fa6dee9SAndroid Build Coastguard Worker				}{
457*1fa6dee9SAndroid Build Coastguard Worker					EmbeddedInterface: &struct{ S string }{
458*1fa6dee9SAndroid Build Coastguard Worker						S: "def",
459*1fa6dee9SAndroid Build Coastguard Worker					},
460*1fa6dee9SAndroid Build Coastguard Worker				},
461*1fa6dee9SAndroid Build Coastguard Worker			},
462*1fa6dee9SAndroid Build Coastguard Worker		},
463*1fa6dee9SAndroid Build Coastguard Worker	},
464*1fa6dee9SAndroid Build Coastguard Worker
465*1fa6dee9SAndroid Build Coastguard Worker	// Anonymous struct with name collision
466*1fa6dee9SAndroid Build Coastguard Worker	{
467*1fa6dee9SAndroid Build Coastguard Worker		name: "embedded name collision",
468*1fa6dee9SAndroid Build Coastguard Worker		input: `
469*1fa6dee9SAndroid Build Coastguard Worker			m {
470*1fa6dee9SAndroid Build Coastguard Worker				s: "abc",
471*1fa6dee9SAndroid Build Coastguard Worker				nested: {
472*1fa6dee9SAndroid Build Coastguard Worker					s: "def",
473*1fa6dee9SAndroid Build Coastguard Worker				},
474*1fa6dee9SAndroid Build Coastguard Worker			}
475*1fa6dee9SAndroid Build Coastguard Worker		`,
476*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
477*1fa6dee9SAndroid Build Coastguard Worker			&struct {
478*1fa6dee9SAndroid Build Coastguard Worker				S string
479*1fa6dee9SAndroid Build Coastguard Worker				EmbeddedStruct
480*1fa6dee9SAndroid Build Coastguard Worker				Nested struct {
481*1fa6dee9SAndroid Build Coastguard Worker					S string
482*1fa6dee9SAndroid Build Coastguard Worker					EmbeddedStruct
483*1fa6dee9SAndroid Build Coastguard Worker				}
484*1fa6dee9SAndroid Build Coastguard Worker			}{
485*1fa6dee9SAndroid Build Coastguard Worker				S: "abc",
486*1fa6dee9SAndroid Build Coastguard Worker				EmbeddedStruct: EmbeddedStruct{
487*1fa6dee9SAndroid Build Coastguard Worker					S: "abc",
488*1fa6dee9SAndroid Build Coastguard Worker				},
489*1fa6dee9SAndroid Build Coastguard Worker				Nested: struct {
490*1fa6dee9SAndroid Build Coastguard Worker					S string
491*1fa6dee9SAndroid Build Coastguard Worker					EmbeddedStruct
492*1fa6dee9SAndroid Build Coastguard Worker				}{
493*1fa6dee9SAndroid Build Coastguard Worker					S: "def",
494*1fa6dee9SAndroid Build Coastguard Worker					EmbeddedStruct: EmbeddedStruct{
495*1fa6dee9SAndroid Build Coastguard Worker						S: "def",
496*1fa6dee9SAndroid Build Coastguard Worker					},
497*1fa6dee9SAndroid Build Coastguard Worker				},
498*1fa6dee9SAndroid Build Coastguard Worker			},
499*1fa6dee9SAndroid Build Coastguard Worker		},
500*1fa6dee9SAndroid Build Coastguard Worker	},
501*1fa6dee9SAndroid Build Coastguard Worker
502*1fa6dee9SAndroid Build Coastguard Worker	// Anonymous interface with name collision
503*1fa6dee9SAndroid Build Coastguard Worker	{
504*1fa6dee9SAndroid Build Coastguard Worker		name: "embeded interface name collision",
505*1fa6dee9SAndroid Build Coastguard Worker		input: `
506*1fa6dee9SAndroid Build Coastguard Worker			m {
507*1fa6dee9SAndroid Build Coastguard Worker				s: "abc",
508*1fa6dee9SAndroid Build Coastguard Worker				nested: {
509*1fa6dee9SAndroid Build Coastguard Worker					s: "def",
510*1fa6dee9SAndroid Build Coastguard Worker				},
511*1fa6dee9SAndroid Build Coastguard Worker			}
512*1fa6dee9SAndroid Build Coastguard Worker		`,
513*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
514*1fa6dee9SAndroid Build Coastguard Worker			&struct {
515*1fa6dee9SAndroid Build Coastguard Worker				S string
516*1fa6dee9SAndroid Build Coastguard Worker				EmbeddedInterface
517*1fa6dee9SAndroid Build Coastguard Worker				Nested struct {
518*1fa6dee9SAndroid Build Coastguard Worker					S string
519*1fa6dee9SAndroid Build Coastguard Worker					EmbeddedInterface
520*1fa6dee9SAndroid Build Coastguard Worker				}
521*1fa6dee9SAndroid Build Coastguard Worker			}{
522*1fa6dee9SAndroid Build Coastguard Worker				S: "abc",
523*1fa6dee9SAndroid Build Coastguard Worker				EmbeddedInterface: &struct{ S string }{
524*1fa6dee9SAndroid Build Coastguard Worker					S: "abc",
525*1fa6dee9SAndroid Build Coastguard Worker				},
526*1fa6dee9SAndroid Build Coastguard Worker				Nested: struct {
527*1fa6dee9SAndroid Build Coastguard Worker					S string
528*1fa6dee9SAndroid Build Coastguard Worker					EmbeddedInterface
529*1fa6dee9SAndroid Build Coastguard Worker				}{
530*1fa6dee9SAndroid Build Coastguard Worker					S: "def",
531*1fa6dee9SAndroid Build Coastguard Worker					EmbeddedInterface: &struct{ S string }{
532*1fa6dee9SAndroid Build Coastguard Worker						S: "def",
533*1fa6dee9SAndroid Build Coastguard Worker					},
534*1fa6dee9SAndroid Build Coastguard Worker				},
535*1fa6dee9SAndroid Build Coastguard Worker			},
536*1fa6dee9SAndroid Build Coastguard Worker		},
537*1fa6dee9SAndroid Build Coastguard Worker	},
538*1fa6dee9SAndroid Build Coastguard Worker
539*1fa6dee9SAndroid Build Coastguard Worker	// Variables
540*1fa6dee9SAndroid Build Coastguard Worker	{
541*1fa6dee9SAndroid Build Coastguard Worker		name: "variables",
542*1fa6dee9SAndroid Build Coastguard Worker		input: `
543*1fa6dee9SAndroid Build Coastguard Worker			list = ["abc"]
544*1fa6dee9SAndroid Build Coastguard Worker			string = "def"
545*1fa6dee9SAndroid Build Coastguard Worker			list_with_variable = [string]
546*1fa6dee9SAndroid Build Coastguard Worker			struct_value = { name: "foo" }
547*1fa6dee9SAndroid Build Coastguard Worker			m {
548*1fa6dee9SAndroid Build Coastguard Worker				s: string,
549*1fa6dee9SAndroid Build Coastguard Worker				list: list,
550*1fa6dee9SAndroid Build Coastguard Worker				list2: list_with_variable,
551*1fa6dee9SAndroid Build Coastguard Worker				structattr: struct_value,
552*1fa6dee9SAndroid Build Coastguard Worker			}
553*1fa6dee9SAndroid Build Coastguard Worker		`,
554*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
555*1fa6dee9SAndroid Build Coastguard Worker			&struct {
556*1fa6dee9SAndroid Build Coastguard Worker				S          string
557*1fa6dee9SAndroid Build Coastguard Worker				List       []string
558*1fa6dee9SAndroid Build Coastguard Worker				List2      []string
559*1fa6dee9SAndroid Build Coastguard Worker				Structattr struct {
560*1fa6dee9SAndroid Build Coastguard Worker					Name string
561*1fa6dee9SAndroid Build Coastguard Worker				}
562*1fa6dee9SAndroid Build Coastguard Worker			}{
563*1fa6dee9SAndroid Build Coastguard Worker				S:     "def",
564*1fa6dee9SAndroid Build Coastguard Worker				List:  []string{"abc"},
565*1fa6dee9SAndroid Build Coastguard Worker				List2: []string{"def"},
566*1fa6dee9SAndroid Build Coastguard Worker				Structattr: struct {
567*1fa6dee9SAndroid Build Coastguard Worker					Name string
568*1fa6dee9SAndroid Build Coastguard Worker				}{
569*1fa6dee9SAndroid Build Coastguard Worker					Name: "foo",
570*1fa6dee9SAndroid Build Coastguard Worker				},
571*1fa6dee9SAndroid Build Coastguard Worker			},
572*1fa6dee9SAndroid Build Coastguard Worker		},
573*1fa6dee9SAndroid Build Coastguard Worker	},
574*1fa6dee9SAndroid Build Coastguard Worker
575*1fa6dee9SAndroid Build Coastguard Worker	// Multiple property structs
576*1fa6dee9SAndroid Build Coastguard Worker	{
577*1fa6dee9SAndroid Build Coastguard Worker		name: "multiple",
578*1fa6dee9SAndroid Build Coastguard Worker		input: `
579*1fa6dee9SAndroid Build Coastguard Worker			m {
580*1fa6dee9SAndroid Build Coastguard Worker				nested: {
581*1fa6dee9SAndroid Build Coastguard Worker					s: "abc",
582*1fa6dee9SAndroid Build Coastguard Worker				}
583*1fa6dee9SAndroid Build Coastguard Worker			}
584*1fa6dee9SAndroid Build Coastguard Worker		`,
585*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
586*1fa6dee9SAndroid Build Coastguard Worker			&struct {
587*1fa6dee9SAndroid Build Coastguard Worker				Nested struct {
588*1fa6dee9SAndroid Build Coastguard Worker					S string
589*1fa6dee9SAndroid Build Coastguard Worker				}
590*1fa6dee9SAndroid Build Coastguard Worker			}{
591*1fa6dee9SAndroid Build Coastguard Worker				Nested: struct{ S string }{
592*1fa6dee9SAndroid Build Coastguard Worker					S: "abc",
593*1fa6dee9SAndroid Build Coastguard Worker				},
594*1fa6dee9SAndroid Build Coastguard Worker			},
595*1fa6dee9SAndroid Build Coastguard Worker			&struct {
596*1fa6dee9SAndroid Build Coastguard Worker				Nested struct {
597*1fa6dee9SAndroid Build Coastguard Worker					S string
598*1fa6dee9SAndroid Build Coastguard Worker				}
599*1fa6dee9SAndroid Build Coastguard Worker			}{
600*1fa6dee9SAndroid Build Coastguard Worker				Nested: struct{ S string }{
601*1fa6dee9SAndroid Build Coastguard Worker					S: "abc",
602*1fa6dee9SAndroid Build Coastguard Worker				},
603*1fa6dee9SAndroid Build Coastguard Worker			},
604*1fa6dee9SAndroid Build Coastguard Worker			&struct {
605*1fa6dee9SAndroid Build Coastguard Worker			}{},
606*1fa6dee9SAndroid Build Coastguard Worker		},
607*1fa6dee9SAndroid Build Coastguard Worker	},
608*1fa6dee9SAndroid Build Coastguard Worker
609*1fa6dee9SAndroid Build Coastguard Worker	// Nil pointer to struct
610*1fa6dee9SAndroid Build Coastguard Worker	{
611*1fa6dee9SAndroid Build Coastguard Worker		name: "nil struct pointer",
612*1fa6dee9SAndroid Build Coastguard Worker		input: `
613*1fa6dee9SAndroid Build Coastguard Worker			m {
614*1fa6dee9SAndroid Build Coastguard Worker				nested: {
615*1fa6dee9SAndroid Build Coastguard Worker					s: "abc",
616*1fa6dee9SAndroid Build Coastguard Worker				}
617*1fa6dee9SAndroid Build Coastguard Worker			}
618*1fa6dee9SAndroid Build Coastguard Worker		`,
619*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
620*1fa6dee9SAndroid Build Coastguard Worker			&struct {
621*1fa6dee9SAndroid Build Coastguard Worker				Nested *struct {
622*1fa6dee9SAndroid Build Coastguard Worker					S string
623*1fa6dee9SAndroid Build Coastguard Worker				}
624*1fa6dee9SAndroid Build Coastguard Worker			}{
625*1fa6dee9SAndroid Build Coastguard Worker				Nested: &struct{ S string }{
626*1fa6dee9SAndroid Build Coastguard Worker					S: "abc",
627*1fa6dee9SAndroid Build Coastguard Worker				},
628*1fa6dee9SAndroid Build Coastguard Worker			},
629*1fa6dee9SAndroid Build Coastguard Worker		},
630*1fa6dee9SAndroid Build Coastguard Worker		empty: []interface{}{
631*1fa6dee9SAndroid Build Coastguard Worker			&struct {
632*1fa6dee9SAndroid Build Coastguard Worker				Nested *struct {
633*1fa6dee9SAndroid Build Coastguard Worker					S string
634*1fa6dee9SAndroid Build Coastguard Worker				}
635*1fa6dee9SAndroid Build Coastguard Worker			}{},
636*1fa6dee9SAndroid Build Coastguard Worker		},
637*1fa6dee9SAndroid Build Coastguard Worker	},
638*1fa6dee9SAndroid Build Coastguard Worker
639*1fa6dee9SAndroid Build Coastguard Worker	// Interface containing nil pointer to struct
640*1fa6dee9SAndroid Build Coastguard Worker	{
641*1fa6dee9SAndroid Build Coastguard Worker		name: "interface nil struct pointer",
642*1fa6dee9SAndroid Build Coastguard Worker		input: `
643*1fa6dee9SAndroid Build Coastguard Worker			m {
644*1fa6dee9SAndroid Build Coastguard Worker				nested: {
645*1fa6dee9SAndroid Build Coastguard Worker					s: "abc",
646*1fa6dee9SAndroid Build Coastguard Worker				}
647*1fa6dee9SAndroid Build Coastguard Worker			}
648*1fa6dee9SAndroid Build Coastguard Worker		`,
649*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
650*1fa6dee9SAndroid Build Coastguard Worker			&struct {
651*1fa6dee9SAndroid Build Coastguard Worker				Nested interface{}
652*1fa6dee9SAndroid Build Coastguard Worker			}{
653*1fa6dee9SAndroid Build Coastguard Worker				Nested: &EmbeddedStruct{
654*1fa6dee9SAndroid Build Coastguard Worker					S: "abc",
655*1fa6dee9SAndroid Build Coastguard Worker				},
656*1fa6dee9SAndroid Build Coastguard Worker			},
657*1fa6dee9SAndroid Build Coastguard Worker		},
658*1fa6dee9SAndroid Build Coastguard Worker		empty: []interface{}{
659*1fa6dee9SAndroid Build Coastguard Worker			&struct {
660*1fa6dee9SAndroid Build Coastguard Worker				Nested interface{}
661*1fa6dee9SAndroid Build Coastguard Worker			}{
662*1fa6dee9SAndroid Build Coastguard Worker				Nested: (*EmbeddedStruct)(nil),
663*1fa6dee9SAndroid Build Coastguard Worker			},
664*1fa6dee9SAndroid Build Coastguard Worker		},
665*1fa6dee9SAndroid Build Coastguard Worker	},
666*1fa6dee9SAndroid Build Coastguard Worker
667*1fa6dee9SAndroid Build Coastguard Worker	// Factory set properties
668*1fa6dee9SAndroid Build Coastguard Worker	{
669*1fa6dee9SAndroid Build Coastguard Worker		name: "factory properties",
670*1fa6dee9SAndroid Build Coastguard Worker		input: `
671*1fa6dee9SAndroid Build Coastguard Worker			m {
672*1fa6dee9SAndroid Build Coastguard Worker				string: "abc",
673*1fa6dee9SAndroid Build Coastguard Worker				string_ptr: "abc",
674*1fa6dee9SAndroid Build Coastguard Worker				bool: false,
675*1fa6dee9SAndroid Build Coastguard Worker				bool_ptr: false,
676*1fa6dee9SAndroid Build Coastguard Worker				list: ["a", "b", "c"],
677*1fa6dee9SAndroid Build Coastguard Worker			}
678*1fa6dee9SAndroid Build Coastguard Worker		`,
679*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
680*1fa6dee9SAndroid Build Coastguard Worker			&struct {
681*1fa6dee9SAndroid Build Coastguard Worker				String     string
682*1fa6dee9SAndroid Build Coastguard Worker				String_ptr *string
683*1fa6dee9SAndroid Build Coastguard Worker				Bool       bool
684*1fa6dee9SAndroid Build Coastguard Worker				Bool_ptr   *bool
685*1fa6dee9SAndroid Build Coastguard Worker				List       []string
686*1fa6dee9SAndroid Build Coastguard Worker			}{
687*1fa6dee9SAndroid Build Coastguard Worker				String:     "012abc",
688*1fa6dee9SAndroid Build Coastguard Worker				String_ptr: StringPtr("abc"),
689*1fa6dee9SAndroid Build Coastguard Worker				Bool:       true,
690*1fa6dee9SAndroid Build Coastguard Worker				Bool_ptr:   BoolPtr(false),
691*1fa6dee9SAndroid Build Coastguard Worker				List:       []string{"0", "1", "2", "a", "b", "c"},
692*1fa6dee9SAndroid Build Coastguard Worker			},
693*1fa6dee9SAndroid Build Coastguard Worker		},
694*1fa6dee9SAndroid Build Coastguard Worker		empty: []interface{}{
695*1fa6dee9SAndroid Build Coastguard Worker			&struct {
696*1fa6dee9SAndroid Build Coastguard Worker				String     string
697*1fa6dee9SAndroid Build Coastguard Worker				String_ptr *string
698*1fa6dee9SAndroid Build Coastguard Worker				Bool       bool
699*1fa6dee9SAndroid Build Coastguard Worker				Bool_ptr   *bool
700*1fa6dee9SAndroid Build Coastguard Worker				List       []string
701*1fa6dee9SAndroid Build Coastguard Worker			}{
702*1fa6dee9SAndroid Build Coastguard Worker				String:     "012",
703*1fa6dee9SAndroid Build Coastguard Worker				String_ptr: StringPtr("012"),
704*1fa6dee9SAndroid Build Coastguard Worker				Bool:       true,
705*1fa6dee9SAndroid Build Coastguard Worker				Bool_ptr:   BoolPtr(true),
706*1fa6dee9SAndroid Build Coastguard Worker				List:       []string{"0", "1", "2"},
707*1fa6dee9SAndroid Build Coastguard Worker			},
708*1fa6dee9SAndroid Build Coastguard Worker		},
709*1fa6dee9SAndroid Build Coastguard Worker	},
710*1fa6dee9SAndroid Build Coastguard Worker	// Captitalized property
711*1fa6dee9SAndroid Build Coastguard Worker	{
712*1fa6dee9SAndroid Build Coastguard Worker		input: `
713*1fa6dee9SAndroid Build Coastguard Worker			m {
714*1fa6dee9SAndroid Build Coastguard Worker				CAPITALIZED: "foo",
715*1fa6dee9SAndroid Build Coastguard Worker			}
716*1fa6dee9SAndroid Build Coastguard Worker		`,
717*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
718*1fa6dee9SAndroid Build Coastguard Worker			&struct {
719*1fa6dee9SAndroid Build Coastguard Worker				CAPITALIZED string
720*1fa6dee9SAndroid Build Coastguard Worker			}{
721*1fa6dee9SAndroid Build Coastguard Worker				CAPITALIZED: "foo",
722*1fa6dee9SAndroid Build Coastguard Worker			},
723*1fa6dee9SAndroid Build Coastguard Worker		},
724*1fa6dee9SAndroid Build Coastguard Worker	},
725*1fa6dee9SAndroid Build Coastguard Worker	{
726*1fa6dee9SAndroid Build Coastguard Worker		name: "String configurable property that isn't configured",
727*1fa6dee9SAndroid Build Coastguard Worker		input: `
728*1fa6dee9SAndroid Build Coastguard Worker			m {
729*1fa6dee9SAndroid Build Coastguard Worker				foo: "bar"
730*1fa6dee9SAndroid Build Coastguard Worker			}
731*1fa6dee9SAndroid Build Coastguard Worker		`,
732*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
733*1fa6dee9SAndroid Build Coastguard Worker			&struct {
734*1fa6dee9SAndroid Build Coastguard Worker				Foo Configurable[string]
735*1fa6dee9SAndroid Build Coastguard Worker			}{
736*1fa6dee9SAndroid Build Coastguard Worker				Foo: newConfigurableWithPropertyName(
737*1fa6dee9SAndroid Build Coastguard Worker					"foo",
738*1fa6dee9SAndroid Build Coastguard Worker					nil,
739*1fa6dee9SAndroid Build Coastguard Worker					[]ConfigurableCase[string]{{
740*1fa6dee9SAndroid Build Coastguard Worker						value: &parser.String{
741*1fa6dee9SAndroid Build Coastguard Worker							LiteralPos: scanner.Position{
742*1fa6dee9SAndroid Build Coastguard Worker								Offset: 17,
743*1fa6dee9SAndroid Build Coastguard Worker								Line:   3,
744*1fa6dee9SAndroid Build Coastguard Worker								Column: 10,
745*1fa6dee9SAndroid Build Coastguard Worker							},
746*1fa6dee9SAndroid Build Coastguard Worker							Value: "bar",
747*1fa6dee9SAndroid Build Coastguard Worker						},
748*1fa6dee9SAndroid Build Coastguard Worker					}},
749*1fa6dee9SAndroid Build Coastguard Worker					false,
750*1fa6dee9SAndroid Build Coastguard Worker				),
751*1fa6dee9SAndroid Build Coastguard Worker			},
752*1fa6dee9SAndroid Build Coastguard Worker		},
753*1fa6dee9SAndroid Build Coastguard Worker	},
754*1fa6dee9SAndroid Build Coastguard Worker	{
755*1fa6dee9SAndroid Build Coastguard Worker		name: "Bool configurable property that isn't configured",
756*1fa6dee9SAndroid Build Coastguard Worker		input: `
757*1fa6dee9SAndroid Build Coastguard Worker			m {
758*1fa6dee9SAndroid Build Coastguard Worker				foo: true,
759*1fa6dee9SAndroid Build Coastguard Worker			}
760*1fa6dee9SAndroid Build Coastguard Worker		`,
761*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
762*1fa6dee9SAndroid Build Coastguard Worker			&struct {
763*1fa6dee9SAndroid Build Coastguard Worker				Foo Configurable[bool]
764*1fa6dee9SAndroid Build Coastguard Worker			}{
765*1fa6dee9SAndroid Build Coastguard Worker				Foo: newConfigurableWithPropertyName(
766*1fa6dee9SAndroid Build Coastguard Worker					"foo",
767*1fa6dee9SAndroid Build Coastguard Worker					nil,
768*1fa6dee9SAndroid Build Coastguard Worker					[]ConfigurableCase[bool]{{
769*1fa6dee9SAndroid Build Coastguard Worker						value: &parser.Bool{
770*1fa6dee9SAndroid Build Coastguard Worker							LiteralPos: scanner.Position{
771*1fa6dee9SAndroid Build Coastguard Worker								Offset: 17,
772*1fa6dee9SAndroid Build Coastguard Worker								Line:   3,
773*1fa6dee9SAndroid Build Coastguard Worker								Column: 10,
774*1fa6dee9SAndroid Build Coastguard Worker							},
775*1fa6dee9SAndroid Build Coastguard Worker							Value: true,
776*1fa6dee9SAndroid Build Coastguard Worker							Token: "true",
777*1fa6dee9SAndroid Build Coastguard Worker						},
778*1fa6dee9SAndroid Build Coastguard Worker					}},
779*1fa6dee9SAndroid Build Coastguard Worker					false,
780*1fa6dee9SAndroid Build Coastguard Worker				),
781*1fa6dee9SAndroid Build Coastguard Worker			},
782*1fa6dee9SAndroid Build Coastguard Worker		},
783*1fa6dee9SAndroid Build Coastguard Worker	},
784*1fa6dee9SAndroid Build Coastguard Worker	{
785*1fa6dee9SAndroid Build Coastguard Worker		name: "String list configurable property that isn't configured",
786*1fa6dee9SAndroid Build Coastguard Worker		input: `
787*1fa6dee9SAndroid Build Coastguard Worker			m {
788*1fa6dee9SAndroid Build Coastguard Worker				foo: ["a", "b"],
789*1fa6dee9SAndroid Build Coastguard Worker			}
790*1fa6dee9SAndroid Build Coastguard Worker		`,
791*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
792*1fa6dee9SAndroid Build Coastguard Worker			&struct {
793*1fa6dee9SAndroid Build Coastguard Worker				Foo Configurable[[]string]
794*1fa6dee9SAndroid Build Coastguard Worker			}{
795*1fa6dee9SAndroid Build Coastguard Worker				Foo: newConfigurableWithPropertyName(
796*1fa6dee9SAndroid Build Coastguard Worker					"foo",
797*1fa6dee9SAndroid Build Coastguard Worker					nil,
798*1fa6dee9SAndroid Build Coastguard Worker					[]ConfigurableCase[[]string]{{
799*1fa6dee9SAndroid Build Coastguard Worker						value: &parser.List{
800*1fa6dee9SAndroid Build Coastguard Worker							LBracePos: scanner.Position{
801*1fa6dee9SAndroid Build Coastguard Worker								Offset: 17,
802*1fa6dee9SAndroid Build Coastguard Worker								Line:   3,
803*1fa6dee9SAndroid Build Coastguard Worker								Column: 10,
804*1fa6dee9SAndroid Build Coastguard Worker							},
805*1fa6dee9SAndroid Build Coastguard Worker							RBracePos: scanner.Position{
806*1fa6dee9SAndroid Build Coastguard Worker								Offset: 26,
807*1fa6dee9SAndroid Build Coastguard Worker								Line:   3,
808*1fa6dee9SAndroid Build Coastguard Worker								Column: 19,
809*1fa6dee9SAndroid Build Coastguard Worker							},
810*1fa6dee9SAndroid Build Coastguard Worker							Values: []parser.Expression{
811*1fa6dee9SAndroid Build Coastguard Worker								&parser.String{
812*1fa6dee9SAndroid Build Coastguard Worker									LiteralPos: scanner.Position{
813*1fa6dee9SAndroid Build Coastguard Worker										Offset: 18,
814*1fa6dee9SAndroid Build Coastguard Worker										Line:   3,
815*1fa6dee9SAndroid Build Coastguard Worker										Column: 11,
816*1fa6dee9SAndroid Build Coastguard Worker									},
817*1fa6dee9SAndroid Build Coastguard Worker									Value: "a",
818*1fa6dee9SAndroid Build Coastguard Worker								},
819*1fa6dee9SAndroid Build Coastguard Worker								&parser.String{
820*1fa6dee9SAndroid Build Coastguard Worker									LiteralPos: scanner.Position{
821*1fa6dee9SAndroid Build Coastguard Worker										Offset: 23,
822*1fa6dee9SAndroid Build Coastguard Worker										Line:   3,
823*1fa6dee9SAndroid Build Coastguard Worker										Column: 16,
824*1fa6dee9SAndroid Build Coastguard Worker									},
825*1fa6dee9SAndroid Build Coastguard Worker									Value: "b",
826*1fa6dee9SAndroid Build Coastguard Worker								},
827*1fa6dee9SAndroid Build Coastguard Worker							},
828*1fa6dee9SAndroid Build Coastguard Worker						},
829*1fa6dee9SAndroid Build Coastguard Worker					}},
830*1fa6dee9SAndroid Build Coastguard Worker					false,
831*1fa6dee9SAndroid Build Coastguard Worker				),
832*1fa6dee9SAndroid Build Coastguard Worker			},
833*1fa6dee9SAndroid Build Coastguard Worker		},
834*1fa6dee9SAndroid Build Coastguard Worker	},
835*1fa6dee9SAndroid Build Coastguard Worker	{
836*1fa6dee9SAndroid Build Coastguard Worker		name: "Configurable property",
837*1fa6dee9SAndroid Build Coastguard Worker		input: `
838*1fa6dee9SAndroid Build Coastguard Worker			m {
839*1fa6dee9SAndroid Build Coastguard Worker				foo: select(soong_config_variable("my_namespace", "my_variable"), {
840*1fa6dee9SAndroid Build Coastguard Worker					"a": "a2",
841*1fa6dee9SAndroid Build Coastguard Worker					"b": "b2",
842*1fa6dee9SAndroid Build Coastguard Worker					default: "c2",
843*1fa6dee9SAndroid Build Coastguard Worker				})
844*1fa6dee9SAndroid Build Coastguard Worker			}
845*1fa6dee9SAndroid Build Coastguard Worker		`,
846*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
847*1fa6dee9SAndroid Build Coastguard Worker			&struct {
848*1fa6dee9SAndroid Build Coastguard Worker				Foo Configurable[string]
849*1fa6dee9SAndroid Build Coastguard Worker			}{
850*1fa6dee9SAndroid Build Coastguard Worker				Foo: newConfigurableWithPropertyName(
851*1fa6dee9SAndroid Build Coastguard Worker					"foo",
852*1fa6dee9SAndroid Build Coastguard Worker					[]ConfigurableCondition{{
853*1fa6dee9SAndroid Build Coastguard Worker						functionName: "soong_config_variable",
854*1fa6dee9SAndroid Build Coastguard Worker						args: []string{
855*1fa6dee9SAndroid Build Coastguard Worker							"my_namespace",
856*1fa6dee9SAndroid Build Coastguard Worker							"my_variable",
857*1fa6dee9SAndroid Build Coastguard Worker						},
858*1fa6dee9SAndroid Build Coastguard Worker					}},
859*1fa6dee9SAndroid Build Coastguard Worker					[]ConfigurableCase[string]{
860*1fa6dee9SAndroid Build Coastguard Worker						{
861*1fa6dee9SAndroid Build Coastguard Worker							patterns: []ConfigurablePattern{{
862*1fa6dee9SAndroid Build Coastguard Worker								typ:         configurablePatternTypeString,
863*1fa6dee9SAndroid Build Coastguard Worker								stringValue: "a",
864*1fa6dee9SAndroid Build Coastguard Worker							}},
865*1fa6dee9SAndroid Build Coastguard Worker							value: &parser.String{
866*1fa6dee9SAndroid Build Coastguard Worker								LiteralPos: scanner.Position{
867*1fa6dee9SAndroid Build Coastguard Worker									Offset: 90,
868*1fa6dee9SAndroid Build Coastguard Worker									Line:   4,
869*1fa6dee9SAndroid Build Coastguard Worker									Column: 11,
870*1fa6dee9SAndroid Build Coastguard Worker								},
871*1fa6dee9SAndroid Build Coastguard Worker								Value: "a2",
872*1fa6dee9SAndroid Build Coastguard Worker							},
873*1fa6dee9SAndroid Build Coastguard Worker						},
874*1fa6dee9SAndroid Build Coastguard Worker						{
875*1fa6dee9SAndroid Build Coastguard Worker							patterns: []ConfigurablePattern{{
876*1fa6dee9SAndroid Build Coastguard Worker								typ:         configurablePatternTypeString,
877*1fa6dee9SAndroid Build Coastguard Worker								stringValue: "b",
878*1fa6dee9SAndroid Build Coastguard Worker							}},
879*1fa6dee9SAndroid Build Coastguard Worker							value: &parser.String{
880*1fa6dee9SAndroid Build Coastguard Worker								LiteralPos: scanner.Position{
881*1fa6dee9SAndroid Build Coastguard Worker									Offset: 106,
882*1fa6dee9SAndroid Build Coastguard Worker									Line:   5,
883*1fa6dee9SAndroid Build Coastguard Worker									Column: 11,
884*1fa6dee9SAndroid Build Coastguard Worker								},
885*1fa6dee9SAndroid Build Coastguard Worker								Value: "b2",
886*1fa6dee9SAndroid Build Coastguard Worker							},
887*1fa6dee9SAndroid Build Coastguard Worker						},
888*1fa6dee9SAndroid Build Coastguard Worker						{
889*1fa6dee9SAndroid Build Coastguard Worker							patterns: []ConfigurablePattern{{
890*1fa6dee9SAndroid Build Coastguard Worker								typ: configurablePatternTypeDefault,
891*1fa6dee9SAndroid Build Coastguard Worker							}},
892*1fa6dee9SAndroid Build Coastguard Worker							value: &parser.String{
893*1fa6dee9SAndroid Build Coastguard Worker								LiteralPos: scanner.Position{
894*1fa6dee9SAndroid Build Coastguard Worker									Offset: 126,
895*1fa6dee9SAndroid Build Coastguard Worker									Line:   6,
896*1fa6dee9SAndroid Build Coastguard Worker									Column: 15,
897*1fa6dee9SAndroid Build Coastguard Worker								},
898*1fa6dee9SAndroid Build Coastguard Worker								Value: "c2",
899*1fa6dee9SAndroid Build Coastguard Worker							},
900*1fa6dee9SAndroid Build Coastguard Worker						},
901*1fa6dee9SAndroid Build Coastguard Worker					},
902*1fa6dee9SAndroid Build Coastguard Worker					true,
903*1fa6dee9SAndroid Build Coastguard Worker				),
904*1fa6dee9SAndroid Build Coastguard Worker			},
905*1fa6dee9SAndroid Build Coastguard Worker		},
906*1fa6dee9SAndroid Build Coastguard Worker	},
907*1fa6dee9SAndroid Build Coastguard Worker	{
908*1fa6dee9SAndroid Build Coastguard Worker		name: "Configurable property appending",
909*1fa6dee9SAndroid Build Coastguard Worker		input: `
910*1fa6dee9SAndroid Build Coastguard Worker			m {
911*1fa6dee9SAndroid Build Coastguard Worker				foo: select(soong_config_variable("my_namespace", "my_variable"), {
912*1fa6dee9SAndroid Build Coastguard Worker					"a": "a2",
913*1fa6dee9SAndroid Build Coastguard Worker					"b": "b2",
914*1fa6dee9SAndroid Build Coastguard Worker					default: "c2",
915*1fa6dee9SAndroid Build Coastguard Worker				}) + select(soong_config_variable("my_namespace", "my_2nd_variable"), {
916*1fa6dee9SAndroid Build Coastguard Worker					"d": "d2",
917*1fa6dee9SAndroid Build Coastguard Worker					"e": "e2",
918*1fa6dee9SAndroid Build Coastguard Worker					default: "f2",
919*1fa6dee9SAndroid Build Coastguard Worker				})
920*1fa6dee9SAndroid Build Coastguard Worker			}
921*1fa6dee9SAndroid Build Coastguard Worker		`,
922*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
923*1fa6dee9SAndroid Build Coastguard Worker			&struct {
924*1fa6dee9SAndroid Build Coastguard Worker				Foo Configurable[string]
925*1fa6dee9SAndroid Build Coastguard Worker			}{
926*1fa6dee9SAndroid Build Coastguard Worker				Foo: func() Configurable[string] {
927*1fa6dee9SAndroid Build Coastguard Worker					result := newConfigurableWithPropertyName(
928*1fa6dee9SAndroid Build Coastguard Worker						"foo",
929*1fa6dee9SAndroid Build Coastguard Worker						[]ConfigurableCondition{{
930*1fa6dee9SAndroid Build Coastguard Worker							functionName: "soong_config_variable",
931*1fa6dee9SAndroid Build Coastguard Worker							args: []string{
932*1fa6dee9SAndroid Build Coastguard Worker								"my_namespace",
933*1fa6dee9SAndroid Build Coastguard Worker								"my_variable",
934*1fa6dee9SAndroid Build Coastguard Worker							},
935*1fa6dee9SAndroid Build Coastguard Worker						}},
936*1fa6dee9SAndroid Build Coastguard Worker						[]ConfigurableCase[string]{
937*1fa6dee9SAndroid Build Coastguard Worker							{
938*1fa6dee9SAndroid Build Coastguard Worker								patterns: []ConfigurablePattern{{
939*1fa6dee9SAndroid Build Coastguard Worker									typ:         configurablePatternTypeString,
940*1fa6dee9SAndroid Build Coastguard Worker									stringValue: "a",
941*1fa6dee9SAndroid Build Coastguard Worker								}},
942*1fa6dee9SAndroid Build Coastguard Worker								value: &parser.String{
943*1fa6dee9SAndroid Build Coastguard Worker									LiteralPos: scanner.Position{
944*1fa6dee9SAndroid Build Coastguard Worker										Offset: 90,
945*1fa6dee9SAndroid Build Coastguard Worker										Line:   4,
946*1fa6dee9SAndroid Build Coastguard Worker										Column: 11,
947*1fa6dee9SAndroid Build Coastguard Worker									},
948*1fa6dee9SAndroid Build Coastguard Worker									Value: "a2",
949*1fa6dee9SAndroid Build Coastguard Worker								},
950*1fa6dee9SAndroid Build Coastguard Worker							},
951*1fa6dee9SAndroid Build Coastguard Worker							{
952*1fa6dee9SAndroid Build Coastguard Worker								patterns: []ConfigurablePattern{{
953*1fa6dee9SAndroid Build Coastguard Worker									typ:         configurablePatternTypeString,
954*1fa6dee9SAndroid Build Coastguard Worker									stringValue: "b",
955*1fa6dee9SAndroid Build Coastguard Worker								}},
956*1fa6dee9SAndroid Build Coastguard Worker								value: &parser.String{
957*1fa6dee9SAndroid Build Coastguard Worker									LiteralPos: scanner.Position{
958*1fa6dee9SAndroid Build Coastguard Worker										Offset: 106,
959*1fa6dee9SAndroid Build Coastguard Worker										Line:   5,
960*1fa6dee9SAndroid Build Coastguard Worker										Column: 11,
961*1fa6dee9SAndroid Build Coastguard Worker									},
962*1fa6dee9SAndroid Build Coastguard Worker									Value: "b2",
963*1fa6dee9SAndroid Build Coastguard Worker								},
964*1fa6dee9SAndroid Build Coastguard Worker							},
965*1fa6dee9SAndroid Build Coastguard Worker							{
966*1fa6dee9SAndroid Build Coastguard Worker								patterns: []ConfigurablePattern{{
967*1fa6dee9SAndroid Build Coastguard Worker									typ: configurablePatternTypeDefault,
968*1fa6dee9SAndroid Build Coastguard Worker								}},
969*1fa6dee9SAndroid Build Coastguard Worker								value: &parser.String{
970*1fa6dee9SAndroid Build Coastguard Worker									LiteralPos: scanner.Position{
971*1fa6dee9SAndroid Build Coastguard Worker										Offset: 126,
972*1fa6dee9SAndroid Build Coastguard Worker										Line:   6,
973*1fa6dee9SAndroid Build Coastguard Worker										Column: 15,
974*1fa6dee9SAndroid Build Coastguard Worker									},
975*1fa6dee9SAndroid Build Coastguard Worker									Value: "c2",
976*1fa6dee9SAndroid Build Coastguard Worker								},
977*1fa6dee9SAndroid Build Coastguard Worker							},
978*1fa6dee9SAndroid Build Coastguard Worker						},
979*1fa6dee9SAndroid Build Coastguard Worker						true,
980*1fa6dee9SAndroid Build Coastguard Worker					)
981*1fa6dee9SAndroid Build Coastguard Worker					result.Append(newConfigurableWithPropertyName(
982*1fa6dee9SAndroid Build Coastguard Worker						"",
983*1fa6dee9SAndroid Build Coastguard Worker						[]ConfigurableCondition{{
984*1fa6dee9SAndroid Build Coastguard Worker							functionName: "soong_config_variable",
985*1fa6dee9SAndroid Build Coastguard Worker							args: []string{
986*1fa6dee9SAndroid Build Coastguard Worker								"my_namespace",
987*1fa6dee9SAndroid Build Coastguard Worker								"my_2nd_variable",
988*1fa6dee9SAndroid Build Coastguard Worker							},
989*1fa6dee9SAndroid Build Coastguard Worker						}},
990*1fa6dee9SAndroid Build Coastguard Worker						[]ConfigurableCase[string]{
991*1fa6dee9SAndroid Build Coastguard Worker							{
992*1fa6dee9SAndroid Build Coastguard Worker								patterns: []ConfigurablePattern{{
993*1fa6dee9SAndroid Build Coastguard Worker									typ:         configurablePatternTypeString,
994*1fa6dee9SAndroid Build Coastguard Worker									stringValue: "d",
995*1fa6dee9SAndroid Build Coastguard Worker								}},
996*1fa6dee9SAndroid Build Coastguard Worker								value: &parser.String{
997*1fa6dee9SAndroid Build Coastguard Worker									LiteralPos: scanner.Position{
998*1fa6dee9SAndroid Build Coastguard Worker										Offset: 218,
999*1fa6dee9SAndroid Build Coastguard Worker										Line:   8,
1000*1fa6dee9SAndroid Build Coastguard Worker										Column: 11,
1001*1fa6dee9SAndroid Build Coastguard Worker									},
1002*1fa6dee9SAndroid Build Coastguard Worker									Value: "d2",
1003*1fa6dee9SAndroid Build Coastguard Worker								},
1004*1fa6dee9SAndroid Build Coastguard Worker							},
1005*1fa6dee9SAndroid Build Coastguard Worker							{
1006*1fa6dee9SAndroid Build Coastguard Worker								patterns: []ConfigurablePattern{{
1007*1fa6dee9SAndroid Build Coastguard Worker									typ:         configurablePatternTypeString,
1008*1fa6dee9SAndroid Build Coastguard Worker									stringValue: "e",
1009*1fa6dee9SAndroid Build Coastguard Worker								}},
1010*1fa6dee9SAndroid Build Coastguard Worker								value: &parser.String{
1011*1fa6dee9SAndroid Build Coastguard Worker									LiteralPos: scanner.Position{
1012*1fa6dee9SAndroid Build Coastguard Worker										Offset: 234,
1013*1fa6dee9SAndroid Build Coastguard Worker										Line:   9,
1014*1fa6dee9SAndroid Build Coastguard Worker										Column: 11,
1015*1fa6dee9SAndroid Build Coastguard Worker									},
1016*1fa6dee9SAndroid Build Coastguard Worker									Value: "e2",
1017*1fa6dee9SAndroid Build Coastguard Worker								},
1018*1fa6dee9SAndroid Build Coastguard Worker							},
1019*1fa6dee9SAndroid Build Coastguard Worker							{
1020*1fa6dee9SAndroid Build Coastguard Worker								patterns: []ConfigurablePattern{{
1021*1fa6dee9SAndroid Build Coastguard Worker									typ: configurablePatternTypeDefault,
1022*1fa6dee9SAndroid Build Coastguard Worker								}},
1023*1fa6dee9SAndroid Build Coastguard Worker								value: &parser.String{
1024*1fa6dee9SAndroid Build Coastguard Worker									LiteralPos: scanner.Position{
1025*1fa6dee9SAndroid Build Coastguard Worker										Offset: 254,
1026*1fa6dee9SAndroid Build Coastguard Worker										Line:   10,
1027*1fa6dee9SAndroid Build Coastguard Worker										Column: 15,
1028*1fa6dee9SAndroid Build Coastguard Worker									},
1029*1fa6dee9SAndroid Build Coastguard Worker									Value: "f2",
1030*1fa6dee9SAndroid Build Coastguard Worker								},
1031*1fa6dee9SAndroid Build Coastguard Worker							},
1032*1fa6dee9SAndroid Build Coastguard Worker						},
1033*1fa6dee9SAndroid Build Coastguard Worker						true,
1034*1fa6dee9SAndroid Build Coastguard Worker					))
1035*1fa6dee9SAndroid Build Coastguard Worker					return result
1036*1fa6dee9SAndroid Build Coastguard Worker				}(),
1037*1fa6dee9SAndroid Build Coastguard Worker			},
1038*1fa6dee9SAndroid Build Coastguard Worker		},
1039*1fa6dee9SAndroid Build Coastguard Worker	},
1040*1fa6dee9SAndroid Build Coastguard Worker	{
1041*1fa6dee9SAndroid Build Coastguard Worker		name: "Unpack variable to configurable property",
1042*1fa6dee9SAndroid Build Coastguard Worker		input: `
1043*1fa6dee9SAndroid Build Coastguard Worker			my_string_variable = "asdf"
1044*1fa6dee9SAndroid Build Coastguard Worker			my_bool_variable = true
1045*1fa6dee9SAndroid Build Coastguard Worker			m {
1046*1fa6dee9SAndroid Build Coastguard Worker				foo: my_string_variable,
1047*1fa6dee9SAndroid Build Coastguard Worker				bar: my_bool_variable,
1048*1fa6dee9SAndroid Build Coastguard Worker			}
1049*1fa6dee9SAndroid Build Coastguard Worker		`,
1050*1fa6dee9SAndroid Build Coastguard Worker		output: []interface{}{
1051*1fa6dee9SAndroid Build Coastguard Worker			&struct {
1052*1fa6dee9SAndroid Build Coastguard Worker				Foo Configurable[string]
1053*1fa6dee9SAndroid Build Coastguard Worker				Bar Configurable[bool]
1054*1fa6dee9SAndroid Build Coastguard Worker			}{
1055*1fa6dee9SAndroid Build Coastguard Worker				Foo: newConfigurableWithPropertyName(
1056*1fa6dee9SAndroid Build Coastguard Worker					"foo",
1057*1fa6dee9SAndroid Build Coastguard Worker					nil,
1058*1fa6dee9SAndroid Build Coastguard Worker					[]ConfigurableCase[string]{{
1059*1fa6dee9SAndroid Build Coastguard Worker						value: &parser.String{
1060*1fa6dee9SAndroid Build Coastguard Worker							LiteralPos: scanner.Position{
1061*1fa6dee9SAndroid Build Coastguard Worker								Offset: 25,
1062*1fa6dee9SAndroid Build Coastguard Worker								Line:   2,
1063*1fa6dee9SAndroid Build Coastguard Worker								Column: 25,
1064*1fa6dee9SAndroid Build Coastguard Worker							},
1065*1fa6dee9SAndroid Build Coastguard Worker							Value: "asdf",
1066*1fa6dee9SAndroid Build Coastguard Worker						},
1067*1fa6dee9SAndroid Build Coastguard Worker					}},
1068*1fa6dee9SAndroid Build Coastguard Worker					false,
1069*1fa6dee9SAndroid Build Coastguard Worker				),
1070*1fa6dee9SAndroid Build Coastguard Worker				Bar: newConfigurableWithPropertyName(
1071*1fa6dee9SAndroid Build Coastguard Worker					"bar",
1072*1fa6dee9SAndroid Build Coastguard Worker					nil,
1073*1fa6dee9SAndroid Build Coastguard Worker					[]ConfigurableCase[bool]{{
1074*1fa6dee9SAndroid Build Coastguard Worker						value: &parser.Bool{
1075*1fa6dee9SAndroid Build Coastguard Worker							LiteralPos: scanner.Position{
1076*1fa6dee9SAndroid Build Coastguard Worker								Offset: 54,
1077*1fa6dee9SAndroid Build Coastguard Worker								Line:   3,
1078*1fa6dee9SAndroid Build Coastguard Worker								Column: 23,
1079*1fa6dee9SAndroid Build Coastguard Worker							},
1080*1fa6dee9SAndroid Build Coastguard Worker							Value: true,
1081*1fa6dee9SAndroid Build Coastguard Worker							Token: "true",
1082*1fa6dee9SAndroid Build Coastguard Worker						},
1083*1fa6dee9SAndroid Build Coastguard Worker					}},
1084*1fa6dee9SAndroid Build Coastguard Worker					false,
1085*1fa6dee9SAndroid Build Coastguard Worker				),
1086*1fa6dee9SAndroid Build Coastguard Worker			},
1087*1fa6dee9SAndroid Build Coastguard Worker		},
1088*1fa6dee9SAndroid Build Coastguard Worker	},
1089*1fa6dee9SAndroid Build Coastguard Worker}
1090*1fa6dee9SAndroid Build Coastguard Worker
1091*1fa6dee9SAndroid Build Coastguard Workerfunc TestUnpackProperties(t *testing.T) {
1092*1fa6dee9SAndroid Build Coastguard Worker	for _, testCase := range validUnpackTestCases {
1093*1fa6dee9SAndroid Build Coastguard Worker		t.Run(testCase.name, func(t *testing.T) {
1094*1fa6dee9SAndroid Build Coastguard Worker			r := bytes.NewBufferString(testCase.input)
1095*1fa6dee9SAndroid Build Coastguard Worker			file, errs := parser.ParseAndEval("", r, parser.NewScope(nil))
1096*1fa6dee9SAndroid Build Coastguard Worker			if len(errs) != 0 {
1097*1fa6dee9SAndroid Build Coastguard Worker				t.Errorf("test case: %s", testCase.input)
1098*1fa6dee9SAndroid Build Coastguard Worker				t.Errorf("unexpected parse errors:")
1099*1fa6dee9SAndroid Build Coastguard Worker				for _, err := range errs {
1100*1fa6dee9SAndroid Build Coastguard Worker					t.Errorf("  %s", err)
1101*1fa6dee9SAndroid Build Coastguard Worker				}
1102*1fa6dee9SAndroid Build Coastguard Worker				t.FailNow()
1103*1fa6dee9SAndroid Build Coastguard Worker			}
1104*1fa6dee9SAndroid Build Coastguard Worker
1105*1fa6dee9SAndroid Build Coastguard Worker			for _, def := range file.Defs {
1106*1fa6dee9SAndroid Build Coastguard Worker				module, ok := def.(*parser.Module)
1107*1fa6dee9SAndroid Build Coastguard Worker				if !ok {
1108*1fa6dee9SAndroid Build Coastguard Worker					continue
1109*1fa6dee9SAndroid Build Coastguard Worker				}
1110*1fa6dee9SAndroid Build Coastguard Worker
1111*1fa6dee9SAndroid Build Coastguard Worker				var output []interface{}
1112*1fa6dee9SAndroid Build Coastguard Worker				if len(testCase.empty) > 0 {
1113*1fa6dee9SAndroid Build Coastguard Worker					for _, p := range testCase.empty {
1114*1fa6dee9SAndroid Build Coastguard Worker						output = append(output, CloneProperties(reflect.ValueOf(p)).Interface())
1115*1fa6dee9SAndroid Build Coastguard Worker					}
1116*1fa6dee9SAndroid Build Coastguard Worker				} else {
1117*1fa6dee9SAndroid Build Coastguard Worker					for _, p := range testCase.output {
1118*1fa6dee9SAndroid Build Coastguard Worker						output = append(output, CloneEmptyProperties(reflect.ValueOf(p)).Interface())
1119*1fa6dee9SAndroid Build Coastguard Worker					}
1120*1fa6dee9SAndroid Build Coastguard Worker				}
1121*1fa6dee9SAndroid Build Coastguard Worker
1122*1fa6dee9SAndroid Build Coastguard Worker				_, errs = UnpackProperties(module.Properties, output...)
1123*1fa6dee9SAndroid Build Coastguard Worker				if len(errs) != 0 && len(testCase.errs) == 0 {
1124*1fa6dee9SAndroid Build Coastguard Worker					t.Errorf("test case: %s", testCase.input)
1125*1fa6dee9SAndroid Build Coastguard Worker					t.Errorf("unexpected unpack errors:")
1126*1fa6dee9SAndroid Build Coastguard Worker					for _, err := range errs {
1127*1fa6dee9SAndroid Build Coastguard Worker						t.Errorf("  %s", err)
1128*1fa6dee9SAndroid Build Coastguard Worker					}
1129*1fa6dee9SAndroid Build Coastguard Worker					t.FailNow()
1130*1fa6dee9SAndroid Build Coastguard Worker				} else if !reflect.DeepEqual(errs, testCase.errs) {
1131*1fa6dee9SAndroid Build Coastguard Worker					t.Errorf("test case: %s", testCase.input)
1132*1fa6dee9SAndroid Build Coastguard Worker					t.Errorf("incorrect errors:")
1133*1fa6dee9SAndroid Build Coastguard Worker					t.Errorf("  expected: %+v", testCase.errs)
1134*1fa6dee9SAndroid Build Coastguard Worker					t.Errorf("       got: %+v", errs)
1135*1fa6dee9SAndroid Build Coastguard Worker				}
1136*1fa6dee9SAndroid Build Coastguard Worker
1137*1fa6dee9SAndroid Build Coastguard Worker				if len(output) != len(testCase.output) {
1138*1fa6dee9SAndroid Build Coastguard Worker					t.Fatalf("incorrect number of property structs, expected %d got %d",
1139*1fa6dee9SAndroid Build Coastguard Worker						len(testCase.output), len(output))
1140*1fa6dee9SAndroid Build Coastguard Worker				}
1141*1fa6dee9SAndroid Build Coastguard Worker
1142*1fa6dee9SAndroid Build Coastguard Worker				for i := range output {
1143*1fa6dee9SAndroid Build Coastguard Worker					got := reflect.ValueOf(output[i]).Interface()
1144*1fa6dee9SAndroid Build Coastguard Worker					if !reflect.DeepEqual(got, testCase.output[i]) {
1145*1fa6dee9SAndroid Build Coastguard Worker						t.Errorf("test case: %s", testCase.input)
1146*1fa6dee9SAndroid Build Coastguard Worker						t.Errorf("incorrect output:")
1147*1fa6dee9SAndroid Build Coastguard Worker						t.Errorf("  expected: %+v", testCase.output[i])
1148*1fa6dee9SAndroid Build Coastguard Worker						t.Errorf("       got: %+v", got)
1149*1fa6dee9SAndroid Build Coastguard Worker					}
1150*1fa6dee9SAndroid Build Coastguard Worker				}
1151*1fa6dee9SAndroid Build Coastguard Worker			}
1152*1fa6dee9SAndroid Build Coastguard Worker		})
1153*1fa6dee9SAndroid Build Coastguard Worker	}
1154*1fa6dee9SAndroid Build Coastguard Worker}
1155*1fa6dee9SAndroid Build Coastguard Worker
1156*1fa6dee9SAndroid Build Coastguard Workerfunc TestUnpackErrors(t *testing.T) {
1157*1fa6dee9SAndroid Build Coastguard Worker	testCases := []struct {
1158*1fa6dee9SAndroid Build Coastguard Worker		name   string
1159*1fa6dee9SAndroid Build Coastguard Worker		input  string
1160*1fa6dee9SAndroid Build Coastguard Worker		output []interface{}
1161*1fa6dee9SAndroid Build Coastguard Worker		errors []string
1162*1fa6dee9SAndroid Build Coastguard Worker	}{
1163*1fa6dee9SAndroid Build Coastguard Worker		{
1164*1fa6dee9SAndroid Build Coastguard Worker			name: "missing",
1165*1fa6dee9SAndroid Build Coastguard Worker			input: `
1166*1fa6dee9SAndroid Build Coastguard Worker				m {
1167*1fa6dee9SAndroid Build Coastguard Worker					missing: true,
1168*1fa6dee9SAndroid Build Coastguard Worker				}
1169*1fa6dee9SAndroid Build Coastguard Worker			`,
1170*1fa6dee9SAndroid Build Coastguard Worker			output: []interface{}{},
1171*1fa6dee9SAndroid Build Coastguard Worker			errors: []string{`<input>:3:13: unrecognized property "missing"`},
1172*1fa6dee9SAndroid Build Coastguard Worker		},
1173*1fa6dee9SAndroid Build Coastguard Worker		{
1174*1fa6dee9SAndroid Build Coastguard Worker			name: "missing nested",
1175*1fa6dee9SAndroid Build Coastguard Worker			input: `
1176*1fa6dee9SAndroid Build Coastguard Worker				m {
1177*1fa6dee9SAndroid Build Coastguard Worker					nested: {
1178*1fa6dee9SAndroid Build Coastguard Worker						missing: true,
1179*1fa6dee9SAndroid Build Coastguard Worker					},
1180*1fa6dee9SAndroid Build Coastguard Worker				}
1181*1fa6dee9SAndroid Build Coastguard Worker			`,
1182*1fa6dee9SAndroid Build Coastguard Worker			output: []interface{}{
1183*1fa6dee9SAndroid Build Coastguard Worker				&struct {
1184*1fa6dee9SAndroid Build Coastguard Worker					Nested struct{}
1185*1fa6dee9SAndroid Build Coastguard Worker				}{},
1186*1fa6dee9SAndroid Build Coastguard Worker			},
1187*1fa6dee9SAndroid Build Coastguard Worker			errors: []string{`<input>:4:14: unrecognized property "nested.missing"`},
1188*1fa6dee9SAndroid Build Coastguard Worker		},
1189*1fa6dee9SAndroid Build Coastguard Worker		{
1190*1fa6dee9SAndroid Build Coastguard Worker			name: "mutated",
1191*1fa6dee9SAndroid Build Coastguard Worker			input: `
1192*1fa6dee9SAndroid Build Coastguard Worker				m {
1193*1fa6dee9SAndroid Build Coastguard Worker					mutated: true,
1194*1fa6dee9SAndroid Build Coastguard Worker				}
1195*1fa6dee9SAndroid Build Coastguard Worker			`,
1196*1fa6dee9SAndroid Build Coastguard Worker			output: []interface{}{
1197*1fa6dee9SAndroid Build Coastguard Worker				&struct {
1198*1fa6dee9SAndroid Build Coastguard Worker					Mutated bool `blueprint:"mutated"`
1199*1fa6dee9SAndroid Build Coastguard Worker				}{},
1200*1fa6dee9SAndroid Build Coastguard Worker			},
1201*1fa6dee9SAndroid Build Coastguard Worker			errors: []string{`<input>:3:13: mutated field mutated cannot be set in a Blueprint file`},
1202*1fa6dee9SAndroid Build Coastguard Worker		},
1203*1fa6dee9SAndroid Build Coastguard Worker		{
1204*1fa6dee9SAndroid Build Coastguard Worker			name: "nested mutated",
1205*1fa6dee9SAndroid Build Coastguard Worker			input: `
1206*1fa6dee9SAndroid Build Coastguard Worker				m {
1207*1fa6dee9SAndroid Build Coastguard Worker					nested: {
1208*1fa6dee9SAndroid Build Coastguard Worker						mutated: true,
1209*1fa6dee9SAndroid Build Coastguard Worker					},
1210*1fa6dee9SAndroid Build Coastguard Worker				}
1211*1fa6dee9SAndroid Build Coastguard Worker			`,
1212*1fa6dee9SAndroid Build Coastguard Worker			output: []interface{}{
1213*1fa6dee9SAndroid Build Coastguard Worker				&struct {
1214*1fa6dee9SAndroid Build Coastguard Worker					Nested struct {
1215*1fa6dee9SAndroid Build Coastguard Worker						Mutated bool `blueprint:"mutated"`
1216*1fa6dee9SAndroid Build Coastguard Worker					}
1217*1fa6dee9SAndroid Build Coastguard Worker				}{},
1218*1fa6dee9SAndroid Build Coastguard Worker			},
1219*1fa6dee9SAndroid Build Coastguard Worker			errors: []string{`<input>:4:14: mutated field nested.mutated cannot be set in a Blueprint file`},
1220*1fa6dee9SAndroid Build Coastguard Worker		},
1221*1fa6dee9SAndroid Build Coastguard Worker		{
1222*1fa6dee9SAndroid Build Coastguard Worker			name: "duplicate",
1223*1fa6dee9SAndroid Build Coastguard Worker			input: `
1224*1fa6dee9SAndroid Build Coastguard Worker				m {
1225*1fa6dee9SAndroid Build Coastguard Worker					exists: true,
1226*1fa6dee9SAndroid Build Coastguard Worker					exists: true,
1227*1fa6dee9SAndroid Build Coastguard Worker				}
1228*1fa6dee9SAndroid Build Coastguard Worker			`,
1229*1fa6dee9SAndroid Build Coastguard Worker			output: []interface{}{
1230*1fa6dee9SAndroid Build Coastguard Worker				&struct {
1231*1fa6dee9SAndroid Build Coastguard Worker					Exists bool
1232*1fa6dee9SAndroid Build Coastguard Worker				}{},
1233*1fa6dee9SAndroid Build Coastguard Worker			},
1234*1fa6dee9SAndroid Build Coastguard Worker			errors: []string{
1235*1fa6dee9SAndroid Build Coastguard Worker				`<input>:4:12: property "exists" already defined`,
1236*1fa6dee9SAndroid Build Coastguard Worker				`<input>:3:12: <-- previous definition here`,
1237*1fa6dee9SAndroid Build Coastguard Worker			},
1238*1fa6dee9SAndroid Build Coastguard Worker		},
1239*1fa6dee9SAndroid Build Coastguard Worker		{
1240*1fa6dee9SAndroid Build Coastguard Worker			name: "nested duplicate",
1241*1fa6dee9SAndroid Build Coastguard Worker			input: `
1242*1fa6dee9SAndroid Build Coastguard Worker				m {
1243*1fa6dee9SAndroid Build Coastguard Worker					nested: {
1244*1fa6dee9SAndroid Build Coastguard Worker						exists: true,
1245*1fa6dee9SAndroid Build Coastguard Worker						exists: true,
1246*1fa6dee9SAndroid Build Coastguard Worker					},
1247*1fa6dee9SAndroid Build Coastguard Worker				}
1248*1fa6dee9SAndroid Build Coastguard Worker			`,
1249*1fa6dee9SAndroid Build Coastguard Worker			output: []interface{}{
1250*1fa6dee9SAndroid Build Coastguard Worker				&struct {
1251*1fa6dee9SAndroid Build Coastguard Worker					Nested struct {
1252*1fa6dee9SAndroid Build Coastguard Worker						Exists bool
1253*1fa6dee9SAndroid Build Coastguard Worker					}
1254*1fa6dee9SAndroid Build Coastguard Worker				}{},
1255*1fa6dee9SAndroid Build Coastguard Worker			},
1256*1fa6dee9SAndroid Build Coastguard Worker			errors: []string{
1257*1fa6dee9SAndroid Build Coastguard Worker				`<input>:5:13: property "nested.exists" already defined`,
1258*1fa6dee9SAndroid Build Coastguard Worker				`<input>:4:13: <-- previous definition here`,
1259*1fa6dee9SAndroid Build Coastguard Worker			},
1260*1fa6dee9SAndroid Build Coastguard Worker		},
1261*1fa6dee9SAndroid Build Coastguard Worker		{
1262*1fa6dee9SAndroid Build Coastguard Worker			name: "wrong type",
1263*1fa6dee9SAndroid Build Coastguard Worker			input: `
1264*1fa6dee9SAndroid Build Coastguard Worker				m {
1265*1fa6dee9SAndroid Build Coastguard Worker					int: "foo",
1266*1fa6dee9SAndroid Build Coastguard Worker				}
1267*1fa6dee9SAndroid Build Coastguard Worker			`,
1268*1fa6dee9SAndroid Build Coastguard Worker			output: []interface{}{
1269*1fa6dee9SAndroid Build Coastguard Worker				&struct {
1270*1fa6dee9SAndroid Build Coastguard Worker					Int *int64
1271*1fa6dee9SAndroid Build Coastguard Worker				}{},
1272*1fa6dee9SAndroid Build Coastguard Worker			},
1273*1fa6dee9SAndroid Build Coastguard Worker			errors: []string{
1274*1fa6dee9SAndroid Build Coastguard Worker				`<input>:3:11: can't assign string value to int64 property "int"`,
1275*1fa6dee9SAndroid Build Coastguard Worker			},
1276*1fa6dee9SAndroid Build Coastguard Worker		},
1277*1fa6dee9SAndroid Build Coastguard Worker		{
1278*1fa6dee9SAndroid Build Coastguard Worker			name: "wrong type for map",
1279*1fa6dee9SAndroid Build Coastguard Worker			input: `
1280*1fa6dee9SAndroid Build Coastguard Worker				m {
1281*1fa6dee9SAndroid Build Coastguard Worker					map: "foo",
1282*1fa6dee9SAndroid Build Coastguard Worker				}
1283*1fa6dee9SAndroid Build Coastguard Worker			`,
1284*1fa6dee9SAndroid Build Coastguard Worker			output: []interface{}{
1285*1fa6dee9SAndroid Build Coastguard Worker				&struct {
1286*1fa6dee9SAndroid Build Coastguard Worker					Map struct {
1287*1fa6dee9SAndroid Build Coastguard Worker						S string
1288*1fa6dee9SAndroid Build Coastguard Worker					}
1289*1fa6dee9SAndroid Build Coastguard Worker				}{},
1290*1fa6dee9SAndroid Build Coastguard Worker			},
1291*1fa6dee9SAndroid Build Coastguard Worker			errors: []string{
1292*1fa6dee9SAndroid Build Coastguard Worker				`<input>:3:11: can't assign string value to map property "map"`,
1293*1fa6dee9SAndroid Build Coastguard Worker			},
1294*1fa6dee9SAndroid Build Coastguard Worker		},
1295*1fa6dee9SAndroid Build Coastguard Worker		{
1296*1fa6dee9SAndroid Build Coastguard Worker			name: "wrong type for list",
1297*1fa6dee9SAndroid Build Coastguard Worker			input: `
1298*1fa6dee9SAndroid Build Coastguard Worker				m {
1299*1fa6dee9SAndroid Build Coastguard Worker					list: "foo",
1300*1fa6dee9SAndroid Build Coastguard Worker				}
1301*1fa6dee9SAndroid Build Coastguard Worker			`,
1302*1fa6dee9SAndroid Build Coastguard Worker			output: []interface{}{
1303*1fa6dee9SAndroid Build Coastguard Worker				&struct {
1304*1fa6dee9SAndroid Build Coastguard Worker					List []string
1305*1fa6dee9SAndroid Build Coastguard Worker				}{},
1306*1fa6dee9SAndroid Build Coastguard Worker			},
1307*1fa6dee9SAndroid Build Coastguard Worker			errors: []string{
1308*1fa6dee9SAndroid Build Coastguard Worker				`<input>:3:12: can't assign string value to list property "list"`,
1309*1fa6dee9SAndroid Build Coastguard Worker			},
1310*1fa6dee9SAndroid Build Coastguard Worker		},
1311*1fa6dee9SAndroid Build Coastguard Worker		{
1312*1fa6dee9SAndroid Build Coastguard Worker			name: "wrong type for list of maps",
1313*1fa6dee9SAndroid Build Coastguard Worker			input: `
1314*1fa6dee9SAndroid Build Coastguard Worker				m {
1315*1fa6dee9SAndroid Build Coastguard Worker					map_list: "foo",
1316*1fa6dee9SAndroid Build Coastguard Worker				}
1317*1fa6dee9SAndroid Build Coastguard Worker			`,
1318*1fa6dee9SAndroid Build Coastguard Worker			output: []interface{}{
1319*1fa6dee9SAndroid Build Coastguard Worker				&struct {
1320*1fa6dee9SAndroid Build Coastguard Worker					Map_list []struct {
1321*1fa6dee9SAndroid Build Coastguard Worker						S string
1322*1fa6dee9SAndroid Build Coastguard Worker					}
1323*1fa6dee9SAndroid Build Coastguard Worker				}{},
1324*1fa6dee9SAndroid Build Coastguard Worker			},
1325*1fa6dee9SAndroid Build Coastguard Worker			errors: []string{
1326*1fa6dee9SAndroid Build Coastguard Worker				`<input>:3:16: can't assign string value to list property "map_list"`,
1327*1fa6dee9SAndroid Build Coastguard Worker			},
1328*1fa6dee9SAndroid Build Coastguard Worker		},
1329*1fa6dee9SAndroid Build Coastguard Worker		{
1330*1fa6dee9SAndroid Build Coastguard Worker			name: "non-existent property",
1331*1fa6dee9SAndroid Build Coastguard Worker			input: `
1332*1fa6dee9SAndroid Build Coastguard Worker				m {
1333*1fa6dee9SAndroid Build Coastguard Worker					foo: {
1334*1fa6dee9SAndroid Build Coastguard Worker						foo_prop1: true,
1335*1fa6dee9SAndroid Build Coastguard Worker						foo_prop2: false,
1336*1fa6dee9SAndroid Build Coastguard Worker						foo_prop3: true,
1337*1fa6dee9SAndroid Build Coastguard Worker					},
1338*1fa6dee9SAndroid Build Coastguard Worker					bar: {
1339*1fa6dee9SAndroid Build Coastguard Worker						bar_prop: false,
1340*1fa6dee9SAndroid Build Coastguard Worker					},
1341*1fa6dee9SAndroid Build Coastguard Worker					baz: true,
1342*1fa6dee9SAndroid Build Coastguard Worker					exist: false,
1343*1fa6dee9SAndroid Build Coastguard Worker				}
1344*1fa6dee9SAndroid Build Coastguard Worker			`,
1345*1fa6dee9SAndroid Build Coastguard Worker			output: []interface{}{
1346*1fa6dee9SAndroid Build Coastguard Worker				&struct {
1347*1fa6dee9SAndroid Build Coastguard Worker					Foo struct {
1348*1fa6dee9SAndroid Build Coastguard Worker						Foo_prop1 bool
1349*1fa6dee9SAndroid Build Coastguard Worker					}
1350*1fa6dee9SAndroid Build Coastguard Worker					Exist bool
1351*1fa6dee9SAndroid Build Coastguard Worker				}{},
1352*1fa6dee9SAndroid Build Coastguard Worker			},
1353*1fa6dee9SAndroid Build Coastguard Worker			errors: []string{
1354*1fa6dee9SAndroid Build Coastguard Worker				`<input>:5:16: unrecognized property "foo.foo_prop2"`,
1355*1fa6dee9SAndroid Build Coastguard Worker				`<input>:6:16: unrecognized property "foo.foo_prop3"`,
1356*1fa6dee9SAndroid Build Coastguard Worker				`<input>:9:15: unrecognized property "bar.bar_prop"`,
1357*1fa6dee9SAndroid Build Coastguard Worker				`<input>:11:9: unrecognized property "baz"`,
1358*1fa6dee9SAndroid Build Coastguard Worker			},
1359*1fa6dee9SAndroid Build Coastguard Worker		},
1360*1fa6dee9SAndroid Build Coastguard Worker	}
1361*1fa6dee9SAndroid Build Coastguard Worker
1362*1fa6dee9SAndroid Build Coastguard Worker	for _, testCase := range testCases {
1363*1fa6dee9SAndroid Build Coastguard Worker		t.Run(testCase.name, func(t *testing.T) {
1364*1fa6dee9SAndroid Build Coastguard Worker			r := bytes.NewBufferString(testCase.input)
1365*1fa6dee9SAndroid Build Coastguard Worker			file, errs := parser.ParseAndEval("", r, parser.NewScope(nil))
1366*1fa6dee9SAndroid Build Coastguard Worker			if len(errs) != 0 {
1367*1fa6dee9SAndroid Build Coastguard Worker				t.Errorf("test case: %s", testCase.input)
1368*1fa6dee9SAndroid Build Coastguard Worker				t.Errorf("unexpected parse errors:")
1369*1fa6dee9SAndroid Build Coastguard Worker				for _, err := range errs {
1370*1fa6dee9SAndroid Build Coastguard Worker					t.Errorf("  %s", err)
1371*1fa6dee9SAndroid Build Coastguard Worker				}
1372*1fa6dee9SAndroid Build Coastguard Worker				t.FailNow()
1373*1fa6dee9SAndroid Build Coastguard Worker			}
1374*1fa6dee9SAndroid Build Coastguard Worker
1375*1fa6dee9SAndroid Build Coastguard Worker			for _, def := range file.Defs {
1376*1fa6dee9SAndroid Build Coastguard Worker				module, ok := def.(*parser.Module)
1377*1fa6dee9SAndroid Build Coastguard Worker				if !ok {
1378*1fa6dee9SAndroid Build Coastguard Worker					continue
1379*1fa6dee9SAndroid Build Coastguard Worker				}
1380*1fa6dee9SAndroid Build Coastguard Worker
1381*1fa6dee9SAndroid Build Coastguard Worker				var output []interface{}
1382*1fa6dee9SAndroid Build Coastguard Worker				for _, p := range testCase.output {
1383*1fa6dee9SAndroid Build Coastguard Worker					output = append(output, CloneEmptyProperties(reflect.ValueOf(p)).Interface())
1384*1fa6dee9SAndroid Build Coastguard Worker				}
1385*1fa6dee9SAndroid Build Coastguard Worker
1386*1fa6dee9SAndroid Build Coastguard Worker				_, errs = UnpackProperties(module.Properties, output...)
1387*1fa6dee9SAndroid Build Coastguard Worker
1388*1fa6dee9SAndroid Build Coastguard Worker				printErrors := false
1389*1fa6dee9SAndroid Build Coastguard Worker				for _, expectedErr := range testCase.errors {
1390*1fa6dee9SAndroid Build Coastguard Worker					foundError := false
1391*1fa6dee9SAndroid Build Coastguard Worker					for _, err := range errs {
1392*1fa6dee9SAndroid Build Coastguard Worker						if err.Error() == expectedErr {
1393*1fa6dee9SAndroid Build Coastguard Worker							foundError = true
1394*1fa6dee9SAndroid Build Coastguard Worker						}
1395*1fa6dee9SAndroid Build Coastguard Worker					}
1396*1fa6dee9SAndroid Build Coastguard Worker					if !foundError {
1397*1fa6dee9SAndroid Build Coastguard Worker						t.Errorf("expected error %s", expectedErr)
1398*1fa6dee9SAndroid Build Coastguard Worker						printErrors = true
1399*1fa6dee9SAndroid Build Coastguard Worker					}
1400*1fa6dee9SAndroid Build Coastguard Worker				}
1401*1fa6dee9SAndroid Build Coastguard Worker				if printErrors {
1402*1fa6dee9SAndroid Build Coastguard Worker					t.Errorf("got errors:")
1403*1fa6dee9SAndroid Build Coastguard Worker					for _, err := range errs {
1404*1fa6dee9SAndroid Build Coastguard Worker						t.Errorf("   %s", err.Error())
1405*1fa6dee9SAndroid Build Coastguard Worker					}
1406*1fa6dee9SAndroid Build Coastguard Worker				}
1407*1fa6dee9SAndroid Build Coastguard Worker			}
1408*1fa6dee9SAndroid Build Coastguard Worker		})
1409*1fa6dee9SAndroid Build Coastguard Worker	}
1410*1fa6dee9SAndroid Build Coastguard Worker}
1411*1fa6dee9SAndroid Build Coastguard Worker
1412*1fa6dee9SAndroid Build Coastguard Workerfunc BenchmarkUnpackProperties(b *testing.B) {
1413*1fa6dee9SAndroid Build Coastguard Worker	run := func(b *testing.B, props []interface{}, input string) {
1414*1fa6dee9SAndroid Build Coastguard Worker		b.ReportAllocs()
1415*1fa6dee9SAndroid Build Coastguard Worker		b.StopTimer()
1416*1fa6dee9SAndroid Build Coastguard Worker		r := bytes.NewBufferString(input)
1417*1fa6dee9SAndroid Build Coastguard Worker		file, errs := parser.ParseAndEval("", r, parser.NewScope(nil))
1418*1fa6dee9SAndroid Build Coastguard Worker		if len(errs) != 0 {
1419*1fa6dee9SAndroid Build Coastguard Worker			b.Errorf("test case: %s", input)
1420*1fa6dee9SAndroid Build Coastguard Worker			b.Errorf("unexpected parse errors:")
1421*1fa6dee9SAndroid Build Coastguard Worker			for _, err := range errs {
1422*1fa6dee9SAndroid Build Coastguard Worker				b.Errorf("  %s", err)
1423*1fa6dee9SAndroid Build Coastguard Worker			}
1424*1fa6dee9SAndroid Build Coastguard Worker			b.FailNow()
1425*1fa6dee9SAndroid Build Coastguard Worker		}
1426*1fa6dee9SAndroid Build Coastguard Worker
1427*1fa6dee9SAndroid Build Coastguard Worker		for i := 0; i < b.N; i++ {
1428*1fa6dee9SAndroid Build Coastguard Worker			for _, def := range file.Defs {
1429*1fa6dee9SAndroid Build Coastguard Worker				module, ok := def.(*parser.Module)
1430*1fa6dee9SAndroid Build Coastguard Worker				if !ok {
1431*1fa6dee9SAndroid Build Coastguard Worker					continue
1432*1fa6dee9SAndroid Build Coastguard Worker				}
1433*1fa6dee9SAndroid Build Coastguard Worker
1434*1fa6dee9SAndroid Build Coastguard Worker				var output []interface{}
1435*1fa6dee9SAndroid Build Coastguard Worker				for _, p := range props {
1436*1fa6dee9SAndroid Build Coastguard Worker					output = append(output, CloneProperties(reflect.ValueOf(p)).Interface())
1437*1fa6dee9SAndroid Build Coastguard Worker				}
1438*1fa6dee9SAndroid Build Coastguard Worker
1439*1fa6dee9SAndroid Build Coastguard Worker				b.StartTimer()
1440*1fa6dee9SAndroid Build Coastguard Worker				_, errs = UnpackProperties(module.Properties, output...)
1441*1fa6dee9SAndroid Build Coastguard Worker				b.StopTimer()
1442*1fa6dee9SAndroid Build Coastguard Worker				if len(errs) > 0 {
1443*1fa6dee9SAndroid Build Coastguard Worker					b.Errorf("unexpected unpack errors:")
1444*1fa6dee9SAndroid Build Coastguard Worker					for _, err := range errs {
1445*1fa6dee9SAndroid Build Coastguard Worker						b.Errorf("  %s", err)
1446*1fa6dee9SAndroid Build Coastguard Worker					}
1447*1fa6dee9SAndroid Build Coastguard Worker				}
1448*1fa6dee9SAndroid Build Coastguard Worker			}
1449*1fa6dee9SAndroid Build Coastguard Worker		}
1450*1fa6dee9SAndroid Build Coastguard Worker	}
1451*1fa6dee9SAndroid Build Coastguard Worker
1452*1fa6dee9SAndroid Build Coastguard Worker	b.Run("basic", func(b *testing.B) {
1453*1fa6dee9SAndroid Build Coastguard Worker		props := []interface{}{
1454*1fa6dee9SAndroid Build Coastguard Worker			&struct {
1455*1fa6dee9SAndroid Build Coastguard Worker				Nested struct {
1456*1fa6dee9SAndroid Build Coastguard Worker					S string
1457*1fa6dee9SAndroid Build Coastguard Worker				}
1458*1fa6dee9SAndroid Build Coastguard Worker			}{},
1459*1fa6dee9SAndroid Build Coastguard Worker		}
1460*1fa6dee9SAndroid Build Coastguard Worker		bp := `
1461*1fa6dee9SAndroid Build Coastguard Worker			m {
1462*1fa6dee9SAndroid Build Coastguard Worker				nested: {
1463*1fa6dee9SAndroid Build Coastguard Worker					s: "abc",
1464*1fa6dee9SAndroid Build Coastguard Worker				},
1465*1fa6dee9SAndroid Build Coastguard Worker			}
1466*1fa6dee9SAndroid Build Coastguard Worker		`
1467*1fa6dee9SAndroid Build Coastguard Worker		run(b, props, bp)
1468*1fa6dee9SAndroid Build Coastguard Worker	})
1469*1fa6dee9SAndroid Build Coastguard Worker
1470*1fa6dee9SAndroid Build Coastguard Worker	b.Run("interface", func(b *testing.B) {
1471*1fa6dee9SAndroid Build Coastguard Worker		props := []interface{}{
1472*1fa6dee9SAndroid Build Coastguard Worker			&struct {
1473*1fa6dee9SAndroid Build Coastguard Worker				Nested interface{}
1474*1fa6dee9SAndroid Build Coastguard Worker			}{
1475*1fa6dee9SAndroid Build Coastguard Worker				Nested: (*struct {
1476*1fa6dee9SAndroid Build Coastguard Worker					S string
1477*1fa6dee9SAndroid Build Coastguard Worker				})(nil),
1478*1fa6dee9SAndroid Build Coastguard Worker			},
1479*1fa6dee9SAndroid Build Coastguard Worker		}
1480*1fa6dee9SAndroid Build Coastguard Worker		bp := `
1481*1fa6dee9SAndroid Build Coastguard Worker			m {
1482*1fa6dee9SAndroid Build Coastguard Worker				nested: {
1483*1fa6dee9SAndroid Build Coastguard Worker					s: "abc",
1484*1fa6dee9SAndroid Build Coastguard Worker				},
1485*1fa6dee9SAndroid Build Coastguard Worker			}
1486*1fa6dee9SAndroid Build Coastguard Worker		`
1487*1fa6dee9SAndroid Build Coastguard Worker		run(b, props, bp)
1488*1fa6dee9SAndroid Build Coastguard Worker	})
1489*1fa6dee9SAndroid Build Coastguard Worker
1490*1fa6dee9SAndroid Build Coastguard Worker	b.Run("many", func(b *testing.B) {
1491*1fa6dee9SAndroid Build Coastguard Worker		props := []interface{}{
1492*1fa6dee9SAndroid Build Coastguard Worker			&struct {
1493*1fa6dee9SAndroid Build Coastguard Worker				A *string
1494*1fa6dee9SAndroid Build Coastguard Worker				B *string
1495*1fa6dee9SAndroid Build Coastguard Worker				C *string
1496*1fa6dee9SAndroid Build Coastguard Worker				D *string
1497*1fa6dee9SAndroid Build Coastguard Worker				E *string
1498*1fa6dee9SAndroid Build Coastguard Worker				F *string
1499*1fa6dee9SAndroid Build Coastguard Worker				G *string
1500*1fa6dee9SAndroid Build Coastguard Worker				H *string
1501*1fa6dee9SAndroid Build Coastguard Worker				I *string
1502*1fa6dee9SAndroid Build Coastguard Worker				J *string
1503*1fa6dee9SAndroid Build Coastguard Worker			}{},
1504*1fa6dee9SAndroid Build Coastguard Worker		}
1505*1fa6dee9SAndroid Build Coastguard Worker		bp := `
1506*1fa6dee9SAndroid Build Coastguard Worker			m {
1507*1fa6dee9SAndroid Build Coastguard Worker				a: "a",
1508*1fa6dee9SAndroid Build Coastguard Worker				b: "b",
1509*1fa6dee9SAndroid Build Coastguard Worker				c: "c",
1510*1fa6dee9SAndroid Build Coastguard Worker				d: "d",
1511*1fa6dee9SAndroid Build Coastguard Worker				e: "e",
1512*1fa6dee9SAndroid Build Coastguard Worker				f: "f",
1513*1fa6dee9SAndroid Build Coastguard Worker				g: "g",
1514*1fa6dee9SAndroid Build Coastguard Worker				h: "h",
1515*1fa6dee9SAndroid Build Coastguard Worker				i: "i",
1516*1fa6dee9SAndroid Build Coastguard Worker				j: "j",
1517*1fa6dee9SAndroid Build Coastguard Worker			}
1518*1fa6dee9SAndroid Build Coastguard Worker		`
1519*1fa6dee9SAndroid Build Coastguard Worker		run(b, props, bp)
1520*1fa6dee9SAndroid Build Coastguard Worker	})
1521*1fa6dee9SAndroid Build Coastguard Worker
1522*1fa6dee9SAndroid Build Coastguard Worker	b.Run("deep", func(b *testing.B) {
1523*1fa6dee9SAndroid Build Coastguard Worker		props := []interface{}{
1524*1fa6dee9SAndroid Build Coastguard Worker			&struct {
1525*1fa6dee9SAndroid Build Coastguard Worker				Nested struct {
1526*1fa6dee9SAndroid Build Coastguard Worker					Nested struct {
1527*1fa6dee9SAndroid Build Coastguard Worker						Nested struct {
1528*1fa6dee9SAndroid Build Coastguard Worker							Nested struct {
1529*1fa6dee9SAndroid Build Coastguard Worker								Nested struct {
1530*1fa6dee9SAndroid Build Coastguard Worker									Nested struct {
1531*1fa6dee9SAndroid Build Coastguard Worker										Nested struct {
1532*1fa6dee9SAndroid Build Coastguard Worker											Nested struct {
1533*1fa6dee9SAndroid Build Coastguard Worker												Nested struct {
1534*1fa6dee9SAndroid Build Coastguard Worker													Nested struct {
1535*1fa6dee9SAndroid Build Coastguard Worker														S string
1536*1fa6dee9SAndroid Build Coastguard Worker													}
1537*1fa6dee9SAndroid Build Coastguard Worker												}
1538*1fa6dee9SAndroid Build Coastguard Worker											}
1539*1fa6dee9SAndroid Build Coastguard Worker										}
1540*1fa6dee9SAndroid Build Coastguard Worker									}
1541*1fa6dee9SAndroid Build Coastguard Worker								}
1542*1fa6dee9SAndroid Build Coastguard Worker							}
1543*1fa6dee9SAndroid Build Coastguard Worker						}
1544*1fa6dee9SAndroid Build Coastguard Worker					}
1545*1fa6dee9SAndroid Build Coastguard Worker				}
1546*1fa6dee9SAndroid Build Coastguard Worker			}{},
1547*1fa6dee9SAndroid Build Coastguard Worker		}
1548*1fa6dee9SAndroid Build Coastguard Worker		bp := `
1549*1fa6dee9SAndroid Build Coastguard Worker			m {
1550*1fa6dee9SAndroid Build Coastguard Worker				nested: { nested: { nested: { nested: { nested: {
1551*1fa6dee9SAndroid Build Coastguard Worker					nested: { nested: { nested: { nested: { nested: {
1552*1fa6dee9SAndroid Build Coastguard Worker						s: "abc",
1553*1fa6dee9SAndroid Build Coastguard Worker					}, }, }, }, },
1554*1fa6dee9SAndroid Build Coastguard Worker				}, }, }, }, },
1555*1fa6dee9SAndroid Build Coastguard Worker			}
1556*1fa6dee9SAndroid Build Coastguard Worker		`
1557*1fa6dee9SAndroid Build Coastguard Worker		run(b, props, bp)
1558*1fa6dee9SAndroid Build Coastguard Worker	})
1559*1fa6dee9SAndroid Build Coastguard Worker
1560*1fa6dee9SAndroid Build Coastguard Worker	b.Run("mix", func(b *testing.B) {
1561*1fa6dee9SAndroid Build Coastguard Worker		props := []interface{}{
1562*1fa6dee9SAndroid Build Coastguard Worker			&struct {
1563*1fa6dee9SAndroid Build Coastguard Worker				Name     string
1564*1fa6dee9SAndroid Build Coastguard Worker				Flag     bool
1565*1fa6dee9SAndroid Build Coastguard Worker				Settings []string
1566*1fa6dee9SAndroid Build Coastguard Worker				Perarch  *struct {
1567*1fa6dee9SAndroid Build Coastguard Worker					Arm   string
1568*1fa6dee9SAndroid Build Coastguard Worker					Arm64 string
1569*1fa6dee9SAndroid Build Coastguard Worker				}
1570*1fa6dee9SAndroid Build Coastguard Worker				Configvars []struct {
1571*1fa6dee9SAndroid Build Coastguard Worker					Name   string
1572*1fa6dee9SAndroid Build Coastguard Worker					Values []string
1573*1fa6dee9SAndroid Build Coastguard Worker				}
1574*1fa6dee9SAndroid Build Coastguard Worker			}{},
1575*1fa6dee9SAndroid Build Coastguard Worker		}
1576*1fa6dee9SAndroid Build Coastguard Worker		bp := `
1577*1fa6dee9SAndroid Build Coastguard Worker			m {
1578*1fa6dee9SAndroid Build Coastguard Worker				name: "mymodule",
1579*1fa6dee9SAndroid Build Coastguard Worker				flag: true,
1580*1fa6dee9SAndroid Build Coastguard Worker				settings: ["foo1", "foo2", "foo3",],
1581*1fa6dee9SAndroid Build Coastguard Worker				perarch: {
1582*1fa6dee9SAndroid Build Coastguard Worker					arm: "32",
1583*1fa6dee9SAndroid Build Coastguard Worker					arm64: "64",
1584*1fa6dee9SAndroid Build Coastguard Worker				},
1585*1fa6dee9SAndroid Build Coastguard Worker				configvars: [
1586*1fa6dee9SAndroid Build Coastguard Worker					{ name: "var1", values: ["var1:1", "var1:2", ], },
1587*1fa6dee9SAndroid Build Coastguard Worker					{ name: "var2", values: ["var2:1", "var2:2", ], },
1588*1fa6dee9SAndroid Build Coastguard Worker				],
1589*1fa6dee9SAndroid Build Coastguard Worker            }
1590*1fa6dee9SAndroid Build Coastguard Worker        `
1591*1fa6dee9SAndroid Build Coastguard Worker		run(b, props, bp)
1592*1fa6dee9SAndroid Build Coastguard Worker	})
1593*1fa6dee9SAndroid Build Coastguard Worker}
1594*1fa6dee9SAndroid Build Coastguard Worker
1595*1fa6dee9SAndroid Build Coastguard Workerfunc TestRemoveUnnecessaryUnusedNames(t *testing.T) {
1596*1fa6dee9SAndroid Build Coastguard Worker	testCases := []struct {
1597*1fa6dee9SAndroid Build Coastguard Worker		name   string
1598*1fa6dee9SAndroid Build Coastguard Worker		input  []string
1599*1fa6dee9SAndroid Build Coastguard Worker		output []string
1600*1fa6dee9SAndroid Build Coastguard Worker	}{
1601*1fa6dee9SAndroid Build Coastguard Worker		{
1602*1fa6dee9SAndroid Build Coastguard Worker			name:   "no unused names",
1603*1fa6dee9SAndroid Build Coastguard Worker			input:  []string{},
1604*1fa6dee9SAndroid Build Coastguard Worker			output: []string{},
1605*1fa6dee9SAndroid Build Coastguard Worker		},
1606*1fa6dee9SAndroid Build Coastguard Worker		{
1607*1fa6dee9SAndroid Build Coastguard Worker			name:   "only one unused name",
1608*1fa6dee9SAndroid Build Coastguard Worker			input:  []string{"a.b.c"},
1609*1fa6dee9SAndroid Build Coastguard Worker			output: []string{"a.b.c"},
1610*1fa6dee9SAndroid Build Coastguard Worker		},
1611*1fa6dee9SAndroid Build Coastguard Worker		{
1612*1fa6dee9SAndroid Build Coastguard Worker			name:   "unused names in a chain",
1613*1fa6dee9SAndroid Build Coastguard Worker			input:  []string{"a", "a.b", "a.b.c"},
1614*1fa6dee9SAndroid Build Coastguard Worker			output: []string{"a.b.c"},
1615*1fa6dee9SAndroid Build Coastguard Worker		},
1616*1fa6dee9SAndroid Build Coastguard Worker		{
1617*1fa6dee9SAndroid Build Coastguard Worker			name:   "unused names unrelated",
1618*1fa6dee9SAndroid Build Coastguard Worker			input:  []string{"a.b.c", "s.t", "x.y"},
1619*1fa6dee9SAndroid Build Coastguard Worker			output: []string{"a.b.c", "s.t", "x.y"},
1620*1fa6dee9SAndroid Build Coastguard Worker		},
1621*1fa6dee9SAndroid Build Coastguard Worker		{
1622*1fa6dee9SAndroid Build Coastguard Worker			name:   "unused names partially related one",
1623*1fa6dee9SAndroid Build Coastguard Worker			input:  []string{"a.b", "a.b.c", "a.b.d"},
1624*1fa6dee9SAndroid Build Coastguard Worker			output: []string{"a.b.c", "a.b.d"},
1625*1fa6dee9SAndroid Build Coastguard Worker		},
1626*1fa6dee9SAndroid Build Coastguard Worker		{
1627*1fa6dee9SAndroid Build Coastguard Worker			name:   "unused names partially related two",
1628*1fa6dee9SAndroid Build Coastguard Worker			input:  []string{"a", "a.b.c", "a.c"},
1629*1fa6dee9SAndroid Build Coastguard Worker			output: []string{"a.b.c", "a.c"},
1630*1fa6dee9SAndroid Build Coastguard Worker		},
1631*1fa6dee9SAndroid Build Coastguard Worker		{
1632*1fa6dee9SAndroid Build Coastguard Worker			name:   "unused names partially related three",
1633*1fa6dee9SAndroid Build Coastguard Worker			input:  []string{"a.b.c", "b.c", "c"},
1634*1fa6dee9SAndroid Build Coastguard Worker			output: []string{"a.b.c", "b.c", "c"},
1635*1fa6dee9SAndroid Build Coastguard Worker		},
1636*1fa6dee9SAndroid Build Coastguard Worker	}
1637*1fa6dee9SAndroid Build Coastguard Worker	for _, testCase := range testCases {
1638*1fa6dee9SAndroid Build Coastguard Worker		t.Run(testCase.name, func(t *testing.T) {
1639*1fa6dee9SAndroid Build Coastguard Worker			simplifiedNames := removeUnnecessaryUnusedNames(testCase.input)
1640*1fa6dee9SAndroid Build Coastguard Worker			if !reflect.DeepEqual(simplifiedNames, testCase.output) {
1641*1fa6dee9SAndroid Build Coastguard Worker				t.Errorf("test case: %s", testCase.name)
1642*1fa6dee9SAndroid Build Coastguard Worker				t.Errorf("  input: %s", testCase.input)
1643*1fa6dee9SAndroid Build Coastguard Worker				t.Errorf("  expect: %s", testCase.output)
1644*1fa6dee9SAndroid Build Coastguard Worker				t.Errorf("  got: %s", simplifiedNames)
1645*1fa6dee9SAndroid Build Coastguard Worker			}
1646*1fa6dee9SAndroid Build Coastguard Worker		})
1647*1fa6dee9SAndroid Build Coastguard Worker	}
1648*1fa6dee9SAndroid Build Coastguard Worker}
1649