blob: 41d8455d2c87f0e03963ca3be606a3650304bd60 [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()
31 ctx.RegisterModuleType("apex", android.ModuleFactoryAdaptor(apexBundleFactory))
32 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))
43 ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
44 ctx.BottomUp("link", cc.LinkageMutator).Parallel()
45 ctx.BottomUp("version", cc.VersionMutator).Parallel()
46 ctx.BottomUp("begin", cc.BeginMutator).Parallel()
47 })
48
49 ctx.Register()
50
51 bp = bp + `
52 toolchain_library {
53 name: "libcompiler_rt-extras",
54 src: "",
55 }
56
57 toolchain_library {
58 name: "libatomic",
59 src: "",
60 }
61
62 toolchain_library {
63 name: "libgcc",
64 src: "",
65 }
66
67 toolchain_library {
68 name: "libclang_rt.builtins-aarch64-android",
69 src: "",
70 }
71
72 toolchain_library {
73 name: "libclang_rt.builtins-arm-android",
74 src: "",
75 }
76
77 cc_object {
78 name: "crtbegin_so",
79 stl: "none",
80 }
81
82 cc_object {
83 name: "crtend_so",
84 stl: "none",
85 }
86
87 `
88
89 ctx.MockFileSystem(map[string][]byte{
90 "Android.bp": []byte(bp),
91 "testkey.avbpubkey": nil,
92 "testkey.pem": nil,
93 "build/target/product/security": nil,
94 "apex_manifest.json": nil,
95 "system/sepolicy/apex/myapex-file_contexts": nil,
96 "mylib.cpp": nil,
97 })
98 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
99 android.FailIfErrored(t, errs)
100 _, errs = ctx.PrepareBuildActions(config)
101 android.FailIfErrored(t, errs)
102
103 return ctx
104}
105
106func setup(t *testing.T) (config android.Config, buildDir string) {
107 buildDir, err := ioutil.TempDir("", "soong_apex_test")
108 if err != nil {
109 t.Fatal(err)
110 }
111
112 config = android.TestArchConfig(buildDir, nil)
113
114 return
115}
116
117func teardown(buildDir string) {
118 os.RemoveAll(buildDir)
119}
120
121// ensure that 'result' contains 'expected'
122func ensureContains(t *testing.T, result string, expected string) {
123 if !strings.Contains(result, expected) {
124 t.Errorf("%q is not found in %q", expected, result)
125 }
126}
127
128// ensures that 'result' does not contain 'notExpected'
129func ensureNotContains(t *testing.T, result string, notExpected string) {
130 if strings.Contains(result, notExpected) {
131 t.Errorf("%q is found in %q", notExpected, result)
132 }
133}
134
135func ensureListContains(t *testing.T, result []string, expected string) {
136 if !android.InList(expected, result) {
137 t.Errorf("%q is not found in %v", expected, result)
138 }
139}
140
141func ensureListNotContains(t *testing.T, result []string, notExpected string) {
142 if android.InList(notExpected, result) {
143 t.Errorf("%q is found in %v", notExpected, result)
144 }
145}
146
147// Minimal test
148func TestBasicApex(t *testing.T) {
149 ctx := testApex(t, `
150 apex {
151 name: "myapex",
152 key: "myapex.key",
153 native_shared_libs: ["mylib"],
154 }
155
156 apex_key {
157 name: "myapex.key",
158 public_key: "testkey.avbpubkey",
159 private_key: "testkey.pem",
160 }
161
162 cc_library {
163 name: "mylib",
164 srcs: ["mylib.cpp"],
165 shared_libs: ["mylib2"],
166 system_shared_libs: [],
167 stl: "none",
168 }
169
170 cc_library {
171 name: "mylib2",
172 srcs: ["mylib.cpp"],
173 system_shared_libs: [],
174 stl: "none",
175 }
176 `)
177
178 apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
179 copyCmds := apexRule.Args["copy_commands"]
180
181 // Ensure that main rule creates an output
182 ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
183
184 // Ensure that apex variant is created for the direct dep
185 ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_myapex")
186
187 // Ensure that apex variant is created for the indirect dep
188 ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_myapex")
189
190 // Ensure that both direct and indirect deps are copied into apex
191 ensureContains(t, copyCmds, "image/lib64/mylib.so")
192 ensureContains(t, copyCmds, "image/lib64/mylib2.so")
193}
194
195func TestApexWithStubs(t *testing.T) {
196 ctx := testApex(t, `
197 apex {
198 name: "myapex",
199 key: "myapex.key",
200 native_shared_libs: ["mylib", "mylib3"],
201 }
202
203 apex_key {
204 name: "myapex.key",
205 public_key: "testkey.avbpubkey",
206 private_key: "testkey.pem",
207 }
208
209 cc_library {
210 name: "mylib",
211 srcs: ["mylib.cpp"],
212 shared_libs: ["mylib2", "mylib3"],
213 system_shared_libs: [],
214 stl: "none",
215 }
216
217 cc_library {
218 name: "mylib2",
219 srcs: ["mylib.cpp"],
220 system_shared_libs: [],
221 stl: "none",
222 stubs: {
223 versions: ["1", "2", "3"],
224 },
225 }
226
227 cc_library {
228 name: "mylib3",
229 srcs: ["mylib.cpp"],
230 system_shared_libs: [],
231 stl: "none",
232 stubs: {
233 versions: ["10", "11", "12"],
234 },
235 }
236 `)
237
238 apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
239 copyCmds := apexRule.Args["copy_commands"]
240
241 // Ensure that direct non-stubs dep is always included
242 ensureContains(t, copyCmds, "image/lib64/mylib.so")
243
244 // Ensure that indirect stubs dep is not included
245 ensureNotContains(t, copyCmds, "image/lib64/mylib2.so")
246
247 // Ensure that direct stubs dep is included
248 ensureContains(t, copyCmds, "image/lib64/mylib3.so")
249
250 mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
251
252 // Ensure that mylib is linking with the latest version of stubs for mylib2
253 ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_3_myapex/mylib2.so")
254 // ... and not linking to the non-stub (impl) variant of mylib2
255 ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_myapex/mylib2.so")
256
257 // Ensure that mylib is linking with the non-stub (impl) of mylib3 (because mylib3 is in the same apex)
258 ensureContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_myapex/mylib3.so")
259 // .. and not linking to the stubs variant of mylib3
260 ensureNotContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_12_myapex/mylib3.so")
261}
262
263func TestApexWithSystemLibsStubs(t *testing.T) {
264 ctx := testApex(t, `
265 apex {
266 name: "myapex",
267 key: "myapex.key",
268 native_shared_libs: ["mylib", "mylib_shared", "libdl", "libm"],
269 }
270
271 apex_key {
272 name: "myapex.key",
273 public_key: "testkey.avbpubkey",
274 private_key: "testkey.pem",
275 }
276
277 cc_library {
278 name: "mylib",
279 srcs: ["mylib.cpp"],
280 shared_libs: ["libdl#27"],
281 stl: "none",
282 }
283
284 cc_library_shared {
285 name: "mylib_shared",
286 srcs: ["mylib.cpp"],
287 shared_libs: ["libdl#27"],
288 stl: "none",
289 }
290
291 cc_library {
292 name: "libc",
293 no_libgcc: true,
294 nocrt: true,
295 system_shared_libs: [],
296 stl: "none",
297 stubs: {
298 versions: ["27", "28", "29"],
299 },
300 }
301
302 cc_library {
303 name: "libm",
304 no_libgcc: true,
305 nocrt: true,
306 system_shared_libs: [],
307 stl: "none",
308 stubs: {
309 versions: ["27", "28", "29"],
310 },
311 }
312
313 cc_library {
314 name: "libdl",
315 no_libgcc: true,
316 nocrt: true,
317 system_shared_libs: [],
318 stl: "none",
319 stubs: {
320 versions: ["27", "28", "29"],
321 },
322 }
323 `)
324
325 apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
326 copyCmds := apexRule.Args["copy_commands"]
327
328 // Ensure that mylib, libm, libdl are included.
329 ensureContains(t, copyCmds, "image/lib64/mylib.so")
330 ensureContains(t, copyCmds, "image/lib64/libm.so")
331 ensureContains(t, copyCmds, "image/lib64/libdl.so")
332
333 // Ensure that libc is not included (since it has stubs and not listed in native_shared_libs)
334 ensureNotContains(t, copyCmds, "image/lib64/libc.so")
335
336 mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
337 mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
338 mylibSharedCFlags := ctx.ModuleForTests("mylib_shared", "android_arm64_armv8-a_shared_myapex").Rule("cc").Args["cFlags"]
339
340 // For dependency to libc
341 // Ensure that mylib is linking with the latest version of stubs
342 ensureContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared_29_myapex/libc.so")
343 // ... and not linking to the non-stub (impl) variant
344 ensureNotContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared_myapex/libc.so")
345 // ... Cflags from stub is correctly exported to mylib
346 ensureContains(t, mylibCFlags, "__LIBC_API__=29")
347 ensureContains(t, mylibSharedCFlags, "__LIBC_API__=29")
348
349 // For dependency to libm
350 // Ensure that mylib is linking with the non-stub (impl) variant
351 ensureContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_myapex/libm.so")
352 // ... and not linking to the stub variant
353 ensureNotContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_29_myapex/libm.so")
354 // ... and is not compiling with the stub
355 ensureNotContains(t, mylibCFlags, "__LIBM_API__=29")
356 ensureNotContains(t, mylibSharedCFlags, "__LIBM_API__=29")
357
358 // For dependency to libdl
359 // Ensure that mylib is linking with the specified version of stubs
360 ensureContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_27_myapex/libdl.so")
361 // ... and not linking to the other versions of stubs
362 ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_28_myapex/libdl.so")
363 ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_29_myapex/libdl.so")
364 // ... and not linking to the non-stub (impl) variant
365 ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_myapex/libdl.so")
366 // ... Cflags from stub is correctly exported to mylib
367 ensureContains(t, mylibCFlags, "__LIBDL_API__=27")
368 ensureContains(t, mylibSharedCFlags, "__LIBDL_API__=27")
369}