blob: c7ef58efa438f1380a8644ccbc3336998f2eeffc [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",
279 srcs: ["mylib.cpp"],
280 system_shared_libs: [],
281 stl: "none",
282 stubs: {
283 versions: ["10", "11", "12"],
284 },
285 }
286 `)
287
288 apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
289 copyCmds := apexRule.Args["copy_commands"]
290
291 // Ensure that direct non-stubs dep is always included
Alex Light5098a612018-11-29 17:12:15 -0800292 ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
Jiyong Park25fc6a92018-11-18 18:02:45 +0900293
294 // Ensure that indirect stubs dep is not included
Alex Light5098a612018-11-29 17:12:15 -0800295 ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
Jiyong Park25fc6a92018-11-18 18:02:45 +0900296
297 // Ensure that direct stubs dep is included
Alex Light5098a612018-11-29 17:12:15 -0800298 ensureContains(t, copyCmds, "image.apex/lib64/mylib3.so")
Jiyong Park25fc6a92018-11-18 18:02:45 +0900299
300 mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
301
302 // Ensure that mylib is linking with the latest version of stubs for mylib2
303 ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_3_myapex/mylib2.so")
304 // ... and not linking to the non-stub (impl) variant of mylib2
305 ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_myapex/mylib2.so")
306
307 // Ensure that mylib is linking with the non-stub (impl) of mylib3 (because mylib3 is in the same apex)
308 ensureContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_myapex/mylib3.so")
309 // .. and not linking to the stubs variant of mylib3
310 ensureNotContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_12_myapex/mylib3.so")
311}
312
313func TestApexWithSystemLibsStubs(t *testing.T) {
314 ctx := testApex(t, `
315 apex {
316 name: "myapex",
317 key: "myapex.key",
318 native_shared_libs: ["mylib", "mylib_shared", "libdl", "libm"],
319 }
320
321 apex_key {
322 name: "myapex.key",
323 public_key: "testkey.avbpubkey",
324 private_key: "testkey.pem",
325 }
326
327 cc_library {
328 name: "mylib",
329 srcs: ["mylib.cpp"],
330 shared_libs: ["libdl#27"],
331 stl: "none",
332 }
333
334 cc_library_shared {
335 name: "mylib_shared",
336 srcs: ["mylib.cpp"],
337 shared_libs: ["libdl#27"],
338 stl: "none",
339 }
340
341 cc_library {
342 name: "libc",
343 no_libgcc: true,
344 nocrt: true,
345 system_shared_libs: [],
346 stl: "none",
347 stubs: {
348 versions: ["27", "28", "29"],
349 },
350 }
351
352 cc_library {
353 name: "libm",
354 no_libgcc: true,
355 nocrt: true,
356 system_shared_libs: [],
357 stl: "none",
358 stubs: {
359 versions: ["27", "28", "29"],
360 },
361 }
362
363 cc_library {
364 name: "libdl",
365 no_libgcc: true,
366 nocrt: true,
367 system_shared_libs: [],
368 stl: "none",
369 stubs: {
370 versions: ["27", "28", "29"],
371 },
372 }
373 `)
374
375 apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
376 copyCmds := apexRule.Args["copy_commands"]
377
378 // Ensure that mylib, libm, libdl are included.
Alex Light5098a612018-11-29 17:12:15 -0800379 ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
380 ensureContains(t, copyCmds, "image.apex/lib64/libm.so")
381 ensureContains(t, copyCmds, "image.apex/lib64/libdl.so")
Jiyong Park25fc6a92018-11-18 18:02:45 +0900382
383 // Ensure that libc is not included (since it has stubs and not listed in native_shared_libs)
Alex Light5098a612018-11-29 17:12:15 -0800384 ensureNotContains(t, copyCmds, "image.apex/lib64/libc.so")
Jiyong Park25fc6a92018-11-18 18:02:45 +0900385
386 mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
387 mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
388 mylibSharedCFlags := ctx.ModuleForTests("mylib_shared", "android_arm64_armv8-a_shared_myapex").Rule("cc").Args["cFlags"]
389
390 // For dependency to libc
391 // Ensure that mylib is linking with the latest version of stubs
392 ensureContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared_29_myapex/libc.so")
393 // ... and not linking to the non-stub (impl) variant
394 ensureNotContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared_myapex/libc.so")
395 // ... Cflags from stub is correctly exported to mylib
396 ensureContains(t, mylibCFlags, "__LIBC_API__=29")
397 ensureContains(t, mylibSharedCFlags, "__LIBC_API__=29")
398
399 // For dependency to libm
400 // Ensure that mylib is linking with the non-stub (impl) variant
401 ensureContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_myapex/libm.so")
402 // ... and not linking to the stub variant
403 ensureNotContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_29_myapex/libm.so")
404 // ... and is not compiling with the stub
405 ensureNotContains(t, mylibCFlags, "__LIBM_API__=29")
406 ensureNotContains(t, mylibSharedCFlags, "__LIBM_API__=29")
407
408 // For dependency to libdl
409 // Ensure that mylib is linking with the specified version of stubs
410 ensureContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_27_myapex/libdl.so")
411 // ... and not linking to the other versions of stubs
412 ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_28_myapex/libdl.so")
413 ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_29_myapex/libdl.so")
414 // ... and not linking to the non-stub (impl) variant
415 ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_myapex/libdl.so")
416 // ... Cflags from stub is correctly exported to mylib
417 ensureContains(t, mylibCFlags, "__LIBDL_API__=27")
418 ensureContains(t, mylibSharedCFlags, "__LIBDL_API__=27")
419}
Jiyong Park7c2ee712018-12-07 00:42:25 +0900420
421func TestFilesInSubDir(t *testing.T) {
422 ctx := testApex(t, `
423 apex {
424 name: "myapex",
425 key: "myapex.key",
426 prebuilts: ["myetc"],
427 }
428
429 apex_key {
430 name: "myapex.key",
431 public_key: "testkey.avbpubkey",
432 private_key: "testkey.pem",
433 }
434
435 prebuilt_etc {
436 name: "myetc",
437 src: "myprebuilt",
438 sub_dir: "foo/bar",
439 }
440 `)
441
442 generateFsRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("generateFsConfig")
443 dirs := strings.Split(generateFsRule.Args["exec_paths"], " ")
444
445 // Ensure that etc, etc/foo, and etc/foo/bar are all listed
446 ensureListContains(t, dirs, "etc")
447 ensureListContains(t, dirs, "etc/foo")
448 ensureListContains(t, dirs, "etc/foo/bar")
449}