• 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 csuite
16
17import (
18	"android/soong/android"
19	"io/ioutil"
20	"os"
21	"strings"
22	"testing"
23)
24
25var buildDir string
26
27func TestBpContainsTestHostPropsThrowsError(t *testing.T) {
28	ctx, _ := createContextAndConfig(t, `
29		csuite_test {
30			name: "plan_name",
31			test_config_template: "config_template.xml",
32			data_native_bins: "bin"
33		}
34	`)
35
36	_, errs := ctx.ParseBlueprintsFiles("Android.bp")
37
38	android.FailIfNoMatchingErrors(t, `unrecognized property`, errs)
39}
40
41func TestBpContainsManifestThrowsError(t *testing.T) {
42	ctx, _ := createContextAndConfig(t, `
43		csuite_test {
44			name: "plan_name",
45			test_config_template: "config_template.xml",
46			test_config: "AndroidTest.xml"
47		}
48	`)
49
50	_, errs := ctx.ParseBlueprintsFiles("Android.bp")
51
52	android.FailIfNoMatchingErrors(t, `unrecognized property`, errs)
53}
54
55func TestBpMissingNameThrowsError(t *testing.T) {
56	ctx, _ := createContextAndConfig(t, `
57		csuite_test {
58			test_config_template: "config_template.xml"
59		}
60	`)
61
62	_, errs := ctx.ParseBlueprintsFiles("Android.bp")
63
64	android.FailIfNoMatchingErrors(t, `'name' is missing`, errs)
65}
66
67func TestBpMissingTemplatePathThrowsError(t *testing.T) {
68	ctx, config := createContextAndConfig(t, `
69		csuite_test {
70			name: "plan_name",
71		}
72	`)
73
74	ctx.ParseBlueprintsFiles("Android.bp")
75	_, errs := ctx.PrepareBuildActions(config)
76
77	android.FailIfNoMatchingErrors(t, `'test_config_template' is missing`, errs)
78}
79
80func TestBpTemplatePathUnexpectedFileExtensionThrowsError(t *testing.T) {
81	ctx, config := createContextAndConfig(t, `
82		csuite_test {
83			name: "plan_name",
84			test_config_template: "config_template.xml.template"
85		}
86	`)
87
88	ctx.ParseBlueprintsFiles("Android.bp")
89	_, errs := ctx.PrepareBuildActions(config)
90
91	android.FailIfNoMatchingErrors(t, `Config template path should ends with .xml`, errs)
92}
93
94func TestBpExtraTemplateUnexpectedFileExtensionThrowsError(t *testing.T) {
95	ctx, config := createContextAndConfig(t, `
96		csuite_test {
97			name: "plan_name",
98			test_config_template: "config_template.xml",
99			extra_test_config_templates: ["another.xml.template"]
100		}
101	`)
102
103	ctx.ParseBlueprintsFiles("Android.bp")
104	_, errs := ctx.PrepareBuildActions(config)
105
106	android.FailIfNoMatchingErrors(t, `Config template path should ends with .xml`, errs)
107}
108
109func TestBpValidExtraTemplateDoesNotThrowError(t *testing.T) {
110	ctx, config := createContextAndConfig(t, `
111		csuite_test {
112			name: "plan_name",
113			test_config_template: "config_template.xml",
114			extra_test_config_templates: ["another.xml"]
115		}
116	`)
117
118	parseBpAndBuild(t, ctx, config)
119}
120
121func TestValidBpMissingPlanIncludeDoesNotThrowError(t *testing.T) {
122	ctx, config := createContextAndConfig(t, `
123		csuite_test {
124			name: "plan_name",
125			test_config_template: "config_template.xml"
126		}
127	`)
128
129	parseBpAndBuild(t, ctx, config)
130}
131
132func TestValidBpMissingPlanIncludeGeneratesPlanXmlWithoutPlaceholders(t *testing.T) {
133	ctx, config := createContextAndConfig(t, `
134		csuite_test {
135			name: "plan_name",
136			test_config_template: "config_template.xml"
137		}
138	`)
139
140	parseBpAndBuild(t, ctx, config)
141
142	module := ctx.ModuleForTests("plan_name", config.BuildOS.String()+"_common")
143	content := android.ContentFromFileRuleForTests(t, module.Output("config/plan_name.xml"))
144	if strings.Contains(content, "{") || strings.Contains(content, "}") {
145		t.Errorf("The generated plan name contains a placeholder: %s", content)
146	}
147}
148
149func TestGeneratedTestPlanContainsPlanName(t *testing.T) {
150	ctx, config := createContextAndConfig(t, `
151		csuite_test {
152			name: "plan_name",
153			test_config_template: "config_template.xml"
154		}
155	`)
156
157	parseBpAndBuild(t, ctx, config)
158
159	module := ctx.ModuleForTests("plan_name", config.BuildOS.String()+"_common")
160	content := android.ContentFromFileRuleForTests(t, module.Output("config/plan_name.xml"))
161	if !strings.Contains(content, "plan_name") {
162		t.Errorf("The plan name is missing from the generated plan: %s", content)
163	}
164}
165
166func TestGeneratedTestPlanContainsTemplatePath(t *testing.T) {
167	ctx, config := createContextAndConfig(t, `
168		csuite_test {
169			name: "plan_name",
170			test_config_template: "config_template.xml"
171		}
172	`)
173
174	parseBpAndBuild(t, ctx, config)
175
176	module := ctx.ModuleForTests("plan_name", config.BuildOS.String()+"_common")
177	content := android.ContentFromFileRuleForTests(t, module.Output("config/plan_name.xml"))
178	if !strings.Contains(content, "config/plan_name/config_template.xml.template") {
179		t.Errorf("The template path is missing from the generated plan: %s", content)
180	}
181}
182
183func TestGeneratedTestPlanContainsExtraTemplatePath(t *testing.T) {
184	ctx, config := createContextAndConfig(t, `
185		csuite_test {
186			name: "plan_name",
187			test_config_template: "config_template.xml",
188			extra_test_config_templates: ["extra.xml"]
189		}
190	`)
191
192	parseBpAndBuild(t, ctx, config)
193
194	module := ctx.ModuleForTests("plan_name", config.BuildOS.String()+"_common")
195	content := android.ContentFromFileRuleForTests(t, module.Output("config/plan_name.xml"))
196	if !strings.Contains(content, "config/plan_name/extra.xml.template") {
197		t.Errorf("The extra template path is missing from the generated plan: %s", content)
198	}
199	if !strings.Contains(content, "extra-templates") {
200		t.Errorf("The extra-templates param is missing from the generated plan: %s", content)
201	}
202}
203
204func TestGeneratedTestPlanDoesNotContainExtraTemplatePath(t *testing.T) {
205	ctx, config := createContextAndConfig(t, `
206		csuite_test {
207			name: "plan_name",
208			test_config_template: "config_template.xml"
209		}
210	`)
211
212	parseBpAndBuild(t, ctx, config)
213
214	module := ctx.ModuleForTests("plan_name", config.BuildOS.String()+"_common")
215	content := android.ContentFromFileRuleForTests(t, module.Output("config/plan_name.xml"))
216	if strings.Contains(content, "extra-templates") {
217		t.Errorf("The extra-templates param should not be included in the generated plan: %s", content)
218	}
219}
220
221func TestTemplateFileCopyRuleExists(t *testing.T) {
222	ctx, config := createContextAndConfig(t, `
223		csuite_test {
224			name: "plan_name",
225			test_config_template: "config_template.xml"
226		}
227	`)
228
229	parseBpAndBuild(t, ctx, config)
230
231	params := ctx.ModuleForTests("plan_name", config.BuildOS.String()+"_common").Rule("CSuite")
232	assertFileCopyRuleExists(t, params, "config_template.xml", "config/plan_name/config_template.xml.template")
233}
234
235func TestExtraTemplateFileCopyRuleExists(t *testing.T) {
236	ctx, config := createContextAndConfig(t, `
237		csuite_test {
238			name: "plan_name",
239			test_config_template: "config_template.xml",
240			extra_test_config_templates: ["extra.xml"]
241		}
242	`)
243
244	parseBpAndBuild(t, ctx, config)
245
246	params := ctx.ModuleForTests("plan_name", config.BuildOS.String()+"_common").Rule("CSuite")
247	assertFileCopyRuleExists(t, params, "config_template.xml", "config/plan_name/extra.xml.template")
248}
249
250func TestGeneratedTestPlanContainsPlanInclude(t *testing.T) {
251	ctx, config := createContextAndConfig(t, `
252		csuite_test {
253			name: "plan_name",
254			test_config_template: "config_template.xml",
255			test_plan_include: "include.xml"
256		}
257	`)
258
259	parseBpAndBuild(t, ctx, config)
260
261	module := ctx.ModuleForTests("plan_name", config.BuildOS.String()+"_common")
262	content := android.ContentFromFileRuleForTests(t, module.Output("config/plan_name.xml"))
263	if !strings.Contains(content, `"includes/plan_name.xml"`) {
264		t.Errorf("The plan include path is missing from the generated plan: %s", content)
265	}
266}
267
268func TestPlanIncludeFileCopyRuleExists(t *testing.T) {
269	ctx, config := createContextAndConfig(t, `
270		csuite_test {
271			name: "plan_name",
272			test_config_template: "config_template.xml",
273			test_plan_include: "include.xml"
274		}
275	`)
276
277	parseBpAndBuild(t, ctx, config)
278
279	params := ctx.ModuleForTests("plan_name", config.BuildOS.String()+"_common").Rule("CSuite")
280	assertFileCopyRuleExists(t, params, "include.xml", "config/includes/plan_name.xml")
281}
282
283func TestMain(m *testing.M) {
284	run := func() int {
285		setUp()
286		defer tearDown()
287
288		return m.Run()
289	}
290
291	os.Exit(run())
292}
293
294func parseBpAndBuild(t *testing.T, ctx *android.TestContext, config android.Config) {
295	_, parsingErrs := ctx.ParseBlueprintsFiles("Android.bp")
296	_, buildErrs := ctx.PrepareBuildActions(config)
297
298	android.FailIfErrored(t, parsingErrs)
299	android.FailIfErrored(t, buildErrs)
300}
301
302func assertFileCopyRuleExists(t *testing.T, params android.TestingBuildParams, src string, dst string) {
303	assertPathsContains(t, getAllInputPaths(params), src)
304	assertWritablePathsContainsRel(t, getAllOutputPaths(params), dst)
305	if !strings.HasPrefix(params.RuleParams.Command, "cp") {
306		t.Errorf("'cp' command is missing.")
307	}
308}
309
310func assertPathsContains(t *testing.T, paths android.Paths, path string) {
311	for _, p := range paths {
312		if p.String() == path {
313			return
314		}
315	}
316	t.Errorf("Cannot find expected path %s", path)
317}
318
319func assertWritablePathsContainsRel(t *testing.T, paths android.WritablePaths, relPath string) {
320	for _, path := range paths {
321		if path.Rel() == relPath {
322			return
323		}
324	}
325	t.Errorf("Cannot find expected relative path %s", relPath)
326}
327
328func getAllOutputPaths(params android.TestingBuildParams) android.WritablePaths {
329	var paths []android.WritablePath
330	if params.Output != nil {
331		paths = append(paths, params.Output)
332	}
333	if params.ImplicitOutput != nil {
334		paths = append(paths, params.ImplicitOutput)
335	}
336	if params.SymlinkOutput != nil {
337		paths = append(paths, params.SymlinkOutput)
338	}
339	paths = append(paths, params.Outputs...)
340	paths = append(paths, params.ImplicitOutputs...)
341	paths = append(paths, params.SymlinkOutputs...)
342
343	return paths
344}
345
346func getAllInputPaths(params android.TestingBuildParams) android.Paths {
347	var paths []android.Path
348	if params.Input != nil {
349		paths = append(paths, params.Input)
350	}
351	if params.Implicit != nil {
352		paths = append(paths, params.Implicit)
353	}
354	paths = append(paths, params.Inputs...)
355	paths = append(paths, params.Implicits...)
356
357	return paths
358}
359
360func setUp() {
361	var err error
362	buildDir, err = ioutil.TempDir("", "soong_csuite_test")
363	if err != nil {
364		panic(err)
365	}
366}
367
368func tearDown() {
369	os.RemoveAll(buildDir)
370}
371
372func createContextAndConfig(t *testing.T, bp string) (*android.TestContext, android.Config) {
373	t.Helper()
374	config := android.TestArchConfig(buildDir, nil, bp, nil)
375	ctx := android.NewTestArchContext(config)
376	ctx.RegisterModuleType("csuite_test", CSuiteTestFactory)
377	ctx.Register()
378
379	return ctx, config
380}
381