blob: 8ce74c4722d56f0a8c3d98ddf3e06f00eeb54b51 [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
325 libfoo := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Module()
326 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
329 android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
330 android.AssertBoolEquals(t, "Stub library variant from API surface should be linked", true, hasDirectDependency(t, ctx, libbarApiImport, libbarApiVariant))
331
332 libFooLibFlags := 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", libFooLibFlags, "libbar_llndk.so")
334
335 libFooCFlags := 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", libFooCFlags, "-Ilibbar_llndk_include")
337}