• 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 the rule restricting use of exclude_static_libs
348	{
349		name: `"exclude_static_libs" outside allowed directory`,
350		fs: map[string][]byte{
351			"a/b/Android.bp": []byte(`
352				java_library {
353					name: "baz",
354					exclude_static_libs: [
355						"bar",
356					],
357				}
358			`),
359		},
360		expectedErrors: []string{
361			`exclude_static_libs property is only allowed for java modules defined in build/soong, libcore, and frameworks/base/api`,
362		},
363	},
364	// Test for only allowing headers_only for framework-minus-apex-headers
365	{
366		name: `"headers_only" outside framework-minus-apex-headers modules`,
367		fs: map[string][]byte{
368			"a/b/Android.bp": []byte(`
369				java_library {
370					name: "baz",
371					headers_only: true,
372				}
373			`),
374		},
375		expectedErrors: []string{
376			`headers_only can only be used for generating framework-minus-apex headers for non-updatable modules`,
377		},
378	},
379}
380
381var prepareForNeverAllowTest = GroupFixturePreparers(
382	FixtureRegisterWithContext(func(ctx RegistrationContext) {
383		ctx.RegisterModuleType("cc_library", newMockCcLibraryModule)
384		ctx.RegisterModuleType("java_library", newMockJavaLibraryModule)
385		ctx.RegisterModuleType("java_library_host", newMockJavaLibraryModule)
386		ctx.RegisterModuleType("java_device_for_host", newMockJavaLibraryModule)
387	}),
388)
389
390func TestNeverallow(t *testing.T) {
391	for _, test := range neverallowTests {
392		t.Run(test.name, func(t *testing.T) {
393			GroupFixturePreparers(
394				prepareForNeverAllowTest,
395				PrepareForTestWithNeverallowRules(test.rules),
396				test.fs.AddToFixture(),
397			).
398				ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
399				RunTest(t)
400		})
401	}
402}
403
404type mockCcLibraryProperties struct {
405	Include_dirs     []string
406	Vendor_available *bool
407	Static_libs      []string
408	Sdk_version      *string
409	Sdk_variant_only *bool
410
411	Vndk struct {
412		Enabled                *bool
413		Support_system_process *bool
414		Extends                *string
415	}
416
417	Product_variables struct {
418		Enforce_vintf_manifest struct {
419			Cflags []string
420		}
421
422		Treble_linker_namespaces struct {
423			Cflags []string
424		}
425	}
426
427	Platform struct {
428		Shared_libs []string
429	}
430
431	Stubs struct {
432		Implementation_installable *bool
433	}
434}
435
436type mockCcLibraryModule struct {
437	ModuleBase
438	properties mockCcLibraryProperties
439}
440
441func newMockCcLibraryModule() Module {
442	m := &mockCcLibraryModule{}
443	m.AddProperties(&m.properties)
444	InitAndroidModule(m)
445	return m
446}
447
448type neverallowTestDependencyTag struct {
449	blueprint.BaseDependencyTag
450	name string
451}
452
453var staticDepTag = neverallowTestDependencyTag{name: "static"}
454
455func (c *mockCcLibraryModule) DepsMutator(ctx BottomUpMutatorContext) {
456	for _, lib := range c.properties.Static_libs {
457		ctx.AddDependency(ctx.Module(), staticDepTag, lib)
458	}
459}
460
461func (p *mockCcLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
462}
463
464type mockJavaLibraryProperties struct {
465	Libs                []string
466	Sdk_version         *string
467	Uncompress_dex      *bool
468	Exclude_static_libs []string
469	Headers_only        *bool
470}
471
472type mockJavaLibraryModule struct {
473	ModuleBase
474	properties mockJavaLibraryProperties
475}
476
477func newMockJavaLibraryModule() Module {
478	m := &mockJavaLibraryModule{}
479	m.AddProperties(&m.properties)
480	InitAndroidModule(m)
481	return m
482}
483
484func (p *mockJavaLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
485}
486