blob: 88c57bc0d05e9803cfdcf06eb286cd402f6274ef [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"],
Jiyong Park64379952018-12-13 18:37:29 +0900270 cflags: ["-include mylib.h"],
Jiyong Park25fc6a92018-11-18 18:02:45 +0900271 system_shared_libs: [],
272 stl: "none",
273 stubs: {
274 versions: ["1", "2", "3"],
275 },
276 }
277
278 cc_library {
279 name: "mylib3",
Jiyong Park28d395a2018-12-07 22:42:47 +0900280 srcs: ["mylib.cpp"],
281 shared_libs: ["mylib4"],
282 system_shared_libs: [],
Jiyong Park25fc6a92018-11-18 18:02:45 +0900283 stl: "none",
284 stubs: {
285 versions: ["10", "11", "12"],
286 },
287 }
Jiyong Park28d395a2018-12-07 22:42:47 +0900288
289 cc_library {
290 name: "mylib4",
291 srcs: ["mylib.cpp"],
292 system_shared_libs: [],
293 stl: "none",
294 }
Jiyong Park25fc6a92018-11-18 18:02:45 +0900295 `)
296
297 apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
298 copyCmds := apexRule.Args["copy_commands"]
299
300 // Ensure that direct non-stubs dep is always included
Alex Light5098a612018-11-29 17:12:15 -0800301 ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
Jiyong Park25fc6a92018-11-18 18:02:45 +0900302
303 // Ensure that indirect stubs dep is not included
Alex Light5098a612018-11-29 17:12:15 -0800304 ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
Jiyong Park25fc6a92018-11-18 18:02:45 +0900305
306 // Ensure that direct stubs dep is included
Alex Light5098a612018-11-29 17:12:15 -0800307 ensureContains(t, copyCmds, "image.apex/lib64/mylib3.so")
Jiyong Park25fc6a92018-11-18 18:02:45 +0900308
309 mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
310
311 // Ensure that mylib is linking with the latest version of stubs for mylib2
312 ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_3_myapex/mylib2.so")
313 // ... and not linking to the non-stub (impl) variant of mylib2
314 ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_myapex/mylib2.so")
315
316 // Ensure that mylib is linking with the non-stub (impl) of mylib3 (because mylib3 is in the same apex)
317 ensureContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_myapex/mylib3.so")
318 // .. and not linking to the stubs variant of mylib3
319 ensureNotContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_12_myapex/mylib3.so")
Jiyong Park64379952018-12-13 18:37:29 +0900320
321 // Ensure that stubs libs are built without -include flags
322 mylib2Cflags := ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
323 ensureNotContains(t, mylib2Cflags, "-include ")
Jiyong Park25fc6a92018-11-18 18:02:45 +0900324}
325
Jiyong Park0ddfcd12018-12-11 01:35:25 +0900326func TestApexWithExplicitStubsDependency(t *testing.T) {
327 ctx := testApex(t, `
328 apex {
329 name: "myapex",
330 key: "myapex.key",
331 native_shared_libs: ["mylib"],
332 }
333
334 apex_key {
335 name: "myapex.key",
336 public_key: "testkey.avbpubkey",
337 private_key: "testkey.pem",
338 }
339
340 cc_library {
341 name: "mylib",
342 srcs: ["mylib.cpp"],
343 shared_libs: ["libfoo#10"],
344 system_shared_libs: [],
345 stl: "none",
346 }
347
348 cc_library {
349 name: "libfoo",
350 srcs: ["mylib.cpp"],
351 shared_libs: ["libbar"],
352 system_shared_libs: [],
353 stl: "none",
354 stubs: {
355 versions: ["10", "20", "30"],
356 },
357 }
358
359 cc_library {
360 name: "libbar",
361 srcs: ["mylib.cpp"],
362 system_shared_libs: [],
363 stl: "none",
364 }
365
366 `)
367
368 apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
369 copyCmds := apexRule.Args["copy_commands"]
370
371 // Ensure that direct non-stubs dep is always included
372 ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
373
374 // Ensure that indirect stubs dep is not included
375 ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo.so")
376
377 // Ensure that dependency of stubs is not included
378 ensureNotContains(t, copyCmds, "image.apex/lib64/libbar.so")
379
380 mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
381
382 // Ensure that mylib is linking with version 10 of libfoo
383 ensureContains(t, mylibLdFlags, "libfoo/android_arm64_armv8-a_shared_10_myapex/libfoo.so")
384 // ... and not linking to the non-stub (impl) variant of libfoo
385 ensureNotContains(t, mylibLdFlags, "libfoo/android_arm64_armv8-a_shared_myapex/libfoo.so")
386
387 libFooStubsLdFlags := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared_10_myapex").Rule("ld").Args["libFlags"]
388
389 // Ensure that libfoo stubs is not linking to libbar (since it is a stubs)
390 ensureNotContains(t, libFooStubsLdFlags, "libbar.so")
391}
392
Jiyong Park25fc6a92018-11-18 18:02:45 +0900393func TestApexWithSystemLibsStubs(t *testing.T) {
394 ctx := testApex(t, `
395 apex {
396 name: "myapex",
397 key: "myapex.key",
398 native_shared_libs: ["mylib", "mylib_shared", "libdl", "libm"],
399 }
400
401 apex_key {
402 name: "myapex.key",
403 public_key: "testkey.avbpubkey",
404 private_key: "testkey.pem",
405 }
406
407 cc_library {
408 name: "mylib",
409 srcs: ["mylib.cpp"],
410 shared_libs: ["libdl#27"],
411 stl: "none",
412 }
413
414 cc_library_shared {
415 name: "mylib_shared",
416 srcs: ["mylib.cpp"],
417 shared_libs: ["libdl#27"],
418 stl: "none",
419 }
420
421 cc_library {
422 name: "libc",
423 no_libgcc: true,
424 nocrt: true,
425 system_shared_libs: [],
426 stl: "none",
427 stubs: {
428 versions: ["27", "28", "29"],
429 },
430 }
431
432 cc_library {
433 name: "libm",
434 no_libgcc: true,
435 nocrt: true,
436 system_shared_libs: [],
437 stl: "none",
438 stubs: {
439 versions: ["27", "28", "29"],
440 },
441 }
442
443 cc_library {
444 name: "libdl",
445 no_libgcc: true,
446 nocrt: true,
447 system_shared_libs: [],
448 stl: "none",
449 stubs: {
450 versions: ["27", "28", "29"],
451 },
452 }
453 `)
454
455 apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
456 copyCmds := apexRule.Args["copy_commands"]
457
458 // Ensure that mylib, libm, libdl are included.
Alex Light5098a612018-11-29 17:12:15 -0800459 ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
460 ensureContains(t, copyCmds, "image.apex/lib64/libm.so")
461 ensureContains(t, copyCmds, "image.apex/lib64/libdl.so")
Jiyong Park25fc6a92018-11-18 18:02:45 +0900462
463 // Ensure that libc is not included (since it has stubs and not listed in native_shared_libs)
Alex Light5098a612018-11-29 17:12:15 -0800464 ensureNotContains(t, copyCmds, "image.apex/lib64/libc.so")
Jiyong Park25fc6a92018-11-18 18:02:45 +0900465
466 mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
467 mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
468 mylibSharedCFlags := ctx.ModuleForTests("mylib_shared", "android_arm64_armv8-a_shared_myapex").Rule("cc").Args["cFlags"]
469
470 // For dependency to libc
471 // Ensure that mylib is linking with the latest version of stubs
472 ensureContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared_29_myapex/libc.so")
473 // ... and not linking to the non-stub (impl) variant
474 ensureNotContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared_myapex/libc.so")
475 // ... Cflags from stub is correctly exported to mylib
476 ensureContains(t, mylibCFlags, "__LIBC_API__=29")
477 ensureContains(t, mylibSharedCFlags, "__LIBC_API__=29")
478
479 // For dependency to libm
480 // Ensure that mylib is linking with the non-stub (impl) variant
481 ensureContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_myapex/libm.so")
482 // ... and not linking to the stub variant
483 ensureNotContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_29_myapex/libm.so")
484 // ... and is not compiling with the stub
485 ensureNotContains(t, mylibCFlags, "__LIBM_API__=29")
486 ensureNotContains(t, mylibSharedCFlags, "__LIBM_API__=29")
487
488 // For dependency to libdl
489 // Ensure that mylib is linking with the specified version of stubs
490 ensureContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_27_myapex/libdl.so")
491 // ... and not linking to the other versions of stubs
492 ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_28_myapex/libdl.so")
493 ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_29_myapex/libdl.so")
494 // ... and not linking to the non-stub (impl) variant
495 ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_myapex/libdl.so")
496 // ... Cflags from stub is correctly exported to mylib
497 ensureContains(t, mylibCFlags, "__LIBDL_API__=27")
498 ensureContains(t, mylibSharedCFlags, "__LIBDL_API__=27")
499}
Jiyong Park7c2ee712018-12-07 00:42:25 +0900500
501func TestFilesInSubDir(t *testing.T) {
502 ctx := testApex(t, `
503 apex {
504 name: "myapex",
505 key: "myapex.key",
506 prebuilts: ["myetc"],
507 }
508
509 apex_key {
510 name: "myapex.key",
511 public_key: "testkey.avbpubkey",
512 private_key: "testkey.pem",
513 }
514
515 prebuilt_etc {
516 name: "myetc",
517 src: "myprebuilt",
518 sub_dir: "foo/bar",
519 }
520 `)
521
522 generateFsRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("generateFsConfig")
523 dirs := strings.Split(generateFsRule.Args["exec_paths"], " ")
524
525 // Ensure that etc, etc/foo, and etc/foo/bar are all listed
526 ensureListContains(t, dirs, "etc")
527 ensureListContains(t, dirs, "etc/foo")
528 ensureListContains(t, dirs, "etc/foo/bar")
529}