• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2018 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	"regexp"
19	"testing"
20
21	"github.com/google/blueprint"
22)
23
24var neverallowTests = []struct {
25	// The name of the test.
26	name string
27
28	// Optional test specific rules. If specified then they are used instead of the default rules.
29	rules []Rule
30
31	// Additional contents to add to the virtual filesystem used by the tests.
32	fs MockFS
33
34	// The expected error patterns. If empty then no errors are expected, otherwise each error
35	// reported must be matched by at least one of these patterns. A pattern matches if the error
36	// message contains the pattern. A pattern does not have to match the whole error message.
37	expectedErrors []string
38}{
39	// Test General Functionality
40
41	// in direct deps tests
42	{
43		name: "not_allowed_in_direct_deps",
44		rules: []Rule{
45			NeverAllow().InDirectDeps("not_allowed_in_direct_deps"),
46		},
47		fs: map[string][]byte{
48			"top/Android.bp": []byte(`
49				cc_library {
50					name: "not_allowed_in_direct_deps",
51				}`),
52			"other/Android.bp": []byte(`
53				cc_library {
54					name: "libother",
55					static_libs: ["not_allowed_in_direct_deps"],
56				}`),
57		},
58		expectedErrors: []string{
59			regexp.QuoteMeta("module \"libother\": violates neverallow requirements. Not allowed:\n\tdep(s): [\"not_allowed_in_direct_deps\"]"),
60		},
61	},
62	{
63		name: "multiple constraints",
64		rules: []Rule{
65			NeverAllow().
66				InDirectDeps("not_allowed_in_direct_deps").
67				In("other").
68				ModuleType("cc_library").
69				NotIn("top").
70				NotModuleType("cc_binary"),
71		},
72		fs: map[string][]byte{
73			"top/Android.bp": []byte(`
74				cc_library {
75					name: "not_allowed_in_direct_deps",
76				}`),
77			"other/Android.bp": []byte(`
78				cc_library {
79					name: "libother",
80					static_libs: ["not_allowed_in_direct_deps"],
81				}`),
82		},
83		expectedErrors: []string{
84			regexp.QuoteMeta(`module "libother": violates neverallow requirements. Not allowed:
85	in dirs: ["other/"]
86	module types: ["cc_library"]
87	dep(s): ["not_allowed_in_direct_deps"]
88	EXCEPT in dirs: ["top/"]
89	EXCEPT module types: ["cc_binary"]`),
90		},
91	},
92
93	// Test android specific rules
94
95	// include_dir rule tests
96	{
97		name: "include_dir not allowed to reference art",
98		fs: map[string][]byte{
99			"other/Android.bp": []byte(`
100				cc_library {
101					name: "libother",
102					include_dirs: ["art/libdexfile/include"],
103				}`),
104		},
105		expectedErrors: []string{
106			"all usages of 'art' have been migrated",
107		},
108	},
109	{
110		name: "include_dir not allowed to reference art",
111		fs: map[string][]byte{
112			"system/libfmq/Android.bp": []byte(`
113				cc_library {
114					name: "libother",
115					include_dirs: ["any/random/file"],
116				}`),
117		},
118		expectedErrors: []string{
119			"all usages of them in 'system/libfmq' have been migrated",
120		},
121	},
122	{
123		name: "include_dir can work",
124		fs: map[string][]byte{
125			"other/Android.bp": []byte(`
126				cc_library {
127					name: "libother",
128					include_dirs: ["another/include"],
129				}`),
130		},
131	},
132	// Treble rule tests
133	{
134		name: "no vndk.enabled under vendor directory",
135		fs: map[string][]byte{
136			"vendor/Android.bp": []byte(`
137				cc_library {
138					name: "libvndk",
139					vendor_available: true,
140					vndk: {
141						enabled: true,
142					},
143				}`),
144		},
145		expectedErrors: []string{
146			"VNDK can never contain a library that is device dependent",
147		},
148	},
149	{
150		name: "no vndk.enabled under device directory",
151		fs: map[string][]byte{
152			"device/Android.bp": []byte(`
153				cc_library {
154					name: "libvndk",
155					vendor_available: true,
156					vndk: {
157						enabled: true,
158					},
159				}`),
160		},
161		expectedErrors: []string{
162			"VNDK can never contain a library that is device dependent",
163		},
164	},
165	{
166		name: "vndk-ext under vendor or device directory",
167		fs: map[string][]byte{
168			"device/Android.bp": []byte(`
169				cc_library {
170					name: "libvndk1_ext",
171					vendor: true,
172					vndk: {
173						enabled: true,
174					},
175				}`),
176			"vendor/Android.bp": []byte(`
177				cc_library {
178					name: "libvndk2_ext",
179					vendor: true,
180					vndk: {
181						enabled: true,
182					},
183				}`),
184		},
185	},
186
187	{
188		name: "no enforce_vintf_manifest.cflags",
189		fs: map[string][]byte{
190			"Android.bp": []byte(`
191				cc_library {
192					name: "libexample",
193					product_variables: {
194						enforce_vintf_manifest: {
195							cflags: ["-DSHOULD_NOT_EXIST"],
196						},
197					},
198				}`),
199		},
200		expectedErrors: []string{
201			"manifest enforcement should be independent",
202		},
203	},
204
205	{
206		name: "no treble_linker_namespaces.cflags",
207		fs: map[string][]byte{
208			"Android.bp": []byte(`
209				cc_library {
210					name: "libexample",
211					product_variables: {
212						treble_linker_namespaces: {
213							cflags: ["-DSHOULD_NOT_EXIST"],
214						},
215					},
216				}`),
217		},
218		expectedErrors: []string{
219			"nothing should care if linker namespaces are enabled or not",
220		},
221	},
222	{
223		name: "libc_bionic_ndk treble_linker_namespaces.cflags",
224		fs: map[string][]byte{
225			"Android.bp": []byte(`
226				cc_library {
227					name: "libc_bionic_ndk",
228					product_variables: {
229						treble_linker_namespaces: {
230							cflags: ["-DSHOULD_NOT_EXIST"],
231						},
232					},
233				}`),
234		},
235	},
236	{
237		name: "java_device_for_host",
238		fs: map[string][]byte{
239			"Android.bp": []byte(`
240				java_device_for_host {
241					name: "device_for_host",
242					libs: ["core-libart"],
243				}`),
244		},
245		expectedErrors: []string{
246			"java_device_for_host can only be used in allowed projects",
247		},
248	},
249	// CC sdk rule tests
250	{
251		name: `"sdk_variant_only" outside allowed list`,
252		fs: map[string][]byte{
253			"Android.bp": []byte(`
254				cc_library {
255					name: "outside_allowed_list",
256					sdk_version: "current",
257					sdk_variant_only: true,
258				}`),
259		},
260		expectedErrors: []string{
261			`module "outside_allowed_list": violates neverallow`,
262		},
263	},
264	{
265		name: `"sdk_variant_only: false" outside allowed list`,
266		fs: map[string][]byte{
267			"Android.bp": []byte(`
268				cc_library {
269					name: "outside_allowed_list",
270					sdk_version: "current",
271					sdk_variant_only: false,
272				}`),
273		},
274		expectedErrors: []string{
275			`module "outside_allowed_list": violates neverallow`,
276		},
277	},
278	{
279		name: `"platform" outside allowed list`,
280		fs: map[string][]byte{
281			"Android.bp": []byte(`
282				cc_library {
283					name: "outside_allowed_list",
284					platform: {
285						shared_libs: ["libfoo"],
286					},
287				}`),
288		},
289		expectedErrors: []string{
290			`module "outside_allowed_list": violates neverallow`,
291		},
292	},
293	{
294		name: "uncompress_dex inside art",
295		fs: map[string][]byte{
296			"art/Android.bp": []byte(`
297				java_library {
298					name: "inside_art_libraries",
299					uncompress_dex: true,
300				}`),
301		},
302	},
303	{
304		name: "uncompress_dex outside art",
305		fs: map[string][]byte{
306			"other/Android.bp": []byte(`
307				java_library {
308					name: "outside_art_libraries",
309					uncompress_dex: true,
310				}`),
311		},
312		expectedErrors: []string{
313			"module \"outside_art_libraries\": violates neverallow",
314		},
315	},
316	// Tests for the rule prohibiting the use of framework
317	{
318		name: "prohibit framework",
319		fs: map[string][]byte{
320			"Android.bp": []byte(`
321				java_library {
322					name: "foo",
323					libs: ["framework"],
324					sdk_version: "current",
325				}`),
326		},
327		expectedErrors: []string{
328			"framework can't be used when building against SDK",
329		},
330	},
331	// Test for the rule restricting use of implementation_installable
332	{
333		name: `"implementation_installable" outside allowed list`,
334		fs: map[string][]byte{
335			"Android.bp": []byte(`
336				cc_library {
337					name: "outside_allowed_list",
338					stubs: {
339                                                implementation_installable: true,
340					},
341				}`),
342		},
343		expectedErrors: []string{
344			`module "outside_allowed_list": violates neverallow`,
345		},
346	},
347	// Test for only allowing headers_only for framework-minus-apex-headers
348	{
349		name: `"headers_only" outside framework-minus-apex-headers modules`,
350		fs: map[string][]byte{
351			"a/b/Android.bp": []byte(`
352				java_library {
353					name: "baz",
354					headers_only: true,
355				}
356			`),
357		},
358		expectedErrors: []string{
359			`headers_only can only be used for generating framework-minus-apex headers for non-updatable modules`,
360		},
361	},
362	// Test for the rule restricting use of is_auto_generated
363	{
364		name: `"is_auto_generated" outside allowed directory`,
365		fs: map[string][]byte{
366			"a/b/Android.bp": []byte(`
367				filesystem {
368					name: "baaz",
369					is_auto_generated: true,
370				}
371			`),
372		},
373		expectedErrors: []string{
374			`is_auto_generated property is only allowed for filesystem modules in build/soong/fsgen directory`,
375		},
376	},
377	// Test for the rule restricting use of prebuilt_* module
378	{
379		name: `"prebuilt_usr_srec" defined in Android.bp file`,
380		fs: map[string][]byte{
381			"a/b/Android.bp": []byte(`
382				prebuilt_usr_srec {
383					name: "foo",
384				}
385			`),
386		},
387		expectedErrors: []string{
388			`module type not allowed to be defined in bp file`,
389		},
390	},
391	// Test the a neverallowed module type can't be smuggled through a soong config module type
392	{
393		name: `smuggling module types through soong config modules`,
394		fs: map[string][]byte{
395			"a/b/Android.bp": []byte(`
396				soong_config_bool_variable {
397					name: "my_var",
398				}
399				soong_config_module_type {
400					name: "smuggled_prebuilt_usr_srec",
401					module_type: "prebuilt_usr_srec",
402					config_namespace: "ANDROID",
403					variables: ["my_var"],
404					properties: ["enabled"],
405				}
406				smuggled_prebuilt_usr_srec {
407					name: "foo",
408				}
409			`),
410		},
411		expectedErrors: []string{
412			`module type not allowed to be defined in bp file`,
413		},
414	},
415}
416
417var prepareForNeverAllowTest = GroupFixturePreparers(
418	FixtureRegisterWithContext(func(ctx RegistrationContext) {
419		ctx.RegisterModuleType("cc_library", newMockCcLibraryModule)
420		ctx.RegisterModuleType("java_library", newMockJavaLibraryModule)
421		ctx.RegisterModuleType("java_library_host", newMockJavaLibraryModule)
422		ctx.RegisterModuleType("java_device_for_host", newMockJavaLibraryModule)
423		ctx.RegisterModuleType("filesystem", newMockFilesystemModule)
424		ctx.RegisterModuleType("prebuilt_usr_srec", newMockPrebuiltUsrSrecModule)
425	}),
426	PrepareForTestWithSoongConfigModuleBuildComponents,
427)
428
429func TestNeverallow(t *testing.T) {
430	for _, test := range neverallowTests {
431		t.Run(test.name, func(t *testing.T) {
432			GroupFixturePreparers(
433				prepareForNeverAllowTest,
434				PrepareForTestWithNeverallowRules(test.rules),
435				test.fs.AddToFixture(),
436			).
437				ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
438				RunTest(t)
439		})
440	}
441}
442
443type mockCcLibraryProperties struct {
444	Include_dirs     []string
445	Vendor_available *bool
446	Static_libs      []string
447	Sdk_version      *string
448	Sdk_variant_only *bool
449
450	Vndk struct {
451		Enabled                *bool
452		Support_system_process *bool
453		Extends                *string
454	}
455
456	Product_variables struct {
457		Enforce_vintf_manifest struct {
458			Cflags []string
459		}
460
461		Treble_linker_namespaces struct {
462			Cflags []string
463		}
464	}
465
466	Platform struct {
467		Shared_libs []string
468	}
469
470	Stubs struct {
471		Implementation_installable *bool
472	}
473}
474
475type mockCcLibraryModule struct {
476	ModuleBase
477	properties mockCcLibraryProperties
478}
479
480func newMockCcLibraryModule() Module {
481	m := &mockCcLibraryModule{}
482	m.AddProperties(&m.properties)
483	InitAndroidModule(m)
484	return m
485}
486
487type neverallowTestDependencyTag struct {
488	blueprint.BaseDependencyTag
489	name string
490}
491
492var staticDepTag = neverallowTestDependencyTag{name: "static"}
493
494func (c *mockCcLibraryModule) DepsMutator(ctx BottomUpMutatorContext) {
495	for _, lib := range c.properties.Static_libs {
496		ctx.AddDependency(ctx.Module(), staticDepTag, lib)
497	}
498}
499
500func (p *mockCcLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
501}
502
503type mockJavaLibraryProperties struct {
504	Libs                []string
505	Sdk_version         *string
506	Uncompress_dex      *bool
507	Exclude_static_libs []string
508	Headers_only        *bool
509}
510
511type mockJavaLibraryModule struct {
512	ModuleBase
513	properties mockJavaLibraryProperties
514}
515
516func newMockJavaLibraryModule() Module {
517	m := &mockJavaLibraryModule{}
518	m.AddProperties(&m.properties)
519	InitAndroidModule(m)
520	return m
521}
522
523func (p *mockJavaLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
524}
525
526type mockPrebuiltUsrSrecModule struct {
527	ModuleBase
528}
529
530func (p *mockPrebuiltUsrSrecModule) GenerateAndroidBuildActions(ModuleContext) {
531}
532
533func newMockPrebuiltUsrSrecModule() Module {
534	m := &mockPrebuiltUsrSrecModule{}
535	InitAndroidModule(m)
536	return m
537}
538