blob: 72f6488c7ec6cd3a84fb27e87563899df11712b6 [file] [log] [blame]
Jiyong Park25fc6a92018-11-18 18:02:45 +09001// 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 "android/soong/android"
19 "android/soong/cc"
20 "io/ioutil"
21 "os"
22 "strings"
23 "testing"
24)
25
26func testApex(t *testing.T, bp string) *android.TestContext {
27 config, buildDir := setup(t)
28 defer teardown(buildDir)
29
30 ctx := android.NewTestArchContext()
Alex Lightee250722018-12-06 14:00:02 -080031 ctx.RegisterModuleType("apex", android.ModuleFactoryAdaptor(ApexBundleFactory))
Jiyong Park25fc6a92018-11-18 18:02:45 +090032 ctx.RegisterModuleType("apex_key", android.ModuleFactoryAdaptor(apexKeyFactory))
33
34 ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
35 ctx.TopDown("apex_deps", apexDepsMutator)
36 ctx.BottomUp("apex", apexMutator)
37 })
38
39 ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
40 ctx.RegisterModuleType("cc_library_shared", android.ModuleFactoryAdaptor(cc.LibrarySharedFactory))
41 ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(cc.ObjectFactory))
42 ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(cc.ToolchainLibraryFactory))
Jiyong Park7c2ee712018-12-07 00:42:25 +090043 ctx.RegisterModuleType("prebuilt_etc", android.ModuleFactoryAdaptor(android.PrebuiltEtcFactory))
Jiyong Park25fc6a92018-11-18 18:02:45 +090044 ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
45 ctx.BottomUp("link", cc.LinkageMutator).Parallel()
46 ctx.BottomUp("version", cc.VersionMutator).Parallel()
47 ctx.BottomUp("begin", cc.BeginMutator).Parallel()
48 })
49
50 ctx.Register()
51
52 bp = bp + `
53 toolchain_library {
54 name: "libcompiler_rt-extras",
55 src: "",
56 }
57
58 toolchain_library {
59 name: "libatomic",
60 src: "",
61 }
62
63 toolchain_library {
64 name: "libgcc",
65 src: "",
66 }
67
68 toolchain_library {
69 name: "libclang_rt.builtins-aarch64-android",
70 src: "",
71 }
72
73 toolchain_library {
74 name: "libclang_rt.builtins-arm-android",
75 src: "",
76 }
77
78 cc_object {
79 name: "crtbegin_so",
80 stl: "none",
81 }
82
83 cc_object {
84 name: "crtend_so",
85 stl: "none",
86 }
87
88 `
89
90 ctx.MockFileSystem(map[string][]byte{
91 "Android.bp": []byte(bp),
92 "testkey.avbpubkey": nil,
93 "testkey.pem": nil,
94 "build/target/product/security": nil,
95 "apex_manifest.json": nil,
96 "system/sepolicy/apex/myapex-file_contexts": nil,
97 "mylib.cpp": nil,
Jiyong Park7c2ee712018-12-07 00:42:25 +090098 "myprebuilt": nil,
Jiyong Park25fc6a92018-11-18 18:02:45 +090099 })
100 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
101 android.FailIfErrored(t, errs)
102 _, errs = ctx.PrepareBuildActions(config)
103 android.FailIfErrored(t, errs)
104
105 return ctx
106}
107
108func setup(t *testing.T) (config android.Config, buildDir string) {
109 buildDir, err := ioutil.TempDir("", "soong_apex_test")
110 if err != nil {
111 t.Fatal(err)
112 }
113
114 config = android.TestArchConfig(buildDir, nil)
115
116 return
117}
118
119func teardown(buildDir string) {
120 os.RemoveAll(buildDir)
121}
122
123// ensure that 'result' contains 'expected'
124func ensureContains(t *testing.T, result string, expected string) {
125 if !strings.Contains(result, expected) {
126 t.Errorf("%q is not found in %q", expected, result)
127 }
128}
129
130// ensures that 'result' does not contain 'notExpected'
131func ensureNotContains(t *testing.T, result string, notExpected string) {
132 if strings.Contains(result, notExpected) {
133 t.Errorf("%q is found in %q", notExpected, result)
134 }
135}
136
137func ensureListContains(t *testing.T, result []string, expected string) {
138 if !android.InList(expected, result) {
139 t.Errorf("%q is not found in %v", expected, result)
140 }
141}
142
143func ensureListNotContains(t *testing.T, result []string, notExpected string) {
144 if android.InList(notExpected, result) {
145 t.Errorf("%q is found in %v", notExpected, result)
146 }
147}
148
149// Minimal test
150func TestBasicApex(t *testing.T) {
151 ctx := testApex(t, `
152 apex {
153 name: "myapex",
154 key: "myapex.key",
155 native_shared_libs: ["mylib"],
156 }
157
158 apex_key {
159 name: "myapex.key",
160 public_key: "testkey.avbpubkey",
161 private_key: "testkey.pem",
162 }
163
164 cc_library {
165 name: "mylib",
166 srcs: ["mylib.cpp"],
167 shared_libs: ["mylib2"],
168 system_shared_libs: [],
169 stl: "none",
170 }
171
172 cc_library {
173 name: "mylib2",
174 srcs: ["mylib.cpp"],
175 system_shared_libs: [],
176 stl: "none",
177 }
178 `)
179
180 apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
181 copyCmds := apexRule.Args["copy_commands"]
182
183 // Ensure that main rule creates an output
184 ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
185
186 // Ensure that apex variant is created for the direct dep
187 ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_myapex")
188
189 // Ensure that apex variant is created for the indirect dep
190 ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_myapex")
191
192 // Ensure that both direct and indirect deps are copied into apex
Alex Light5098a612018-11-29 17:12:15 -0800193 ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
194 ensureContains(t, copyCmds, "image.apex/lib64/mylib2.so")
195}
196
197func TestBasicZipApex(t *testing.T) {
198 ctx := testApex(t, `
199 apex {
200 name: "myapex",
201 key: "myapex.key",
202 payload_type: "zip",
203 native_shared_libs: ["mylib"],
204 }
205
206 apex_key {
207 name: "myapex.key",
208 public_key: "testkey.avbpubkey",
209 private_key: "testkey.pem",
210 }
211
212 cc_library {
213 name: "mylib",
214 srcs: ["mylib.cpp"],
215 shared_libs: ["mylib2"],
216 system_shared_libs: [],
217 stl: "none",
218 }
219
220 cc_library {
221 name: "mylib2",
222 srcs: ["mylib.cpp"],
223 system_shared_libs: [],
224 stl: "none",
225 }
226 `)
227
228 zipApexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("zipApexRule")
229 copyCmds := zipApexRule.Args["copy_commands"]
230
231 // Ensure that main rule creates an output
232 ensureContains(t, zipApexRule.Output.String(), "myapex.zipapex.unsigned")
233
234 // Ensure that APEX variant is created for the direct dep
235 ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_myapex")
236
237 // Ensure that APEX variant is created for the indirect dep
238 ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_myapex")
239
240 // Ensure that both direct and indirect deps are copied into apex
241 ensureContains(t, copyCmds, "image.zipapex/lib64/mylib.so")
242 ensureContains(t, copyCmds, "image.zipapex/lib64/mylib2.so")
Jiyong Park25fc6a92018-11-18 18:02:45 +0900243}
244
245func TestApexWithStubs(t *testing.T) {
246 ctx := testApex(t, `
247 apex {
248 name: "myapex",
249 key: "myapex.key",
250 native_shared_libs: ["mylib", "mylib3"],
251 }
252
253 apex_key {
254 name: "myapex.key",
255 public_key: "testkey.avbpubkey",
256 private_key: "testkey.pem",
257 }
258
259 cc_library {
260 name: "mylib",
261 srcs: ["mylib.cpp"],
262 shared_libs: ["mylib2", "mylib3"],
263 system_shared_libs: [],
264 stl: "none",
265 }
266
267 cc_library {
268 name: "mylib2",
269 srcs: ["mylib.cpp"],
270 system_shared_libs: [],
271 stl: "none",
272 stubs: {
273 versions: ["1", "2", "3"],
274 },
275 }
276
277 cc_library {
278 name: "mylib3",
Jiyong Park28d395a2018-12-07 22:42:47 +0900279 srcs: ["mylib.cpp"],
280 shared_libs: ["mylib4"],
281 system_shared_libs: [],
Jiyong Park25fc6a92018-11-18 18:02:45 +0900282 stl: "none",
283 stubs: {
284 versions: ["10", "11", "12"],
285 },
286 }
Jiyong Park28d395a2018-12-07 22:42:47 +0900287
288 cc_library {
289 name: "mylib4",
290 srcs: ["mylib.cpp"],
291 system_shared_libs: [],
292 stl: "none",
293 }
Jiyong Park25fc6a92018-11-18 18:02:45 +0900294 `)
295
296 apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
297 copyCmds := apexRule.Args["copy_commands"]
298
299 // Ensure that direct non-stubs dep is always included
Alex Light5098a612018-11-29 17:12:15 -0800300 ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
Jiyong Park25fc6a92018-11-18 18:02:45 +0900301
302 // Ensure that indirect stubs dep is not included
Alex Light5098a612018-11-29 17:12:15 -0800303 ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
Jiyong Park25fc6a92018-11-18 18:02:45 +0900304
305 // Ensure that direct stubs dep is included
Alex Light5098a612018-11-29 17:12:15 -0800306 ensureContains(t, copyCmds, "image.apex/lib64/mylib3.so")
Jiyong Park25fc6a92018-11-18 18:02:45 +0900307
308 mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
309
310 // Ensure that mylib is linking with the latest version of stubs for mylib2
311 ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_3_myapex/mylib2.so")
312 // ... and not linking to the non-stub (impl) variant of mylib2
313 ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_myapex/mylib2.so")
314
315 // Ensure that mylib is linking with the non-stub (impl) of mylib3 (because mylib3 is in the same apex)
316 ensureContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_myapex/mylib3.so")
317 // .. and not linking to the stubs variant of mylib3
318 ensureNotContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_12_myapex/mylib3.so")
319}
320
Jiyong Park0ddfcd12018-12-11 01:35:25 +0900321func TestApexWithExplicitStubsDependency(t *testing.T) {
322 ctx := testApex(t, `
323 apex {
324 name: "myapex",
325 key: "myapex.key",
326 native_shared_libs: ["mylib"],
327 }
328
329 apex_key {
330 name: "myapex.key",
331 public_key: "testkey.avbpubkey",
332 private_key: "testkey.pem",
333 }
334
335 cc_library {
336 name: "mylib",
337 srcs: ["mylib.cpp"],
338 shared_libs: ["libfoo#10"],
339 system_shared_libs: [],
340 stl: "none",
341 }
342
343 cc_library {
344 name: "libfoo",
345 srcs: ["mylib.cpp"],
346 shared_libs: ["libbar"],
347 system_shared_libs: [],
348 stl: "none",
349 stubs: {
350 versions: ["10", "20", "30"],
351 },
352 }
353
354 cc_library {
355 name: "libbar",
356 srcs: ["mylib.cpp"],
357 system_shared_libs: [],
358 stl: "none",
359 }
360
361 `)
362
363 apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
364 copyCmds := apexRule.Args["copy_commands"]
365
366 // Ensure that direct non-stubs dep is always included
367 ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
368
369 // Ensure that indirect stubs dep is not included
370 ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo.so")
371
372 // Ensure that dependency of stubs is not included
373 ensureNotContains(t, copyCmds, "image.apex/lib64/libbar.so")
374
375 mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
376
377 // Ensure that mylib is linking with version 10 of libfoo
378 ensureContains(t, mylibLdFlags, "libfoo/android_arm64_armv8-a_shared_10_myapex/libfoo.so")
379 // ... and not linking to the non-stub (impl) variant of libfoo
380 ensureNotContains(t, mylibLdFlags, "libfoo/android_arm64_armv8-a_shared_myapex/libfoo.so")
381
382 libFooStubsLdFlags := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared_10_myapex").Rule("ld").Args["libFlags"]
383
384 // Ensure that libfoo stubs is not linking to libbar (since it is a stubs)
385 ensureNotContains(t, libFooStubsLdFlags, "libbar.so")
386}
387
Jiyong Park25fc6a92018-11-18 18:02:45 +0900388func TestApexWithSystemLibsStubs(t *testing.T) {
389 ctx := testApex(t, `
390 apex {
391 name: "myapex",
392 key: "myapex.key",
393 native_shared_libs: ["mylib", "mylib_shared", "libdl", "libm"],
394 }
395
396 apex_key {
397 name: "myapex.key",
398 public_key: "testkey.avbpubkey",
399 private_key: "testkey.pem",
400 }
401
402 cc_library {
403 name: "mylib",
404 srcs: ["mylib.cpp"],
405 shared_libs: ["libdl#27"],
406 stl: "none",
407 }
408
409 cc_library_shared {
410 name: "mylib_shared",
411 srcs: ["mylib.cpp"],
412 shared_libs: ["libdl#27"],
413 stl: "none",
414 }
415
416 cc_library {
417 name: "libc",
418 no_libgcc: true,
419 nocrt: true,
420 system_shared_libs: [],
421 stl: "none",
422 stubs: {
423 versions: ["27", "28", "29"],
424 },
425 }
426
427 cc_library {
428 name: "libm",
429 no_libgcc: true,
430 nocrt: true,
431 system_shared_libs: [],
432 stl: "none",
433 stubs: {
434 versions: ["27", "28", "29"],
435 },
436 }
437
438 cc_library {
439 name: "libdl",
440 no_libgcc: true,
441 nocrt: true,
442 system_shared_libs: [],
443 stl: "none",
444 stubs: {
445 versions: ["27", "28", "29"],
446 },
447 }
448 `)
449
450 apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
451 copyCmds := apexRule.Args["copy_commands"]
452
453 // Ensure that mylib, libm, libdl are included.
Alex Light5098a612018-11-29 17:12:15 -0800454 ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
455 ensureContains(t, copyCmds, "image.apex/lib64/libm.so")
456 ensureContains(t, copyCmds, "image.apex/lib64/libdl.so")
Jiyong Park25fc6a92018-11-18 18:02:45 +0900457
458 // Ensure that libc is not included (since it has stubs and not listed in native_shared_libs)
Alex Light5098a612018-11-29 17:12:15 -0800459 ensureNotContains(t, copyCmds, "image.apex/lib64/libc.so")
Jiyong Park25fc6a92018-11-18 18:02:45 +0900460
461 mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
462 mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
463 mylibSharedCFlags := ctx.ModuleForTests("mylib_shared", "android_arm64_armv8-a_shared_myapex").Rule("cc").Args["cFlags"]
464
465 // For dependency to libc
466 // Ensure that mylib is linking with the latest version of stubs
467 ensureContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared_29_myapex/libc.so")
468 // ... and not linking to the non-stub (impl) variant
469 ensureNotContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared_myapex/libc.so")
470 // ... Cflags from stub is correctly exported to mylib
471 ensureContains(t, mylibCFlags, "__LIBC_API__=29")
472 ensureContains(t, mylibSharedCFlags, "__LIBC_API__=29")
473
474 // For dependency to libm
475 // Ensure that mylib is linking with the non-stub (impl) variant
476 ensureContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_myapex/libm.so")
477 // ... and not linking to the stub variant
478 ensureNotContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_29_myapex/libm.so")
479 // ... and is not compiling with the stub
480 ensureNotContains(t, mylibCFlags, "__LIBM_API__=29")
481 ensureNotContains(t, mylibSharedCFlags, "__LIBM_API__=29")
482
483 // For dependency to libdl
484 // Ensure that mylib is linking with the specified version of stubs
485 ensureContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_27_myapex/libdl.so")
486 // ... and not linking to the other versions of stubs
487 ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_28_myapex/libdl.so")
488 ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_29_myapex/libdl.so")
489 // ... and not linking to the non-stub (impl) variant
490 ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_myapex/libdl.so")
491 // ... Cflags from stub is correctly exported to mylib
492 ensureContains(t, mylibCFlags, "__LIBDL_API__=27")
493 ensureContains(t, mylibSharedCFlags, "__LIBDL_API__=27")
494}
Jiyong Park7c2ee712018-12-07 00:42:25 +0900495
496func TestFilesInSubDir(t *testing.T) {
497 ctx := testApex(t, `
498 apex {
499 name: "myapex",
500 key: "myapex.key",
501 prebuilts: ["myetc"],
502 }
503
504 apex_key {
505 name: "myapex.key",
506 public_key: "testkey.avbpubkey",
507 private_key: "testkey.pem",
508 }
509
510 prebuilt_etc {
511 name: "myetc",
512 src: "myprebuilt",
513 sub_dir: "foo/bar",
514 }
515 `)
516
517 generateFsRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("generateFsConfig")
518 dirs := strings.Split(generateFsRule.Args["exec_paths"], " ")
519
520 // Ensure that etc, etc/foo, and etc/foo/bar are all listed
521 ensureListContains(t, dirs, "etc")
522 ensureListContains(t, dirs, "etc/foo")
523 ensureListContains(t, dirs, "etc/foo/bar")
524}