• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2022 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.
14package apex
15
16import (
17	"android/soong/android"
18	"android/soong/bazel/cquery"
19	"strings"
20	"testing"
21)
22
23func TestApexImageInMixedBuilds(t *testing.T) {
24	bp := `
25apex_key{
26	name: "foo_key",
27}
28
29apex {
30	name: "foo",
31	key: "foo_key",
32	updatable: true,
33	min_sdk_version: "31",
34	file_contexts: ":myapex-file_contexts",
35	bazel_module: { label: "//:foo" },
36}`
37
38	outputBaseDir := "out/bazel"
39	result := android.GroupFixturePreparers(
40		prepareForApexTest,
41		android.FixtureModifyConfig(func(config android.Config) {
42			config.BazelContext = android.MockBazelContext{
43				OutputBaseDir: outputBaseDir,
44				LabelToApexInfo: map[string]cquery.ApexInfo{
45					"//:foo": cquery.ApexInfo{
46						// ApexInfo Starlark provider.
47						SignedOutput:           "signed_out.apex",
48						SignedCompressedOutput: "signed_out.capex",
49						UnsignedOutput:         "unsigned_out.apex",
50						BundleKeyInfo:          []string{"public_key", "private_key"},
51						ContainerKeyInfo:       []string{"container_cert", "container_private"},
52						SymbolsUsedByApex:      "foo_using.txt",
53						JavaSymbolsUsedByApex:  "foo_using.xml",
54						BundleFile:             "apex_bundle.zip",
55						InstalledFiles:         "installed-files.txt",
56						RequiresLibs:           []string{"//path/c:c", "//path/d:d"},
57
58						// unused
59						PackageName:  "pkg_name",
60						ProvidesLibs: []string{"a", "b"},
61
62						// ApexMkInfo Starlark provider
63						PayloadFilesInfo: []map[string]string{
64							{
65								"built_file":       "bazel-out/adbd",
66								"install_dir":      "bin",
67								"class":            "nativeExecutable",
68								"make_module_name": "adbd",
69								"basename":         "adbd",
70								"package":          "foo",
71							},
72						},
73						MakeModulesToInstall: []string{"c"}, // d deliberately omitted
74					},
75				},
76			}
77		}),
78	).RunTestWithBp(t, bp)
79
80	m := result.ModuleForTests("foo", "android_common_foo_image").Module()
81	ab, ok := m.(*apexBundle)
82
83	if !ok {
84		t.Fatalf("Expected module to be an apexBundle, was not")
85	}
86
87	// TODO: refactor to android.AssertStringEquals
88	if w, g := "out/bazel/execroot/__main__/public_key", ab.publicKeyFile.String(); w != g {
89		t.Errorf("Expected public key %q, got %q", w, g)
90	}
91
92	if w, g := "out/bazel/execroot/__main__/private_key", ab.privateKeyFile.String(); w != g {
93		t.Errorf("Expected private key %q, got %q", w, g)
94	}
95
96	if w, g := "out/bazel/execroot/__main__/container_cert", ab.containerCertificateFile.String(); w != g {
97		t.Errorf("Expected public container key %q, got %q", w, g)
98	}
99
100	if w, g := "out/bazel/execroot/__main__/container_private", ab.containerPrivateKeyFile.String(); w != g {
101		t.Errorf("Expected private container key %q, got %q", w, g)
102	}
103
104	if w, g := "out/bazel/execroot/__main__/signed_out.apex", ab.outputFile.String(); w != g {
105		t.Errorf("Expected output file %q, got %q", w, g)
106	}
107
108	if w, g := "out/bazel/execroot/__main__/foo_using.txt", ab.nativeApisUsedByModuleFile.String(); w != g {
109		t.Errorf("Expected output file %q, got %q", w, g)
110	}
111
112	if w, g := "out/bazel/execroot/__main__/foo_using.xml", ab.javaApisUsedByModuleFile.String(); w != g {
113		t.Errorf("Expected output file %q, got %q", w, g)
114	}
115
116	if w, g := "out/bazel/execroot/__main__/installed-files.txt", ab.installedFilesFile.String(); w != g {
117		t.Errorf("Expected installed-files.txt %q, got %q", w, g)
118	}
119
120	mkData := android.AndroidMkDataForTest(t, result.TestContext, m)
121	var builder strings.Builder
122	mkData.Custom(&builder, "foo", "BAZEL_TARGET_", "", mkData)
123
124	data := builder.String()
125	if w := "ALL_MODULES.$(my_register_name).BUNDLE := out/bazel/execroot/__main__/apex_bundle.zip"; !strings.Contains(data, w) {
126		t.Errorf("Expected %q in androidmk data, but did not find %q", w, data)
127	}
128	if w := "$(call dist-for-goals,checkbuild,out/bazel/execroot/__main__/installed-files.txt:foo-installed-files.txt)"; !strings.Contains(data, w) {
129		t.Errorf("Expected %q in androidmk data, but did not find %q", w, data)
130	}
131
132	// make modules to be installed to system
133	if len(ab.makeModulesToInstall) != 1 && ab.makeModulesToInstall[0] != "c" {
134		t.Errorf("Expected makeModulesToInstall slice to only contain 'c', got %q", ab.makeModulesToInstall)
135	}
136	if w := "LOCAL_REQUIRED_MODULES := adbd.foo c"; !strings.Contains(data, w) {
137		t.Errorf("Expected %q in androidmk data, but did not find it in %q", w, data)
138	}
139}
140
141func TestApexImageCreatesFilesInfoForMake(t *testing.T) {
142	bp := `
143apex_key{
144	name: "foo_key",
145}
146
147apex {
148	name: "foo",
149	key: "foo_key",
150	updatable: true,
151	min_sdk_version: "31",
152	file_contexts: ":myapex-file_contexts",
153	bazel_module: { label: "//:foo" },
154}`
155
156	outputBaseDir := "out/bazel"
157	result := android.GroupFixturePreparers(
158		prepareForApexTest,
159		android.FixtureModifyConfig(func(config android.Config) {
160			config.BazelContext = android.MockBazelContext{
161				OutputBaseDir: outputBaseDir,
162				LabelToApexInfo: map[string]cquery.ApexInfo{
163					"//:foo": {
164						// ApexInfo Starlark provider. Necessary for the test.
165						SignedOutput:     "signed_out.apex",
166						BundleKeyInfo:    []string{"public_key", "private_key"},
167						ContainerKeyInfo: []string{"container_cert", "container_private"},
168
169						// ApexMkInfo Starlark provider
170						PayloadFilesInfo: []map[string]string{
171							{
172								"arch":                  "arm64",
173								"basename":              "libcrypto.so",
174								"built_file":            "bazel-out/64/libcrypto.so",
175								"class":                 "nativeSharedLib",
176								"install_dir":           "lib64",
177								"make_module_name":      "libcrypto",
178								"package":               "foo/bar",
179								"unstripped_built_file": "bazel-out/64/unstripped_libcrypto.so",
180							},
181							{
182								"arch":             "arm",
183								"basename":         "libcrypto.so",
184								"built_file":       "bazel-out/32/libcrypto.so",
185								"class":            "nativeSharedLib",
186								"install_dir":      "lib",
187								"make_module_name": "libcrypto",
188								"package":          "foo/bar",
189							},
190							{
191								"arch":             "arm64",
192								"basename":         "adbd",
193								"built_file":       "bazel-out/adbd",
194								"class":            "nativeExecutable",
195								"install_dir":      "bin",
196								"make_module_name": "adbd",
197								"package":          "foo",
198							},
199						},
200					},
201				},
202			}
203		}),
204	).RunTestWithBp(t, bp)
205
206	m := result.ModuleForTests("foo", "android_common_foo_image").Module()
207	ab, ok := m.(*apexBundle)
208
209	if !ok {
210		t.Fatalf("Expected module to be an apexBundle, was not")
211	}
212
213	expectedFilesInfo := []apexFile{
214		{
215			androidMkModuleName: "libcrypto",
216			builtFile:           android.PathForTesting("out/bazel/execroot/__main__/bazel-out/64/libcrypto.so"),
217			class:               nativeSharedLib,
218			customStem:          "libcrypto.so",
219			installDir:          "lib64",
220			moduleDir:           "foo/bar",
221			arch:                "arm64",
222			unstrippedBuiltFile: android.PathForTesting("out/bazel/execroot/__main__/bazel-out/64/unstripped_libcrypto.so"),
223		},
224		{
225			androidMkModuleName: "libcrypto",
226			builtFile:           android.PathForTesting("out/bazel/execroot/__main__/bazel-out/32/libcrypto.so"),
227			class:               nativeSharedLib,
228			customStem:          "libcrypto.so",
229			installDir:          "lib",
230			moduleDir:           "foo/bar",
231			arch:                "arm",
232		},
233		{
234			androidMkModuleName: "adbd",
235			builtFile:           android.PathForTesting("out/bazel/execroot/__main__/bazel-out/adbd"),
236			class:               nativeExecutable,
237			customStem:          "adbd",
238			installDir:          "bin",
239			moduleDir:           "foo",
240			arch:                "arm64",
241		},
242	}
243
244	if len(ab.filesInfo) != len(expectedFilesInfo) {
245		t.Errorf("Expected %d entries in ab.filesInfo, but got %d", len(ab.filesInfo), len(expectedFilesInfo))
246	}
247
248	for idx, f := range ab.filesInfo {
249		expected := expectedFilesInfo[idx]
250		android.AssertSame(t, "different class", expected.class, f.class)
251		android.AssertStringEquals(t, "different built file", expected.builtFile.String(), f.builtFile.String())
252		android.AssertStringEquals(t, "different custom stem", expected.customStem, f.customStem)
253		android.AssertStringEquals(t, "different install dir", expected.installDir, f.installDir)
254		android.AssertStringEquals(t, "different make module name", expected.androidMkModuleName, f.androidMkModuleName)
255		android.AssertStringEquals(t, "different moduleDir", expected.moduleDir, f.moduleDir)
256		android.AssertStringEquals(t, "different arch", expected.arch, f.arch)
257		if expected.unstrippedBuiltFile != nil {
258			if f.unstrippedBuiltFile == nil {
259				t.Errorf("expected an unstripped built file path.")
260			}
261			android.AssertStringEquals(t, "different unstripped built file", expected.unstrippedBuiltFile.String(), f.unstrippedBuiltFile.String())
262		}
263	}
264}
265
266func TestCompressedApexImageInMixedBuilds(t *testing.T) {
267	bp := `
268apex_key{
269	name: "foo_key",
270}
271apex {
272	name: "foo",
273	key: "foo_key",
274	updatable: true,
275	min_sdk_version: "31",
276	file_contexts: ":myapex-file_contexts",
277	bazel_module: { label: "//:foo" },
278	test_only_force_compression: true, // force compression
279}`
280
281	outputBaseDir := "out/bazel"
282	result := android.GroupFixturePreparers(
283		prepareForApexTest,
284		android.FixtureModifyConfig(func(config android.Config) {
285			config.BazelContext = android.MockBazelContext{
286				OutputBaseDir: outputBaseDir,
287				LabelToApexInfo: map[string]cquery.ApexInfo{
288					"//:foo": cquery.ApexInfo{
289						SignedOutput:           "signed_out.apex",
290						SignedCompressedOutput: "signed_out.capex",
291						BundleKeyInfo:          []string{"public_key", "private_key"},
292						ContainerKeyInfo:       []string{"container_cert", "container_private"},
293					},
294				},
295			}
296		}),
297	).RunTestWithBp(t, bp)
298
299	m := result.ModuleForTests("foo", "android_common_foo_image").Module()
300	ab, ok := m.(*apexBundle)
301	if !ok {
302		t.Fatalf("Expected module to be an apexBundle, was not")
303	}
304
305	if w, g := "out/bazel/execroot/__main__/signed_out.capex", ab.outputFile.String(); w != g {
306		t.Errorf("Expected output file to be compressed apex %q, got %q", w, g)
307	}
308
309	mkData := android.AndroidMkDataForTest(t, result.TestContext, m)
310	var builder strings.Builder
311	mkData.Custom(&builder, "foo", "BAZEL_TARGET_", "", mkData)
312
313	data := builder.String()
314
315	expectedAndroidMk := []string{
316		"LOCAL_PREBUILT_MODULE_FILE := out/bazel/execroot/__main__/signed_out.capex",
317
318		// Check that the source install file is the capex. The dest is not important.
319		"LOCAL_SOONG_INSTALL_PAIRS := out/bazel/execroot/__main__/signed_out.capex:",
320	}
321	for _, androidMk := range expectedAndroidMk {
322		if !strings.Contains(data, androidMk) {
323			t.Errorf("Expected %q in androidmk data, but did not find %q", androidMk, data)
324		}
325	}
326}
327
328func TestOverrideApexImageInMixedBuilds(t *testing.T) {
329	bp := `
330apex_key{
331	name: "foo_key",
332}
333apex_key{
334	name: "override_foo_key",
335}
336apex {
337	name: "foo",
338	key: "foo_key",
339	updatable: true,
340	min_sdk_version: "31",
341	package_name: "pkg_name",
342	file_contexts: ":myapex-file_contexts",
343	bazel_module: { label: "//:foo" },
344}
345override_apex {
346	name: "override_foo",
347	key: "override_foo_key",
348	package_name: "override_pkg_name",
349	base: "foo",
350	bazel_module: { label: "//:override_foo" },
351}
352`
353
354	outputBaseDir := "out/bazel"
355	result := android.GroupFixturePreparers(
356		prepareForApexTest,
357		android.FixtureModifyConfig(func(config android.Config) {
358			config.BazelContext = android.MockBazelContext{
359				OutputBaseDir: outputBaseDir,
360				LabelToApexInfo: map[string]cquery.ApexInfo{
361					"//:foo": cquery.ApexInfo{
362						// ApexInfo Starlark provider
363						SignedOutput:          "signed_out.apex",
364						UnsignedOutput:        "unsigned_out.apex",
365						BundleKeyInfo:         []string{"public_key", "private_key"},
366						ContainerKeyInfo:      []string{"container_cert", "container_private"},
367						SymbolsUsedByApex:     "foo_using.txt",
368						JavaSymbolsUsedByApex: "foo_using.xml",
369						BundleFile:            "apex_bundle.zip",
370						InstalledFiles:        "installed-files.txt",
371						RequiresLibs:          []string{"//path/c:c", "//path/d:d"},
372
373						// unused
374						PackageName:  "pkg_name",
375						ProvidesLibs: []string{"a", "b"},
376
377						// ApexMkInfo Starlark provider
378						MakeModulesToInstall: []string{"c"}, // d deliberately omitted
379					},
380					"//:override_foo": cquery.ApexInfo{
381						// ApexInfo Starlark provider
382						SignedOutput:          "override_signed_out.apex",
383						UnsignedOutput:        "override_unsigned_out.apex",
384						BundleKeyInfo:         []string{"override_public_key", "override_private_key"},
385						ContainerKeyInfo:      []string{"override_container_cert", "override_container_private"},
386						SymbolsUsedByApex:     "override_foo_using.txt",
387						JavaSymbolsUsedByApex: "override_foo_using.xml",
388						BundleFile:            "override_apex_bundle.zip",
389						InstalledFiles:        "override_installed-files.txt",
390						RequiresLibs:          []string{"//path/c:c", "//path/d:d"},
391
392						// unused
393						PackageName:  "override_pkg_name",
394						ProvidesLibs: []string{"a", "b"},
395
396						// ApexMkInfo Starlark provider
397						MakeModulesToInstall: []string{"c"}, // d deliberately omitted
398					},
399				},
400			}
401		}),
402	).RunTestWithBp(t, bp)
403
404	m := result.ModuleForTests("foo", "android_common_override_foo_foo_image").Module()
405	ab, ok := m.(*apexBundle)
406	if !ok {
407		t.Fatalf("Expected module to be an apexBundle, was not")
408	}
409
410	if w, g := "out/bazel/execroot/__main__/override_public_key", ab.publicKeyFile.String(); w != g {
411		t.Errorf("Expected public key %q, got %q", w, g)
412	}
413
414	if w, g := "out/bazel/execroot/__main__/override_private_key", ab.privateKeyFile.String(); w != g {
415		t.Errorf("Expected private key %q, got %q", w, g)
416	}
417
418	if w, g := "out/bazel/execroot/__main__/override_container_cert", ab.containerCertificateFile.String(); w != g {
419		t.Errorf("Expected public container key %q, got %q", w, g)
420	}
421
422	if w, g := "out/bazel/execroot/__main__/override_container_private", ab.containerPrivateKeyFile.String(); w != g {
423		t.Errorf("Expected private container key %q, got %q", w, g)
424	}
425
426	if w, g := "out/bazel/execroot/__main__/override_signed_out.apex", ab.outputFile.String(); w != g {
427		t.Errorf("Expected output file %q, got %q", w, g)
428	}
429
430	if w, g := "out/bazel/execroot/__main__/override_foo_using.txt", ab.nativeApisUsedByModuleFile.String(); w != g {
431		t.Errorf("Expected output file %q, got %q", w, g)
432	}
433
434	if w, g := "out/bazel/execroot/__main__/override_foo_using.xml", ab.javaApisUsedByModuleFile.String(); w != g {
435		t.Errorf("Expected output file %q, got %q", w, g)
436	}
437
438	if w, g := "out/bazel/execroot/__main__/override_installed-files.txt", ab.installedFilesFile.String(); w != g {
439		t.Errorf("Expected installed-files.txt %q, got %q", w, g)
440	}
441
442	mkData := android.AndroidMkDataForTest(t, result.TestContext, m)
443	var builder strings.Builder
444	mkData.Custom(&builder, "override_foo", "BAZEL_TARGET_", "", mkData)
445
446	data := builder.String()
447	if w := "ALL_MODULES.$(my_register_name).BUNDLE := out/bazel/execroot/__main__/override_apex_bundle.zip"; !strings.Contains(data, w) {
448		t.Errorf("Expected %q in androidmk data, but did not find %q", w, data)
449	}
450	if w := "$(call dist-for-goals,checkbuild,out/bazel/execroot/__main__/override_installed-files.txt:override_foo-installed-files.txt)"; !strings.Contains(data, w) {
451		t.Errorf("Expected %q in androidmk data, but did not find %q", w, data)
452	}
453
454	// make modules to be installed to system
455	if len(ab.makeModulesToInstall) != 1 && ab.makeModulesToInstall[0] != "c" {
456		t.Errorf("Expected makeModulestoInstall slice to only contain 'c', got %q", ab.makeModulesToInstall)
457	}
458	if w := "LOCAL_REQUIRED_MODULES := c"; !strings.Contains(data, w) {
459		t.Errorf("Expected %q in androidmk data, but did not find it in %q", w, data)
460	}
461}
462