blob: cd061722e918bbc4b2495a47c84ccc120fb05ba7 [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"
24 "android/soong/multitree"
Kiyoung Kim487689e2022-07-26 09:48:22 +090025
26 "github.com/google/blueprint"
Inseob Kim5eb7ee92022-04-27 10:30:34 +090027)
28
29func TestCcApiStubLibraryOutputFiles(t *testing.T) {
30 bp := `
31 cc_api_stub_library {
32 name: "foo",
33 symbol_file: "foo.map.txt",
34 first_version: "29",
35 }
36 `
37 result := prepareForCcTest.RunTestWithBp(t, bp)
38 outputs := result.ModuleForTests("foo", "android_arm64_armv8-a_shared").AllOutputs()
39 expected_file_suffixes := []string{".c", "stub.map", ".o", ".so"}
40 for _, expected_file_suffix := range expected_file_suffixes {
41 android.AssertBoolEquals(t, expected_file_suffix+" file not found in output", true, android.SuffixInList(outputs, expected_file_suffix))
42 }
43}
44
45func TestCcApiStubLibraryVariants(t *testing.T) {
46 bp := `
47 cc_api_stub_library {
48 name: "foo",
49 symbol_file: "foo.map.txt",
50 first_version: "29",
51 }
52 `
53 result := prepareForCcTest.RunTestWithBp(t, bp)
54 variants := result.ModuleVariantsForTests("foo")
55 expected_variants := []string{"29", "30", "S", "Tiramisu"} //TODO: make this test deterministic by using fixtures
56 for _, expected_variant := range expected_variants {
57 android.AssertBoolEquals(t, expected_variant+" variant not found in foo", true, android.SubstringInList(variants, expected_variant))
58 }
59}
60
61func TestCcLibraryUsesCcApiStubLibrary(t *testing.T) {
62 bp := `
63 cc_api_stub_library {
64 name: "foo",
65 symbol_file: "foo.map.txt",
66 first_version: "29",
67 }
68 cc_library {
69 name: "foo_user",
70 shared_libs: [
71 "foo#29",
72 ],
73 }
74
75 `
76 prepareForCcTest.RunTestWithBp(t, bp)
77}
78
79func TestApiSurfaceOutputs(t *testing.T) {
80 bp := `
81 api_surface {
82 name: "mysdk",
83 contributions: [
84 "foo",
85 ],
86 }
87
88 cc_api_contribution {
89 name: "foo",
90 symbol_file: "foo.map.txt",
91 first_version: "29",
92 }
93 `
94 result := android.GroupFixturePreparers(
95 prepareForCcTest,
96 multitree.PrepareForTestWithApiSurface,
97 ).RunTestWithBp(t, bp)
98 mysdk := result.ModuleForTests("mysdk", "")
99
100 actual_surface_inputs := mysdk.Rule("phony").BuildParams.Inputs.Strings()
101 expected_file_suffixes := []string{"mysdk/foo/foo.map.txt"}
102 for _, expected_file_suffix := range expected_file_suffixes {
103 android.AssertBoolEquals(t, expected_file_suffix+" file not found in input", true, android.SuffixInList(actual_surface_inputs, expected_file_suffix))
104 }
105
106 // check args/inputs to rule
107 /*api_surface_gen_rule_args := result.ModuleForTests("mysdk", "").Rule("genApiSurfaceBuildFiles").Args
108 android.AssertStringEquals(t, "name", "foo.mysdk", api_surface_gen_rule_args["name"])
109 android.AssertStringEquals(t, "symbol_file", "foo.map.txt", api_surface_gen_rule_args["symbol_file"])*/
110}
Kiyoung Kim487689e2022-07-26 09:48:22 +0900111
112func hasDirectDependency(t *testing.T, ctx *android.TestResult, from android.Module, to android.Module) bool {
113 t.Helper()
114 var found bool
115 ctx.VisitDirectDeps(from, func(dep blueprint.Module) {
116 if dep == to {
117 found = true
118 }
119 })
120 return found
121}
122
123func TestApiLibraryReplacesExistingModule(t *testing.T) {
124 bp := `
125 cc_library {
126 name: "libfoo",
127 shared_libs: ["libbar"],
128 }
129
130 cc_library {
131 name: "libbar",
132 }
133
134 cc_api_library {
135 name: "libbar",
136 src: "libbar.so",
137 }
138
139 api_imports {
140 name: "api_imports",
141 shared_libs: [
142 "libbar",
143 ],
144 header_libs: [],
145 }
146 `
147
148 ctx := prepareForCcTest.RunTestWithBp(t, bp)
149
150 libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
151 libbar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module()
152 libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_shared").Module()
153
154 android.AssertBoolEquals(t, "original library should not be linked", false, hasDirectDependency(t, ctx, libfoo, libbar))
155 android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
156}
157
158func TestApiLibraryDoNotRequireOriginalModule(t *testing.T) {
159 bp := `
160 cc_library {
161 name: "libfoo",
162 shared_libs: ["libbar"],
163 }
164
165 cc_api_library {
166 name: "libbar",
167 src: "libbar.so",
168 }
169
170 api_imports {
171 name: "api_imports",
172 shared_libs: [
173 "libbar",
174 ],
175 header_libs: [],
176 }
177 `
178
179 ctx := prepareForCcTest.RunTestWithBp(t, bp)
180
181 libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
182 libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_shared").Module()
183
184 android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
185}
186
187func TestApiLibraryShouldNotReplaceWithoutApiImport(t *testing.T) {
188 bp := `
189 cc_library {
190 name: "libfoo",
191 shared_libs: ["libbar"],
192 }
193
194 cc_library {
195 name: "libbar",
196 }
197
198 cc_api_library {
199 name: "libbar",
200 src: "libbar.so",
201 }
202
203 api_imports {
204 name: "api_imports",
205 shared_libs: [],
206 header_libs: [],
207 }
208 `
209
210 ctx := prepareForCcTest.RunTestWithBp(t, bp)
211
212 libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
213 libbar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module()
214 libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_shared").Module()
215
216 android.AssertBoolEquals(t, "original library should be linked", true, hasDirectDependency(t, ctx, libfoo, libbar))
217 android.AssertBoolEquals(t, "Stub library from API surface should not be linked", false, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
218}
Kiyoung Kim51279d32022-08-24 14:10:46 +0900219
220func TestApiHeaderReplacesExistingModule(t *testing.T) {
221 bp := `
222 cc_library {
223 name: "libfoo",
224 header_libs: ["libfoo_headers"],
225 }
226
227 cc_api_library {
228 name: "libfoo",
229 header_libs: ["libfoo_headers"],
230 src: "libfoo.so",
231 }
232
233 cc_library_headers {
234 name: "libfoo_headers",
235 }
236
237 cc_api_headers {
238 name: "libfoo_headers",
239 }
240
241 api_imports {
242 name: "api_imports",
243 shared_libs: [
244 "libfoo",
245 ],
246 header_libs: [
247 "libfoo_headers",
248 ],
249 }
250 `
251
252 ctx := prepareForCcTest.RunTestWithBp(t, bp)
253
254 libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
255 libfooApiImport := ctx.ModuleForTests("libfoo.apiimport", "android_arm64_armv8-a_shared").Module()
256 libfooHeader := ctx.ModuleForTests("libfoo_headers", "android_arm64_armv8-a").Module()
257 libfooHeaderApiImport := ctx.ModuleForTests("libfoo_headers.apiimport", "android_arm64_armv8-a").Module()
258
259 android.AssertBoolEquals(t, "original header should not be used for original library", false, hasDirectDependency(t, ctx, libfoo, libfooHeader))
260 android.AssertBoolEquals(t, "Header from API surface should be used for original library", true, hasDirectDependency(t, ctx, libfoo, libfooHeaderApiImport))
261 android.AssertBoolEquals(t, "original header should not be used for library imported from API surface", false, hasDirectDependency(t, ctx, libfooApiImport, libfooHeader))
262 android.AssertBoolEquals(t, "Header from API surface should be used for library imported from API surface", true, hasDirectDependency(t, ctx, libfooApiImport, libfooHeaderApiImport))
263}
264
265func TestApiHeadersDoNotRequireOriginalModule(t *testing.T) {
266 bp := `
267 cc_library {
268 name: "libfoo",
269 header_libs: ["libfoo_headers"],
270 }
271
272 cc_api_headers {
273 name: "libfoo_headers",
274 }
275
276 api_imports {
277 name: "api_imports",
278 shared_libs: [
279 "libfoo",
280 ],
281 header_libs: [
282 "libfoo_headers",
283 ],
284 }
285 `
286
287 ctx := prepareForCcTest.RunTestWithBp(t, bp)
288
289 libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
290 libfooHeaderApiImport := ctx.ModuleForTests("libfoo_headers.apiimport", "android_arm64_armv8-a").Module()
291
292 android.AssertBoolEquals(t, "Header from API surface should be used for original library", true, hasDirectDependency(t, ctx, libfoo, libfooHeaderApiImport))
293}
294
295func TestApiHeadersShouldNotReplaceWithoutApiImport(t *testing.T) {
296 bp := `
297 cc_library {
298 name: "libfoo",
299 header_libs: ["libfoo_headers"],
300 }
301
302 cc_library_headers {
303 name: "libfoo_headers",
304 }
305
306 cc_api_headers {
307 name: "libfoo_headers",
308 }
309
310 api_imports {
311 name: "api_imports",
312 shared_libs: [
313 "libfoo",
314 ],
315 header_libs: [],
316 }
317 `
318
319 ctx := prepareForCcTest.RunTestWithBp(t, bp)
320
321 libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
322 libfooHeader := ctx.ModuleForTests("libfoo_headers", "android_arm64_armv8-a").Module()
323 libfooHeaderApiImport := ctx.ModuleForTests("libfoo_headers.apiimport", "android_arm64_armv8-a").Module()
324
325 android.AssertBoolEquals(t, "original header should be used for original library", true, hasDirectDependency(t, ctx, libfoo, libfooHeader))
326 android.AssertBoolEquals(t, "Header from API surface should not be used for original library", false, hasDirectDependency(t, ctx, libfoo, libfooHeaderApiImport))
327}