• 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	{
317		name: "disallowed makefile_goal",
318		fs: map[string][]byte{
319			"Android.bp": []byte(`
320				makefile_goal {
321					name: "foo",
322					product_out_path: "boot/trap.img"
323				}
324			`),
325		},
326		expectedErrors: []string{
327			"Only boot images.* may be imported as a makefile goal",
328		},
329	},
330	{
331		name: "disallowed makefile_goal outside external",
332		fs: map[string][]byte{
333			"project/Android.bp": []byte(`
334				makefile_goal {
335					name: "foo",
336					product_out_path: "obj/EXE/foo",
337				}
338			`),
339		},
340		expectedErrors: []string{
341			"not in allowed projects",
342		},
343	},
344	{
345		name: "allow makefile_goal within external",
346		fs: map[string][]byte{
347			"frameworks/opt/net/wifi/libwifi_hal/Android.bp": []byte(`
348				makefile_goal {
349					name: "foo",
350					product_out_path: "obj/EXE/foo",
351				}
352			`),
353		},
354	},
355	// Tests for the rule prohibiting the use of framework
356	{
357		name: "prohibit framework",
358		fs: map[string][]byte{
359			"Android.bp": []byte(`
360				java_library {
361					name: "foo",
362					libs: ["framework"],
363					sdk_version: "current",
364				}`),
365		},
366		expectedErrors: []string{
367			"framework can't be used when building against SDK",
368		},
369	},
370	// Test for the rule restricting use of implementation_installable
371	{
372		name: `"implementation_installable" outside allowed list`,
373		fs: map[string][]byte{
374			"Android.bp": []byte(`
375				cc_library {
376					name: "outside_allowed_list",
377					stubs: {
378                                                implementation_installable: true,
379					},
380				}`),
381		},
382		expectedErrors: []string{
383			`module "outside_allowed_list": violates neverallow`,
384		},
385	},
386}
387
388var prepareForNeverAllowTest = GroupFixturePreparers(
389	FixtureRegisterWithContext(func(ctx RegistrationContext) {
390		ctx.RegisterModuleType("cc_library", newMockCcLibraryModule)
391		ctx.RegisterModuleType("java_library", newMockJavaLibraryModule)
392		ctx.RegisterModuleType("java_library_host", newMockJavaLibraryModule)
393		ctx.RegisterModuleType("java_device_for_host", newMockJavaLibraryModule)
394		ctx.RegisterModuleType("makefile_goal", newMockMakefileGoalModule)
395	}),
396)
397
398func TestNeverallow(t *testing.T) {
399	for _, test := range neverallowTests {
400		t.Run(test.name, func(t *testing.T) {
401			GroupFixturePreparers(
402				prepareForNeverAllowTest,
403				PrepareForTestWithNeverallowRules(test.rules),
404				test.fs.AddToFixture(),
405			).
406				ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
407				RunTest(t)
408		})
409	}
410}
411
412type mockCcLibraryProperties struct {
413	Include_dirs     []string
414	Vendor_available *bool
415	Static_libs      []string
416	Sdk_version      *string
417	Sdk_variant_only *bool
418
419	Vndk struct {
420		Enabled                *bool
421		Support_system_process *bool
422		Extends                *string
423	}
424
425	Product_variables struct {
426		Enforce_vintf_manifest struct {
427			Cflags []string
428		}
429
430		Treble_linker_namespaces struct {
431			Cflags []string
432		}
433	}
434
435	Platform struct {
436		Shared_libs []string
437	}
438
439	Stubs struct {
440		Implementation_installable *bool
441	}
442}
443
444type mockCcLibraryModule struct {
445	ModuleBase
446	properties mockCcLibraryProperties
447}
448
449func newMockCcLibraryModule() Module {
450	m := &mockCcLibraryModule{}
451	m.AddProperties(&m.properties)
452	InitAndroidModule(m)
453	return m
454}
455
456type neverallowTestDependencyTag struct {
457	blueprint.BaseDependencyTag
458	name string
459}
460
461var staticDepTag = neverallowTestDependencyTag{name: "static"}
462
463func (c *mockCcLibraryModule) DepsMutator(ctx BottomUpMutatorContext) {
464	for _, lib := range c.properties.Static_libs {
465		ctx.AddDependency(ctx.Module(), staticDepTag, lib)
466	}
467}
468
469func (p *mockCcLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
470}
471
472type mockJavaLibraryProperties struct {
473	Libs           []string
474	Sdk_version    *string
475	Uncompress_dex *bool
476}
477
478type mockJavaLibraryModule struct {
479	ModuleBase
480	properties mockJavaLibraryProperties
481}
482
483func newMockJavaLibraryModule() Module {
484	m := &mockJavaLibraryModule{}
485	m.AddProperties(&m.properties)
486	InitAndroidModule(m)
487	return m
488}
489
490func (p *mockJavaLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
491}
492
493type mockMakefileGoalProperties struct {
494	Product_out_path *string
495}
496
497type mockMakefileGoalModule struct {
498	ModuleBase
499	properties mockMakefileGoalProperties
500}
501
502func newMockMakefileGoalModule() Module {
503	m := &mockMakefileGoalModule{}
504	m.AddProperties(&m.properties)
505	InitAndroidModule(m)
506	return m
507}
508
509func (p *mockMakefileGoalModule) GenerateAndroidBuildActions(ModuleContext) {
510}
511