1// 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 (
18	"android/soong/android"
19	"fmt"
20	"path/filepath"
21	"regexp"
22	"testing"
23
24	"github.com/google/blueprint/proptools"
25)
26
27func TestJavaSdkLibrary(t *testing.T) {
28	result := android.GroupFixturePreparers(
29		prepareForJavaTest,
30		PrepareForTestWithJavaSdkLibraryFiles,
31		FixtureWithPrebuiltApis(map[string][]string{
32			"28": {"foo"},
33			"29": {"foo"},
34			"30": {"bar", "barney", "baz", "betty", "foo", "fred", "quuz", "wilma"},
35		}),
36	).RunTestWithBp(t, `
37		droiddoc_exported_dir {
38			name: "droiddoc-templates-sdk",
39			path: ".",
40		}
41		java_sdk_library {
42			name: "foo",
43			srcs: ["a.java", "b.java"],
44			api_packages: ["foo"],
45		}
46		java_sdk_library {
47			name: "bar",
48			srcs: ["a.java", "b.java"],
49			api_packages: ["bar"],
50		}
51		java_library {
52			name: "baz",
53			srcs: ["c.java"],
54			libs: ["foo", "bar.stubs"],
55			sdk_version: "system_current",
56		}
57		java_sdk_library {
58			name: "barney",
59			srcs: ["c.java"],
60			api_only: true,
61		}
62		java_sdk_library {
63			name: "betty",
64			srcs: ["c.java"],
65			shared_library: false,
66		}
67		java_sdk_library_import {
68		    name: "quuz",
69				public: {
70					jars: ["c.jar"],
71				},
72		}
73		java_sdk_library_import {
74		    name: "fred",
75				public: {
76					jars: ["b.jar"],
77				},
78		}
79		java_sdk_library_import {
80		    name: "wilma",
81				public: {
82					jars: ["b.jar"],
83				},
84				shared_library: false,
85		}
86		java_library {
87		    name: "qux",
88		    srcs: ["c.java"],
89		    libs: ["baz", "fred", "quuz.stubs", "wilma", "barney", "betty"],
90		    sdk_version: "system_current",
91		}
92		java_library {
93			name: "baz-test",
94			srcs: ["c.java"],
95			libs: ["foo"],
96			sdk_version: "test_current",
97		}
98		java_library {
99			name: "baz-29",
100			srcs: ["c.java"],
101			libs: ["foo"],
102			sdk_version: "system_29",
103		}
104		java_library {
105			name: "baz-module-30",
106			srcs: ["c.java"],
107			libs: ["foo"],
108			sdk_version: "module_30",
109		}
110		`)
111
112	// check the existence of the internal modules
113	foo := result.ModuleForTests("foo", "android_common")
114	result.ModuleForTests(apiScopePublic.stubsLibraryModuleName("foo"), "android_common")
115	result.ModuleForTests(apiScopeSystem.stubsLibraryModuleName("foo"), "android_common")
116	result.ModuleForTests(apiScopeTest.stubsLibraryModuleName("foo"), "android_common")
117	result.ModuleForTests(apiScopePublic.stubsSourceModuleName("foo"), "android_common")
118	result.ModuleForTests(apiScopeSystem.stubsSourceModuleName("foo"), "android_common")
119	result.ModuleForTests(apiScopeTest.stubsSourceModuleName("foo"), "android_common")
120	result.ModuleForTests("foo"+sdkXmlFileSuffix, "android_common")
121	result.ModuleForTests("foo.api.public.28", "")
122	result.ModuleForTests("foo.api.system.28", "")
123	result.ModuleForTests("foo.api.test.28", "")
124
125	exportedComponentsInfo := result.ModuleProvider(foo.Module(), ExportedComponentsInfoProvider).(ExportedComponentsInfo)
126	expectedFooExportedComponents := []string{
127		"foo.stubs",
128		"foo.stubs.source",
129		"foo.stubs.source.system",
130		"foo.stubs.source.test",
131		"foo.stubs.system",
132		"foo.stubs.test",
133	}
134	android.AssertArrayString(t, "foo exported components", expectedFooExportedComponents, exportedComponentsInfo.Components)
135
136	bazJavac := result.ModuleForTests("baz", "android_common").Rule("javac")
137	// tests if baz is actually linked to the stubs lib
138	android.AssertStringDoesContain(t, "baz javac classpath", bazJavac.Args["classpath"], "foo.stubs.system.jar")
139	// ... and not to the impl lib
140	android.AssertStringDoesNotContain(t, "baz javac classpath", bazJavac.Args["classpath"], "foo.jar")
141	// test if baz is not linked to the system variant of foo
142	android.AssertStringDoesNotContain(t, "baz javac classpath", bazJavac.Args["classpath"], "foo.stubs.jar")
143
144	bazTestJavac := result.ModuleForTests("baz-test", "android_common").Rule("javac")
145	// tests if baz-test is actually linked to the test stubs lib
146	android.AssertStringDoesContain(t, "baz-test javac classpath", bazTestJavac.Args["classpath"], "foo.stubs.test.jar")
147
148	baz29Javac := result.ModuleForTests("baz-29", "android_common").Rule("javac")
149	// tests if baz-29 is actually linked to the system 29 stubs lib
150	android.AssertStringDoesContain(t, "baz-29 javac classpath", baz29Javac.Args["classpath"], "prebuilts/sdk/29/system/foo.jar")
151
152	bazModule30Javac := result.ModuleForTests("baz-module-30", "android_common").Rule("javac")
153	// tests if "baz-module-30" is actually linked to the module 30 stubs lib
154	android.AssertStringDoesContain(t, "baz-module-30 javac classpath", bazModule30Javac.Args["classpath"], "prebuilts/sdk/30/module-lib/foo.jar")
155
156	// test if baz has exported SDK lib names foo and bar to qux
157	qux := result.ModuleForTests("qux", "android_common")
158	if quxLib, ok := qux.Module().(*Library); ok {
159		sdkLibs := quxLib.ClassLoaderContexts().UsesLibs()
160		android.AssertDeepEquals(t, "qux exports", []string{"foo", "bar", "fred", "quuz"}, sdkLibs)
161	}
162}
163
164func TestJavaSdkLibrary_StubOrImplOnlyLibs(t *testing.T) {
165	result := android.GroupFixturePreparers(
166		prepareForJavaTest,
167		PrepareForTestWithJavaSdkLibraryFiles,
168		FixtureWithLastReleaseApis("sdklib"),
169	).RunTestWithBp(t, `
170		java_sdk_library {
171			name: "sdklib",
172			srcs: ["a.java"],
173			libs: ["lib"],
174			static_libs: ["static-lib"],
175			impl_only_libs: ["impl-only-lib"],
176			stub_only_libs: ["stub-only-lib"],
177			stub_only_static_libs: ["stub-only-static-lib"],
178		}
179		java_defaults {
180			name: "defaults",
181			srcs: ["a.java"],
182			sdk_version: "current",
183		}
184		java_library { name: "lib", defaults: ["defaults"] }
185		java_library { name: "static-lib", defaults: ["defaults"] }
186		java_library { name: "impl-only-lib", defaults: ["defaults"] }
187		java_library { name: "stub-only-lib", defaults: ["defaults"] }
188		java_library { name: "stub-only-static-lib", defaults: ["defaults"] }
189		`)
190	var expectations = []struct {
191		lib               string
192		on_impl_classpath bool
193		on_stub_classpath bool
194		in_impl_combined  bool
195		in_stub_combined  bool
196	}{
197		{lib: "lib", on_impl_classpath: true},
198		{lib: "static-lib", in_impl_combined: true},
199		{lib: "impl-only-lib", on_impl_classpath: true},
200		{lib: "stub-only-lib", on_stub_classpath: true},
201		{lib: "stub-only-static-lib", in_stub_combined: true},
202	}
203	verify := func(sdklib, dep string, cp, combined bool) {
204		sdklibCp := result.ModuleForTests(sdklib, "android_common").Rule("javac").Args["classpath"]
205		expected := cp || combined // Every combined jar is also on the classpath.
206		android.AssertStringContainsEquals(t, "bad classpath for "+sdklib, sdklibCp, "/"+dep+".jar", expected)
207
208		combineJarInputs := result.ModuleForTests(sdklib, "android_common").Rule("combineJar").Inputs.Strings()
209		depPath := filepath.Join("out", "soong", ".intermediates", dep, "android_common", "turbine-combined", dep+".jar")
210		android.AssertStringListContainsEquals(t, "bad combined inputs for "+sdklib, combineJarInputs, depPath, combined)
211	}
212	for _, expectation := range expectations {
213		verify("sdklib", expectation.lib, expectation.on_impl_classpath, expectation.in_impl_combined)
214		verify("sdklib.impl", expectation.lib, expectation.on_impl_classpath, expectation.in_impl_combined)
215
216		stubName := apiScopePublic.stubsLibraryModuleName("sdklib")
217		verify(stubName, expectation.lib, expectation.on_stub_classpath, expectation.in_stub_combined)
218	}
219}
220
221func TestJavaSdkLibrary_DoNotAccessImplWhenItIsNotBuilt(t *testing.T) {
222	result := android.GroupFixturePreparers(
223		prepareForJavaTest,
224		PrepareForTestWithJavaSdkLibraryFiles,
225		FixtureWithLastReleaseApis("foo"),
226	).RunTestWithBp(t, `
227		java_sdk_library {
228			name: "foo",
229			srcs: ["a.java"],
230			api_only: true,
231			public: {
232				enabled: true,
233			},
234		}
235
236		java_library {
237			name: "bar",
238			srcs: ["b.java"],
239			libs: ["foo"],
240		}
241		`)
242
243	// The bar library should depend on the stubs jar.
244	barLibrary := result.ModuleForTests("bar", "android_common").Rule("javac")
245	if expected, actual := `^-classpath .*:out/soong/[^:]*/turbine-combined/foo\.stubs\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
246		t.Errorf("expected %q, found %#q", expected, actual)
247	}
248}
249
250func TestJavaSdkLibrary_UseSourcesFromAnotherSdkLibrary(t *testing.T) {
251	android.GroupFixturePreparers(
252		prepareForJavaTest,
253		PrepareForTestWithJavaSdkLibraryFiles,
254		FixtureWithLastReleaseApis("foo"),
255	).RunTestWithBp(t, `
256		java_sdk_library {
257			name: "foo",
258			srcs: ["a.java"],
259			api_packages: ["foo"],
260			public: {
261				enabled: true,
262			},
263		}
264
265		java_library {
266			name: "bar",
267			srcs: ["b.java", ":foo{.public.stubs.source}"],
268		}
269		`)
270}
271
272func TestJavaSdkLibrary_AccessOutputFiles_MissingScope(t *testing.T) {
273	android.GroupFixturePreparers(
274		prepareForJavaTest,
275		PrepareForTestWithJavaSdkLibraryFiles,
276		FixtureWithLastReleaseApis("foo"),
277	).
278		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`"foo" does not provide api scope system`)).
279		RunTestWithBp(t, `
280		java_sdk_library {
281			name: "foo",
282			srcs: ["a.java"],
283			api_packages: ["foo"],
284			public: {
285				enabled: true,
286			},
287		}
288
289		java_library {
290			name: "bar",
291			srcs: ["b.java", ":foo{.system.stubs.source}"],
292		}
293		`)
294}
295
296func TestJavaSdkLibrary_Deps(t *testing.T) {
297	result := android.GroupFixturePreparers(
298		prepareForJavaTest,
299		PrepareForTestWithJavaSdkLibraryFiles,
300		FixtureWithLastReleaseApis("sdklib"),
301	).RunTestWithBp(t, `
302		java_sdk_library {
303			name: "sdklib",
304			srcs: ["a.java"],
305			sdk_version: "none",
306			system_modules: "none",
307			public: {
308				enabled: true,
309			},
310		}
311		`)
312
313	CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{
314		`dex2oatd`,
315		`sdklib.impl`,
316		`sdklib.stubs`,
317		`sdklib.stubs.source`,
318		`sdklib.xml`,
319	})
320}
321
322func TestJavaSdkLibraryImport_AccessOutputFiles(t *testing.T) {
323	prepareForJavaTest.RunTestWithBp(t, `
324		java_sdk_library_import {
325			name: "foo",
326			public: {
327				jars: ["a.jar"],
328				stub_srcs: ["a.java"],
329				current_api: "api/current.txt",
330				removed_api: "api/removed.txt",
331			},
332		}
333
334		java_library {
335			name: "bar",
336			srcs: [":foo{.public.stubs.source}"],
337			java_resources: [
338				":foo{.public.api.txt}",
339				":foo{.public.removed-api.txt}",
340			],
341		}
342		`)
343}
344
345func TestJavaSdkLibraryImport_AccessOutputFiles_Invalid(t *testing.T) {
346	bp := `
347		java_sdk_library_import {
348			name: "foo",
349			public: {
350				jars: ["a.jar"],
351			},
352		}
353		`
354
355	t.Run("stubs.source", func(t *testing.T) {
356		prepareForJavaTest.
357			ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`stubs.source not available for api scope public`)).
358			RunTestWithBp(t, bp+`
359				java_library {
360					name: "bar",
361					srcs: [":foo{.public.stubs.source}"],
362					java_resources: [
363						":foo{.public.api.txt}",
364						":foo{.public.removed-api.txt}",
365					],
366				}
367			`)
368	})
369
370	t.Run("api.txt", func(t *testing.T) {
371		prepareForJavaTest.
372			ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`api.txt not available for api scope public`)).
373			RunTestWithBp(t, bp+`
374				java_library {
375					name: "bar",
376					srcs: ["a.java"],
377					java_resources: [
378						":foo{.public.api.txt}",
379					],
380				}
381			`)
382	})
383
384	t.Run("removed-api.txt", func(t *testing.T) {
385		prepareForJavaTest.
386			ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`removed-api.txt not available for api scope public`)).
387			RunTestWithBp(t, bp+`
388				java_library {
389					name: "bar",
390					srcs: ["a.java"],
391					java_resources: [
392						":foo{.public.removed-api.txt}",
393					],
394				}
395			`)
396	})
397}
398
399func TestJavaSdkLibrary_InvalidScopes(t *testing.T) {
400	prepareForJavaTest.
401		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "foo": enabled api scope "system" depends on disabled scope "public"`)).
402		RunTestWithBp(t, `
403			java_sdk_library {
404				name: "foo",
405				srcs: ["a.java", "b.java"],
406				api_packages: ["foo"],
407				// Explicitly disable public to test the check that ensures the set of enabled
408				// scopes is consistent.
409				public: {
410					enabled: false,
411				},
412				system: {
413					enabled: true,
414				},
415			}
416		`)
417}
418
419func TestJavaSdkLibrary_SdkVersion_ForScope(t *testing.T) {
420	android.GroupFixturePreparers(
421		prepareForJavaTest,
422		PrepareForTestWithJavaSdkLibraryFiles,
423		FixtureWithLastReleaseApis("foo"),
424	).RunTestWithBp(t, `
425		java_sdk_library {
426			name: "foo",
427			srcs: ["a.java", "b.java"],
428			api_packages: ["foo"],
429			system: {
430				enabled: true,
431				sdk_version: "module_current",
432			},
433		}
434		`)
435}
436
437func TestJavaSdkLibrary_ModuleLib(t *testing.T) {
438	android.GroupFixturePreparers(
439		prepareForJavaTest,
440		PrepareForTestWithJavaSdkLibraryFiles,
441		FixtureWithLastReleaseApis("foo"),
442	).RunTestWithBp(t, `
443		java_sdk_library {
444			name: "foo",
445			srcs: ["a.java", "b.java"],
446			api_packages: ["foo"],
447			system: {
448				enabled: true,
449			},
450			module_lib: {
451				enabled: true,
452			},
453		}
454		`)
455}
456
457func TestJavaSdkLibrary_SystemServer(t *testing.T) {
458	android.GroupFixturePreparers(
459		prepareForJavaTest,
460		PrepareForTestWithJavaSdkLibraryFiles,
461		FixtureWithLastReleaseApis("foo"),
462	).RunTestWithBp(t, `
463		java_sdk_library {
464			name: "foo",
465			srcs: ["a.java", "b.java"],
466			api_packages: ["foo"],
467			system: {
468				enabled: true,
469			},
470			system_server: {
471				enabled: true,
472			},
473		}
474		`)
475}
476
477func TestJavaSdkLibrary_MissingScope(t *testing.T) {
478	prepareForJavaTest.
479		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`requires api scope module-lib from foo but it only has \[\] available`)).
480		RunTestWithBp(t, `
481			java_sdk_library {
482				name: "foo",
483				srcs: ["a.java"],
484				public: {
485					enabled: false,
486				},
487			}
488
489			java_library {
490				name: "baz",
491				srcs: ["a.java"],
492				libs: ["foo"],
493				sdk_version: "module_current",
494			}
495		`)
496}
497
498func TestJavaSdkLibrary_FallbackScope(t *testing.T) {
499	android.GroupFixturePreparers(
500		prepareForJavaTest,
501		PrepareForTestWithJavaSdkLibraryFiles,
502		FixtureWithLastReleaseApis("foo"),
503	).RunTestWithBp(t, `
504		java_sdk_library {
505			name: "foo",
506			srcs: ["a.java"],
507			system: {
508				enabled: true,
509			},
510		}
511
512		java_library {
513			name: "baz",
514			srcs: ["a.java"],
515			libs: ["foo"],
516			// foo does not have module-lib scope so it should fallback to system
517			sdk_version: "module_current",
518		}
519		`)
520}
521
522func TestJavaSdkLibrary_DefaultToStubs(t *testing.T) {
523	result := android.GroupFixturePreparers(
524		prepareForJavaTest,
525		PrepareForTestWithJavaSdkLibraryFiles,
526		FixtureWithLastReleaseApis("foo"),
527	).RunTestWithBp(t, `
528		java_sdk_library {
529			name: "foo",
530			srcs: ["a.java"],
531			system: {
532				enabled: true,
533			},
534			default_to_stubs: true,
535		}
536
537		java_library {
538			name: "baz",
539			srcs: ["a.java"],
540			libs: ["foo"],
541			// does not have sdk_version set, should fallback to module,
542			// which will then fallback to system because the module scope
543			// is not enabled.
544		}
545		`)
546	// The baz library should depend on the system stubs jar.
547	bazLibrary := result.ModuleForTests("baz", "android_common").Rule("javac")
548	if expected, actual := `^-classpath .*:out/soong/[^:]*/turbine-combined/foo\.stubs.system\.jar$`, bazLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
549		t.Errorf("expected %q, found %#q", expected, actual)
550	}
551}
552
553func TestJavaSdkLibraryImport(t *testing.T) {
554	result := prepareForJavaTest.RunTestWithBp(t, `
555		java_library {
556			name: "foo",
557			srcs: ["a.java"],
558			libs: ["sdklib"],
559			sdk_version: "current",
560		}
561
562		java_library {
563			name: "foo.system",
564			srcs: ["a.java"],
565			libs: ["sdklib"],
566			sdk_version: "system_current",
567		}
568
569		java_library {
570			name: "foo.test",
571			srcs: ["a.java"],
572			libs: ["sdklib"],
573			sdk_version: "test_current",
574		}
575
576		java_sdk_library_import {
577			name: "sdklib",
578			public: {
579				jars: ["a.jar"],
580			},
581			system: {
582				jars: ["b.jar"],
583			},
584			test: {
585				jars: ["c.jar"],
586				stub_srcs: ["c.java"],
587			},
588		}
589		`)
590
591	for _, scope := range []string{"", ".system", ".test"} {
592		fooModule := result.ModuleForTests("foo"+scope, "android_common")
593		javac := fooModule.Rule("javac")
594
595		sdklibStubsJar := result.ModuleForTests("sdklib.stubs"+scope, "android_common").Rule("combineJar").Output
596		android.AssertStringDoesContain(t, "foo classpath", javac.Args["classpath"], sdklibStubsJar.String())
597	}
598
599	CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{
600		`prebuilt_sdklib.stubs`,
601		`prebuilt_sdklib.stubs.source.test`,
602		`prebuilt_sdklib.stubs.system`,
603		`prebuilt_sdklib.stubs.test`,
604	})
605}
606
607func TestJavaSdkLibraryImport_WithSource(t *testing.T) {
608	result := android.GroupFixturePreparers(
609		prepareForJavaTest,
610		PrepareForTestWithJavaSdkLibraryFiles,
611		FixtureWithLastReleaseApis("sdklib"),
612	).RunTestWithBp(t, `
613		java_sdk_library {
614			name: "sdklib",
615			srcs: ["a.java"],
616			sdk_version: "none",
617			system_modules: "none",
618			public: {
619				enabled: true,
620			},
621		}
622
623		java_sdk_library_import {
624			name: "sdklib",
625			public: {
626				jars: ["a.jar"],
627			},
628		}
629		`)
630
631	CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{
632		`dex2oatd`,
633		`prebuilt_sdklib`,
634		`sdklib.impl`,
635		`sdklib.stubs`,
636		`sdklib.stubs.source`,
637		`sdklib.xml`,
638	})
639
640	CheckModuleDependencies(t, result.TestContext, "prebuilt_sdklib", "android_common", []string{
641		`prebuilt_sdklib.stubs`,
642		`sdklib.impl`,
643		// This should be prebuilt_sdklib.stubs but is set to sdklib.stubs because the
644		// dependency is added after prebuilts may have been renamed and so has to use
645		// the renamed name.
646		`sdklib.xml`,
647	})
648}
649
650func TestJavaSdkLibraryImport_Preferred(t *testing.T) {
651	result := android.GroupFixturePreparers(
652		prepareForJavaTest,
653		PrepareForTestWithJavaSdkLibraryFiles,
654		FixtureWithLastReleaseApis("sdklib"),
655	).RunTestWithBp(t, `
656		java_sdk_library {
657			name: "sdklib",
658			srcs: ["a.java"],
659			sdk_version: "none",
660			system_modules: "none",
661			public: {
662				enabled: true,
663			},
664		}
665
666		java_sdk_library_import {
667			name: "sdklib",
668			prefer: true,
669			public: {
670				jars: ["a.jar"],
671			},
672		}
673		`)
674
675	CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{
676		`dex2oatd`,
677		`prebuilt_sdklib`,
678		`sdklib.impl`,
679		`sdklib.stubs`,
680		`sdklib.stubs.source`,
681		`sdklib.xml`,
682	})
683
684	CheckModuleDependencies(t, result.TestContext, "prebuilt_sdklib", "android_common", []string{
685		`prebuilt_sdklib.stubs`,
686		`sdklib.impl`,
687		`sdklib.xml`,
688	})
689}
690
691func TestJavaSdkLibraryEnforce(t *testing.T) {
692	partitionToBpOption := func(partition string) string {
693		switch partition {
694		case "system":
695			return ""
696		case "vendor":
697			return "soc_specific: true,"
698		case "product":
699			return "product_specific: true,"
700		default:
701			panic("Invalid partition group name: " + partition)
702		}
703	}
704
705	type testConfigInfo struct {
706		libraryType                string
707		fromPartition              string
708		toPartition                string
709		enforceVendorInterface     bool
710		enforceProductInterface    bool
711		enforceJavaSdkLibraryCheck bool
712		allowList                  []string
713	}
714
715	createPreparer := func(info testConfigInfo) android.FixturePreparer {
716		bpFileTemplate := `
717			java_library {
718				name: "foo",
719				srcs: ["foo.java"],
720				libs: ["bar"],
721				sdk_version: "current",
722				%s
723			}
724
725			%s {
726				name: "bar",
727				srcs: ["bar.java"],
728				sdk_version: "current",
729				%s
730			}
731		`
732
733		bpFile := fmt.Sprintf(bpFileTemplate,
734			partitionToBpOption(info.fromPartition),
735			info.libraryType,
736			partitionToBpOption(info.toPartition))
737
738		return android.GroupFixturePreparers(
739			PrepareForTestWithJavaSdkLibraryFiles,
740			FixtureWithLastReleaseApis("bar"),
741			android.FixtureWithRootAndroidBp(bpFile),
742			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
743				variables.EnforceProductPartitionInterface = proptools.BoolPtr(info.enforceProductInterface)
744				if info.enforceVendorInterface {
745					variables.DeviceVndkVersion = proptools.StringPtr("current")
746				}
747				variables.EnforceInterPartitionJavaSdkLibrary = proptools.BoolPtr(info.enforceJavaSdkLibraryCheck)
748				variables.InterPartitionJavaLibraryAllowList = info.allowList
749			}),
750		)
751	}
752
753	runTest := func(t *testing.T, info testConfigInfo, expectedErrorPattern string) {
754		t.Run(fmt.Sprintf("%v", info), func(t *testing.T) {
755			errorHandler := android.FixtureExpectsNoErrors
756			if expectedErrorPattern != "" {
757				errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(expectedErrorPattern)
758			}
759			android.GroupFixturePreparers(
760				prepareForJavaTest,
761				createPreparer(info),
762			).
763				ExtendWithErrorHandler(errorHandler).
764				RunTest(t)
765		})
766	}
767
768	errorMessage := "is not allowed across the partitions"
769
770	runTest(t, testConfigInfo{
771		libraryType:                "java_library",
772		fromPartition:              "product",
773		toPartition:                "system",
774		enforceVendorInterface:     true,
775		enforceProductInterface:    true,
776		enforceJavaSdkLibraryCheck: false,
777	}, "")
778
779	runTest(t, testConfigInfo{
780		libraryType:                "java_library",
781		fromPartition:              "product",
782		toPartition:                "system",
783		enforceVendorInterface:     true,
784		enforceProductInterface:    false,
785		enforceJavaSdkLibraryCheck: true,
786	}, "")
787
788	runTest(t, testConfigInfo{
789		libraryType:                "java_library",
790		fromPartition:              "product",
791		toPartition:                "system",
792		enforceVendorInterface:     true,
793		enforceProductInterface:    true,
794		enforceJavaSdkLibraryCheck: true,
795	}, errorMessage)
796
797	runTest(t, testConfigInfo{
798		libraryType:                "java_library",
799		fromPartition:              "vendor",
800		toPartition:                "system",
801		enforceVendorInterface:     true,
802		enforceProductInterface:    true,
803		enforceJavaSdkLibraryCheck: true,
804	}, errorMessage)
805
806	runTest(t, testConfigInfo{
807		libraryType:                "java_library",
808		fromPartition:              "vendor",
809		toPartition:                "system",
810		enforceVendorInterface:     true,
811		enforceProductInterface:    true,
812		enforceJavaSdkLibraryCheck: true,
813		allowList:                  []string{"bar"},
814	}, "")
815
816	runTest(t, testConfigInfo{
817		libraryType:                "java_library",
818		fromPartition:              "vendor",
819		toPartition:                "product",
820		enforceVendorInterface:     true,
821		enforceProductInterface:    true,
822		enforceJavaSdkLibraryCheck: true,
823	}, errorMessage)
824
825	runTest(t, testConfigInfo{
826		libraryType:                "java_sdk_library",
827		fromPartition:              "product",
828		toPartition:                "system",
829		enforceVendorInterface:     true,
830		enforceProductInterface:    true,
831		enforceJavaSdkLibraryCheck: true,
832	}, "")
833
834	runTest(t, testConfigInfo{
835		libraryType:                "java_sdk_library",
836		fromPartition:              "vendor",
837		toPartition:                "system",
838		enforceVendorInterface:     true,
839		enforceProductInterface:    true,
840		enforceJavaSdkLibraryCheck: true,
841	}, "")
842
843	runTest(t, testConfigInfo{
844		libraryType:                "java_sdk_library",
845		fromPartition:              "vendor",
846		toPartition:                "product",
847		enforceVendorInterface:     true,
848		enforceProductInterface:    true,
849		enforceJavaSdkLibraryCheck: true,
850	}, "")
851}
852
853func TestJavaSdkLibraryDist(t *testing.T) {
854	result := android.GroupFixturePreparers(
855		PrepareForTestWithJavaBuildComponents,
856		PrepareForTestWithJavaDefaultModules,
857		PrepareForTestWithJavaSdkLibraryFiles,
858		FixtureWithLastReleaseApis(
859			"sdklib_no_group",
860			"sdklib_group_foo",
861			"sdklib_owner_foo",
862			"foo"),
863	).RunTestWithBp(t, `
864		java_sdk_library {
865			name: "sdklib_no_group",
866			srcs: ["foo.java"],
867		}
868
869		java_sdk_library {
870			name: "sdklib_group_foo",
871			srcs: ["foo.java"],
872			dist_group: "foo",
873		}
874
875		java_sdk_library {
876			name: "sdklib_owner_foo",
877			srcs: ["foo.java"],
878			owner: "foo",
879		}
880
881		java_sdk_library {
882			name: "sdklib_stem_foo",
883			srcs: ["foo.java"],
884			dist_stem: "foo",
885		}
886	`)
887
888	type testCase struct {
889		module   string
890		distDir  string
891		distStem string
892	}
893	testCases := []testCase{
894		{
895			module:   "sdklib_no_group",
896			distDir:  "apistubs/unknown/public",
897			distStem: "sdklib_no_group.jar",
898		},
899		{
900			module:   "sdklib_group_foo",
901			distDir:  "apistubs/foo/public",
902			distStem: "sdklib_group_foo.jar",
903		},
904		{
905			// Owner doesn't affect distDir after b/186723288.
906			module:   "sdklib_owner_foo",
907			distDir:  "apistubs/unknown/public",
908			distStem: "sdklib_owner_foo.jar",
909		},
910		{
911			module:   "sdklib_stem_foo",
912			distDir:  "apistubs/unknown/public",
913			distStem: "foo.jar",
914		},
915	}
916
917	for _, tt := range testCases {
918		t.Run(tt.module, func(t *testing.T) {
919			m := result.ModuleForTests(tt.module+".stubs", "android_common").Module().(*Library)
920			dists := m.Dists()
921			if len(dists) != 1 {
922				t.Fatalf("expected exactly 1 dist entry, got %d", len(dists))
923			}
924			if g, w := String(dists[0].Dir), tt.distDir; g != w {
925				t.Errorf("expected dist dir %q, got %q", w, g)
926			}
927			if g, w := String(dists[0].Dest), tt.distStem; g != w {
928				t.Errorf("expected dist stem %q, got %q", w, g)
929			}
930		})
931	}
932}
933