• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2020 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package main
16
17import (
18	"strings"
19	"testing"
20
21	"github.com/google/blueprint/parser"
22	"github.com/google/blueprint/proptools"
23)
24
25var testCases = []struct {
26	name           string
27	input          string
28	output         string
29	property       string
30	addSet         string
31	removeSet      string
32	addLiteral     *string
33	setString      *string
34	removeProperty bool
35}{
36	{
37		name: "add",
38		input: `
39			cc_foo {
40				name: "foo",
41			}
42		`,
43		output: `
44			cc_foo {
45				name: "foo",
46				deps: ["bar"],
47			}
48		`,
49		property: "deps",
50		addSet:   "bar",
51	},
52	{
53		name: "remove",
54		input: `
55			cc_foo {
56				name: "foo",
57				deps: ["bar"],
58			}
59		`,
60		output: `
61			cc_foo {
62				name: "foo",
63				deps: [],
64			}
65		`,
66		property:  "deps",
67		removeSet: "bar",
68	},
69	{
70		name: "nested add",
71		input: `
72			cc_foo {
73				name: "foo",
74			}
75		`,
76		output: `
77			cc_foo {
78				name: "foo",
79				arch: {
80					arm: {
81						deps: [
82							"dep2",
83							"nested_dep",],
84					},
85				},
86			}
87		`,
88		property: "arch.arm.deps",
89		addSet:   "nested_dep,dep2",
90	},
91	{
92		name: "nested remove",
93		input: `
94			cc_foo {
95				name: "foo",
96				arch: {
97					arm: {
98						deps: [
99							"dep2",
100							"nested_dep",
101						],
102					},
103				},
104			}
105		`,
106		output: `
107			cc_foo {
108				name: "foo",
109				arch: {
110					arm: {
111						deps: [
112						],
113					},
114				},
115			}
116		`,
117		property:  "arch.arm.deps",
118		removeSet: "nested_dep,dep2",
119	},
120	{
121		name: "add existing",
122		input: `
123			cc_foo {
124				name: "foo",
125				arch: {
126					arm: {
127						deps: [
128							"nested_dep",
129							"dep2",
130						],
131					},
132				},
133			}
134		`,
135		output: `
136			cc_foo {
137				name: "foo",
138				arch: {
139					arm: {
140						deps: [
141							"nested_dep",
142							"dep2",
143						],
144					},
145				},
146			}
147		`,
148		property: "arch.arm.deps",
149		addSet:   "dep2,dep2",
150	},
151	{
152		name: "remove missing",
153		input: `
154			cc_foo {
155				name: "foo",
156				arch: {
157					arm: {
158						deps: [
159							"nested_dep",
160							"dep2",
161						],
162					},
163				},
164			}
165		`,
166		output: `
167			cc_foo {
168				name: "foo",
169				arch: {
170					arm: {
171						deps: [
172							"nested_dep",
173							"dep2",
174						],
175					},
176				},
177			}
178		`,
179		property:  "arch.arm.deps",
180		removeSet: "dep3,dep4",
181	},
182	{
183		name: "remove non existent",
184		input: `
185			cc_foo {
186				name: "foo",
187			}
188		`,
189		output: `
190			cc_foo {
191				name: "foo",
192			}
193		`,
194		property:  "deps",
195		removeSet: "bar",
196	},
197	{
198		name: "remove non existent nested",
199		input: `
200			cc_foo {
201				name: "foo",
202				arch: {},
203			}
204		`,
205		output: `
206			cc_foo {
207				name: "foo",
208				arch: {},
209			}
210		`,
211		property:  "arch.arm.deps",
212		removeSet: "dep3,dep4",
213	},
214	{
215		name: "add numeric sorted",
216		input: `
217			cc_foo {
218				name: "foo",
219				versions: ["1", "2"],
220			}
221		`,
222		output: `
223			cc_foo {
224				name: "foo",
225				versions: [
226					"1",
227					"2",
228					"10",
229				],
230			}
231		`,
232		property: "versions",
233		addSet:   "10",
234	},
235	{
236		name: "add mixed sorted",
237		input: `
238			cc_foo {
239				name: "foo",
240				deps: ["bar-v1-bar", "bar-v2-bar"],
241			}
242		`,
243		output: `
244			cc_foo {
245				name: "foo",
246				deps: [
247					"bar-v1-bar",
248					"bar-v2-bar",
249					"bar-v10-bar",
250				],
251			}
252		`,
253		property: "deps",
254		addSet:   "bar-v10-bar",
255	},
256	{
257		name:  "add a struct with literal",
258		input: `cc_foo {name: "foo"}`,
259		output: `cc_foo {
260    name: "foo",
261    structs: [
262        {
263            version: "1",
264            imports: [
265                "bar1",
266                "bar2",
267            ],
268        },
269    ],
270}
271`,
272		property:   "structs",
273		addLiteral: proptools.StringPtr(`{version: "1", imports: ["bar1", "bar2"]}`),
274	},
275	{
276		name: "set string",
277		input: `
278			cc_foo {
279				name: "foo",
280			}
281		`,
282		output: `
283			cc_foo {
284				name: "foo",
285				foo: "bar",
286			}
287		`,
288		property:  "foo",
289		setString: proptools.StringPtr("bar"),
290	},
291	{
292		name: "set existing string",
293		input: `
294			cc_foo {
295				name: "foo",
296				foo: "baz",
297			}
298		`,
299		output: `
300			cc_foo {
301				name: "foo",
302				foo: "bar",
303			}
304		`,
305		property:  "foo",
306		setString: proptools.StringPtr("bar"),
307	},
308	{
309		name: "remove existing property",
310		input: `
311			cc_foo {
312				name: "foo",
313				foo: "baz",
314			}
315		`,
316		output: `
317			cc_foo {
318				name: "foo",
319			}
320		`,
321		property:       "foo",
322		removeProperty: true,
323	}, {
324		name: "remove nested property",
325		input: `
326		cc_foo {
327			name: "foo",
328			foo: {
329				bar: "baz",
330			},
331		}
332	`,
333		output: `
334		cc_foo {
335			name: "foo",
336			foo: {},
337		}
338	`,
339		property:       "foo.bar",
340		removeProperty: true,
341	}, {
342		name: "remove non-existing property",
343		input: `
344			cc_foo {
345				name: "foo",
346				foo: "baz",
347			}
348		`,
349		output: `
350			cc_foo {
351				name: "foo",
352				foo: "baz",
353			}
354		`,
355		property:       "bar",
356		removeProperty: true,
357	},
358}
359
360func simplifyModuleDefinition(def string) string {
361	var result string
362	for _, line := range strings.Split(def, "\n") {
363		result += strings.TrimSpace(line)
364	}
365	return result
366}
367
368func TestProcessModule(t *testing.T) {
369	for i, testCase := range testCases {
370		t.Run(testCase.name, func(t *testing.T) {
371			targetedProperty.Set(testCase.property)
372			addIdents.Set(testCase.addSet)
373			removeIdents.Set(testCase.removeSet)
374			removeProperty = &testCase.removeProperty
375			setString = testCase.setString
376			addLiteral = testCase.addLiteral
377
378			inAst, errs := parser.ParseAndEval("", strings.NewReader(testCase.input), parser.NewScope(nil))
379			if len(errs) > 0 {
380				for _, err := range errs {
381					t.Errorf("  %s", err)
382				}
383				t.Errorf("failed to parse:")
384				t.Errorf("%+v", testCase)
385				t.FailNow()
386			}
387
388			if inModule, ok := inAst.Defs[0].(*parser.Module); !ok {
389				t.Fatalf("  input must only contain a single module definition: %s", testCase.input)
390			} else {
391				_, errs := processModule(inModule, "", inAst)
392				if len(errs) > 0 {
393					t.Errorf("test case %d:", i)
394					for _, err := range errs {
395						t.Errorf("  %s", err)
396					}
397				}
398				inModuleText, _ := parser.Print(inAst)
399				inModuleString := string(inModuleText)
400				if simplifyModuleDefinition(inModuleString) != simplifyModuleDefinition(testCase.output) {
401					t.Errorf("test case %d:", i)
402					t.Errorf("expected module definition:")
403					t.Errorf("  %s", testCase.output)
404					t.Errorf("actual module definition:")
405					t.Errorf("  %s", inModuleString)
406				}
407			}
408		})
409	}
410
411}
412