• 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	// Tests for the rule prohibiting the use of framework
331	{
332		name: "prohibit framework",
333		fs: map[string][]byte{
334			"Android.bp": []byte(`
335				java_library {
336					name: "foo",
337					libs: ["framework"],
338					sdk_version: "current",
339				}`),
340		},
341		expectedErrors: []string{
342			"framework can't be used when building against SDK",
343		},
344	},
345}
346
347var prepareForNeverAllowTest = GroupFixturePreparers(
348	FixtureRegisterWithContext(func(ctx RegistrationContext) {
349		ctx.RegisterModuleType("cc_library", newMockCcLibraryModule)
350		ctx.RegisterModuleType("java_library", newMockJavaLibraryModule)
351		ctx.RegisterModuleType("java_library_host", newMockJavaLibraryModule)
352		ctx.RegisterModuleType("java_device_for_host", newMockJavaLibraryModule)
353		ctx.RegisterModuleType("makefile_goal", newMockMakefileGoalModule)
354	}),
355)
356
357func TestNeverallow(t *testing.T) {
358	for _, test := range neverallowTests {
359		t.Run(test.name, func(t *testing.T) {
360			GroupFixturePreparers(
361				prepareForNeverAllowTest,
362				PrepareForTestWithNeverallowRules(test.rules),
363				test.fs.AddToFixture(),
364			).
365				ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
366				RunTest(t)
367		})
368	}
369}
370
371type mockCcLibraryProperties struct {
372	Include_dirs     []string
373	Vendor_available *bool
374	Static_libs      []string
375	Sdk_version      *string
376	Sdk_variant_only *bool
377
378	Vndk struct {
379		Enabled                *bool
380		Support_system_process *bool
381		Extends                *string
382	}
383
384	Product_variables struct {
385		Enforce_vintf_manifest struct {
386			Cflags []string
387		}
388
389		Treble_linker_namespaces struct {
390			Cflags []string
391		}
392	}
393
394	Platform struct {
395		Shared_libs []string
396	}
397}
398
399type mockCcLibraryModule struct {
400	ModuleBase
401	properties mockCcLibraryProperties
402}
403
404func newMockCcLibraryModule() Module {
405	m := &mockCcLibraryModule{}
406	m.AddProperties(&m.properties)
407	InitAndroidModule(m)
408	return m
409}
410
411type neverallowTestDependencyTag struct {
412	blueprint.BaseDependencyTag
413	name string
414}
415
416var staticDepTag = neverallowTestDependencyTag{name: "static"}
417
418func (c *mockCcLibraryModule) DepsMutator(ctx BottomUpMutatorContext) {
419	for _, lib := range c.properties.Static_libs {
420		ctx.AddDependency(ctx.Module(), staticDepTag, lib)
421	}
422}
423
424func (p *mockCcLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
425}
426
427type mockJavaLibraryProperties struct {
428	Libs           []string
429	Sdk_version    *string
430	Uncompress_dex *bool
431}
432
433type mockJavaLibraryModule struct {
434	ModuleBase
435	properties mockJavaLibraryProperties
436}
437
438func newMockJavaLibraryModule() Module {
439	m := &mockJavaLibraryModule{}
440	m.AddProperties(&m.properties)
441	InitAndroidModule(m)
442	return m
443}
444
445func (p *mockJavaLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
446}
447
448type mockMakefileGoalProperties struct {
449	Product_out_path *string
450}
451
452type mockMakefileGoalModule struct {
453	ModuleBase
454	properties mockMakefileGoalProperties
455}
456
457func newMockMakefileGoalModule() Module {
458	m := &mockMakefileGoalModule{}
459	m.AddProperties(&m.properties)
460	InitAndroidModule(m)
461	return m
462}
463
464func (p *mockMakefileGoalModule) GenerateAndroidBuildActions(ModuleContext) {
465}
466