blob: 3471bc9da068d0c09ba91d82f20eff688977ac23 [file] [log] [blame]
Jiyong Parkd1063c12019-07-17 20:08:41 +09001// Copyright 2019 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 sdk
16
17import (
18 "io/ioutil"
19 "os"
Jiyong Park232e7852019-11-04 12:23:40 +090020 "path/filepath"
Jiyong Parkd1063c12019-07-17 20:08:41 +090021 "strings"
22 "testing"
23
24 "android/soong/android"
25 "android/soong/apex"
26 "android/soong/cc"
27 "android/soong/java"
28)
29
30func testSdkContext(t *testing.T, bp string) (*android.TestContext, android.Config) {
31 config := android.TestArchConfig(buildDir, nil)
32 ctx := android.NewTestArchContext()
33
34 // from android package
35 ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
36 ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
37 ctx.BottomUp("prebuilts", android.PrebuiltMutator).Parallel()
38 })
39 ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
40 ctx.TopDown("prebuilt_select", android.PrebuiltSelectModuleMutator).Parallel()
41 ctx.BottomUp("prebuilt_postdeps", android.PrebuiltPostDepsMutator).Parallel()
42 })
43
44 // from java package
45 ctx.RegisterModuleType("android_app_certificate", android.ModuleFactoryAdaptor(java.AndroidAppCertificateFactory))
46 ctx.RegisterModuleType("java_library", android.ModuleFactoryAdaptor(java.LibraryFactory))
47 ctx.RegisterModuleType("java_import", android.ModuleFactoryAdaptor(java.ImportFactory))
48
49 // from cc package
50 ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
51 ctx.RegisterModuleType("cc_library_shared", android.ModuleFactoryAdaptor(cc.LibrarySharedFactory))
52 ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(cc.ObjectFactory))
53 ctx.RegisterModuleType("cc_prebuilt_library_shared", android.ModuleFactoryAdaptor(cc.PrebuiltSharedLibraryFactory))
54 ctx.RegisterModuleType("cc_prebuilt_library_static", android.ModuleFactoryAdaptor(cc.PrebuiltStaticLibraryFactory))
55 ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(cc.LlndkLibraryFactory))
56 ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(cc.ToolchainLibraryFactory))
57 ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
58 ctx.BottomUp("image", cc.ImageMutator).Parallel()
59 ctx.BottomUp("link", cc.LinkageMutator).Parallel()
60 ctx.BottomUp("vndk", cc.VndkMutator).Parallel()
61 ctx.BottomUp("test_per_src", cc.TestPerSrcMutator).Parallel()
62 ctx.BottomUp("version", cc.VersionMutator).Parallel()
63 ctx.BottomUp("begin", cc.BeginMutator).Parallel()
64 })
65
66 // from apex package
67 ctx.RegisterModuleType("apex", android.ModuleFactoryAdaptor(apex.BundleFactory))
68 ctx.RegisterModuleType("apex_key", android.ModuleFactoryAdaptor(apex.ApexKeyFactory))
69 ctx.PostDepsMutators(apex.RegisterPostDepsMutators)
70
71 // from this package
72 ctx.RegisterModuleType("sdk", android.ModuleFactoryAdaptor(ModuleFactory))
Jiyong Park9b409bc2019-10-11 14:59:13 +090073 ctx.RegisterModuleType("sdk_snapshot", android.ModuleFactoryAdaptor(SnapshotModuleFactory))
Jiyong Parkd1063c12019-07-17 20:08:41 +090074 ctx.PreDepsMutators(RegisterPreDepsMutators)
75 ctx.PostDepsMutators(RegisterPostDepsMutators)
76
77 ctx.Register()
78
79 bp = bp + `
80 apex_key {
81 name: "myapex.key",
82 public_key: "myapex.avbpubkey",
83 private_key: "myapex.pem",
84 }
85
86 android_app_certificate {
87 name: "myapex.cert",
88 certificate: "myapex",
89 }
90 ` + cc.GatherRequiredDepsForTest(android.Android)
91
92 ctx.MockFileSystem(map[string][]byte{
93 "Android.bp": []byte(bp),
94 "build/make/target/product/security": nil,
95 "apex_manifest.json": nil,
96 "system/sepolicy/apex/myapex-file_contexts": nil,
97 "system/sepolicy/apex/myapex2-file_contexts": nil,
98 "myapex.avbpubkey": nil,
99 "myapex.pem": nil,
100 "myapex.x509.pem": nil,
101 "myapex.pk8": nil,
102 "Test.java": nil,
103 "Test.cpp": nil,
Jiyong Park232e7852019-11-04 12:23:40 +0900104 "include/Test.h": nil,
105 "aidl/foo/bar/Test.aidl": nil,
Jiyong Parkd1063c12019-07-17 20:08:41 +0900106 "libfoo.so": nil,
107 })
108
109 return ctx, config
110}
111
112func testSdk(t *testing.T, bp string) (*android.TestContext, android.Config) {
113 ctx, config := testSdkContext(t, bp)
114 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
115 android.FailIfErrored(t, errs)
116 _, errs = ctx.PrepareBuildActions(config)
117 android.FailIfErrored(t, errs)
118 return ctx, config
119}
120
Jiyong Parka7bc8ad2019-10-15 15:20:07 +0900121func testSdkError(t *testing.T, pattern, bp string) {
122 t.Helper()
123 ctx, config := testSdkContext(t, bp)
124 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
125 if len(errs) > 0 {
126 android.FailIfNoMatchingErrors(t, pattern, errs)
127 return
128 }
129 _, errs = ctx.PrepareBuildActions(config)
130 if len(errs) > 0 {
131 android.FailIfNoMatchingErrors(t, pattern, errs)
132 return
133 }
134
135 t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
136}
137
Jiyong Parkd1063c12019-07-17 20:08:41 +0900138// ensure that 'result' contains 'expected'
139func ensureContains(t *testing.T, result string, expected string) {
140 t.Helper()
141 if !strings.Contains(result, expected) {
142 t.Errorf("%q is not found in %q", expected, result)
143 }
144}
145
146// ensures that 'result' does not contain 'notExpected'
147func ensureNotContains(t *testing.T, result string, notExpected string) {
148 t.Helper()
149 if strings.Contains(result, notExpected) {
150 t.Errorf("%q is found in %q", notExpected, result)
151 }
152}
153
154func ensureListContains(t *testing.T, result []string, expected string) {
155 t.Helper()
156 if !android.InList(expected, result) {
157 t.Errorf("%q is not found in %v", expected, result)
158 }
159}
160
161func ensureListNotContains(t *testing.T, result []string, notExpected string) {
162 t.Helper()
163 if android.InList(notExpected, result) {
164 t.Errorf("%q is found in %v", notExpected, result)
165 }
166}
167
168func pathsToStrings(paths android.Paths) []string {
169 ret := []string{}
170 for _, p := range paths {
171 ret = append(ret, p.String())
172 }
173 return ret
174}
175
176func TestBasicSdkWithJava(t *testing.T) {
177 ctx, _ := testSdk(t, `
178 sdk {
Jiyong Park9b409bc2019-10-11 14:59:13 +0900179 name: "mysdk",
180 java_libs: ["sdkmember"],
181 }
182
183 sdk_snapshot {
184 name: "mysdk@1",
Jiyong Parkd1063c12019-07-17 20:08:41 +0900185 java_libs: ["sdkmember_mysdk_1"],
186 }
187
Jiyong Park9b409bc2019-10-11 14:59:13 +0900188 sdk_snapshot {
189 name: "mysdk@2",
Jiyong Parkd1063c12019-07-17 20:08:41 +0900190 java_libs: ["sdkmember_mysdk_2"],
191 }
192
193 java_import {
194 name: "sdkmember",
195 prefer: false,
196 host_supported: true,
197 }
198
199 java_import {
200 name: "sdkmember_mysdk_1",
201 sdk_member_name: "sdkmember",
202 host_supported: true,
203 }
204
205 java_import {
206 name: "sdkmember_mysdk_2",
207 sdk_member_name: "sdkmember",
208 host_supported: true,
209 }
210
211 java_library {
212 name: "myjavalib",
213 srcs: ["Test.java"],
214 libs: ["sdkmember"],
215 system_modules: "none",
216 sdk_version: "none",
217 compile_dex: true,
218 host_supported: true,
219 }
220
221 apex {
222 name: "myapex",
223 java_libs: ["myjavalib"],
Jiyong Park9b409bc2019-10-11 14:59:13 +0900224 uses_sdks: ["mysdk@1"],
Jiyong Parkd1063c12019-07-17 20:08:41 +0900225 key: "myapex.key",
226 certificate: ":myapex.cert",
227 }
228
229 apex {
230 name: "myapex2",
231 java_libs: ["myjavalib"],
Jiyong Park9b409bc2019-10-11 14:59:13 +0900232 uses_sdks: ["mysdk@2"],
Jiyong Parkd1063c12019-07-17 20:08:41 +0900233 key: "myapex.key",
234 certificate: ":myapex.cert",
235 }
236 `)
237
238 sdkMemberV1 := ctx.ModuleForTests("sdkmember_mysdk_1", "android_common_myapex").Rule("combineJar").Output
239 sdkMemberV2 := ctx.ModuleForTests("sdkmember_mysdk_2", "android_common_myapex2").Rule("combineJar").Output
240
241 javalibForMyApex := ctx.ModuleForTests("myjavalib", "android_common_myapex")
242 javalibForMyApex2 := ctx.ModuleForTests("myjavalib", "android_common_myapex2")
243
244 // Depending on the uses_sdks value, different libs are linked
245 ensureListContains(t, pathsToStrings(javalibForMyApex.Rule("javac").Implicits), sdkMemberV1.String())
246 ensureListContains(t, pathsToStrings(javalibForMyApex2.Rule("javac").Implicits), sdkMemberV2.String())
247}
248
249func TestBasicSdkWithCc(t *testing.T) {
250 ctx, _ := testSdk(t, `
251 sdk {
Jiyong Park9b409bc2019-10-11 14:59:13 +0900252 name: "mysdk",
253 native_shared_libs: ["sdkmember"],
254 }
255
256 sdk_snapshot {
257 name: "mysdk@1",
Jiyong Parkd1063c12019-07-17 20:08:41 +0900258 native_shared_libs: ["sdkmember_mysdk_1"],
259 }
260
Jiyong Park9b409bc2019-10-11 14:59:13 +0900261 sdk_snapshot {
262 name: "mysdk@2",
Jiyong Parkd1063c12019-07-17 20:08:41 +0900263 native_shared_libs: ["sdkmember_mysdk_2"],
264 }
265
266 cc_prebuilt_library_shared {
267 name: "sdkmember",
268 srcs: ["libfoo.so"],
269 prefer: false,
270 system_shared_libs: [],
271 stl: "none",
272 }
273
274 cc_prebuilt_library_shared {
275 name: "sdkmember_mysdk_1",
276 sdk_member_name: "sdkmember",
277 srcs: ["libfoo.so"],
278 system_shared_libs: [],
279 stl: "none",
280 }
281
282 cc_prebuilt_library_shared {
283 name: "sdkmember_mysdk_2",
284 sdk_member_name: "sdkmember",
285 srcs: ["libfoo.so"],
286 system_shared_libs: [],
287 stl: "none",
288 }
289
290 cc_library_shared {
291 name: "mycpplib",
292 srcs: ["Test.cpp"],
293 shared_libs: ["sdkmember"],
294 system_shared_libs: [],
295 stl: "none",
296 }
297
298 apex {
299 name: "myapex",
300 native_shared_libs: ["mycpplib"],
Jiyong Park9b409bc2019-10-11 14:59:13 +0900301 uses_sdks: ["mysdk@1"],
Jiyong Parkd1063c12019-07-17 20:08:41 +0900302 key: "myapex.key",
303 certificate: ":myapex.cert",
304 }
305
306 apex {
307 name: "myapex2",
308 native_shared_libs: ["mycpplib"],
Jiyong Park9b409bc2019-10-11 14:59:13 +0900309 uses_sdks: ["mysdk@2"],
Jiyong Parkd1063c12019-07-17 20:08:41 +0900310 key: "myapex.key",
311 certificate: ":myapex.cert",
312 }
313 `)
314
315 sdkMemberV1 := ctx.ModuleForTests("sdkmember_mysdk_1", "android_arm64_armv8-a_core_shared_myapex").Rule("toc").Output
316 sdkMemberV2 := ctx.ModuleForTests("sdkmember_mysdk_2", "android_arm64_armv8-a_core_shared_myapex2").Rule("toc").Output
317
318 cpplibForMyApex := ctx.ModuleForTests("mycpplib", "android_arm64_armv8-a_core_shared_myapex")
319 cpplibForMyApex2 := ctx.ModuleForTests("mycpplib", "android_arm64_armv8-a_core_shared_myapex2")
320
321 // Depending on the uses_sdks value, different libs are linked
322 ensureListContains(t, pathsToStrings(cpplibForMyApex.Rule("ld").Implicits), sdkMemberV1.String())
323 ensureListContains(t, pathsToStrings(cpplibForMyApex2.Rule("ld").Implicits), sdkMemberV2.String())
324}
325
Jiyong Parka7bc8ad2019-10-15 15:20:07 +0900326func TestDepNotInRequiredSdks(t *testing.T) {
327 testSdkError(t, `module "myjavalib".*depends on "otherlib".*that isn't part of the required SDKs:.*`, `
328 sdk {
329 name: "mysdk",
330 java_libs: ["sdkmember"],
331 }
332
333 sdk_snapshot {
334 name: "mysdk@1",
335 java_libs: ["sdkmember_mysdk_1"],
336 }
337
338 java_import {
339 name: "sdkmember",
340 prefer: false,
341 host_supported: true,
342 }
343
344 java_import {
345 name: "sdkmember_mysdk_1",
346 sdk_member_name: "sdkmember",
347 host_supported: true,
348 }
349
350 java_library {
351 name: "myjavalib",
352 srcs: ["Test.java"],
353 libs: [
354 "sdkmember",
355 "otherlib",
356 ],
357 system_modules: "none",
358 sdk_version: "none",
359 compile_dex: true,
360 host_supported: true,
361 }
362
363 // this lib is no in mysdk
364 java_library {
365 name: "otherlib",
366 srcs: ["Test.java"],
367 system_modules: "none",
368 sdk_version: "none",
369 compile_dex: true,
370 host_supported: true,
371 }
372
373 apex {
374 name: "myapex",
375 java_libs: ["myjavalib"],
376 uses_sdks: ["mysdk@1"],
377 key: "myapex.key",
378 certificate: ":myapex.cert",
379 }
380 `)
381}
382
Jiyong Park100f3fd2019-11-06 16:03:32 +0900383func TestSdkIsCompileMultilibBoth(t *testing.T) {
384 ctx, _ := testSdk(t, `
385 sdk {
386 name: "mysdk",
387 native_shared_libs: ["sdkmember"],
388 }
389
390 cc_library_shared {
391 name: "sdkmember",
392 srcs: ["Test.cpp"],
393 system_shared_libs: [],
394 stl: "none",
395 }
396 `)
397
398 armOutput := ctx.ModuleForTests("sdkmember", "android_arm_armv7-a-neon_core_shared").Module().(*cc.Module).OutputFile()
399 arm64Output := ctx.ModuleForTests("sdkmember", "android_arm64_armv8-a_core_shared").Module().(*cc.Module).OutputFile()
400
401 var inputs []string
402 buildParams := ctx.ModuleForTests("mysdk", "android_common").Module().BuildParamsForTests()
403 for _, bp := range buildParams {
Jiyong Park232e7852019-11-04 12:23:40 +0900404 if bp.Input != nil {
405 inputs = append(inputs, bp.Input.String())
406 }
Jiyong Park100f3fd2019-11-06 16:03:32 +0900407 }
408
409 // ensure that both 32/64 outputs are inputs of the sdk snapshot
410 ensureListContains(t, inputs, armOutput.String())
411 ensureListContains(t, inputs, arm64Output.String())
412}
413
Jiyong Park232e7852019-11-04 12:23:40 +0900414func TestSnapshot(t *testing.T) {
415 ctx, config := testSdk(t, `
416 sdk {
417 name: "mysdk",
418 java_libs: ["myjavalib"],
419 native_shared_libs: ["mynativelib"],
420 }
421
422 java_library {
423 name: "myjavalib",
424 srcs: ["Test.java"],
425 aidl: {
426 export_include_dirs: ["aidl"],
427 },
428 system_modules: "none",
429 sdk_version: "none",
430 compile_dex: true,
431 host_supported: true,
432 }
433
434 cc_library_shared {
435 name: "mynativelib",
436 srcs: [
437 "Test.cpp",
438 "aidl/foo/bar/Test.aidl",
439 ],
440 export_include_dirs: ["include"],
441 aidl: {
442 export_aidl_headers: true,
443 },
444 system_shared_libs: [],
445 stl: "none",
446 }
447 `)
448
449 var copySrcs []string
450 var copyDests []string
451 buildParams := ctx.ModuleForTests("mysdk", "android_common").Module().BuildParamsForTests()
452 for _, bp := range buildParams {
453 if bp.Rule.String() == "android/soong/android.Cp" {
454 copySrcs = append(copySrcs, bp.Input.String())
455 copyDests = append(copyDests, bp.Output.Rel()) // rooted at the snapshot root
456 }
457 }
458
459 buildDir := config.BuildDir()
460 ensureListContains(t, copySrcs, "aidl/foo/bar/Test.aidl")
461 ensureListContains(t, copySrcs, "include/Test.h")
462 ensureListContains(t, copySrcs, filepath.Join(buildDir, ".intermediates/mynativelib/android_arm64_armv8-a_core_shared/gen/aidl/aidl/foo/bar/BnTest.h"))
463 ensureListContains(t, copySrcs, filepath.Join(buildDir, ".intermediates/mynativelib/android_arm64_armv8-a_core_shared/gen/aidl/aidl/foo/bar/BpTest.h"))
464 ensureListContains(t, copySrcs, filepath.Join(buildDir, ".intermediates/mynativelib/android_arm64_armv8-a_core_shared/gen/aidl/aidl/foo/bar/Test.h"))
465 ensureListContains(t, copySrcs, filepath.Join(buildDir, ".intermediates/myjavalib/android_common/turbine-combined/myjavalib.jar"))
466 ensureListContains(t, copySrcs, filepath.Join(buildDir, ".intermediates/mynativelib/android_arm64_armv8-a_core_shared/mynativelib.so"))
467
468 ensureListContains(t, copyDests, "aidl/aidl/foo/bar/Test.aidl")
469 ensureListContains(t, copyDests, "arm64/include/include/Test.h")
470 ensureListContains(t, copyDests, "arm64/include_gen/mynativelib/aidl/foo/bar/BnTest.h")
471 ensureListContains(t, copyDests, "arm64/include_gen/mynativelib/aidl/foo/bar/BpTest.h")
472 ensureListContains(t, copyDests, "arm64/include_gen/mynativelib/aidl/foo/bar/Test.h")
473 ensureListContains(t, copyDests, "java/myjavalib.jar")
474 ensureListContains(t, copyDests, "arm64/lib/mynativelib.so")
475}
476
Jiyong Parkd1063c12019-07-17 20:08:41 +0900477var buildDir string
478
479func setUp() {
480 var err error
481 buildDir, err = ioutil.TempDir("", "soong_sdk_test")
482 if err != nil {
483 panic(err)
484 }
485}
486
487func tearDown() {
488 os.RemoveAll(buildDir)
489}
490
491func TestMain(m *testing.M) {
492 run := func() int {
493 setUp()
494 defer tearDown()
495
496 return m.Run()
497 }
498
499 os.Exit(run())
500}