blob: faa9a1539d24917026c1816ab9e8e1e81396fcae [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 Kang35349462024-02-22 19:52:46 +000025
26 "github.com/google/blueprint/proptools"
Colin Cross2207f872021-03-24 12:39:08 -070027)
28
29func TestDroidstubs(t *testing.T) {
Colin Cross844cb6a2025-01-29 15:53:21 -080030 t.Parallel()
Colin Cross2207f872021-03-24 12:39:08 -070031 ctx, _ := testJavaWithFS(t, `
32 droiddoc_exported_dir {
33 name: "droiddoc-templates-sdk",
34 path: ".",
35 }
36
37 droidstubs {
38 name: "bar-stubs",
39 srcs: ["bar-doc/a.java"],
40 api_levels_annotations_dirs: ["droiddoc-templates-sdk"],
41 api_levels_annotations_enabled: true,
42 }
43
44 droidstubs {
45 name: "bar-stubs-other",
46 srcs: ["bar-doc/a.java"],
47 high_mem: true,
48 api_levels_annotations_dirs: ["droiddoc-templates-sdk"],
49 api_levels_annotations_enabled: true,
50 api_levels_jar_filename: "android.other.jar",
51 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +000052
53 droidstubs {
54 name: "stubs-applying-api-versions",
55 srcs: ["bar-doc/a.java"],
56 api_levels_module: "bar-stubs-other",
57 }
Colin Cross2207f872021-03-24 12:39:08 -070058 `,
59 map[string][]byte{
60 "bar-doc/a.java": nil,
61 })
62 testcases := []struct {
63 moduleName string
64 expectedJarFilename string
Anton Hanssonc04a16e2022-05-09 09:30:26 +000065 generate_xml bool
Colin Cross2207f872021-03-24 12:39:08 -070066 high_mem bool
67 }{
68 {
69 moduleName: "bar-stubs",
Anton Hanssonc04a16e2022-05-09 09:30:26 +000070 generate_xml: true,
Colin Cross2207f872021-03-24 12:39:08 -070071 expectedJarFilename: "android.jar",
72 high_mem: false,
73 },
74 {
75 moduleName: "bar-stubs-other",
Anton Hanssonc04a16e2022-05-09 09:30:26 +000076 generate_xml: true,
Colin Cross2207f872021-03-24 12:39:08 -070077 expectedJarFilename: "android.other.jar",
78 high_mem: true,
79 },
Anton Hanssonc04a16e2022-05-09 09:30:26 +000080 {
81 moduleName: "stubs-applying-api-versions",
82 generate_xml: false,
83 },
Colin Cross2207f872021-03-24 12:39:08 -070084 }
85 for _, c := range testcases {
86 m := ctx.ModuleForTests(c.moduleName, "android_common")
Colin Cross8095c292021-03-30 16:40:48 -070087 manifest := m.Output("metalava.sbox.textproto")
Colin Crossf61d03d2023-11-02 16:56:39 -070088 sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx, manifest)
Anton Hanssonc04a16e2022-05-09 09:30:26 +000089 cmdline := String(sboxProto.Commands[0].Command)
90 android.AssertStringContainsEquals(t, "api-versions generation flag", cmdline, "--generate-api-levels", c.generate_xml)
91 if c.expectedJarFilename != "" {
Paul Duffin9820c1a2025-01-20 10:35:45 +000092 expected := "--android-jar-pattern ./{version:major.minor?}/public/" + c.expectedJarFilename
Anton Hanssonc04a16e2022-05-09 09:30:26 +000093 if !strings.Contains(cmdline, expected) {
94 t.Errorf("For %q, expected metalava argument %q, but was not found %q", c.moduleName, expected, cmdline)
95 }
Colin Cross2207f872021-03-24 12:39:08 -070096 }
97
Colin Cross8095c292021-03-30 16:40:48 -070098 metalava := m.Rule("metalava")
99 rp := metalava.RuleParams
Colin Cross2207f872021-03-24 12:39:08 -0700100 if actual := rp.Pool != nil && strings.Contains(rp.Pool.String(), "highmem"); actual != c.high_mem {
101 t.Errorf("Expected %q high_mem to be %v, was %v", c.moduleName, c.high_mem, actual)
102 }
103 }
104}
105
Pedro Loureirocc203502021-10-04 17:24:00 +0000106// runs a test for droidstubs with a customizable sdkType argument and returns
107// the list of jar patterns that is passed as `--android-jar-pattern`
108func getAndroidJarPatternsForDroidstubs(t *testing.T, sdkType string) []string {
109 ctx, _ := testJavaWithFS(t, fmt.Sprintf(`
satayev783195c2021-06-23 21:49:57 +0100110 droiddoc_exported_dir {
111 name: "some-exported-dir",
112 path: "somedir",
113 }
114
115 droiddoc_exported_dir {
116 name: "some-other-exported-dir",
117 path: "someotherdir",
118 }
119
120 droidstubs {
121 name: "foo-stubs",
122 srcs: ["foo-doc/a.java"],
123 api_levels_annotations_dirs: [
124 "some-exported-dir",
125 "some-other-exported-dir",
126 ],
127 api_levels_annotations_enabled: true,
Cole Faust051fa912022-10-05 12:45:42 -0700128 api_levels_sdk_type: "%s",
satayev783195c2021-06-23 21:49:57 +0100129 }
Pedro Loureirocc203502021-10-04 17:24:00 +0000130 `, sdkType),
satayev783195c2021-06-23 21:49:57 +0100131 map[string][]byte{
132 "foo-doc/a.java": nil,
133 })
134
135 m := ctx.ModuleForTests("foo-stubs", "android_common")
136 manifest := m.Output("metalava.sbox.textproto")
Colin Crossf61d03d2023-11-02 16:56:39 -0700137 cmd := String(android.RuleBuilderSboxProtoForTests(t, ctx, manifest).Commands[0].Command)
satayev783195c2021-06-23 21:49:57 +0100138 r := regexp.MustCompile(`--android-jar-pattern [^ ]+/android.jar`)
Pedro Loureirocc203502021-10-04 17:24:00 +0000139 return r.FindAllString(cmd, -1)
140}
141
142func TestPublicDroidstubs(t *testing.T) {
Colin Cross844cb6a2025-01-29 15:53:21 -0800143 t.Parallel()
Pedro Loureirocc203502021-10-04 17:24:00 +0000144 patterns := getAndroidJarPatternsForDroidstubs(t, "public")
145
146 android.AssertArrayString(t, "order of patterns", []string{
Paul Duffin9820c1a2025-01-20 10:35:45 +0000147 "--android-jar-pattern somedir/{version:major.minor?}/public/android.jar",
148 "--android-jar-pattern someotherdir/{version:major.minor?}/public/android.jar",
Pedro Loureirocc203502021-10-04 17:24:00 +0000149 }, patterns)
150}
151
152func TestSystemDroidstubs(t *testing.T) {
Colin Cross844cb6a2025-01-29 15:53:21 -0800153 t.Parallel()
Pedro Loureirocc203502021-10-04 17:24:00 +0000154 patterns := getAndroidJarPatternsForDroidstubs(t, "system")
155
satayev783195c2021-06-23 21:49:57 +0100156 android.AssertArrayString(t, "order of patterns", []string{
Paul Duffin9820c1a2025-01-20 10:35:45 +0000157 "--android-jar-pattern somedir/{version:major.minor?}/system/android.jar",
158 "--android-jar-pattern someotherdir/{version:major.minor?}/system/android.jar",
159 "--android-jar-pattern somedir/{version:major.minor?}/public/android.jar",
160 "--android-jar-pattern someotherdir/{version:major.minor?}/public/android.jar",
Pedro Loureirocc203502021-10-04 17:24:00 +0000161 }, patterns)
162}
163
164func TestModuleLibDroidstubs(t *testing.T) {
Colin Cross844cb6a2025-01-29 15:53:21 -0800165 t.Parallel()
Pedro Loureirocc203502021-10-04 17:24:00 +0000166 patterns := getAndroidJarPatternsForDroidstubs(t, "module-lib")
167
168 android.AssertArrayString(t, "order of patterns", []string{
Paul Duffin9820c1a2025-01-20 10:35:45 +0000169 "--android-jar-pattern somedir/{version:major.minor?}/module-lib/android.jar",
170 "--android-jar-pattern someotherdir/{version:major.minor?}/module-lib/android.jar",
171 "--android-jar-pattern somedir/{version:major.minor?}/system/android.jar",
172 "--android-jar-pattern someotherdir/{version:major.minor?}/system/android.jar",
173 "--android-jar-pattern somedir/{version:major.minor?}/public/android.jar",
174 "--android-jar-pattern someotherdir/{version:major.minor?}/public/android.jar",
Pedro Loureirocc203502021-10-04 17:24:00 +0000175 }, patterns)
satayev783195c2021-06-23 21:49:57 +0100176}
177
Cole Faust051fa912022-10-05 12:45:42 -0700178func TestSystemServerDroidstubs(t *testing.T) {
179 patterns := getAndroidJarPatternsForDroidstubs(t, "system-server")
180
181 android.AssertArrayString(t, "order of patterns", []string{
Paul Duffin9820c1a2025-01-20 10:35:45 +0000182 "--android-jar-pattern somedir/{version:major.minor?}/system-server/android.jar",
183 "--android-jar-pattern someotherdir/{version:major.minor?}/system-server/android.jar",
184 "--android-jar-pattern somedir/{version:major.minor?}/module-lib/android.jar",
185 "--android-jar-pattern someotherdir/{version:major.minor?}/module-lib/android.jar",
186 "--android-jar-pattern somedir/{version:major.minor?}/system/android.jar",
187 "--android-jar-pattern someotherdir/{version:major.minor?}/system/android.jar",
188 "--android-jar-pattern somedir/{version:major.minor?}/public/android.jar",
189 "--android-jar-pattern someotherdir/{version:major.minor?}/public/android.jar",
Cole Faust051fa912022-10-05 12:45:42 -0700190 }, patterns)
191}
192
Colin Cross6aa5c402021-03-24 12:28:50 -0700193func TestDroidstubsSandbox(t *testing.T) {
194 ctx, _ := testJavaWithFS(t, `
Colin Crossbc139922021-03-25 18:33:16 -0700195 genrule {
196 name: "foo",
197 out: ["foo.txt"],
198 cmd: "touch $(out)",
199 }
200
Colin Cross6aa5c402021-03-24 12:28:50 -0700201 droidstubs {
202 name: "bar-stubs",
203 srcs: ["bar-doc/a.java"],
Colin Crossbc139922021-03-25 18:33:16 -0700204
205 args: "--reference $(location :foo)",
206 arg_files: [":foo"],
Colin Cross6aa5c402021-03-24 12:28:50 -0700207 }
208 `,
209 map[string][]byte{
210 "bar-doc/a.java": nil,
211 })
212
213 m := ctx.ModuleForTests("bar-stubs", "android_common")
214 metalava := m.Rule("metalava")
215 if g, w := metalava.Inputs.Strings(), []string{"bar-doc/a.java"}; !reflect.DeepEqual(w, g) {
216 t.Errorf("Expected inputs %q, got %q", w, g)
217 }
Colin Crossbc139922021-03-25 18:33:16 -0700218
Colin Crossf61d03d2023-11-02 16:56:39 -0700219 manifest := android.RuleBuilderSboxProtoForTests(t, ctx, m.Output("metalava.sbox.textproto"))
Cole Fauste8561c62023-11-30 17:26:37 -0800220 if g, w := manifest.Commands[0].GetCommand(), "reference __SBOX_SANDBOX_DIR__/out/soong/.intermediates/foo/gen/foo.txt"; !strings.Contains(g, w) {
Colin Crossbc139922021-03-25 18:33:16 -0700221 t.Errorf("Expected command to contain %q, got %q", w, g)
222 }
Colin Cross6aa5c402021-03-24 12:28:50 -0700223}
224
Colin Cross2207f872021-03-24 12:39:08 -0700225func TestDroidstubsWithSystemModules(t *testing.T) {
226 ctx, _ := testJava(t, `
227 droidstubs {
228 name: "stubs-source-system-modules",
229 srcs: [
230 "bar-doc/a.java",
231 ],
232 sdk_version: "none",
233 system_modules: "source-system-modules",
234 }
235
236 java_library {
237 name: "source-jar",
238 srcs: [
239 "a.java",
240 ],
241 }
242
243 java_system_modules {
244 name: "source-system-modules",
245 libs: ["source-jar"],
246 }
247
248 droidstubs {
249 name: "stubs-prebuilt-system-modules",
250 srcs: [
251 "bar-doc/a.java",
252 ],
253 sdk_version: "none",
254 system_modules: "prebuilt-system-modules",
255 }
256
257 java_import {
258 name: "prebuilt-jar",
259 jars: ["a.jar"],
260 }
261
262 java_system_modules_import {
263 name: "prebuilt-system-modules",
264 libs: ["prebuilt-jar"],
265 }
266 `)
267
268 checkSystemModulesUseByDroidstubs(t, ctx, "stubs-source-system-modules", "source-jar.jar")
269
270 checkSystemModulesUseByDroidstubs(t, ctx, "stubs-prebuilt-system-modules", "prebuilt-jar.jar")
271}
272
Colin Cross2207f872021-03-24 12:39:08 -0700273func checkSystemModulesUseByDroidstubs(t *testing.T, ctx *android.TestContext, moduleName string, systemJar string) {
274 metalavaRule := ctx.ModuleForTests(moduleName, "android_common").Rule("metalava")
275 var systemJars []string
276 for _, i := range metalavaRule.Implicits {
277 systemJars = append(systemJars, i.Base())
278 }
279 if len(systemJars) < 1 || systemJars[0] != systemJar {
280 t.Errorf("inputs of %q must be []string{%q}, but was %#v.", moduleName, systemJar, systemJars)
281 }
282}
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200283
284func TestDroidstubsWithSdkExtensions(t *testing.T) {
285 ctx, _ := testJavaWithFS(t, `
286 droiddoc_exported_dir {
287 name: "sdk-dir",
288 path: "sdk",
289 }
290
291 droidstubs {
292 name: "baz-stubs",
293 api_levels_annotations_dirs: ["sdk-dir"],
294 api_levels_annotations_enabled: true,
295 extensions_info_file: ":info-file",
296 }
297
298 filegroup {
299 name: "info-file",
300 srcs: ["sdk/extensions/info.txt"],
301 }
302 `,
303 map[string][]byte{
304 "sdk/extensions/1/public/some-mainline-module-stubs.jar": nil,
305 "sdk/extensions/info.txt": nil,
306 })
307 m := ctx.ModuleForTests("baz-stubs", "android_common")
308 manifest := m.Output("metalava.sbox.textproto")
Colin Crossf61d03d2023-11-02 16:56:39 -0700309 cmdline := String(android.RuleBuilderSboxProtoForTests(t, ctx, manifest).Commands[0].Command)
Paul Duffin4f707292025-01-16 14:12:31 +0000310 android.AssertStringDoesContain(t, "android-jar-pattern present", cmdline, "--android-jar-pattern sdk/extensions/{version:extension}/public/{module}.jar")
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200311 android.AssertStringDoesContain(t, "sdk-extensions-info present", cmdline, "--sdk-extensions-info sdk/extensions/info.txt")
312}
Spandan Das0b555e32022-11-28 18:48:51 +0000313
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000314func TestDroidStubsApiContributionGeneration(t *testing.T) {
315 ctx, _ := testJavaWithFS(t, `
316 droidstubs {
317 name: "foo",
318 srcs: ["A/a.java"],
319 api_surface: "public",
320 check_api: {
321 current: {
322 api_file: "A/current.txt",
323 removed_api_file: "A/removed.txt",
324 }
325 }
326 }
327 `,
328 map[string][]byte{
329 "A/a.java": nil,
330 "A/current.txt": nil,
331 "A/removed.txt": nil,
332 },
333 )
334
335 ctx.ModuleForTests("foo.api.contribution", "")
336}
Jihoon Kang42b589c2023-02-03 22:56:13 +0000337
338func TestGeneratedApiContributionVisibilityTest(t *testing.T) {
339 library_bp := `
340 java_api_library {
341 name: "bar",
342 api_surface: "public",
343 api_contributions: ["foo.api.contribution"],
Jihoon Kang5d701272024-02-15 21:53:49 +0000344 stubs_type: "everything",
Jihoon Kang42b589c2023-02-03 22:56:13 +0000345 }
346 `
347 ctx, _ := testJavaWithFS(t, `
348 droidstubs {
349 name: "foo",
350 srcs: ["A/a.java"],
351 api_surface: "public",
352 check_api: {
353 current: {
354 api_file: "A/current.txt",
355 removed_api_file: "A/removed.txt",
356 }
357 },
Jihoon Kang063ec002023-06-28 01:16:23 +0000358 visibility: ["//a", "//b"],
Jihoon Kang42b589c2023-02-03 22:56:13 +0000359 }
360 `,
361 map[string][]byte{
362 "a/a.java": nil,
363 "a/current.txt": nil,
364 "a/removed.txt": nil,
365 "b/Android.bp": []byte(library_bp),
366 },
367 )
368
369 ctx.ModuleForTests("bar", "android_common")
370}
Jihoon Kangc8313892023-09-20 00:54:47 +0000371
Jihoon Kang6592e872023-12-19 01:13:16 +0000372func TestAconfigDeclarations(t *testing.T) {
373 result := android.GroupFixturePreparers(
374 prepareForJavaTest,
375 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
376 }),
377 android.FixtureMergeMockFs(map[string][]byte{
378 "a/A.java": nil,
379 "a/current.txt": nil,
380 "a/removed.txt": nil,
381 }),
382 ).RunTestWithBp(t, `
383 aconfig_declarations {
384 name: "bar",
385 package: "com.example.package",
Yu Liu315a53c2024-04-24 16:41:57 +0000386 container: "com.android.foo",
Jihoon Kang6592e872023-12-19 01:13:16 +0000387 srcs: [
388 "bar.aconfig",
389 ],
390 }
391 droidstubs {
392 name: "foo",
393 srcs: ["a/A.java"],
394 api_surface: "public",
395 check_api: {
396 current: {
397 api_file: "a/current.txt",
398 removed_api_file: "a/removed.txt",
399 }
400 },
401 aconfig_declarations: [
402 "bar",
403 ],
404 }
405 `)
406
407 // Check that droidstubs depend on aconfig_declarations
408 android.AssertBoolEquals(t, "foo expected to depend on bar",
409 CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "bar"), true)
410
Jihoon Kangd40c5912024-03-05 16:12:20 +0000411 m := result.ModuleForTests("foo", "android_common")
Jihoon Kang6592e872023-12-19 01:13:16 +0000412 android.AssertStringDoesContain(t, "foo generates revert annotations file",
Jihoon Kangd40c5912024-03-05 16:12:20 +0000413 strings.Join(m.AllOutputs(), ""), "revert-annotations-exportable.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000414
415 // revert-annotations.txt passed to exportable stubs generation metalava command
Jihoon Kangd40c5912024-03-05 16:12:20 +0000416 manifest := m.Output("metalava_exportable.sbox.textproto")
417 cmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, manifest).Commands[0].Command)
418 android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "revert-annotations-exportable.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000419
420 android.AssertStringDoesContain(t, "foo generates exportable stubs jar",
Jihoon Kangd40c5912024-03-05 16:12:20 +0000421 strings.Join(m.AllOutputs(), ""), "exportable/foo-stubs.srcjar")
Jihoon Kang6592e872023-12-19 01:13:16 +0000422}
Jihoon Kang59198152024-02-06 22:43:18 +0000423
424func TestReleaseExportRuntimeApis(t *testing.T) {
425 result := android.GroupFixturePreparers(
426 prepareForJavaTest,
427 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
Jihoon Kang35349462024-02-22 19:52:46 +0000428 variables.ExportRuntimeApis = proptools.BoolPtr(true)
Jihoon Kang59198152024-02-06 22:43:18 +0000429 }),
Colin Crossa66b4632024-08-08 15:50:47 -0700430 android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
Jihoon Kang59198152024-02-06 22:43:18 +0000431 android.FixtureMergeMockFs(map[string][]byte{
432 "a/A.java": nil,
433 "a/current.txt": nil,
434 "a/removed.txt": nil,
435 }),
436 ).RunTestWithBp(t, `
437 aconfig_declarations {
438 name: "bar",
439 package: "com.example.package",
Yu Liu315a53c2024-04-24 16:41:57 +0000440 container: "com.android.foo",
Jihoon Kang59198152024-02-06 22:43:18 +0000441 srcs: [
442 "bar.aconfig",
443 ],
444 }
445 droidstubs {
446 name: "foo",
447 srcs: ["a/A.java"],
448 api_surface: "public",
449 check_api: {
450 current: {
451 api_file: "a/current.txt",
452 removed_api_file: "a/removed.txt",
453 }
454 },
455 aconfig_declarations: [
456 "bar",
457 ],
458 }
459 `)
460
461 m := result.ModuleForTests("foo", "android_common")
462
463 rule := m.Output("released-flagged-apis-exportable.txt")
464 exposeWritableApisFilter := "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
465 android.AssertStringEquals(t, "Filter argument expected to contain READ_WRITE permissions", exposeWritableApisFilter, rule.Args["filter_args"])
466}