• 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 apex
16
17import (
18	"io/ioutil"
19	"os"
20	"strings"
21	"testing"
22
23	"github.com/google/blueprint/proptools"
24
25	"android/soong/android"
26	"android/soong/cc"
27	"android/soong/java"
28)
29
30var buildDir string
31
32func testApex(t *testing.T, bp string) *android.TestContext {
33	var config android.Config
34	config, buildDir = setup(t)
35	defer teardown(buildDir)
36
37	ctx := android.NewTestArchContext()
38	ctx.RegisterModuleType("apex", android.ModuleFactoryAdaptor(apexBundleFactory))
39	ctx.RegisterModuleType("apex_test", android.ModuleFactoryAdaptor(testApexBundleFactory))
40	ctx.RegisterModuleType("apex_key", android.ModuleFactoryAdaptor(apexKeyFactory))
41	ctx.RegisterModuleType("apex_defaults", android.ModuleFactoryAdaptor(defaultsFactory))
42	ctx.RegisterModuleType("prebuilt_apex", android.ModuleFactoryAdaptor(PrebuiltFactory))
43	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
44
45	ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
46		ctx.TopDown("apex_deps", apexDepsMutator)
47		ctx.BottomUp("apex", apexMutator)
48		ctx.TopDown("prebuilt_select", android.PrebuiltSelectModuleMutator).Parallel()
49		ctx.BottomUp("prebuilt_postdeps", android.PrebuiltPostDepsMutator).Parallel()
50	})
51
52	ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
53	ctx.RegisterModuleType("cc_library_shared", android.ModuleFactoryAdaptor(cc.LibrarySharedFactory))
54	ctx.RegisterModuleType("cc_library_headers", android.ModuleFactoryAdaptor(cc.LibraryHeaderFactory))
55	ctx.RegisterModuleType("cc_binary", android.ModuleFactoryAdaptor(cc.BinaryFactory))
56	ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(cc.ObjectFactory))
57	ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(cc.LlndkLibraryFactory))
58	ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(cc.ToolchainLibraryFactory))
59	ctx.RegisterModuleType("prebuilt_etc", android.ModuleFactoryAdaptor(android.PrebuiltEtcFactory))
60	ctx.RegisterModuleType("sh_binary", android.ModuleFactoryAdaptor(android.ShBinaryFactory))
61	ctx.RegisterModuleType("android_app_certificate", android.ModuleFactoryAdaptor(java.AndroidAppCertificateFactory))
62	ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(android.FileGroupFactory))
63	ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
64		ctx.BottomUp("prebuilts", android.PrebuiltMutator).Parallel()
65	})
66	ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
67		ctx.BottomUp("image", cc.ImageMutator).Parallel()
68		ctx.BottomUp("link", cc.LinkageMutator).Parallel()
69		ctx.BottomUp("vndk", cc.VndkMutator).Parallel()
70		ctx.BottomUp("version", cc.VersionMutator).Parallel()
71		ctx.BottomUp("begin", cc.BeginMutator).Parallel()
72	})
73
74	ctx.Register()
75
76	bp = bp + `
77		toolchain_library {
78			name: "libcompiler_rt-extras",
79			src: "",
80			vendor_available: true,
81			recovery_available: true,
82		}
83
84		toolchain_library {
85			name: "libatomic",
86			src: "",
87			vendor_available: true,
88			recovery_available: true,
89		}
90
91		toolchain_library {
92			name: "libgcc",
93			src: "",
94			vendor_available: true,
95			recovery_available: true,
96		}
97
98		toolchain_library {
99			name: "libgcc_stripped",
100			src: "",
101			vendor_available: true,
102			recovery_available: true,
103		}
104
105		toolchain_library {
106			name: "libclang_rt.builtins-aarch64-android",
107			src: "",
108			vendor_available: true,
109			recovery_available: true,
110		}
111
112		toolchain_library {
113			name: "libclang_rt.builtins-arm-android",
114			src: "",
115			vendor_available: true,
116			recovery_available: true,
117		}
118
119		cc_object {
120			name: "crtbegin_so",
121			stl: "none",
122			vendor_available: true,
123			recovery_available: true,
124		}
125
126		cc_object {
127			name: "crtend_so",
128			stl: "none",
129			vendor_available: true,
130			recovery_available: true,
131		}
132
133		cc_object {
134			name: "crtbegin_static",
135			stl: "none",
136		}
137
138		cc_object {
139			name: "crtend_android",
140			stl: "none",
141		}
142
143		llndk_library {
144			name: "libc",
145			symbol_file: "",
146		}
147
148		llndk_library {
149			name: "libm",
150			symbol_file: "",
151		}
152
153		llndk_library {
154			name: "libdl",
155			symbol_file: "",
156		}
157	`
158
159	ctx.MockFileSystem(map[string][]byte{
160		"Android.bp":                                        []byte(bp),
161		"build/target/product/security":                     nil,
162		"apex_manifest.json":                                nil,
163		"AndroidManifest.xml":                               nil,
164		"system/sepolicy/apex/myapex-file_contexts":         nil,
165		"system/sepolicy/apex/myapex_keytest-file_contexts": nil,
166		"system/sepolicy/apex/otherapex-file_contexts":      nil,
167		"mylib.cpp":                            nil,
168		"myprebuilt":                           nil,
169		"my_include":                           nil,
170		"vendor/foo/devkeys/test.x509.pem":     nil,
171		"vendor/foo/devkeys/test.pk8":          nil,
172		"testkey.x509.pem":                     nil,
173		"testkey.pk8":                          nil,
174		"testkey.override.x509.pem":            nil,
175		"testkey.override.pk8":                 nil,
176		"vendor/foo/devkeys/testkey.avbpubkey": nil,
177		"vendor/foo/devkeys/testkey.pem":       nil,
178		"NOTICE":                               nil,
179		"custom_notice":                        nil,
180		"testkey2.avbpubkey":                   nil,
181		"testkey2.pem":                         nil,
182		"myapex-arm64.apex":                    nil,
183		"myapex-arm.apex":                      nil,
184		"frameworks/base/api/current.txt":      nil,
185	})
186	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
187	android.FailIfErrored(t, errs)
188	_, errs = ctx.PrepareBuildActions(config)
189	android.FailIfErrored(t, errs)
190
191	return ctx
192}
193
194func setup(t *testing.T) (config android.Config, buildDir string) {
195	buildDir, err := ioutil.TempDir("", "soong_apex_test")
196	if err != nil {
197		t.Fatal(err)
198	}
199
200	config = android.TestArchConfig(buildDir, nil)
201	config.TestProductVariables.DeviceVndkVersion = proptools.StringPtr("current")
202	config.TestProductVariables.DefaultAppCertificate = proptools.StringPtr("vendor/foo/devkeys/test")
203	config.TestProductVariables.CertificateOverrides = []string{"myapex_keytest:myapex.certificate.override"}
204	config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("Q")
205	config.TestProductVariables.Platform_sdk_final = proptools.BoolPtr(false)
206	return
207}
208
209func teardown(buildDir string) {
210	os.RemoveAll(buildDir)
211}
212
213// ensure that 'result' contains 'expected'
214func ensureContains(t *testing.T, result string, expected string) {
215	if !strings.Contains(result, expected) {
216		t.Errorf("%q is not found in %q", expected, result)
217	}
218}
219
220// ensures that 'result' does not contain 'notExpected'
221func ensureNotContains(t *testing.T, result string, notExpected string) {
222	if strings.Contains(result, notExpected) {
223		t.Errorf("%q is found in %q", notExpected, result)
224	}
225}
226
227func ensureListContains(t *testing.T, result []string, expected string) {
228	if !android.InList(expected, result) {
229		t.Errorf("%q is not found in %v", expected, result)
230	}
231}
232
233func ensureListNotContains(t *testing.T, result []string, notExpected string) {
234	if android.InList(notExpected, result) {
235		t.Errorf("%q is found in %v", notExpected, result)
236	}
237}
238
239// Minimal test
240func TestBasicApex(t *testing.T) {
241	ctx := testApex(t, `
242		apex_defaults {
243			name: "myapex-defaults",
244			manifest: ":myapex.manifest",
245			androidManifest: ":myapex.androidmanifest",
246			key: "myapex.key",
247			native_shared_libs: ["mylib"],
248			multilib: {
249				both: {
250					binaries: ["foo",],
251				}
252			}
253		}
254
255		apex {
256			name: "myapex",
257			defaults: ["myapex-defaults"],
258		}
259
260		apex_key {
261			name: "myapex.key",
262			public_key: "testkey.avbpubkey",
263			private_key: "testkey.pem",
264		}
265
266		filegroup {
267			name: "myapex.manifest",
268			srcs: ["apex_manifest.json"],
269		}
270
271		filegroup {
272			name: "myapex.androidmanifest",
273			srcs: ["AndroidManifest.xml"],
274		}
275
276		cc_library {
277			name: "mylib",
278			srcs: ["mylib.cpp"],
279			shared_libs: ["mylib2"],
280			system_shared_libs: [],
281			stl: "none",
282		}
283
284		cc_binary {
285			name: "foo",
286			srcs: ["mylib.cpp"],
287			compile_multilib: "both",
288			multilib: {
289					lib32: {
290							suffix: "32",
291					},
292					lib64: {
293							suffix: "64",
294					},
295			},
296			symlinks: ["foo_link_"],
297			symlink_preferred_arch: true,
298			system_shared_libs: [],
299			static_executable: true,
300			stl: "none",
301		}
302
303		cc_library {
304			name: "mylib2",
305			srcs: ["mylib.cpp"],
306			system_shared_libs: [],
307			stl: "none",
308			notice: "custom_notice",
309		}
310	`)
311
312	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
313
314	optFlags := apexRule.Args["opt_flags"]
315	ensureContains(t, optFlags, "--pubkey vendor/foo/devkeys/testkey.avbpubkey")
316	// Ensure that the NOTICE output is being packaged as an asset.
317	ensureContains(t, optFlags, "--assets_dir "+buildDir+"/.intermediates/myapex/android_common_myapex/NOTICE")
318
319	copyCmds := apexRule.Args["copy_commands"]
320
321	// Ensure that main rule creates an output
322	ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
323
324	// Ensure that apex variant is created for the direct dep
325	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_core_shared_myapex")
326
327	// Ensure that apex variant is created for the indirect dep
328	ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_core_shared_myapex")
329
330	// Ensure that both direct and indirect deps are copied into apex
331	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
332	ensureContains(t, copyCmds, "image.apex/lib64/mylib2.so")
333
334	// Ensure that the platform variant ends with _core_shared
335	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_core_shared")
336	ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_core_shared")
337
338	// Ensure that all symlinks are present.
339	found_foo_link_64 := false
340	found_foo := false
341	for _, cmd := range strings.Split(copyCmds, " && ") {
342		if strings.HasPrefix(cmd, "ln -s foo64") {
343			if strings.HasSuffix(cmd, "bin/foo") {
344				found_foo = true
345			} else if strings.HasSuffix(cmd, "bin/foo_link_64") {
346				found_foo_link_64 = true
347			}
348		}
349	}
350	good := found_foo && found_foo_link_64
351	if !good {
352		t.Errorf("Could not find all expected symlinks! foo: %t, foo_link_64: %t. Command was %s", found_foo, found_foo_link_64, copyCmds)
353	}
354
355	mergeNoticesRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("mergeNoticesRule")
356	noticeInputs := mergeNoticesRule.Inputs.Strings()
357	if len(noticeInputs) != 2 {
358		t.Errorf("number of input notice files: expected = 2, actual = %q", len(noticeInputs))
359	}
360	ensureListContains(t, noticeInputs, "NOTICE")
361	ensureListContains(t, noticeInputs, "custom_notice")
362}
363
364func TestBasicZipApex(t *testing.T) {
365	ctx := testApex(t, `
366		apex {
367			name: "myapex",
368			key: "myapex.key",
369			payload_type: "zip",
370			native_shared_libs: ["mylib"],
371		}
372
373		apex_key {
374			name: "myapex.key",
375			public_key: "testkey.avbpubkey",
376			private_key: "testkey.pem",
377		}
378
379		cc_library {
380			name: "mylib",
381			srcs: ["mylib.cpp"],
382			shared_libs: ["mylib2"],
383			system_shared_libs: [],
384			stl: "none",
385		}
386
387		cc_library {
388			name: "mylib2",
389			srcs: ["mylib.cpp"],
390			system_shared_libs: [],
391			stl: "none",
392		}
393	`)
394
395	zipApexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("zipApexRule")
396	copyCmds := zipApexRule.Args["copy_commands"]
397
398	// Ensure that main rule creates an output
399	ensureContains(t, zipApexRule.Output.String(), "myapex.zipapex.unsigned")
400
401	// Ensure that APEX variant is created for the direct dep
402	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_core_shared_myapex")
403
404	// Ensure that APEX variant is created for the indirect dep
405	ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_core_shared_myapex")
406
407	// Ensure that both direct and indirect deps are copied into apex
408	ensureContains(t, copyCmds, "image.zipapex/lib64/mylib.so")
409	ensureContains(t, copyCmds, "image.zipapex/lib64/mylib2.so")
410}
411
412func TestApexWithStubs(t *testing.T) {
413	ctx := testApex(t, `
414		apex {
415			name: "myapex",
416			key: "myapex.key",
417			native_shared_libs: ["mylib", "mylib3"],
418		}
419
420		apex_key {
421			name: "myapex.key",
422			public_key: "testkey.avbpubkey",
423			private_key: "testkey.pem",
424		}
425
426		cc_library {
427			name: "mylib",
428			srcs: ["mylib.cpp"],
429			shared_libs: ["mylib2", "mylib3"],
430			system_shared_libs: [],
431			stl: "none",
432		}
433
434		cc_library {
435			name: "mylib2",
436			srcs: ["mylib.cpp"],
437			cflags: ["-include mylib.h"],
438			system_shared_libs: [],
439			stl: "none",
440			stubs: {
441				versions: ["1", "2", "3"],
442			},
443		}
444
445		cc_library {
446			name: "mylib3",
447			srcs: ["mylib.cpp"],
448			shared_libs: ["mylib4"],
449			system_shared_libs: [],
450			stl: "none",
451			stubs: {
452				versions: ["10", "11", "12"],
453			},
454		}
455
456		cc_library {
457			name: "mylib4",
458			srcs: ["mylib.cpp"],
459			system_shared_libs: [],
460			stl: "none",
461		}
462	`)
463
464	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
465	copyCmds := apexRule.Args["copy_commands"]
466
467	// Ensure that direct non-stubs dep is always included
468	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
469
470	// Ensure that indirect stubs dep is not included
471	ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
472
473	// Ensure that direct stubs dep is included
474	ensureContains(t, copyCmds, "image.apex/lib64/mylib3.so")
475
476	mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_shared_myapex").Rule("ld").Args["libFlags"]
477
478	// Ensure that mylib is linking with the latest version of stubs for mylib2
479	ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_core_shared_3_myapex/mylib2.so")
480	// ... and not linking to the non-stub (impl) variant of mylib2
481	ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_core_shared_myapex/mylib2.so")
482
483	// Ensure that mylib is linking with the non-stub (impl) of mylib3 (because mylib3 is in the same apex)
484	ensureContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_core_shared_myapex/mylib3.so")
485	// .. and not linking to the stubs variant of mylib3
486	ensureNotContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_core_shared_12_myapex/mylib3.so")
487
488	// Ensure that stubs libs are built without -include flags
489	mylib2Cflags := ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_core_static_myapex").Rule("cc").Args["cFlags"]
490	ensureNotContains(t, mylib2Cflags, "-include ")
491
492	// Ensure that genstub is invoked with --apex
493	ensureContains(t, "--apex", ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_core_static_3_myapex").Rule("genStubSrc").Args["flags"])
494}
495
496func TestApexWithExplicitStubsDependency(t *testing.T) {
497	ctx := testApex(t, `
498		apex {
499			name: "myapex",
500			key: "myapex.key",
501			native_shared_libs: ["mylib"],
502		}
503
504		apex_key {
505			name: "myapex.key",
506			public_key: "testkey.avbpubkey",
507			private_key: "testkey.pem",
508		}
509
510		cc_library {
511			name: "mylib",
512			srcs: ["mylib.cpp"],
513			shared_libs: ["libfoo#10"],
514			system_shared_libs: [],
515			stl: "none",
516		}
517
518		cc_library {
519			name: "libfoo",
520			srcs: ["mylib.cpp"],
521			shared_libs: ["libbar"],
522			system_shared_libs: [],
523			stl: "none",
524			stubs: {
525				versions: ["10", "20", "30"],
526			},
527		}
528
529		cc_library {
530			name: "libbar",
531			srcs: ["mylib.cpp"],
532			system_shared_libs: [],
533			stl: "none",
534		}
535
536	`)
537
538	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
539	copyCmds := apexRule.Args["copy_commands"]
540
541	// Ensure that direct non-stubs dep is always included
542	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
543
544	// Ensure that indirect stubs dep is not included
545	ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo.so")
546
547	// Ensure that dependency of stubs is not included
548	ensureNotContains(t, copyCmds, "image.apex/lib64/libbar.so")
549
550	mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_shared_myapex").Rule("ld").Args["libFlags"]
551
552	// Ensure that mylib is linking with version 10 of libfoo
553	ensureContains(t, mylibLdFlags, "libfoo/android_arm64_armv8-a_core_shared_10_myapex/libfoo.so")
554	// ... and not linking to the non-stub (impl) variant of libfoo
555	ensureNotContains(t, mylibLdFlags, "libfoo/android_arm64_armv8-a_core_shared_myapex/libfoo.so")
556
557	libFooStubsLdFlags := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_core_shared_10_myapex").Rule("ld").Args["libFlags"]
558
559	// Ensure that libfoo stubs is not linking to libbar (since it is a stubs)
560	ensureNotContains(t, libFooStubsLdFlags, "libbar.so")
561}
562
563func TestApexWithSystemLibsStubs(t *testing.T) {
564	ctx := testApex(t, `
565		apex {
566			name: "myapex",
567			key: "myapex.key",
568			native_shared_libs: ["mylib", "mylib_shared", "libdl", "libm"],
569		}
570
571		apex_key {
572			name: "myapex.key",
573			public_key: "testkey.avbpubkey",
574			private_key: "testkey.pem",
575		}
576
577		cc_library {
578			name: "mylib",
579			srcs: ["mylib.cpp"],
580			shared_libs: ["libdl#27"],
581			stl: "none",
582		}
583
584		cc_library_shared {
585			name: "mylib_shared",
586			srcs: ["mylib.cpp"],
587			shared_libs: ["libdl#27"],
588			stl: "none",
589		}
590
591		cc_library {
592			name: "libc",
593			no_libgcc: true,
594			nocrt: true,
595			system_shared_libs: [],
596			stl: "none",
597			stubs: {
598				versions: ["27", "28", "29"],
599			},
600		}
601
602		cc_library {
603			name: "libm",
604			no_libgcc: true,
605			nocrt: true,
606			system_shared_libs: [],
607			stl: "none",
608			stubs: {
609				versions: ["27", "28", "29"],
610			},
611		}
612
613		cc_library {
614			name: "libdl",
615			no_libgcc: true,
616			nocrt: true,
617			system_shared_libs: [],
618			stl: "none",
619			stubs: {
620				versions: ["27", "28", "29"],
621			},
622		}
623
624		cc_library {
625			name: "libBootstrap",
626			srcs: ["mylib.cpp"],
627			stl: "none",
628			bootstrap: true,
629		}
630	`)
631
632	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
633	copyCmds := apexRule.Args["copy_commands"]
634
635	// Ensure that mylib, libm, libdl are included.
636	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
637	ensureContains(t, copyCmds, "image.apex/lib64/bionic/libm.so")
638	ensureContains(t, copyCmds, "image.apex/lib64/bionic/libdl.so")
639
640	// Ensure that libc is not included (since it has stubs and not listed in native_shared_libs)
641	ensureNotContains(t, copyCmds, "image.apex/lib64/bionic/libc.so")
642
643	mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_shared_myapex").Rule("ld").Args["libFlags"]
644	mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_static_myapex").Rule("cc").Args["cFlags"]
645	mylibSharedCFlags := ctx.ModuleForTests("mylib_shared", "android_arm64_armv8-a_core_shared_myapex").Rule("cc").Args["cFlags"]
646
647	// For dependency to libc
648	// Ensure that mylib is linking with the latest version of stubs
649	ensureContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_core_shared_29_myapex/libc.so")
650	// ... and not linking to the non-stub (impl) variant
651	ensureNotContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_core_shared_myapex/libc.so")
652	// ... Cflags from stub is correctly exported to mylib
653	ensureContains(t, mylibCFlags, "__LIBC_API__=29")
654	ensureContains(t, mylibSharedCFlags, "__LIBC_API__=29")
655
656	// For dependency to libm
657	// Ensure that mylib is linking with the non-stub (impl) variant
658	ensureContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_core_shared_myapex/libm.so")
659	// ... and not linking to the stub variant
660	ensureNotContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_core_shared_29_myapex/libm.so")
661	// ... and is not compiling with the stub
662	ensureNotContains(t, mylibCFlags, "__LIBM_API__=29")
663	ensureNotContains(t, mylibSharedCFlags, "__LIBM_API__=29")
664
665	// For dependency to libdl
666	// Ensure that mylib is linking with the specified version of stubs
667	ensureContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_core_shared_27_myapex/libdl.so")
668	// ... and not linking to the other versions of stubs
669	ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_core_shared_28_myapex/libdl.so")
670	ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_core_shared_29_myapex/libdl.so")
671	// ... and not linking to the non-stub (impl) variant
672	ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_core_shared_myapex/libdl.so")
673	// ... Cflags from stub is correctly exported to mylib
674	ensureContains(t, mylibCFlags, "__LIBDL_API__=27")
675	ensureContains(t, mylibSharedCFlags, "__LIBDL_API__=27")
676
677	// Ensure that libBootstrap is depending on the platform variant of bionic libs
678	libFlags := ctx.ModuleForTests("libBootstrap", "android_arm64_armv8-a_core_shared").Rule("ld").Args["libFlags"]
679	ensureContains(t, libFlags, "libc/android_arm64_armv8-a_core_shared/libc.so")
680	ensureContains(t, libFlags, "libm/android_arm64_armv8-a_core_shared/libm.so")
681	ensureContains(t, libFlags, "libdl/android_arm64_armv8-a_core_shared/libdl.so")
682}
683
684func TestFilesInSubDir(t *testing.T) {
685	ctx := testApex(t, `
686		apex {
687			name: "myapex",
688			key: "myapex.key",
689			native_shared_libs: ["mylib"],
690			binaries: ["mybin"],
691			prebuilts: ["myetc"],
692			compile_multilib: "both",
693		}
694
695		apex_key {
696			name: "myapex.key",
697			public_key: "testkey.avbpubkey",
698			private_key: "testkey.pem",
699		}
700
701		prebuilt_etc {
702			name: "myetc",
703			src: "myprebuilt",
704			sub_dir: "foo/bar",
705		}
706
707		cc_library {
708			name: "mylib",
709			srcs: ["mylib.cpp"],
710			relative_install_path: "foo/bar",
711			system_shared_libs: [],
712			stl: "none",
713		}
714
715		cc_binary {
716			name: "mybin",
717			srcs: ["mylib.cpp"],
718			relative_install_path: "foo/bar",
719			system_shared_libs: [],
720			static_executable: true,
721			stl: "none",
722		}
723	`)
724
725	generateFsRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("generateFsConfig")
726	dirs := strings.Split(generateFsRule.Args["exec_paths"], " ")
727
728	// Ensure that the subdirectories are all listed
729	ensureListContains(t, dirs, "etc")
730	ensureListContains(t, dirs, "etc/foo")
731	ensureListContains(t, dirs, "etc/foo/bar")
732	ensureListContains(t, dirs, "lib64")
733	ensureListContains(t, dirs, "lib64/foo")
734	ensureListContains(t, dirs, "lib64/foo/bar")
735	ensureListContains(t, dirs, "lib")
736	ensureListContains(t, dirs, "lib/foo")
737	ensureListContains(t, dirs, "lib/foo/bar")
738
739	ensureListContains(t, dirs, "bin")
740	ensureListContains(t, dirs, "bin/foo")
741	ensureListContains(t, dirs, "bin/foo/bar")
742}
743
744func TestUseVendor(t *testing.T) {
745	ctx := testApex(t, `
746		apex {
747			name: "myapex",
748			key: "myapex.key",
749			native_shared_libs: ["mylib"],
750			use_vendor: true,
751		}
752
753		apex_key {
754			name: "myapex.key",
755			public_key: "testkey.avbpubkey",
756			private_key: "testkey.pem",
757		}
758
759		cc_library {
760			name: "mylib",
761			srcs: ["mylib.cpp"],
762			shared_libs: ["mylib2"],
763			system_shared_libs: [],
764			vendor_available: true,
765			stl: "none",
766		}
767
768		cc_library {
769			name: "mylib2",
770			srcs: ["mylib.cpp"],
771			system_shared_libs: [],
772			vendor_available: true,
773			stl: "none",
774		}
775	`)
776
777	inputsList := []string{}
778	for _, i := range ctx.ModuleForTests("myapex", "android_common_myapex").Module().BuildParamsForTests() {
779		for _, implicit := range i.Implicits {
780			inputsList = append(inputsList, implicit.String())
781		}
782	}
783	inputsString := strings.Join(inputsList, " ")
784
785	// ensure that the apex includes vendor variants of the direct and indirect deps
786	ensureContains(t, inputsString, "android_arm64_armv8-a_vendor_shared_myapex/mylib.so")
787	ensureContains(t, inputsString, "android_arm64_armv8-a_vendor_shared_myapex/mylib2.so")
788
789	// ensure that the apex does not include core variants
790	ensureNotContains(t, inputsString, "android_arm64_armv8-a_core_shared_myapex/mylib.so")
791	ensureNotContains(t, inputsString, "android_arm64_armv8-a_core_shared_myapex/mylib2.so")
792}
793
794func TestStaticLinking(t *testing.T) {
795	ctx := testApex(t, `
796		apex {
797			name: "myapex",
798			key: "myapex.key",
799			native_shared_libs: ["mylib"],
800		}
801
802		apex_key {
803			name: "myapex.key",
804			public_key: "testkey.avbpubkey",
805			private_key: "testkey.pem",
806		}
807
808		cc_library {
809			name: "mylib",
810			srcs: ["mylib.cpp"],
811			system_shared_libs: [],
812			stl: "none",
813			stubs: {
814				versions: ["1", "2", "3"],
815			},
816		}
817
818		cc_binary {
819			name: "not_in_apex",
820			srcs: ["mylib.cpp"],
821			static_libs: ["mylib"],
822			static_executable: true,
823			system_shared_libs: [],
824			stl: "none",
825		}
826	`)
827
828	ldFlags := ctx.ModuleForTests("not_in_apex", "android_arm64_armv8-a_core").Rule("ld").Args["libFlags"]
829
830	// Ensure that not_in_apex is linking with the static variant of mylib
831	ensureContains(t, ldFlags, "mylib/android_arm64_armv8-a_core_static/mylib.a")
832}
833
834func TestKeys(t *testing.T) {
835	ctx := testApex(t, `
836		apex {
837			name: "myapex_keytest",
838			key: "myapex.key",
839			certificate: ":myapex.certificate",
840			native_shared_libs: ["mylib"],
841		}
842
843		cc_library {
844			name: "mylib",
845			srcs: ["mylib.cpp"],
846			system_shared_libs: [],
847			stl: "none",
848		}
849
850		apex_key {
851			name: "myapex.key",
852			public_key: "testkey.avbpubkey",
853			private_key: "testkey.pem",
854		}
855
856		android_app_certificate {
857			name: "myapex.certificate",
858			certificate: "testkey",
859		}
860
861		android_app_certificate {
862			name: "myapex.certificate.override",
863			certificate: "testkey.override",
864		}
865
866	`)
867
868	// check the APEX keys
869	keys := ctx.ModuleForTests("myapex.key", "android_common").Module().(*apexKey)
870
871	if keys.public_key_file.String() != "vendor/foo/devkeys/testkey.avbpubkey" {
872		t.Errorf("public key %q is not %q", keys.public_key_file.String(),
873			"vendor/foo/devkeys/testkey.avbpubkey")
874	}
875	if keys.private_key_file.String() != "vendor/foo/devkeys/testkey.pem" {
876		t.Errorf("private key %q is not %q", keys.private_key_file.String(),
877			"vendor/foo/devkeys/testkey.pem")
878	}
879
880	// check the APK certs. It should be overridden to myapex.certificate.override
881	certs := ctx.ModuleForTests("myapex_keytest", "android_common_myapex_keytest").Rule("signapk").Args["certificates"]
882	if certs != "testkey.override.x509.pem testkey.override.pk8" {
883		t.Errorf("cert and private key %q are not %q", certs,
884			"testkey.override.509.pem testkey.override.pk8")
885	}
886}
887
888func TestMacro(t *testing.T) {
889	ctx := testApex(t, `
890		apex {
891			name: "myapex",
892			key: "myapex.key",
893			native_shared_libs: ["mylib"],
894		}
895
896		apex {
897			name: "otherapex",
898			key: "myapex.key",
899			native_shared_libs: ["mylib"],
900		}
901
902		apex_key {
903			name: "myapex.key",
904			public_key: "testkey.avbpubkey",
905			private_key: "testkey.pem",
906		}
907
908		cc_library {
909			name: "mylib",
910			srcs: ["mylib.cpp"],
911			system_shared_libs: [],
912			stl: "none",
913		}
914	`)
915
916	// non-APEX variant does not have __ANDROID__APEX__ defined
917	mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_static").Rule("cc").Args["cFlags"]
918	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__=myapex")
919	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__=otherapex")
920
921	// APEX variant has __ANDROID_APEX__=<apexname> defined
922	mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_static_myapex").Rule("cc").Args["cFlags"]
923	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__=myapex")
924	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__=otherapex")
925
926	// APEX variant has __ANDROID_APEX__=<apexname> defined
927	mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_static_otherapex").Rule("cc").Args["cFlags"]
928	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__=myapex")
929	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__=otherapex")
930}
931
932func TestHeaderLibsDependency(t *testing.T) {
933	ctx := testApex(t, `
934		apex {
935			name: "myapex",
936			key: "myapex.key",
937			native_shared_libs: ["mylib"],
938		}
939
940		apex_key {
941			name: "myapex.key",
942			public_key: "testkey.avbpubkey",
943			private_key: "testkey.pem",
944		}
945
946		cc_library_headers {
947			name: "mylib_headers",
948			export_include_dirs: ["my_include"],
949			system_shared_libs: [],
950			stl: "none",
951		}
952
953		cc_library {
954			name: "mylib",
955			srcs: ["mylib.cpp"],
956			system_shared_libs: [],
957			stl: "none",
958			header_libs: ["mylib_headers"],
959			export_header_lib_headers: ["mylib_headers"],
960			stubs: {
961				versions: ["1", "2", "3"],
962			},
963		}
964
965		cc_library {
966			name: "otherlib",
967			srcs: ["mylib.cpp"],
968			system_shared_libs: [],
969			stl: "none",
970			shared_libs: ["mylib"],
971		}
972	`)
973
974	cFlags := ctx.ModuleForTests("otherlib", "android_arm64_armv8-a_core_static").Rule("cc").Args["cFlags"]
975
976	// Ensure that the include path of the header lib is exported to 'otherlib'
977	ensureContains(t, cFlags, "-Imy_include")
978}
979
980func TestNonTestApex(t *testing.T) {
981	ctx := testApex(t, `
982		apex {
983			name: "myapex",
984			key: "myapex.key",
985			native_shared_libs: ["mylib_common"],
986		}
987
988		apex_key {
989			name: "myapex.key",
990			public_key: "testkey.avbpubkey",
991			private_key: "testkey.pem",
992		}
993
994		cc_library {
995			name: "mylib_common",
996			srcs: ["mylib.cpp"],
997			system_shared_libs: [],
998			stl: "none",
999		}
1000	`)
1001
1002	module := ctx.ModuleForTests("myapex", "android_common_myapex")
1003	apexRule := module.Rule("apexRule")
1004	copyCmds := apexRule.Args["copy_commands"]
1005
1006	if apex, ok := module.Module().(*apexBundle); !ok || apex.testApex {
1007		t.Log("Apex was a test apex!")
1008		t.Fail()
1009	}
1010	// Ensure that main rule creates an output
1011	ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
1012
1013	// Ensure that apex variant is created for the direct dep
1014	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_core_shared_myapex")
1015
1016	// Ensure that both direct and indirect deps are copied into apex
1017	ensureContains(t, copyCmds, "image.apex/lib64/mylib_common.so")
1018
1019	// Ensure that the platform variant ends with _core_shared
1020	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_core_shared")
1021
1022	if !android.InAnyApex("mylib_common") {
1023		t.Log("Found mylib_common not in any apex!")
1024		t.Fail()
1025	}
1026}
1027
1028func TestTestApex(t *testing.T) {
1029	if android.InAnyApex("mylib_common_test") {
1030		t.Fatal("mylib_common_test must not be used in any other tests since this checks that global state is not updated in an illegal way!")
1031	}
1032	ctx := testApex(t, `
1033		apex_test {
1034			name: "myapex",
1035			key: "myapex.key",
1036			native_shared_libs: ["mylib_common_test"],
1037		}
1038
1039		apex_key {
1040			name: "myapex.key",
1041			public_key: "testkey.avbpubkey",
1042			private_key: "testkey.pem",
1043		}
1044
1045		cc_library {
1046			name: "mylib_common_test",
1047			srcs: ["mylib.cpp"],
1048			system_shared_libs: [],
1049			stl: "none",
1050		}
1051	`)
1052
1053	module := ctx.ModuleForTests("myapex", "android_common_myapex")
1054	apexRule := module.Rule("apexRule")
1055	copyCmds := apexRule.Args["copy_commands"]
1056
1057	if apex, ok := module.Module().(*apexBundle); !ok || !apex.testApex {
1058		t.Log("Apex was not a test apex!")
1059		t.Fail()
1060	}
1061	// Ensure that main rule creates an output
1062	ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
1063
1064	// Ensure that apex variant is created for the direct dep
1065	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common_test"), "android_arm64_armv8-a_core_shared_myapex")
1066
1067	// Ensure that both direct and indirect deps are copied into apex
1068	ensureContains(t, copyCmds, "image.apex/lib64/mylib_common_test.so")
1069
1070	// Ensure that the platform variant ends with _core_shared
1071	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common_test"), "android_arm64_armv8-a_core_shared")
1072
1073	if android.InAnyApex("mylib_common_test") {
1074		t.Log("Found mylib_common_test in some apex!")
1075		t.Fail()
1076	}
1077}
1078
1079func TestApexWithTarget(t *testing.T) {
1080	ctx := testApex(t, `
1081		apex {
1082			name: "myapex",
1083			key: "myapex.key",
1084			multilib: {
1085				first: {
1086					native_shared_libs: ["mylib_common"],
1087				}
1088			},
1089			target: {
1090				android: {
1091					multilib: {
1092						first: {
1093							native_shared_libs: ["mylib"],
1094						}
1095					}
1096				},
1097				host: {
1098					multilib: {
1099						first: {
1100							native_shared_libs: ["mylib2"],
1101						}
1102					}
1103				}
1104			}
1105		}
1106
1107		apex_key {
1108			name: "myapex.key",
1109			public_key: "testkey.avbpubkey",
1110			private_key: "testkey.pem",
1111		}
1112
1113		cc_library {
1114			name: "mylib",
1115			srcs: ["mylib.cpp"],
1116			system_shared_libs: [],
1117			stl: "none",
1118		}
1119
1120		cc_library {
1121			name: "mylib_common",
1122			srcs: ["mylib.cpp"],
1123			system_shared_libs: [],
1124			stl: "none",
1125			compile_multilib: "first",
1126		}
1127
1128		cc_library {
1129			name: "mylib2",
1130			srcs: ["mylib.cpp"],
1131			system_shared_libs: [],
1132			stl: "none",
1133			compile_multilib: "first",
1134		}
1135	`)
1136
1137	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
1138	copyCmds := apexRule.Args["copy_commands"]
1139
1140	// Ensure that main rule creates an output
1141	ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
1142
1143	// Ensure that apex variant is created for the direct dep
1144	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_core_shared_myapex")
1145	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_core_shared_myapex")
1146	ensureListNotContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_core_shared_myapex")
1147
1148	// Ensure that both direct and indirect deps are copied into apex
1149	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
1150	ensureContains(t, copyCmds, "image.apex/lib64/mylib_common.so")
1151	ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
1152
1153	// Ensure that the platform variant ends with _core_shared
1154	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_core_shared")
1155	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_core_shared")
1156	ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_core_shared")
1157}
1158
1159func TestApexWithShBinary(t *testing.T) {
1160	ctx := testApex(t, `
1161		apex {
1162			name: "myapex",
1163			key: "myapex.key",
1164			binaries: ["myscript"],
1165		}
1166
1167		apex_key {
1168			name: "myapex.key",
1169			public_key: "testkey.avbpubkey",
1170			private_key: "testkey.pem",
1171		}
1172
1173		sh_binary {
1174			name: "myscript",
1175			src: "mylib.cpp",
1176			filename: "myscript.sh",
1177			sub_dir: "script",
1178		}
1179	`)
1180
1181	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
1182	copyCmds := apexRule.Args["copy_commands"]
1183
1184	ensureContains(t, copyCmds, "image.apex/bin/script/myscript.sh")
1185}
1186
1187func TestApexInProductPartition(t *testing.T) {
1188	ctx := testApex(t, `
1189		apex {
1190			name: "myapex",
1191			key: "myapex.key",
1192			native_shared_libs: ["mylib"],
1193			product_specific: true,
1194		}
1195
1196		apex_key {
1197			name: "myapex.key",
1198			public_key: "testkey.avbpubkey",
1199			private_key: "testkey.pem",
1200			product_specific: true,
1201		}
1202
1203		cc_library {
1204			name: "mylib",
1205			srcs: ["mylib.cpp"],
1206			system_shared_libs: [],
1207			stl: "none",
1208		}
1209	`)
1210
1211	apex := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*apexBundle)
1212	expected := "target/product/test_device/product/apex"
1213	actual := apex.installDir.RelPathString()
1214	if actual != expected {
1215		t.Errorf("wrong install path. expected %q. actual %q", expected, actual)
1216	}
1217}
1218
1219func TestApexKeyFromOtherModule(t *testing.T) {
1220	ctx := testApex(t, `
1221		apex_key {
1222			name: "myapex.key",
1223			public_key: ":my.avbpubkey",
1224			private_key: ":my.pem",
1225			product_specific: true,
1226		}
1227
1228		filegroup {
1229			name: "my.avbpubkey",
1230			srcs: ["testkey2.avbpubkey"],
1231		}
1232
1233		filegroup {
1234			name: "my.pem",
1235			srcs: ["testkey2.pem"],
1236		}
1237	`)
1238
1239	apex_key := ctx.ModuleForTests("myapex.key", "android_common").Module().(*apexKey)
1240	expected_pubkey := "testkey2.avbpubkey"
1241	actual_pubkey := apex_key.public_key_file.String()
1242	if actual_pubkey != expected_pubkey {
1243		t.Errorf("wrong public key path. expected %q. actual %q", expected_pubkey, actual_pubkey)
1244	}
1245	expected_privkey := "testkey2.pem"
1246	actual_privkey := apex_key.private_key_file.String()
1247	if actual_privkey != expected_privkey {
1248		t.Errorf("wrong private key path. expected %q. actual %q", expected_privkey, actual_privkey)
1249	}
1250}
1251
1252func TestPrebuilt(t *testing.T) {
1253	ctx := testApex(t, `
1254		prebuilt_apex {
1255			name: "myapex",
1256			arch: {
1257				arm64: {
1258					src: "myapex-arm64.apex",
1259				},
1260				arm: {
1261					src: "myapex-arm.apex",
1262				},
1263			},
1264		}
1265	`)
1266
1267	prebuilt := ctx.ModuleForTests("myapex", "android_common").Module().(*Prebuilt)
1268
1269	expectedInput := "myapex-arm64.apex"
1270	if prebuilt.inputApex.String() != expectedInput {
1271		t.Errorf("inputApex invalid. expected: %q, actual: %q", expectedInput, prebuilt.inputApex.String())
1272	}
1273}
1274
1275func TestPrebuiltFilenameOverride(t *testing.T) {
1276	ctx := testApex(t, `
1277		prebuilt_apex {
1278			name: "myapex",
1279			src: "myapex-arm.apex",
1280			filename: "notmyapex.apex",
1281		}
1282	`)
1283
1284	p := ctx.ModuleForTests("myapex", "android_common").Module().(*Prebuilt)
1285
1286	expected := "notmyapex.apex"
1287	if p.installFilename != expected {
1288		t.Errorf("installFilename invalid. expected: %q, actual: %q", expected, p.installFilename)
1289	}
1290}
1291