blob: e3728606ac20e58a1b43acfb3c6bd3eb92306c70 [file] [log] [blame]
Inseob Kim5eb7ee92022-04-27 10:30:34 +09001// Copyright 2021 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 cc
16
17import (
18 _ "fmt"
19 _ "sort"
20
21 "testing"
22
23 "android/soong/android"
Kiyoung Kim487689e2022-07-26 09:48:22 +090024
25 "github.com/google/blueprint"
Inseob Kim5eb7ee92022-04-27 10:30:34 +090026)
27
Kiyoung Kim487689e2022-07-26 09:48:22 +090028func hasDirectDependency(t *testing.T, ctx *android.TestResult, from android.Module, to android.Module) bool {
29 t.Helper()
30 var found bool
31 ctx.VisitDirectDeps(from, func(dep blueprint.Module) {
32 if dep == to {
33 found = true
34 }
35 })
36 return found
37}
38
39func TestApiLibraryReplacesExistingModule(t *testing.T) {
40 bp := `
41 cc_library {
42 name: "libfoo",
43 shared_libs: ["libbar"],
44 }
45
46 cc_library {
47 name: "libbar",
48 }
49
50 cc_api_library {
51 name: "libbar",
52 src: "libbar.so",
53 }
54
55 api_imports {
56 name: "api_imports",
57 shared_libs: [
58 "libbar",
59 ],
60 header_libs: [],
61 }
62 `
63
64 ctx := prepareForCcTest.RunTestWithBp(t, bp)
65
66 libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
67 libbar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module()
68 libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_shared").Module()
69
70 android.AssertBoolEquals(t, "original library should not be linked", false, hasDirectDependency(t, ctx, libfoo, libbar))
71 android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
72}
73
74func TestApiLibraryDoNotRequireOriginalModule(t *testing.T) {
75 bp := `
76 cc_library {
77 name: "libfoo",
78 shared_libs: ["libbar"],
79 }
80
81 cc_api_library {
82 name: "libbar",
83 src: "libbar.so",
84 }
85
86 api_imports {
87 name: "api_imports",
88 shared_libs: [
89 "libbar",
90 ],
91 header_libs: [],
92 }
93 `
94
95 ctx := prepareForCcTest.RunTestWithBp(t, bp)
96
97 libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
98 libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_shared").Module()
99
100 android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
101}
102
103func TestApiLibraryShouldNotReplaceWithoutApiImport(t *testing.T) {
104 bp := `
105 cc_library {
106 name: "libfoo",
107 shared_libs: ["libbar"],
108 }
109
110 cc_library {
111 name: "libbar",
112 }
113
114 cc_api_library {
115 name: "libbar",
116 src: "libbar.so",
117 }
118
119 api_imports {
120 name: "api_imports",
121 shared_libs: [],
122 header_libs: [],
123 }
124 `
125
126 ctx := prepareForCcTest.RunTestWithBp(t, bp)
127
128 libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
129 libbar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module()
130 libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_shared").Module()
131
132 android.AssertBoolEquals(t, "original library should be linked", true, hasDirectDependency(t, ctx, libfoo, libbar))
133 android.AssertBoolEquals(t, "Stub library from API surface should not be linked", false, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
134}
Kiyoung Kim51279d32022-08-24 14:10:46 +0900135
136func TestApiHeaderReplacesExistingModule(t *testing.T) {
137 bp := `
138 cc_library {
139 name: "libfoo",
140 header_libs: ["libfoo_headers"],
141 }
142
143 cc_api_library {
144 name: "libfoo",
145 header_libs: ["libfoo_headers"],
146 src: "libfoo.so",
147 }
148
149 cc_library_headers {
150 name: "libfoo_headers",
151 }
152
153 cc_api_headers {
154 name: "libfoo_headers",
155 }
156
157 api_imports {
158 name: "api_imports",
159 shared_libs: [
160 "libfoo",
161 ],
162 header_libs: [
163 "libfoo_headers",
164 ],
165 }
166 `
167
168 ctx := prepareForCcTest.RunTestWithBp(t, bp)
169
170 libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
171 libfooApiImport := ctx.ModuleForTests("libfoo.apiimport", "android_arm64_armv8-a_shared").Module()
172 libfooHeader := ctx.ModuleForTests("libfoo_headers", "android_arm64_armv8-a").Module()
173 libfooHeaderApiImport := ctx.ModuleForTests("libfoo_headers.apiimport", "android_arm64_armv8-a").Module()
174
175 android.AssertBoolEquals(t, "original header should not be used for original library", false, hasDirectDependency(t, ctx, libfoo, libfooHeader))
176 android.AssertBoolEquals(t, "Header from API surface should be used for original library", true, hasDirectDependency(t, ctx, libfoo, libfooHeaderApiImport))
177 android.AssertBoolEquals(t, "original header should not be used for library imported from API surface", false, hasDirectDependency(t, ctx, libfooApiImport, libfooHeader))
178 android.AssertBoolEquals(t, "Header from API surface should be used for library imported from API surface", true, hasDirectDependency(t, ctx, libfooApiImport, libfooHeaderApiImport))
179}
180
181func TestApiHeadersDoNotRequireOriginalModule(t *testing.T) {
182 bp := `
183 cc_library {
184 name: "libfoo",
185 header_libs: ["libfoo_headers"],
186 }
187
188 cc_api_headers {
189 name: "libfoo_headers",
190 }
191
192 api_imports {
193 name: "api_imports",
194 shared_libs: [
195 "libfoo",
196 ],
197 header_libs: [
198 "libfoo_headers",
199 ],
200 }
201 `
202
203 ctx := prepareForCcTest.RunTestWithBp(t, bp)
204
205 libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
206 libfooHeaderApiImport := ctx.ModuleForTests("libfoo_headers.apiimport", "android_arm64_armv8-a").Module()
207
208 android.AssertBoolEquals(t, "Header from API surface should be used for original library", true, hasDirectDependency(t, ctx, libfoo, libfooHeaderApiImport))
209}
210
211func TestApiHeadersShouldNotReplaceWithoutApiImport(t *testing.T) {
212 bp := `
213 cc_library {
214 name: "libfoo",
215 header_libs: ["libfoo_headers"],
216 }
217
218 cc_library_headers {
219 name: "libfoo_headers",
220 }
221
222 cc_api_headers {
223 name: "libfoo_headers",
224 }
225
226 api_imports {
227 name: "api_imports",
228 shared_libs: [
229 "libfoo",
230 ],
231 header_libs: [],
232 }
233 `
234
235 ctx := prepareForCcTest.RunTestWithBp(t, bp)
236
237 libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
238 libfooHeader := ctx.ModuleForTests("libfoo_headers", "android_arm64_armv8-a").Module()
239 libfooHeaderApiImport := ctx.ModuleForTests("libfoo_headers.apiimport", "android_arm64_armv8-a").Module()
240
241 android.AssertBoolEquals(t, "original header should be used for original library", true, hasDirectDependency(t, ctx, libfoo, libfooHeader))
242 android.AssertBoolEquals(t, "Header from API surface should not be used for original library", false, hasDirectDependency(t, ctx, libfoo, libfooHeaderApiImport))
243}
Spandan Dasf0beebc2022-10-18 18:23:28 +0000244
245func TestExportDirFromStubLibrary(t *testing.T) {
246 bp := `
247 cc_library {
248 name: "libfoo",
249 export_include_dirs: ["source_include_dir"],
250 export_system_include_dirs: ["source_system_include_dir"],
251 vendor_available: true,
252 }
253 cc_api_library {
254 name: "libfoo",
255 export_include_dirs: ["stub_include_dir"],
256 export_system_include_dirs: ["stub_system_include_dir"],
257 vendor_available: true,
258 src: "libfoo.so",
259 }
260 api_imports {
261 name: "api_imports",
262 shared_libs: [
263 "libfoo",
264 ],
265 header_libs: [],
266 }
267 // vendor binary
268 cc_binary {
269 name: "vendorbin",
270 vendor: true,
271 srcs: ["vendor.cc"],
272 shared_libs: ["libfoo"],
273 }
274 `
275 ctx := prepareForCcTest.RunTestWithBp(t, bp)
276 vendorCFlags := ctx.ModuleForTests("vendorbin", "android_vendor.29_arm64_armv8-a").Rule("cc").Args["cFlags"]
277 android.AssertStringDoesContain(t, "Vendor binary should compile using headers provided by stub", vendorCFlags, "-Istub_include_dir")
278 android.AssertStringDoesNotContain(t, "Vendor binary should not compile using headers of source", vendorCFlags, "-Isource_include_dir")
279 android.AssertStringDoesContain(t, "Vendor binary should compile using system headers provided by stub", vendorCFlags, "-isystem stub_system_include_dir")
280 android.AssertStringDoesNotContain(t, "Vendor binary should not compile using system headers of source", vendorCFlags, "-isystem source_system_include_dir")
Spandan Dasa3c8a172022-10-26 20:54:32 +0000281
282 vendorImplicits := ctx.ModuleForTests("vendorbin", "android_vendor.29_arm64_armv8-a").Rule("cc").OrderOnly.Strings()
283 // Building the stub.so file first assembles its .h files in multi-tree out.
284 // These header files are required for compiling the other API domain (vendor in this case)
285 android.AssertStringListContains(t, "Vendor binary compilation should have an implicit dep on the stub .so file", vendorImplicits, "libfoo.so")
Spandan Dasf0beebc2022-10-18 18:23:28 +0000286}
Kiyoung Kimee58c932022-10-25 22:59:41 +0900287
288func TestApiLibraryWithLlndkVariant(t *testing.T) {
289 bp := `
290 cc_binary {
291 name: "binfoo",
292 vendor: true,
293 srcs: ["binfoo.cc"],
294 shared_libs: ["libbar"],
295 }
296
297 cc_api_library {
298 name: "libbar",
299 // TODO(b/244244438) Remove src property once all variants are implemented.
300 src: "libbar.so",
301 vendor_available: true,
302 variants: [
303 "llndk",
304 ],
305 }
306
307 cc_api_variant {
308 name: "libbar",
309 variant: "llndk",
310 src: "libbar_llndk.so",
311 export_headers: ["libbar_llndk_include"]
312 }
313
314 api_imports {
315 name: "api_imports",
316 shared_libs: [
317 "libbar",
318 ],
319 header_libs: [],
320 }
321 `
322
323 ctx := prepareForCcTest.RunTestWithBp(t, bp)
324
Kiyoung Kimd5d1ab12022-11-28 16:47:10 +0900325 binfoo := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Module()
Kiyoung Kimee58c932022-10-25 22:59:41 +0900326 libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
327 libbarApiVariant := ctx.ModuleForTests("libbar.llndk.apiimport", "android_vendor.29_arm64_armv8-a").Module()
328
Kiyoung Kimd5d1ab12022-11-28 16:47:10 +0900329 android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, binfoo, libbarApiImport))
Kiyoung Kimee58c932022-10-25 22:59:41 +0900330 android.AssertBoolEquals(t, "Stub library variant from API surface should be linked", true, hasDirectDependency(t, ctx, libbarApiImport, libbarApiVariant))
331
Kiyoung Kimd5d1ab12022-11-28 16:47:10 +0900332 binFooLibFlags := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Rule("ld").Args["libFlags"]
333 android.AssertStringDoesContain(t, "Vendor binary should be linked with LLNDK variant source", binFooLibFlags, "libbar_llndk.so")
Kiyoung Kimee58c932022-10-25 22:59:41 +0900334
Kiyoung Kimd5d1ab12022-11-28 16:47:10 +0900335 binFooCFlags := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Rule("cc").Args["cFlags"]
336 android.AssertStringDoesContain(t, "Vendor binary should include headers from the LLNDK variant source", binFooCFlags, "-Ilibbar_llndk_include")
337}
338
339func TestApiLibraryWithNdkVariant(t *testing.T) {
340 bp := `
341 cc_binary {
342 name: "binfoo",
343 sdk_version: "29",
344 srcs: ["binfoo.cc"],
345 shared_libs: ["libbar"],
346 stl: "c++_shared",
347 }
348
349 cc_binary {
350 name: "binbaz",
351 sdk_version: "30",
352 srcs: ["binbaz.cc"],
353 shared_libs: ["libbar"],
354 stl: "c++_shared",
355 }
356
357 cc_api_library {
358 name: "libbar",
359 // TODO(b/244244438) Remove src property once all variants are implemented.
360 src: "libbar.so",
361 variants: [
362 "ndk.29",
363 "ndk.30",
364 "ndk.current",
365 ],
366 }
367
368 cc_api_variant {
369 name: "libbar",
370 variant: "ndk",
371 version: "29",
372 src: "libbar_ndk_29.so",
373 export_headers: ["libbar_ndk_29_include"]
374 }
375
376 cc_api_variant {
377 name: "libbar",
378 variant: "ndk",
379 version: "30",
380 src: "libbar_ndk_30.so",
381 export_headers: ["libbar_ndk_30_include"]
382 }
383
384 cc_api_variant {
385 name: "libbar",
386 variant: "ndk",
387 version: "current",
388 src: "libbar_ndk_current.so",
389 export_headers: ["libbar_ndk_current_include"]
390 }
391
392 api_imports {
393 name: "api_imports",
394 shared_libs: [
395 "libbar",
396 ],
397 header_libs: [],
398 }
399 `
400
401 ctx := prepareForCcTest.RunTestWithBp(t, bp)
402
403 binfoo := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Module()
404 libbarApiImportv29 := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_sdk_shared_29").Module()
405 libbarApiVariantv29 := ctx.ModuleForTests("libbar.ndk.29.apiimport", "android_arm64_armv8-a_sdk").Module()
406 libbarApiImportv30 := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_sdk_shared_30").Module()
407 libbarApiVariantv30 := ctx.ModuleForTests("libbar.ndk.30.apiimport", "android_arm64_armv8-a_sdk").Module()
408
409 android.AssertBoolEquals(t, "Stub library from API surface should be linked with target version", true, hasDirectDependency(t, ctx, binfoo, libbarApiImportv29))
410 android.AssertBoolEquals(t, "Stub library variant from API surface should be linked with target version", true, hasDirectDependency(t, ctx, libbarApiImportv29, libbarApiVariantv29))
411 android.AssertBoolEquals(t, "Stub library from API surface should not be linked with different version", false, hasDirectDependency(t, ctx, binfoo, libbarApiImportv30))
412 android.AssertBoolEquals(t, "Stub library variant from API surface should not be linked with different version", false, hasDirectDependency(t, ctx, libbarApiImportv29, libbarApiVariantv30))
413
414 binbaz := ctx.ModuleForTests("binbaz", "android_arm64_armv8-a_sdk").Module()
415
416 android.AssertBoolEquals(t, "Stub library from API surface should be linked with target version", true, hasDirectDependency(t, ctx, binbaz, libbarApiImportv30))
417 android.AssertBoolEquals(t, "Stub library from API surface should not be linked with different version", false, hasDirectDependency(t, ctx, binbaz, libbarApiImportv29))
418
419 binFooLibFlags := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Rule("ld").Args["libFlags"]
420 android.AssertStringDoesContain(t, "Binary using sdk should be linked with NDK variant source", binFooLibFlags, "libbar_ndk_29.so")
421
422 binFooCFlags := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Rule("cc").Args["cFlags"]
423 android.AssertStringDoesContain(t, "Binary using sdk should include headers from the NDK variant source", binFooCFlags, "-Ilibbar_ndk_29_include")
424}
425
426func TestApiLibraryWithMultipleVariants(t *testing.T) {
427 bp := `
428 cc_binary {
429 name: "binfoo",
430 sdk_version: "29",
431 srcs: ["binfoo.cc"],
432 shared_libs: ["libbar"],
433 stl: "c++_shared",
434 }
435
436 cc_binary {
437 name: "binbaz",
438 vendor: true,
439 srcs: ["binbaz.cc"],
440 shared_libs: ["libbar"],
441 }
442
443 cc_api_library {
444 name: "libbar",
445 // TODO(b/244244438) Remove src property once all variants are implemented.
446 src: "libbar.so",
447 vendor_available: true,
448 variants: [
449 "llndk",
450 "ndk.29",
451 "ndk.30",
452 "ndk.current",
453 ],
454 }
455
456 cc_api_variant {
457 name: "libbar",
458 variant: "ndk",
459 version: "29",
460 src: "libbar_ndk_29.so",
461 export_headers: ["libbar_ndk_29_include"]
462 }
463
464 cc_api_variant {
465 name: "libbar",
466 variant: "ndk",
467 version: "30",
468 src: "libbar_ndk_30.so",
469 export_headers: ["libbar_ndk_30_include"]
470 }
471
472 cc_api_variant {
473 name: "libbar",
474 variant: "ndk",
475 version: "current",
476 src: "libbar_ndk_current.so",
477 export_headers: ["libbar_ndk_current_include"]
478 }
479
480 cc_api_variant {
481 name: "libbar",
482 variant: "llndk",
483 src: "libbar_llndk.so",
484 export_headers: ["libbar_llndk_include"]
485 }
486
487 api_imports {
488 name: "api_imports",
489 shared_libs: [
490 "libbar",
491 ],
492 header_libs: [],
493 }
494 `
495 ctx := prepareForCcTest.RunTestWithBp(t, bp)
496
497 binfoo := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Module()
498 libbarApiImportv29 := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_sdk_shared_29").Module()
499 libbarApiImportLlndk := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
500
501 android.AssertBoolEquals(t, "Binary using SDK should be linked with API library from NDK variant", true, hasDirectDependency(t, ctx, binfoo, libbarApiImportv29))
502 android.AssertBoolEquals(t, "Binary using SDK should not be linked with API library from LLNDK variant", false, hasDirectDependency(t, ctx, binfoo, libbarApiImportLlndk))
503
504 binbaz := ctx.ModuleForTests("binbaz", "android_vendor.29_arm64_armv8-a").Module()
505
506 android.AssertBoolEquals(t, "Vendor binary should be linked with API library from LLNDK variant", true, hasDirectDependency(t, ctx, binbaz, libbarApiImportLlndk))
507 android.AssertBoolEquals(t, "Vendor binary should not be linked with API library from NDK variant", false, hasDirectDependency(t, ctx, binbaz, libbarApiImportv29))
508
Kiyoung Kimee58c932022-10-25 22:59:41 +0900509}