blob: 7b89dded4c16ec29d74f139f50d6a05bd8a81b37 [file] [log] [blame]
Colin Cross2207f872021-03-24 12:39:08 -07001// 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 java
16
17import (
Pedro Loureirocc203502021-10-04 17:24:00 +000018 "fmt"
Colin Cross6aa5c402021-03-24 12:28:50 -070019 "reflect"
satayev783195c2021-06-23 21:49:57 +010020 "regexp"
Colin Cross2207f872021-03-24 12:39:08 -070021 "strings"
22 "testing"
23
24 "android/soong/android"
Jihoon Kangc8313892023-09-20 00:54:47 +000025
26 "github.com/google/blueprint/proptools"
Colin Cross2207f872021-03-24 12:39:08 -070027)
28
29func TestDroidstubs(t *testing.T) {
30 ctx, _ := testJavaWithFS(t, `
31 droiddoc_exported_dir {
32 name: "droiddoc-templates-sdk",
33 path: ".",
34 }
35
36 droidstubs {
37 name: "bar-stubs",
38 srcs: ["bar-doc/a.java"],
39 api_levels_annotations_dirs: ["droiddoc-templates-sdk"],
40 api_levels_annotations_enabled: true,
41 }
42
43 droidstubs {
44 name: "bar-stubs-other",
45 srcs: ["bar-doc/a.java"],
46 high_mem: true,
47 api_levels_annotations_dirs: ["droiddoc-templates-sdk"],
48 api_levels_annotations_enabled: true,
49 api_levels_jar_filename: "android.other.jar",
50 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +000051
52 droidstubs {
53 name: "stubs-applying-api-versions",
54 srcs: ["bar-doc/a.java"],
55 api_levels_module: "bar-stubs-other",
56 }
Colin Cross2207f872021-03-24 12:39:08 -070057 `,
58 map[string][]byte{
59 "bar-doc/a.java": nil,
60 })
61 testcases := []struct {
62 moduleName string
63 expectedJarFilename string
Anton Hanssonc04a16e2022-05-09 09:30:26 +000064 generate_xml bool
Colin Cross2207f872021-03-24 12:39:08 -070065 high_mem bool
66 }{
67 {
68 moduleName: "bar-stubs",
Anton Hanssonc04a16e2022-05-09 09:30:26 +000069 generate_xml: true,
Colin Cross2207f872021-03-24 12:39:08 -070070 expectedJarFilename: "android.jar",
71 high_mem: false,
72 },
73 {
74 moduleName: "bar-stubs-other",
Anton Hanssonc04a16e2022-05-09 09:30:26 +000075 generate_xml: true,
Colin Cross2207f872021-03-24 12:39:08 -070076 expectedJarFilename: "android.other.jar",
77 high_mem: true,
78 },
Anton Hanssonc04a16e2022-05-09 09:30:26 +000079 {
80 moduleName: "stubs-applying-api-versions",
81 generate_xml: false,
82 },
Colin Cross2207f872021-03-24 12:39:08 -070083 }
84 for _, c := range testcases {
85 m := ctx.ModuleForTests(c.moduleName, "android_common")
Colin Cross8095c292021-03-30 16:40:48 -070086 manifest := m.Output("metalava.sbox.textproto")
Colin Crossf61d03d2023-11-02 16:56:39 -070087 sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx, manifest)
Anton Hanssonc04a16e2022-05-09 09:30:26 +000088 cmdline := String(sboxProto.Commands[0].Command)
89 android.AssertStringContainsEquals(t, "api-versions generation flag", cmdline, "--generate-api-levels", c.generate_xml)
90 if c.expectedJarFilename != "" {
91 expected := "--android-jar-pattern ./%/public/" + c.expectedJarFilename
92 if !strings.Contains(cmdline, expected) {
93 t.Errorf("For %q, expected metalava argument %q, but was not found %q", c.moduleName, expected, cmdline)
94 }
Colin Cross2207f872021-03-24 12:39:08 -070095 }
96
Colin Cross8095c292021-03-30 16:40:48 -070097 metalava := m.Rule("metalava")
98 rp := metalava.RuleParams
Colin Cross2207f872021-03-24 12:39:08 -070099 if actual := rp.Pool != nil && strings.Contains(rp.Pool.String(), "highmem"); actual != c.high_mem {
100 t.Errorf("Expected %q high_mem to be %v, was %v", c.moduleName, c.high_mem, actual)
101 }
102 }
103}
104
Pedro Loureirocc203502021-10-04 17:24:00 +0000105// runs a test for droidstubs with a customizable sdkType argument and returns
106// the list of jar patterns that is passed as `--android-jar-pattern`
107func getAndroidJarPatternsForDroidstubs(t *testing.T, sdkType string) []string {
108 ctx, _ := testJavaWithFS(t, fmt.Sprintf(`
satayev783195c2021-06-23 21:49:57 +0100109 droiddoc_exported_dir {
110 name: "some-exported-dir",
111 path: "somedir",
112 }
113
114 droiddoc_exported_dir {
115 name: "some-other-exported-dir",
116 path: "someotherdir",
117 }
118
119 droidstubs {
120 name: "foo-stubs",
121 srcs: ["foo-doc/a.java"],
122 api_levels_annotations_dirs: [
123 "some-exported-dir",
124 "some-other-exported-dir",
125 ],
126 api_levels_annotations_enabled: true,
Cole Faust051fa912022-10-05 12:45:42 -0700127 api_levels_sdk_type: "%s",
satayev783195c2021-06-23 21:49:57 +0100128 }
Pedro Loureirocc203502021-10-04 17:24:00 +0000129 `, sdkType),
satayev783195c2021-06-23 21:49:57 +0100130 map[string][]byte{
131 "foo-doc/a.java": nil,
132 })
133
134 m := ctx.ModuleForTests("foo-stubs", "android_common")
135 manifest := m.Output("metalava.sbox.textproto")
Colin Crossf61d03d2023-11-02 16:56:39 -0700136 cmd := String(android.RuleBuilderSboxProtoForTests(t, ctx, manifest).Commands[0].Command)
satayev783195c2021-06-23 21:49:57 +0100137 r := regexp.MustCompile(`--android-jar-pattern [^ ]+/android.jar`)
Pedro Loureirocc203502021-10-04 17:24:00 +0000138 return r.FindAllString(cmd, -1)
139}
140
141func TestPublicDroidstubs(t *testing.T) {
142 patterns := getAndroidJarPatternsForDroidstubs(t, "public")
143
144 android.AssertArrayString(t, "order of patterns", []string{
145 "--android-jar-pattern somedir/%/public/android.jar",
146 "--android-jar-pattern someotherdir/%/public/android.jar",
147 }, patterns)
148}
149
150func TestSystemDroidstubs(t *testing.T) {
151 patterns := getAndroidJarPatternsForDroidstubs(t, "system")
152
satayev783195c2021-06-23 21:49:57 +0100153 android.AssertArrayString(t, "order of patterns", []string{
154 "--android-jar-pattern somedir/%/system/android.jar",
155 "--android-jar-pattern someotherdir/%/system/android.jar",
156 "--android-jar-pattern somedir/%/public/android.jar",
157 "--android-jar-pattern someotherdir/%/public/android.jar",
Pedro Loureirocc203502021-10-04 17:24:00 +0000158 }, patterns)
159}
160
161func TestModuleLibDroidstubs(t *testing.T) {
162 patterns := getAndroidJarPatternsForDroidstubs(t, "module-lib")
163
164 android.AssertArrayString(t, "order of patterns", []string{
165 "--android-jar-pattern somedir/%/module-lib/android.jar",
166 "--android-jar-pattern someotherdir/%/module-lib/android.jar",
167 "--android-jar-pattern somedir/%/system/android.jar",
168 "--android-jar-pattern someotherdir/%/system/android.jar",
169 "--android-jar-pattern somedir/%/public/android.jar",
170 "--android-jar-pattern someotherdir/%/public/android.jar",
171 }, patterns)
satayev783195c2021-06-23 21:49:57 +0100172}
173
Cole Faust051fa912022-10-05 12:45:42 -0700174func TestSystemServerDroidstubs(t *testing.T) {
175 patterns := getAndroidJarPatternsForDroidstubs(t, "system-server")
176
177 android.AssertArrayString(t, "order of patterns", []string{
178 "--android-jar-pattern somedir/%/system-server/android.jar",
179 "--android-jar-pattern someotherdir/%/system-server/android.jar",
180 "--android-jar-pattern somedir/%/module-lib/android.jar",
181 "--android-jar-pattern someotherdir/%/module-lib/android.jar",
182 "--android-jar-pattern somedir/%/system/android.jar",
183 "--android-jar-pattern someotherdir/%/system/android.jar",
184 "--android-jar-pattern somedir/%/public/android.jar",
185 "--android-jar-pattern someotherdir/%/public/android.jar",
186 }, patterns)
187}
188
Colin Cross6aa5c402021-03-24 12:28:50 -0700189func TestDroidstubsSandbox(t *testing.T) {
190 ctx, _ := testJavaWithFS(t, `
Colin Crossbc139922021-03-25 18:33:16 -0700191 genrule {
192 name: "foo",
193 out: ["foo.txt"],
194 cmd: "touch $(out)",
195 }
196
Colin Cross6aa5c402021-03-24 12:28:50 -0700197 droidstubs {
198 name: "bar-stubs",
199 srcs: ["bar-doc/a.java"],
Colin Crossbc139922021-03-25 18:33:16 -0700200
201 args: "--reference $(location :foo)",
202 arg_files: [":foo"],
Colin Cross6aa5c402021-03-24 12:28:50 -0700203 }
204 `,
205 map[string][]byte{
206 "bar-doc/a.java": nil,
207 })
208
209 m := ctx.ModuleForTests("bar-stubs", "android_common")
210 metalava := m.Rule("metalava")
211 if g, w := metalava.Inputs.Strings(), []string{"bar-doc/a.java"}; !reflect.DeepEqual(w, g) {
212 t.Errorf("Expected inputs %q, got %q", w, g)
213 }
Colin Crossbc139922021-03-25 18:33:16 -0700214
Colin Crossf61d03d2023-11-02 16:56:39 -0700215 manifest := android.RuleBuilderSboxProtoForTests(t, ctx, m.Output("metalava.sbox.textproto"))
Colin Crossbc139922021-03-25 18:33:16 -0700216 if g, w := manifest.Commands[0].GetCommand(), "reference __SBOX_SANDBOX_DIR__/out/.intermediates/foo/gen/foo.txt"; !strings.Contains(g, w) {
217 t.Errorf("Expected command to contain %q, got %q", w, g)
218 }
Colin Cross6aa5c402021-03-24 12:28:50 -0700219}
220
Colin Cross2207f872021-03-24 12:39:08 -0700221func TestDroidstubsWithSystemModules(t *testing.T) {
222 ctx, _ := testJava(t, `
223 droidstubs {
224 name: "stubs-source-system-modules",
225 srcs: [
226 "bar-doc/a.java",
227 ],
228 sdk_version: "none",
229 system_modules: "source-system-modules",
230 }
231
232 java_library {
233 name: "source-jar",
234 srcs: [
235 "a.java",
236 ],
237 }
238
239 java_system_modules {
240 name: "source-system-modules",
241 libs: ["source-jar"],
242 }
243
244 droidstubs {
245 name: "stubs-prebuilt-system-modules",
246 srcs: [
247 "bar-doc/a.java",
248 ],
249 sdk_version: "none",
250 system_modules: "prebuilt-system-modules",
251 }
252
253 java_import {
254 name: "prebuilt-jar",
255 jars: ["a.jar"],
256 }
257
258 java_system_modules_import {
259 name: "prebuilt-system-modules",
260 libs: ["prebuilt-jar"],
261 }
262 `)
263
264 checkSystemModulesUseByDroidstubs(t, ctx, "stubs-source-system-modules", "source-jar.jar")
265
266 checkSystemModulesUseByDroidstubs(t, ctx, "stubs-prebuilt-system-modules", "prebuilt-jar.jar")
267}
268
Colin Cross2207f872021-03-24 12:39:08 -0700269func checkSystemModulesUseByDroidstubs(t *testing.T, ctx *android.TestContext, moduleName string, systemJar string) {
270 metalavaRule := ctx.ModuleForTests(moduleName, "android_common").Rule("metalava")
271 var systemJars []string
272 for _, i := range metalavaRule.Implicits {
273 systemJars = append(systemJars, i.Base())
274 }
275 if len(systemJars) < 1 || systemJars[0] != systemJar {
276 t.Errorf("inputs of %q must be []string{%q}, but was %#v.", moduleName, systemJar, systemJars)
277 }
278}
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200279
280func TestDroidstubsWithSdkExtensions(t *testing.T) {
281 ctx, _ := testJavaWithFS(t, `
282 droiddoc_exported_dir {
283 name: "sdk-dir",
284 path: "sdk",
285 }
286
287 droidstubs {
288 name: "baz-stubs",
289 api_levels_annotations_dirs: ["sdk-dir"],
290 api_levels_annotations_enabled: true,
291 extensions_info_file: ":info-file",
292 }
293
294 filegroup {
295 name: "info-file",
296 srcs: ["sdk/extensions/info.txt"],
297 }
298 `,
299 map[string][]byte{
300 "sdk/extensions/1/public/some-mainline-module-stubs.jar": nil,
301 "sdk/extensions/info.txt": nil,
302 })
303 m := ctx.ModuleForTests("baz-stubs", "android_common")
304 manifest := m.Output("metalava.sbox.textproto")
Colin Crossf61d03d2023-11-02 16:56:39 -0700305 cmdline := String(android.RuleBuilderSboxProtoForTests(t, ctx, manifest).Commands[0].Command)
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200306 android.AssertStringDoesContain(t, "sdk-extensions-root present", cmdline, "--sdk-extensions-root sdk/extensions")
307 android.AssertStringDoesContain(t, "sdk-extensions-info present", cmdline, "--sdk-extensions-info sdk/extensions/info.txt")
308}
Spandan Das0b555e32022-11-28 18:48:51 +0000309
310func TestApiSurfaceFromDroidStubsName(t *testing.T) {
311 testCases := []struct {
312 desc string
313 name string
314 expectedApiSurface string
315 }{
316 {
317 desc: "Default is publicapi",
318 name: "mydroidstubs",
319 expectedApiSurface: "publicapi",
320 },
321 {
322 desc: "name contains system substring",
323 name: "mydroidstubs.system.suffix",
324 expectedApiSurface: "systemapi",
325 },
326 {
327 desc: "name contains system_server substring",
328 name: "mydroidstubs.system_server.suffix",
329 expectedApiSurface: "system-serverapi",
330 },
331 {
332 desc: "name contains module_lib substring",
333 name: "mydroidstubs.module_lib.suffix",
334 expectedApiSurface: "module-libapi",
335 },
336 {
337 desc: "name contains test substring",
338 name: "mydroidstubs.test.suffix",
339 expectedApiSurface: "testapi",
340 },
341 {
342 desc: "name contains intra.core substring",
343 name: "mydroidstubs.intra.core.suffix",
344 expectedApiSurface: "intracoreapi",
345 },
346 }
347 for _, tc := range testCases {
348 android.AssertStringEquals(t, tc.desc, tc.expectedApiSurface, bazelApiSurfaceName(tc.name))
349 }
350}
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000351
352func TestDroidStubsApiContributionGeneration(t *testing.T) {
353 ctx, _ := testJavaWithFS(t, `
354 droidstubs {
355 name: "foo",
356 srcs: ["A/a.java"],
357 api_surface: "public",
358 check_api: {
359 current: {
360 api_file: "A/current.txt",
361 removed_api_file: "A/removed.txt",
362 }
363 }
364 }
365 `,
366 map[string][]byte{
367 "A/a.java": nil,
368 "A/current.txt": nil,
369 "A/removed.txt": nil,
370 },
371 )
372
373 ctx.ModuleForTests("foo.api.contribution", "")
374}
Jihoon Kang42b589c2023-02-03 22:56:13 +0000375
376func TestGeneratedApiContributionVisibilityTest(t *testing.T) {
377 library_bp := `
378 java_api_library {
379 name: "bar",
380 api_surface: "public",
381 api_contributions: ["foo.api.contribution"],
382 }
383 `
384 ctx, _ := testJavaWithFS(t, `
385 droidstubs {
386 name: "foo",
387 srcs: ["A/a.java"],
388 api_surface: "public",
389 check_api: {
390 current: {
391 api_file: "A/current.txt",
392 removed_api_file: "A/removed.txt",
393 }
394 },
Jihoon Kang063ec002023-06-28 01:16:23 +0000395 visibility: ["//a", "//b"],
Jihoon Kang42b589c2023-02-03 22:56:13 +0000396 }
397 `,
398 map[string][]byte{
399 "a/a.java": nil,
400 "a/current.txt": nil,
401 "a/removed.txt": nil,
402 "b/Android.bp": []byte(library_bp),
403 },
404 )
405
406 ctx.ModuleForTests("bar", "android_common")
407}
Jihoon Kangc8313892023-09-20 00:54:47 +0000408
409func TestDroidstubsHideFlaggedApi(t *testing.T) {
410 result := android.GroupFixturePreparers(
411 prepareForJavaTest,
412 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
413 variables.NextReleaseHideFlaggedApi = proptools.BoolPtr(true)
414 variables.Release_expose_flagged_api = proptools.BoolPtr(false)
415 }),
416 android.FixtureMergeMockFs(map[string][]byte{
417 "a/A.java": nil,
418 "a/current.txt": nil,
419 "a/removed.txt": nil,
420 }),
421 ).RunTestWithBp(t, `
422 droidstubs {
423 name: "foo",
424 srcs: ["a/A.java"],
425 api_surface: "public",
426 check_api: {
427 current: {
428 api_file: "a/current.txt",
429 removed_api_file: "a/removed.txt",
430 }
431 },
432 }
433 `)
434
435 m := result.ModuleForTests("foo", "android_common")
436 manifest := m.Output("metalava.sbox.textproto")
Colin Crossf61d03d2023-11-02 16:56:39 -0700437 cmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, manifest).Commands[0].Command)
Jihoon Kangc8313892023-09-20 00:54:47 +0000438 android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "--hide-annotation android.annotation.FlaggedApi")
439}