• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2016 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 android
16
17import (
18	"fmt"
19	"testing"
20
21	"github.com/google/blueprint"
22)
23
24var prebuiltsTests = []struct {
25	name      string
26	replaceBp bool // modules is added to default bp boilerplate if false.
27	modules   string
28	prebuilt  []OsType
29}{
30	{
31		name: "no prebuilt",
32		modules: `
33			source {
34				name: "bar",
35			}`,
36		prebuilt: nil,
37	},
38	{
39		name: "no source prebuilt not preferred",
40		modules: `
41			prebuilt {
42				name: "bar",
43				prefer: false,
44				srcs: ["prebuilt_file"],
45			}`,
46		prebuilt: []OsType{Android, BuildOs},
47	},
48	{
49		name: "no source prebuilt preferred",
50		modules: `
51			prebuilt {
52				name: "bar",
53				prefer: true,
54				srcs: ["prebuilt_file"],
55			}`,
56		prebuilt: []OsType{Android, BuildOs},
57	},
58	{
59		name: "prebuilt not preferred",
60		modules: `
61			source {
62				name: "bar",
63			}
64
65			prebuilt {
66				name: "bar",
67				prefer: false,
68				srcs: ["prebuilt_file"],
69			}`,
70		prebuilt: nil,
71	},
72	{
73		name: "prebuilt preferred",
74		modules: `
75			source {
76				name: "bar",
77			}
78
79			prebuilt {
80				name: "bar",
81				prefer: true,
82				srcs: ["prebuilt_file"],
83			}`,
84		prebuilt: []OsType{Android, BuildOs},
85	},
86	{
87		name: "prebuilt no file not preferred",
88		modules: `
89			source {
90				name: "bar",
91			}
92
93			prebuilt {
94				name: "bar",
95				prefer: false,
96			}`,
97		prebuilt: nil,
98	},
99	{
100		name: "prebuilt no file preferred",
101		modules: `
102			source {
103				name: "bar",
104			}
105
106			prebuilt {
107				name: "bar",
108				prefer: true,
109			}`,
110		prebuilt: nil,
111	},
112	{
113		name: "prebuilt file from filegroup preferred",
114		modules: `
115			filegroup {
116				name: "fg",
117				srcs: ["prebuilt_file"],
118			}
119			prebuilt {
120				name: "bar",
121				prefer: true,
122				srcs: [":fg"],
123			}`,
124		prebuilt: []OsType{Android, BuildOs},
125	},
126	{
127		name: "prebuilt module for device only",
128		modules: `
129			source {
130				name: "bar",
131			}
132
133			prebuilt {
134				name: "bar",
135				host_supported: false,
136				prefer: true,
137				srcs: ["prebuilt_file"],
138			}`,
139		prebuilt: []OsType{Android},
140	},
141	{
142		name: "prebuilt file for host only",
143		modules: `
144			source {
145				name: "bar",
146			}
147
148			prebuilt {
149				name: "bar",
150				prefer: true,
151				target: {
152					host: {
153						srcs: ["prebuilt_file"],
154					},
155				},
156			}`,
157		prebuilt: []OsType{BuildOs},
158	},
159	{
160		name: "prebuilt override not preferred",
161		modules: `
162			source {
163				name: "baz",
164			}
165
166			override_source {
167				name: "bar",
168				base: "baz",
169			}
170
171			prebuilt {
172				name: "bar",
173				prefer: false,
174				srcs: ["prebuilt_file"],
175			}`,
176		prebuilt: nil,
177	},
178	{
179		name: "prebuilt override preferred",
180		modules: `
181			source {
182				name: "baz",
183			}
184
185			override_source {
186				name: "bar",
187				base: "baz",
188			}
189
190			prebuilt {
191				name: "bar",
192				prefer: true,
193				srcs: ["prebuilt_file"],
194			}`,
195		prebuilt: []OsType{Android, BuildOs},
196	},
197	{
198		name:      "prebuilt including default-disabled OS",
199		replaceBp: true,
200		modules: `
201			source {
202				name: "foo",
203				deps: [":bar"],
204				target: {
205					windows: {
206						enabled: true,
207					},
208				},
209			}
210
211			source {
212				name: "bar",
213				target: {
214					windows: {
215						enabled: true,
216					},
217				},
218			}
219
220			prebuilt {
221				name: "bar",
222				prefer: true,
223				srcs: ["prebuilt_file"],
224				target: {
225					windows: {
226						enabled: true,
227					},
228				},
229			}`,
230		prebuilt: []OsType{Android, BuildOs, Windows},
231	},
232	{
233		name:      "fall back to source for default-disabled OS",
234		replaceBp: true,
235		modules: `
236			source {
237				name: "foo",
238				deps: [":bar"],
239				target: {
240					windows: {
241						enabled: true,
242					},
243				},
244			}
245
246			source {
247				name: "bar",
248				target: {
249					windows: {
250						enabled: true,
251					},
252				},
253			}
254
255			prebuilt {
256				name: "bar",
257				prefer: true,
258				srcs: ["prebuilt_file"],
259			}`,
260		prebuilt: []OsType{Android, BuildOs},
261	},
262	{
263		name:      "prebuilt properties customizable",
264		replaceBp: true,
265		modules: `
266			source {
267				name: "foo",
268				deps: [":bar"],
269			}
270
271			soong_config_module_type {
272				name: "prebuilt_with_config",
273				module_type: "prebuilt",
274				config_namespace: "any_namespace",
275				bool_variables: ["bool_var"],
276				properties: ["prefer"],
277			}
278
279			prebuilt_with_config {
280				name: "bar",
281				prefer: true,
282				srcs: ["prebuilt_file"],
283				soong_config_variables: {
284					bool_var: {
285						prefer: false,
286						conditions_default: {
287							prefer: true,
288						},
289					},
290				},
291			}`,
292		prebuilt: []OsType{Android, BuildOs},
293	},
294}
295
296func TestPrebuilts(t *testing.T) {
297	fs := MockFS{
298		"prebuilt_file": nil,
299		"source_file":   nil,
300	}
301
302	for _, test := range prebuiltsTests {
303		t.Run(test.name, func(t *testing.T) {
304			bp := test.modules
305			if !test.replaceBp {
306				bp = bp + `
307					source {
308						name: "foo",
309						deps: [":bar"],
310					}`
311			}
312
313			// Add windows to the target list to test the logic when a variant is
314			// disabled by default.
315			if !Windows.DefaultDisabled {
316				t.Errorf("windows is assumed to be disabled by default")
317			}
318
319			result := GroupFixturePreparers(
320				PrepareForTestWithArchMutator,
321				PrepareForTestWithPrebuilts,
322				PrepareForTestWithOverrides,
323				PrepareForTestWithFilegroup,
324				// Add a Windows target to the configuration.
325				FixtureModifyConfig(func(config Config) {
326					config.Targets[Windows] = []Target{
327						{Windows, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", true},
328					}
329				}),
330				fs.AddToFixture(),
331				FixtureRegisterWithContext(registerTestPrebuiltModules),
332			).RunTestWithBp(t, bp)
333
334			for _, variant := range result.ModuleVariantsForTests("foo") {
335				foo := result.ModuleForTests("foo", variant)
336				t.Run(foo.Module().Target().Os.String(), func(t *testing.T) {
337					var dependsOnSourceModule, dependsOnPrebuiltModule bool
338					result.VisitDirectDeps(foo.Module(), func(m blueprint.Module) {
339						if _, ok := m.(*sourceModule); ok {
340							dependsOnSourceModule = true
341						}
342						if p, ok := m.(*prebuiltModule); ok {
343							dependsOnPrebuiltModule = true
344							if !p.Prebuilt().properties.UsePrebuilt {
345								t.Errorf("dependency on prebuilt module not marked used")
346							}
347						}
348					})
349
350					moduleIsDisabled := !foo.Module().Enabled()
351					deps := foo.Module().(*sourceModule).deps
352					if moduleIsDisabled {
353						if len(deps) > 0 {
354							t.Errorf("disabled module got deps: %v", deps)
355						}
356					} else {
357						if len(deps) != 1 {
358							t.Errorf("deps does not have single path, but is %v", deps)
359						}
360					}
361
362					var usingSourceFile, usingPrebuiltFile bool
363					if len(deps) > 0 && deps[0].String() == "source_file" {
364						usingSourceFile = true
365					}
366					if len(deps) > 0 && deps[0].String() == "prebuilt_file" {
367						usingPrebuiltFile = true
368					}
369
370					prebuilt := false
371					for _, os := range test.prebuilt {
372						if os == foo.Module().Target().Os {
373							prebuilt = true
374						}
375					}
376
377					if prebuilt {
378						if moduleIsDisabled {
379							t.Errorf("dependent module for prebuilt is disabled")
380						}
381
382						if !dependsOnPrebuiltModule {
383							t.Errorf("doesn't depend on prebuilt module")
384						}
385						if !usingPrebuiltFile {
386							t.Errorf("doesn't use prebuilt_file")
387						}
388
389						if dependsOnSourceModule {
390							t.Errorf("depends on source module")
391						}
392						if usingSourceFile {
393							t.Errorf("using source_file")
394						}
395					} else if !moduleIsDisabled {
396						if dependsOnPrebuiltModule {
397							t.Errorf("depends on prebuilt module")
398						}
399						if usingPrebuiltFile {
400							t.Errorf("using prebuilt_file")
401						}
402
403						if !dependsOnSourceModule {
404							t.Errorf("doesn't depend on source module")
405						}
406						if !usingSourceFile {
407							t.Errorf("doesn't use source_file")
408						}
409					}
410				})
411			}
412		})
413	}
414}
415
416func registerTestPrebuiltBuildComponents(ctx RegistrationContext) {
417	registerTestPrebuiltModules(ctx)
418
419	RegisterPrebuiltMutators(ctx)
420	ctx.PostDepsMutators(RegisterOverridePostDepsMutators)
421}
422
423var prepareForTestWithFakePrebuiltModules = FixtureRegisterWithContext(registerTestPrebuiltModules)
424
425func registerTestPrebuiltModules(ctx RegistrationContext) {
426	ctx.RegisterModuleType("prebuilt", newPrebuiltModule)
427	ctx.RegisterModuleType("source", newSourceModule)
428	ctx.RegisterModuleType("override_source", newOverrideSourceModule)
429	ctx.RegisterModuleType("soong_config_module_type", soongConfigModuleTypeFactory)
430	ctx.RegisterModuleType("soong_config_string_variable", soongConfigStringVariableDummyFactory)
431	ctx.RegisterModuleType("soong_config_bool_variable", soongConfigBoolVariableDummyFactory)
432}
433
434type prebuiltModule struct {
435	ModuleBase
436	prebuilt   Prebuilt
437	properties struct {
438		Srcs []string `android:"path,arch_variant"`
439	}
440	src Path
441}
442
443func newPrebuiltModule() Module {
444	m := &prebuiltModule{}
445	m.AddProperties(&m.properties)
446	InitPrebuiltModule(m, &m.properties.Srcs)
447	InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon)
448	return m
449}
450
451func (p *prebuiltModule) Name() string {
452	return p.prebuilt.Name(p.ModuleBase.Name())
453}
454
455func (p *prebuiltModule) GenerateAndroidBuildActions(ctx ModuleContext) {
456	if len(p.properties.Srcs) >= 1 {
457		p.src = p.prebuilt.SingleSourcePath(ctx)
458	}
459}
460
461func (p *prebuiltModule) Prebuilt() *Prebuilt {
462	return &p.prebuilt
463}
464
465func (p *prebuiltModule) OutputFiles(tag string) (Paths, error) {
466	switch tag {
467	case "":
468		return Paths{p.src}, nil
469	default:
470		return nil, fmt.Errorf("unsupported module reference tag %q", tag)
471	}
472}
473
474type sourceModuleProperties struct {
475	Deps []string `android:"path,arch_variant"`
476}
477
478type sourceModule struct {
479	ModuleBase
480	OverridableModuleBase
481
482	properties                                     sourceModuleProperties
483	dependsOnSourceModule, dependsOnPrebuiltModule bool
484	deps                                           Paths
485	src                                            Path
486}
487
488func newSourceModule() Module {
489	m := &sourceModule{}
490	m.AddProperties(&m.properties)
491	InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon)
492	InitOverridableModule(m, nil)
493	return m
494}
495
496func (s *sourceModule) OverridablePropertiesDepsMutator(ctx BottomUpMutatorContext) {
497	// s.properties.Deps are annotated with android:path, so they are
498	// automatically added to the dependency by pathDeps mutator
499}
500
501func (s *sourceModule) GenerateAndroidBuildActions(ctx ModuleContext) {
502	s.deps = PathsForModuleSrc(ctx, s.properties.Deps)
503	s.src = PathForModuleSrc(ctx, "source_file")
504}
505
506func (s *sourceModule) Srcs() Paths {
507	return Paths{s.src}
508}
509
510type overrideSourceModule struct {
511	ModuleBase
512	OverrideModuleBase
513}
514
515func (o *overrideSourceModule) GenerateAndroidBuildActions(_ ModuleContext) {
516}
517
518func newOverrideSourceModule() Module {
519	m := &overrideSourceModule{}
520	m.AddProperties(&sourceModuleProperties{})
521
522	InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon)
523	InitOverrideModule(m)
524	return m
525}
526