• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2017 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	"fmt"
19	"os"
20	"path/filepath"
21	"reflect"
22	"runtime"
23	"slices"
24	"strconv"
25	"strings"
26	"testing"
27
28	"github.com/google/blueprint"
29	"github.com/google/blueprint/proptools"
30
31	"android/soong/aconfig"
32	"android/soong/android"
33	"android/soong/cc"
34	"android/soong/dexpreopt"
35	"android/soong/genrule"
36)
37
38// Legacy preparer used for running tests within the java package.
39//
40// This includes everything that was needed to run any test in the java package prior to the
41// introduction of the test fixtures. Tests that are being converted to use fixtures directly
42// rather than through the testJava...() methods should avoid using this and instead use the
43// various preparers directly, using android.GroupFixturePreparers(...) to group them when
44// necessary.
45//
46// deprecated
47var prepareForJavaTest = android.GroupFixturePreparers(
48	genrule.PrepareForTestWithGenRuleBuildComponents,
49	// Get the CC build components but not default modules.
50	cc.PrepareForTestWithCcBuildComponents,
51	// Include all the default java modules.
52	PrepareForTestWithDexpreopt,
53	// Include aconfig modules.
54	aconfig.PrepareForTestWithAconfigBuildComponents,
55)
56
57func TestMain(m *testing.M) {
58	os.Exit(m.Run())
59}
60
61// testJavaError is a legacy way of running tests of java modules that expect errors.
62//
63// See testJava for an explanation as to how to stop using this deprecated method.
64//
65// deprecated
66func testJavaError(t *testing.T, pattern string, bp string) (*android.TestContext, android.Config) {
67	t.Helper()
68	result := android.GroupFixturePreparers(
69		prepareForJavaTest, dexpreopt.PrepareForTestByEnablingDexpreopt).
70		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)).
71		RunTestWithBp(t, bp)
72	return result.TestContext, result.Config
73}
74
75// testJavaWithFS runs tests using the prepareForJavaTest
76//
77// See testJava for an explanation as to how to stop using this deprecated method.
78//
79// deprecated
80func testJavaWithFS(t *testing.T, bp string, fs android.MockFS) (*android.TestContext, android.Config) {
81	t.Helper()
82	result := android.GroupFixturePreparers(
83		prepareForJavaTest, fs.AddToFixture()).RunTestWithBp(t, bp)
84	return result.TestContext, result.Config
85}
86
87// testJava runs tests using the prepareForJavaTest
88//
89// Do not add any new usages of this, instead use the prepareForJavaTest directly as it makes it
90// much easier to customize the test behavior.
91//
92// If it is necessary to customize the behavior of an existing test that uses this then please first
93// convert the test to using prepareForJavaTest first and then in a following change add the
94// appropriate fixture preparers. Keeping the conversion change separate makes it easy to verify
95// that it did not change the test behavior unexpectedly.
96//
97// deprecated
98func testJava(t *testing.T, bp string) (*android.TestContext, android.Config) {
99	t.Helper()
100	result := prepareForJavaTest.RunTestWithBp(t, bp)
101	return result.TestContext, result.Config
102}
103
104// defaultModuleToPath constructs a path to the turbine generate jar for a default test module that
105// is defined in PrepareForIntegrationTestWithJava
106func defaultModuleToPath(name string) string {
107	switch {
108	case name == `""`:
109		return name
110	case strings.HasSuffix(name, ".jar"):
111		return name
112	default:
113		return filepath.Join("out", "soong", ".intermediates", defaultJavaDir, name, "android_common", "turbine", name+".jar")
114	}
115}
116
117// Test that the PrepareForTestWithJavaDefaultModules provides all the files that it uses by
118// running it in a fixture that requires all source files to exist.
119func TestPrepareForTestWithJavaDefaultModules(t *testing.T) {
120	t.Parallel()
121	android.GroupFixturePreparers(
122		PrepareForTestWithJavaDefaultModules,
123		android.PrepareForTestDisallowNonExistentPaths,
124	).RunTest(t)
125}
126
127func TestJavaLinkType(t *testing.T) {
128	t.Parallel()
129	testJava(t, `
130		java_library {
131			name: "foo",
132			srcs: ["a.java"],
133			libs: ["bar"],
134			static_libs: ["baz"],
135		}
136
137		java_library {
138			name: "bar",
139			sdk_version: "current",
140			srcs: ["b.java"],
141		}
142
143		java_library {
144			name: "baz",
145			sdk_version: "system_current",
146			srcs: ["c.java"],
147		}
148	`)
149
150	testJavaError(t, "consider adjusting sdk_version: OR platform_apis:", `
151		java_library {
152			name: "foo",
153			srcs: ["a.java"],
154			libs: ["bar"],
155			sdk_version: "current",
156			static_libs: ["baz"],
157		}
158
159		java_library {
160			name: "bar",
161			sdk_version: "current",
162			srcs: ["b.java"],
163		}
164
165		java_library {
166			name: "baz",
167			sdk_version: "system_current",
168			srcs: ["c.java"],
169		}
170	`)
171
172	testJava(t, `
173		java_library {
174			name: "foo",
175			srcs: ["a.java"],
176			libs: ["bar"],
177			sdk_version: "system_current",
178			static_libs: ["baz"],
179		}
180
181		java_library {
182			name: "bar",
183			sdk_version: "current",
184			srcs: ["b.java"],
185		}
186
187		java_library {
188			name: "baz",
189			sdk_version: "system_current",
190			srcs: ["c.java"],
191		}
192	`)
193
194	testJavaError(t, "consider adjusting sdk_version: OR platform_apis:", `
195		java_library {
196			name: "foo",
197			srcs: ["a.java"],
198			libs: ["bar"],
199			sdk_version: "system_current",
200			static_libs: ["baz"],
201		}
202
203		java_library {
204			name: "bar",
205			sdk_version: "current",
206			srcs: ["b.java"],
207		}
208
209		java_library {
210			name: "baz",
211			srcs: ["c.java"],
212		}
213	`)
214}
215
216func TestSimple(t *testing.T) {
217	t.Parallel()
218	bp := `
219		java_library {
220			name: "foo",
221			srcs: ["a.java"],
222			libs: ["bar"],
223			static_libs: ["baz"],
224		}
225
226		java_library {
227			name: "bar",
228			srcs: ["b.java"],
229			static_libs: ["quz"],
230		}
231
232		java_library {
233			name: "baz",
234			srcs: ["c.java"],
235			static_libs: ["quz"],
236		}
237
238		java_library {
239			name: "quz",
240			srcs: ["d.java"],
241		}`
242
243	frameworkTurbineJars := []string{
244		"out/soong/.intermediates/default/java/ext/android_common/turbine/ext.jar",
245		"out/soong/.intermediates/default/java/framework/android_common/turbine/framework.jar",
246	}
247
248	testCases := []struct {
249		name string
250
251		preparer android.FixturePreparer
252
253		fooJavacInputs          []string
254		fooJavacClasspath       []string
255		fooCombinedInputs       []string
256		fooHeaderCombinedInputs []string
257
258		barJavacInputs          []string
259		barJavacClasspath       []string
260		barCombinedInputs       []string
261		barHeaderCombinedInputs []string
262	}{
263		{
264			name:           "normal",
265			preparer:       android.NullFixturePreparer,
266			fooJavacInputs: []string{"a.java"},
267			fooJavacClasspath: slices.Concat(
268				frameworkTurbineJars,
269				[]string{
270					"out/soong/.intermediates/bar/android_common/turbine/bar.jar",
271					"out/soong/.intermediates/quz/android_common/turbine/quz.jar",
272					"out/soong/.intermediates/baz/android_common/turbine/baz.jar",
273				},
274			),
275			fooCombinedInputs: []string{
276				"out/soong/.intermediates/foo/android_common/javac/foo.jar",
277				"out/soong/.intermediates/baz/android_common/javac/baz.jar",
278				"out/soong/.intermediates/quz/android_common/javac/quz.jar",
279			},
280
281			fooHeaderCombinedInputs: []string{
282				"out/soong/.intermediates/foo/android_common/turbine/foo.jar",
283				"out/soong/.intermediates/baz/android_common/turbine/baz.jar",
284				"out/soong/.intermediates/quz/android_common/turbine/quz.jar",
285			},
286
287			barJavacInputs: []string{"b.java"},
288			barJavacClasspath: slices.Concat(
289				frameworkTurbineJars,
290				[]string{"out/soong/.intermediates/quz/android_common/turbine/quz.jar"},
291			),
292			barCombinedInputs: []string{
293				"out/soong/.intermediates/bar/android_common/javac/bar.jar",
294				"out/soong/.intermediates/quz/android_common/javac/quz.jar",
295			},
296			barHeaderCombinedInputs: []string{
297				"out/soong/.intermediates/bar/android_common/turbine/bar.jar",
298				"out/soong/.intermediates/quz/android_common/turbine/quz.jar",
299			},
300		},
301	}
302
303	for _, tt := range testCases {
304		t.Run(tt.name, func(t *testing.T) {
305			t.Parallel()
306			result := android.GroupFixturePreparers(
307				PrepareForTestWithJavaDefaultModules,
308				tt.preparer,
309			).RunTestWithBp(t, bp)
310			foo := result.ModuleForTests(t, "foo", "android_common")
311
312			fooJavac := foo.Rule("javac")
313			android.AssertPathsRelativeToTopEquals(t, "foo javac inputs", tt.fooJavacInputs, fooJavac.Inputs)
314
315			fooJavacClasspath := fooJavac.Args["classpath"]
316			android.AssertStringPathsRelativeToTopEquals(t, "foo javac classpath", result.Config, tt.fooJavacClasspath,
317				strings.Split(strings.TrimPrefix(fooJavacClasspath, "-classpath "), ":"))
318
319			fooCombinedJar := foo.Output("combined/foo.jar")
320			android.AssertPathsRelativeToTopEquals(t, "foo combined inputs", tt.fooCombinedInputs, fooCombinedJar.Inputs)
321
322			fooCombinedHeaderJar := foo.Output("turbine-combined/foo.jar")
323			android.AssertPathsRelativeToTopEquals(t, "foo header combined inputs", tt.fooHeaderCombinedInputs, fooCombinedHeaderJar.Inputs)
324
325			bar := result.ModuleForTests(t, "bar", "android_common")
326			barJavac := bar.Rule("javac")
327			android.AssertPathsRelativeToTopEquals(t, "bar javac inputs", tt.barJavacInputs, barJavac.Inputs)
328
329			barJavacClasspath := barJavac.Args["classpath"]
330			android.AssertStringPathsRelativeToTopEquals(t, "bar javac classpath", result.Config, tt.barJavacClasspath,
331				strings.Split(strings.TrimPrefix(barJavacClasspath, "-classpath "), ":"))
332
333			barCombinedJar := bar.Output("combined/bar.jar")
334			android.AssertPathsRelativeToTopEquals(t, "bar combined inputs", tt.barCombinedInputs, barCombinedJar.Inputs)
335
336			barCombinedHeaderJar := bar.Output("turbine-combined/bar.jar")
337			android.AssertPathsRelativeToTopEquals(t, "bar header combined inputs", tt.barHeaderCombinedInputs, barCombinedHeaderJar.Inputs)
338		})
339	}
340}
341
342func TestExportedPlugins(t *testing.T) {
343	t.Parallel()
344	type Result struct {
345		library        string
346		processors     string
347		disableTurbine bool
348	}
349	var tests = []struct {
350		name    string
351		extra   string
352		results []Result
353	}{
354		{
355			name:    "Exported plugin is not a direct plugin",
356			extra:   `java_library { name: "exports", srcs: ["a.java"], exported_plugins: ["plugin"] }`,
357			results: []Result{{library: "exports", processors: "-proc:none"}},
358		},
359		{
360			name: "Exports plugin to dependee",
361			extra: `
362				java_library{name: "exports", exported_plugins: ["plugin"]}
363				java_library{name: "foo", srcs: ["a.java"], libs: ["exports"]}
364				java_library{name: "bar", srcs: ["a.java"], static_libs: ["exports"]}
365			`,
366			results: []Result{
367				{library: "foo", processors: "-processor com.android.TestPlugin"},
368				{library: "bar", processors: "-processor com.android.TestPlugin"},
369			},
370		},
371		{
372			name: "Exports plugin to android_library",
373			extra: `
374				java_library{name: "exports", exported_plugins: ["plugin"]}
375				android_library{name: "foo", srcs: ["a.java"],  libs: ["exports"]}
376				android_library{name: "bar", srcs: ["a.java"], static_libs: ["exports"]}
377			`,
378			results: []Result{
379				{library: "foo", processors: "-processor com.android.TestPlugin"},
380				{library: "bar", processors: "-processor com.android.TestPlugin"},
381			},
382		},
383		{
384			name: "Exports plugin is not propagated via transitive deps",
385			extra: `
386				java_library{name: "exports", exported_plugins: ["plugin"]}
387				java_library{name: "foo", srcs: ["a.java"], libs: ["exports"]}
388				java_library{name: "bar", srcs: ["a.java"], static_libs: ["foo"]}
389			`,
390			results: []Result{
391				{library: "foo", processors: "-processor com.android.TestPlugin"},
392				{library: "bar", processors: "-proc:none"},
393			},
394		},
395		{
396			name: "Exports plugin appends to plugins",
397			extra: `
398                java_plugin{name: "plugin2", processor_class: "com.android.TestPlugin2"}
399				java_library{name: "exports", exported_plugins: ["plugin"]}
400				java_library{name: "foo", srcs: ["a.java"], libs: ["exports"], plugins: ["plugin2"]}
401			`,
402			results: []Result{
403				{library: "foo", processors: "-processor com.android.TestPlugin,com.android.TestPlugin2"},
404			},
405		},
406		{
407			name: "Exports plugin to with generates_api to dependee",
408			extra: `
409				java_library{name: "exports", exported_plugins: ["plugin_generates_api"]}
410				java_library{name: "foo", srcs: ["a.java"], libs: ["exports"]}
411				java_library{name: "bar", srcs: ["a.java"], static_libs: ["exports"]}
412			`,
413			results: []Result{
414				{library: "foo", processors: "-processor com.android.TestPlugin", disableTurbine: true},
415				{library: "bar", processors: "-processor com.android.TestPlugin", disableTurbine: true},
416			},
417		},
418	}
419
420	for _, test := range tests {
421		t.Run(test.name, func(t *testing.T) {
422			t.Parallel()
423			ctx, _ := testJava(t, `
424				java_plugin {
425					name: "plugin",
426					processor_class: "com.android.TestPlugin",
427				}
428				java_plugin {
429					name: "plugin_generates_api",
430					generates_api: true,
431					processor_class: "com.android.TestPlugin",
432				}
433			`+test.extra)
434
435			for _, want := range test.results {
436				javac := ctx.ModuleForTests(t, want.library, "android_common").Rule("javac")
437				if javac.Args["processor"] != want.processors {
438					t.Errorf("For library %v, expected %v, found %v", want.library, want.processors, javac.Args["processor"])
439				}
440				turbine := ctx.ModuleForTests(t, want.library, "android_common").MaybeRule("turbine")
441				disableTurbine := turbine.BuildParams.Rule == nil
442				if disableTurbine != want.disableTurbine {
443					t.Errorf("For library %v, expected disableTurbine %v, found %v", want.library, want.disableTurbine, disableTurbine)
444				}
445			}
446		})
447	}
448}
449
450func TestSdkVersionByPartition(t *testing.T) {
451	t.Parallel()
452	testJavaError(t, "sdk_version must have a value when the module is located at vendor or product", `
453		java_library {
454			name: "foo",
455			srcs: ["a.java"],
456			vendor: true,
457		}
458	`)
459
460	testJava(t, `
461		java_library {
462			name: "bar",
463			srcs: ["b.java"],
464		}
465	`)
466
467	for _, enforce := range []bool{true, false} {
468		bp := `
469			java_library {
470				name: "foo",
471				srcs: ["a.java"],
472				product_specific: true,
473			}
474		`
475
476		errorHandler := android.FixtureExpectsNoErrors
477		if enforce {
478			errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern("sdk_version must have a value when the module is located at vendor or product")
479		}
480
481		android.GroupFixturePreparers(
482			PrepareForTestWithJavaDefaultModules,
483			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
484				variables.EnforceProductPartitionInterface = proptools.BoolPtr(enforce)
485			}),
486		).
487			ExtendWithErrorHandler(errorHandler).
488			RunTestWithBp(t, bp)
489	}
490}
491
492func TestArchSpecific(t *testing.T) {
493	t.Parallel()
494	ctx, _ := testJava(t, `
495		java_library {
496			name: "foo",
497			srcs: ["a.java"],
498			target: {
499				android: {
500					srcs: ["b.java"],
501				},
502			},
503		}
504	`)
505
506	javac := ctx.ModuleForTests(t, "foo", "android_common").Rule("javac")
507	if len(javac.Inputs) != 2 || javac.Inputs[0].String() != "a.java" || javac.Inputs[1].String() != "b.java" {
508		t.Errorf(`foo inputs %v != ["a.java", "b.java"]`, javac.Inputs)
509	}
510}
511
512func TestBinary(t *testing.T) {
513	t.Parallel()
514	ctx, _ := testJava(t, `
515		java_library_host {
516			name: "foo",
517			srcs: ["a.java"],
518		}
519
520		java_binary_host {
521			name: "bar",
522			srcs: ["b.java"],
523			static_libs: ["foo"],
524			jni_libs: ["libjni"],
525		}
526
527		cc_library_shared {
528			name: "libjni",
529			host_supported: true,
530			device_supported: false,
531			stl: "none",
532		}
533	`)
534
535	buildOS := ctx.Config().BuildOS.String()
536
537	bar := ctx.ModuleForTests(t, "bar", buildOS+"_common")
538	barJar := bar.Output("bar.jar").Output.String()
539	barWrapperDeps := bar.Output("bar").Implicits.Strings()
540
541	libjni := ctx.ModuleForTests(t, "libjni", buildOS+"_x86_64_shared")
542	libjniSO := libjni.Rule("Cp").Output.String()
543
544	// Test that the install binary wrapper depends on the installed jar file
545	if g, w := barWrapperDeps, barJar; !android.InList(w, g) {
546		t.Errorf("expected binary wrapper implicits to contain %q, got %q", w, g)
547	}
548
549	// Test that the install binary wrapper depends on the installed JNI libraries
550	if g, w := barWrapperDeps, libjniSO; !android.InList(w, g) {
551		t.Errorf("expected binary wrapper implicits to contain %q, got %q", w, g)
552	}
553}
554
555func TestTest(t *testing.T) {
556	t.Parallel()
557	ctx, _ := testJava(t, `
558		java_test_host {
559			name: "foo",
560			srcs: ["a.java"],
561			jni_libs: ["libjni"],
562		}
563
564		cc_library_shared {
565			name: "libjni",
566			host_supported: true,
567			device_supported: false,
568			stl: "none",
569		}
570	`)
571
572	buildOS := ctx.Config().BuildOS.String()
573
574	foo := ctx.ModuleForTests(t, "foo", buildOS+"_common").Module().(*TestHost)
575
576	expected := "lib64/libjni.so"
577	if runtime.GOOS == "darwin" {
578		expected = "lib64/libjni.dylib"
579	}
580
581	fooTestData := foo.data
582	if len(fooTestData) != 1 || fooTestData[0].Rel() != expected {
583		t.Errorf(`expected foo test data relative path [%q], got %q`,
584			expected, fooTestData.Strings())
585	}
586}
587
588func TestHostCommonData(t *testing.T) {
589	t.Parallel()
590	ctx, _ := testJava(t, `
591		java_library_host {
592			name: "host",
593			srcs: ["a.java"],
594		}
595
596		java_test {
597			name: "foo",
598			srcs: ["a.java"],
599			host_common_data: [":host"],
600		}
601	`)
602
603	foo := ctx.ModuleForTests(t, "foo", "android_common").Module().(*Test)
604	host := ctx.ModuleForTests(t, "host", ctx.Config().BuildOSCommonTarget.String()).Module().(*Library)
605
606	if g, w := foo.data.RelativeToTop().Strings(), []string{host.outputFile.RelativeToTop().String()}; !slices.Equal(g, w) {
607		t.Errorf("expected test data %q, got %q\n", w, g)
608	}
609}
610
611func TestHostBinaryNoJavaDebugInfoOverride(t *testing.T) {
612	t.Parallel()
613	bp := `
614		java_library {
615			name: "target_library",
616			srcs: ["a.java"],
617		}
618
619		java_binary_host {
620			name: "host_binary",
621			srcs: ["b.java"],
622		}
623	`
624
625	result := android.GroupFixturePreparers(
626		PrepareForTestWithJavaDefaultModules,
627		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
628			variables.MinimizeJavaDebugInfo = proptools.BoolPtr(true)
629		}),
630	).RunTestWithBp(t, bp)
631
632	// first, check that the -g flag is added to target modules
633	targetLibrary := result.ModuleForTests(t, "target_library", "android_common")
634	targetJavaFlags := targetLibrary.Module().VariablesForTests()["javacFlags"]
635	if !strings.Contains(targetJavaFlags, "-g:source,lines") {
636		t.Errorf("target library javac flags %v should contain "+
637			"-g:source,lines override with MinimizeJavaDebugInfo", targetJavaFlags)
638	}
639
640	// check that -g is not overridden for host modules
641	buildOS := result.Config.BuildOS.String()
642	hostBinary := result.ModuleForTests(t, "host_binary", buildOS+"_common")
643	hostJavaFlags := hostBinary.Module().VariablesForTests()["javacFlags"]
644	if strings.Contains(hostJavaFlags, "-g:source,lines") {
645		t.Errorf("java_binary_host javac flags %v should not have "+
646			"-g:source,lines override with MinimizeJavaDebugInfo", hostJavaFlags)
647	}
648}
649
650// A minimal context object for use with DexJarBuildPath
651type moduleErrorfTestCtx struct {
652}
653
654func (ctx moduleErrorfTestCtx) ModuleErrorf(format string, args ...interface{}) {
655}
656
657var _ android.ModuleErrorfContext = (*moduleErrorfTestCtx)(nil)
658
659func TestPrebuilts(t *testing.T) {
660	t.Parallel()
661	ctx, _ := testJava(t, `
662		java_library {
663			name: "foo",
664			srcs: ["a.java", ":stubs-source"],
665			libs: ["bar", "sdklib.stubs"],
666			static_libs: ["baz"],
667		}
668
669		java_import {
670			name: "bar",
671			jars: ["a.jar"],
672		}
673
674		java_import {
675			name: "baz",
676			jars: ["b.jar"],
677			sdk_version: "current",
678			compile_dex: true,
679		}
680
681		dex_import {
682			name: "qux",
683			jars: ["b.jar"],
684		}
685
686		java_sdk_library_import {
687			name: "sdklib",
688			public: {
689				jars: ["c.jar"],
690			},
691		}
692
693		prebuilt_stubs_sources {
694			name: "stubs-source",
695			srcs: ["stubs/sources"],
696		}
697
698		java_test_import {
699			name: "test",
700			jars: ["a.jar"],
701			test_suites: ["cts"],
702			test_config: "AndroidTest.xml",
703		}
704		`)
705
706	fooModule := ctx.ModuleForTests(t, "foo", "android_common")
707	javac := fooModule.Rule("javac")
708	combineJar := ctx.ModuleForTests(t, "foo", "android_common").Description("for javac")
709	barModule := ctx.ModuleForTests(t, "bar", "android_common")
710	barJar := barModule.Output("local-combined/bar.jar").Output
711	bazModule := ctx.ModuleForTests(t, "baz", "android_common")
712	bazJar := bazModule.Output("local-combined/baz.jar").Output
713	sdklibStubsJar := ctx.ModuleForTests(t, "sdklib.stubs", "android_common").
714		Output("local-combined/sdklib.stubs.jar").Output
715
716	fooLibrary := fooModule.Module().(*Library)
717	assertDeepEquals(t, "foo unique sources incorrect",
718		[]string{"a.java"}, fooLibrary.uniqueSrcFiles.Strings())
719
720	assertDeepEquals(t, "foo java source jars incorrect",
721		[]string{".intermediates/stubs-source/android_common/stubs-source-stubs.srcjar"},
722		android.NormalizePathsForTesting(fooLibrary.compiledSrcJars))
723
724	if !strings.Contains(javac.Args["classpath"], barJar.String()) {
725		t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barJar.String())
726	}
727
728	errCtx := moduleErrorfTestCtx{}
729	barDexJar := barModule.Module().(*Import).DexJarBuildPath(errCtx)
730	if barDexJar.IsSet() {
731		t.Errorf("bar dex jar build path expected to be set, got %s", barDexJar)
732	}
733
734	if !strings.Contains(javac.Args["classpath"], sdklibStubsJar.String()) {
735		t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], sdklibStubsJar.String())
736	}
737
738	if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != bazJar.String() {
739		t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, bazJar.String())
740	}
741
742	bazDexJar := bazModule.Module().(*Import).DexJarBuildPath(errCtx).Path()
743	expectedDexJar := "out/soong/.intermediates/baz/android_common/dex/baz.jar"
744	android.AssertPathRelativeToTopEquals(t, "baz dex jar build path", expectedDexJar, bazDexJar)
745
746	ctx.ModuleForTests(t, "qux", "android_common").Rule("Cp")
747
748	entries := android.AndroidMkEntriesForTest(t, ctx, fooModule.Module())[0]
749	android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "java_library", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
750	entries = android.AndroidMkEntriesForTest(t, ctx, barModule.Module())[0]
751	android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "java_import", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
752}
753
754func assertDeepEquals(t *testing.T, message string, expected interface{}, actual interface{}) {
755	if !reflect.DeepEqual(expected, actual) {
756		t.Errorf("%s: expected %q, found %q", message, expected, actual)
757	}
758}
759
760func TestPrebuiltStubsSources(t *testing.T) {
761	t.Parallel()
762	test := func(t *testing.T, sourcesPath string, expectedInputs []string) {
763		ctx, _ := testJavaWithFS(t, fmt.Sprintf(`
764prebuilt_stubs_sources {
765  name: "stubs-source",
766	srcs: ["%s"],
767}`, sourcesPath), map[string][]byte{
768			"stubs/sources/pkg/A.java": nil,
769			"stubs/sources/pkg/B.java": nil,
770		})
771
772		zipSrc := ctx.ModuleForTests(t, "stubs-source", "android_common").Rule("zip_src")
773		if expected, actual := expectedInputs, zipSrc.Inputs.Strings(); !reflect.DeepEqual(expected, actual) {
774			t.Errorf("mismatch of inputs to soong_zip: expected %q, actual %q", expected, actual)
775		}
776	}
777
778	t.Run("empty/missing directory", func(t *testing.T) {
779		t.Parallel()
780		test(t, "empty-directory", nil)
781	})
782
783	t.Run("non-empty set of sources", func(t *testing.T) {
784		t.Parallel()
785		test(t, "stubs/sources", []string{
786			"stubs/sources/pkg/A.java",
787			"stubs/sources/pkg/B.java",
788		})
789	})
790}
791
792func TestDefaults(t *testing.T) {
793	t.Parallel()
794	ctx, _ := testJava(t, `
795		java_defaults {
796			name: "defaults",
797			srcs: ["a.java"],
798			libs: ["bar"],
799			static_libs: ["baz"],
800			optimize: {enabled: false},
801		}
802
803		java_library {
804			name: "foo",
805			defaults: ["defaults"],
806		}
807
808		java_library {
809			name: "bar",
810			srcs: ["b.java"],
811		}
812
813		java_library {
814			name: "baz",
815			srcs: ["c.java"],
816		}
817
818		android_test {
819			name: "atestOptimize",
820			defaults: ["defaults"],
821			optimize: {enabled: true},
822		}
823
824		android_test {
825			name: "atestNoOptimize",
826			defaults: ["defaults"],
827		}
828
829		android_test {
830			name: "atestDefault",
831			srcs: ["a.java"],
832		}
833		`)
834
835	javac := ctx.ModuleForTests(t, "foo", "android_common").Rule("javac")
836	combineJar := ctx.ModuleForTests(t, "foo", "android_common").Description("for javac")
837
838	if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
839		t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
840	}
841
842	barTurbine := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine", "bar.jar")
843	if !strings.Contains(javac.Args["classpath"], barTurbine) {
844		t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barTurbine)
845	}
846
847	baz := ctx.ModuleForTests(t, "baz", "android_common").Rule("javac").Output.String()
848	if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != baz {
849		t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, baz)
850	}
851
852	atestOptimize := ctx.ModuleForTests(t, "atestOptimize", "android_common").MaybeRule("r8")
853	if atestOptimize.Output == nil {
854		t.Errorf("atestOptimize should optimize APK")
855	}
856
857	atestNoOptimize := ctx.ModuleForTests(t, "atestNoOptimize", "android_common").MaybeRule("d8")
858	if atestNoOptimize.Output == nil {
859		t.Errorf("atestNoOptimize should not optimize APK")
860	}
861
862	atestDefault := ctx.ModuleForTests(t, "atestDefault", "android_common").MaybeRule("d8")
863	if atestDefault.Output == nil {
864		t.Errorf("atestDefault should not optimize APK")
865	}
866}
867
868func TestResources(t *testing.T) {
869	t.Parallel()
870	var table = []struct {
871		name  string
872		prop  string
873		extra string
874		args  string
875	}{
876		{
877			// Test that a module with java_resource_dirs includes the files
878			name: "resource dirs",
879			prop: `java_resource_dirs: ["java-res"]`,
880			args: "-C java-res -f java-res/a/a -f java-res/b/b",
881		},
882		{
883			// Test that a module with java_resources includes the files
884			name: "resource files",
885			prop: `java_resources: ["java-res/a/a", "java-res/b/b"]`,
886			args: "-C . -f java-res/a/a -f java-res/b/b",
887		},
888		{
889			// Test that a module with a filegroup in java_resources includes the files with the
890			// path prefix
891			name: "resource filegroup",
892			prop: `java_resources: [":foo-res"]`,
893			extra: `
894				filegroup {
895					name: "foo-res",
896					path: "java-res",
897					srcs: ["java-res/a/a", "java-res/b/b"],
898				}`,
899			args: "-C java-res -f java-res/a/a -f java-res/b/b",
900		},
901		{
902			// Test that a module with wildcards in java_resource_dirs has the correct path prefixes
903			name: "wildcard dirs",
904			prop: `java_resource_dirs: ["java-res/*"]`,
905			args: "-C java-res/a -f java-res/a/a -C java-res/b -f java-res/b/b",
906		},
907		{
908			// Test that a module exclude_java_resource_dirs excludes the files
909			name: "wildcard dirs",
910			prop: `java_resource_dirs: ["java-res/*"], exclude_java_resource_dirs: ["java-res/b"]`,
911			args: "-C java-res/a -f java-res/a/a",
912		},
913		{
914			// Test wildcards in java_resources
915			name: "wildcard files",
916			prop: `java_resources: ["java-res/**/*"]`,
917			args: "-C . -f java-res/a/a -f java-res/b/b",
918		},
919		{
920			// Test exclude_java_resources with java_resources
921			name: "wildcard files with exclude",
922			prop: `java_resources: ["java-res/**/*"], exclude_java_resources: ["java-res/b/*"]`,
923			args: "-C . -f java-res/a/a",
924		},
925		{
926			// Test exclude_java_resources with java_resource_dirs
927			name: "resource dirs with exclude files",
928			prop: `java_resource_dirs: ["java-res"], exclude_java_resources: ["java-res/b/b"]`,
929			args: "-C java-res -f java-res/a/a",
930		},
931		{
932			// Test exclude_java_resource_dirs with java_resource_dirs
933			name: "resource dirs with exclude files",
934			prop: `java_resource_dirs: ["java-res", "java-res2"], exclude_java_resource_dirs: ["java-res2"]`,
935			args: "-C java-res -f java-res/a/a -f java-res/b/b",
936		},
937	}
938
939	for _, test := range table {
940		t.Run(test.name, func(t *testing.T) {
941			t.Parallel()
942			ctx, _ := testJavaWithFS(t, `
943				java_library {
944					name: "foo",
945					srcs: [
946						"a.java",
947						"b.java",
948						"c.java",
949					],
950					`+test.prop+`,
951				}
952			`+test.extra,
953				map[string][]byte{
954					"java-res/a/a": nil,
955					"java-res/b/b": nil,
956					"java-res2/a":  nil,
957				},
958			)
959
960			foo := ctx.ModuleForTests(t, "foo", "android_common").Output("withres/foo.jar")
961			fooRes := ctx.ModuleForTests(t, "foo", "android_common").Output("res/foo.jar")
962
963			if !inList(fooRes.Output.String(), foo.Inputs.Strings()) {
964				t.Errorf("foo combined jars %v does not contain %q",
965					foo.Inputs.Strings(), fooRes.Output.String())
966			}
967
968			if fooRes.Args["jarArgs"] != test.args {
969				t.Errorf("foo resource jar args %q is not %q",
970					fooRes.Args["jarArgs"], test.args)
971			}
972		})
973	}
974}
975
976func TestIncludeSrcs(t *testing.T) {
977	t.Parallel()
978	ctx, _ := testJavaWithFS(t, `
979		java_library {
980			name: "foo",
981			srcs: [
982				"a.java",
983				"b.java",
984				"c.java",
985			],
986			include_srcs: true,
987		}
988
989		java_library {
990			name: "bar",
991			srcs: [
992				"a.java",
993				"b.java",
994				"c.java",
995			],
996			java_resource_dirs: ["java-res"],
997			include_srcs: true,
998		}
999	`, map[string][]byte{
1000		"java-res/a/a": nil,
1001		"java-res/b/b": nil,
1002		"java-res2/a":  nil,
1003	})
1004
1005	// Test a library with include_srcs: true
1006	foo := ctx.ModuleForTests(t, "foo", "android_common").Output("withres/foo.jar")
1007	fooSrcJar := ctx.ModuleForTests(t, "foo", "android_common").Output("foo.srcjar")
1008
1009	if g, w := fooSrcJar.Output.String(), foo.Inputs.Strings(); !inList(g, w) {
1010		t.Errorf("foo combined jars %v does not contain %q", w, g)
1011	}
1012
1013	if g, w := fooSrcJar.Args["jarArgs"], "-C . -f a.java -f b.java -f c.java"; g != w {
1014		t.Errorf("foo source jar args %q is not %q", w, g)
1015	}
1016
1017	// Test a library with include_srcs: true and resources
1018	bar := ctx.ModuleForTests(t, "bar", "android_common").Output("withres/bar.jar")
1019	barResCombined := ctx.ModuleForTests(t, "bar", "android_common").Output("res-combined/bar.jar")
1020	barRes := ctx.ModuleForTests(t, "bar", "android_common").Output("res/bar.jar")
1021	barSrcJar := ctx.ModuleForTests(t, "bar", "android_common").Output("bar.srcjar")
1022
1023	if g, w := barSrcJar.Output.String(), barResCombined.Inputs.Strings(); !inList(g, w) {
1024		t.Errorf("bar combined resource jars %v does not contain %q", w, g)
1025	}
1026
1027	if g, w := barRes.Output.String(), barResCombined.Inputs.Strings(); !inList(g, w) {
1028		t.Errorf("bar combined resource jars %v does not contain %q", w, g)
1029	}
1030
1031	if g, w := barRes.Output.String(), bar.Inputs.Strings(); !inList(g, w) {
1032		t.Errorf("bar combined jars %v does not contain %q", w, g)
1033	}
1034
1035	if g, w := barSrcJar.Args["jarArgs"], "-C . -f a.java -f b.java -f c.java"; g != w {
1036		t.Errorf("bar source jar args %q is not %q", w, g)
1037	}
1038
1039	if g, w := barRes.Args["jarArgs"], "-C java-res -f java-res/a/a -f java-res/b/b"; g != w {
1040		t.Errorf("bar resource jar args %q is not %q", w, g)
1041	}
1042}
1043
1044func TestGeneratedSources(t *testing.T) {
1045	t.Parallel()
1046	ctx, _ := testJavaWithFS(t, `
1047		java_library {
1048			name: "foo",
1049			srcs: [
1050				"a*.java",
1051				":gen",
1052				"b*.java",
1053			],
1054		}
1055
1056		genrule {
1057			name: "gen",
1058			tool_files: ["java-res/a"],
1059			out: ["gen.java"],
1060		}
1061	`, map[string][]byte{
1062		"a.java": nil,
1063		"b.java": nil,
1064	})
1065
1066	javac := ctx.ModuleForTests(t, "foo", "android_common").Rule("javac")
1067	genrule := ctx.ModuleForTests(t, "gen", "").Rule("generator")
1068
1069	if filepath.Base(genrule.Output.String()) != "gen.java" {
1070		t.Fatalf(`gen output file %v is not ".../gen.java"`, genrule.Output.String())
1071	}
1072
1073	if len(javac.Inputs) != 3 ||
1074		javac.Inputs[0].String() != "a.java" ||
1075		javac.Inputs[1].String() != genrule.Output.String() ||
1076		javac.Inputs[2].String() != "b.java" {
1077		t.Errorf(`foo inputs %v != ["a.java", ".../gen.java", "b.java"]`, javac.Inputs)
1078	}
1079}
1080
1081func TestTurbine(t *testing.T) {
1082	t.Parallel()
1083	result := android.GroupFixturePreparers(
1084		prepareForJavaTest, FixtureWithPrebuiltApis(map[string][]string{"14": {"foo"}})).
1085		RunTestWithBp(t, `
1086		java_library {
1087			name: "foo",
1088			srcs: ["a.java"],
1089			sdk_version: "14",
1090		}
1091
1092		java_library {
1093			name: "bar",
1094			srcs: ["b.java"],
1095			static_libs: ["foo"],
1096			sdk_version: "14",
1097		}
1098
1099		java_library {
1100			name: "baz",
1101			srcs: ["c.java"],
1102			libs: ["bar"],
1103			sdk_version: "14",
1104		}
1105		`)
1106
1107	fooTurbine := result.ModuleForTests(t, "foo", "android_common").Rule("turbine")
1108	barTurbine := result.ModuleForTests(t, "bar", "android_common").Rule("turbine")
1109	barJavac := result.ModuleForTests(t, "bar", "android_common").Rule("javac")
1110	barTurbineCombined := result.ModuleForTests(t, "bar", "android_common").Description("for turbine")
1111	bazJavac := result.ModuleForTests(t, "baz", "android_common").Rule("javac")
1112
1113	android.AssertPathsRelativeToTopEquals(t, "foo inputs", []string{"a.java"}, fooTurbine.Inputs)
1114
1115	fooHeaderJar := filepath.Join("out", "soong", ".intermediates", "foo", "android_common", "turbine", "foo.jar")
1116	barTurbineJar := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine", "bar.jar")
1117	android.AssertStringDoesContain(t, "bar turbine classpath", barTurbine.Args["turbineFlags"], fooHeaderJar)
1118	android.AssertStringDoesContain(t, "bar javac classpath", barJavac.Args["classpath"], fooHeaderJar)
1119	android.AssertPathsRelativeToTopEquals(t, "bar turbine combineJar", []string{barTurbineJar, fooHeaderJar}, barTurbineCombined.Inputs)
1120	android.AssertStringDoesContain(t, "baz javac classpath", bazJavac.Args["classpath"], "prebuilts/sdk/14/public/android.jar")
1121}
1122
1123func TestSharding(t *testing.T) {
1124	t.Parallel()
1125	ctx, _ := testJava(t, `
1126		java_library {
1127			name: "bar",
1128			srcs: ["a.java","b.java","c.java"],
1129			javac_shard_size: 1
1130		}
1131		`)
1132
1133	barHeaderJar := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine", "bar.jar")
1134	for i := 0; i < 3; i++ {
1135		barJavac := ctx.ModuleForTests(t, "bar", "android_common").Description("javac" + strconv.Itoa(i))
1136		if !strings.HasPrefix(barJavac.Args["classpath"], "-classpath "+barHeaderJar+":") {
1137			t.Errorf("bar javac classpath %v does start with %q", barJavac.Args["classpath"], barHeaderJar)
1138		}
1139	}
1140}
1141
1142func TestExcludeFileGroupInSrcs(t *testing.T) {
1143	t.Parallel()
1144	ctx, _ := testJava(t, `
1145		java_library {
1146			name: "foo",
1147			srcs: ["a.java", ":foo-srcs"],
1148			exclude_srcs: ["a.java", ":foo-excludes"],
1149		}
1150
1151		filegroup {
1152			name: "foo-srcs",
1153			srcs: ["java-fg/a.java", "java-fg/b.java", "java-fg/c.java"],
1154		}
1155
1156		filegroup {
1157			name: "foo-excludes",
1158			srcs: ["java-fg/a.java", "java-fg/b.java"],
1159		}
1160	`)
1161
1162	javac := ctx.ModuleForTests(t, "foo", "android_common").Rule("javac")
1163
1164	if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "java-fg/c.java" {
1165		t.Errorf(`foo inputs %v != ["java-fg/c.java"]`, javac.Inputs)
1166	}
1167}
1168
1169func TestJavaLibraryOutputFiles(t *testing.T) {
1170	t.Parallel()
1171	testJavaWithFS(t, "", map[string][]byte{
1172		"libcore/Android.bp": []byte(`
1173				java_library {
1174						name: "core",
1175						sdk_version: "none",
1176						system_modules: "none",
1177				}
1178
1179				filegroup {
1180					name: "core-jar",
1181					device_common_srcs: [":core{.jar}"],
1182				}
1183		`),
1184	})
1185}
1186
1187func TestJavaImportOutputFiles(t *testing.T) {
1188	t.Parallel()
1189	testJavaWithFS(t, "", map[string][]byte{
1190		"libcore/Android.bp": []byte(`
1191				java_import {
1192						name: "core",
1193						sdk_version: "none",
1194				}
1195
1196				filegroup {
1197					name: "core-jar",
1198					device_common_srcs: [":core{.jar}"],
1199				}
1200		`),
1201	})
1202}
1203
1204func TestJavaImport(t *testing.T) {
1205	t.Parallel()
1206	bp := `
1207		java_library {
1208			name: "source_library",
1209			srcs: ["source.java"],
1210		}
1211
1212		java_import {
1213			name: "import_with_no_deps",
1214			jars: ["no_deps.jar"],
1215		}
1216
1217		java_import {
1218			name: "import_with_source_deps",
1219			jars: ["source_deps.jar"],
1220			static_libs: ["source_library"],
1221		}
1222
1223		java_import {
1224			name: "import_with_import_deps",
1225			jars: ["import_deps.jar"],
1226			static_libs: ["import_with_no_deps"],
1227		}
1228	`
1229	ctx := android.GroupFixturePreparers(
1230		PrepareForTestWithJavaDefaultModules,
1231	).RunTestWithBp(t, bp)
1232
1233	source := ctx.ModuleForTests(t, "source_library", "android_common")
1234	sourceJar := source.Output("javac/source_library.jar")
1235	sourceHeaderJar := source.Output("turbine/source_library.jar")
1236	sourceCombinedHeaderJar := source.Output("turbine-combined/source_library.jar")
1237	sourceJavaInfo, _ := android.OtherModuleProvider(ctx, source.Module(), JavaInfoProvider)
1238
1239	// The source library produces separate implementation and header jars
1240	android.AssertPathsRelativeToTopEquals(t, "source library implementation jar",
1241		[]string{sourceJar.Output.String()}, sourceJavaInfo.ImplementationAndResourcesJars)
1242	android.AssertPathsRelativeToTopEquals(t, "source library header jar",
1243		[]string{sourceCombinedHeaderJar.Output.String()}, sourceJavaInfo.HeaderJars)
1244
1245	importWithNoDeps := ctx.ModuleForTests(t, "import_with_no_deps", "android_common")
1246	importWithNoDepsLocalJar := importWithNoDeps.Output("local-combined/import_with_no_deps.jar")
1247	importWithNoDepsJar := importWithNoDeps.Output("combined/import_with_no_deps.jar")
1248	importWithNoDepsJavaInfo, _ := android.OtherModuleProvider(ctx, importWithNoDeps.Module(), JavaInfoProvider)
1249
1250	// An import with no deps produces a single jar used as both the header and implementation jar.
1251	android.AssertPathsRelativeToTopEquals(t, "import with no deps implementation jar",
1252		[]string{importWithNoDepsJar.Output.String()}, importWithNoDepsJavaInfo.ImplementationAndResourcesJars)
1253	android.AssertPathsRelativeToTopEquals(t, "import with no deps header jar",
1254		[]string{importWithNoDepsJar.Output.String()}, importWithNoDepsJavaInfo.HeaderJars)
1255	android.AssertPathsRelativeToTopEquals(t, "import with no deps combined inputs",
1256		[]string{importWithNoDepsLocalJar.Output.String()}, importWithNoDepsJar.Inputs)
1257	android.AssertPathsRelativeToTopEquals(t, "import with no deps local combined inputs",
1258		[]string{"no_deps.jar"}, importWithNoDepsLocalJar.Inputs)
1259
1260	importWithSourceDeps := ctx.ModuleForTests(t, "import_with_source_deps", "android_common")
1261	importWithSourceDepsLocalJar := importWithSourceDeps.Output("local-combined/import_with_source_deps.jar")
1262	importWithSourceDepsJar := importWithSourceDeps.Output("combined/import_with_source_deps.jar")
1263	importWithSourceDepsLocalHeaderJar := importWithSourceDeps.Output("local-combined/import_with_source_deps.jar")
1264	importWithSourceDepsHeaderJar := importWithSourceDeps.Output("turbine-combined/import_with_source_deps.jar")
1265	importWithSourceDepsJavaInfo, _ := android.OtherModuleProvider(ctx, importWithSourceDeps.Module(), JavaInfoProvider)
1266
1267	// An import with source deps produces separate header and implementation jars.
1268	android.AssertPathsRelativeToTopEquals(t, "import with source deps implementation jar",
1269		[]string{importWithSourceDepsJar.Output.String()}, importWithSourceDepsJavaInfo.ImplementationAndResourcesJars)
1270	android.AssertPathsRelativeToTopEquals(t, "import with source deps header jar",
1271		[]string{importWithSourceDepsHeaderJar.Output.String()}, importWithSourceDepsJavaInfo.HeaderJars)
1272	android.AssertPathsRelativeToTopEquals(t, "import with source deps combined implementation jar inputs",
1273		[]string{importWithSourceDepsLocalJar.Output.String(), sourceJar.Output.String()}, importWithSourceDepsJar.Inputs)
1274	android.AssertPathsRelativeToTopEquals(t, "import with source deps combined header jar inputs",
1275		[]string{importWithSourceDepsLocalHeaderJar.Output.String(), sourceHeaderJar.Output.String()}, importWithSourceDepsHeaderJar.Inputs)
1276	android.AssertPathsRelativeToTopEquals(t, "import with source deps local combined implementation jar inputs",
1277		[]string{"source_deps.jar"}, importWithSourceDepsLocalJar.Inputs)
1278	android.AssertPathsRelativeToTopEquals(t, "import with source deps local combined header jar inputs",
1279		[]string{"source_deps.jar"}, importWithSourceDepsLocalHeaderJar.Inputs)
1280
1281	importWithImportDeps := ctx.ModuleForTests(t, "import_with_import_deps", "android_common")
1282	importWithImportDepsLocalJar := importWithImportDeps.Output("local-combined/import_with_import_deps.jar")
1283	importWithImportDepsJar := importWithImportDeps.Output("combined/import_with_import_deps.jar")
1284	importWithImportDepsJavaInfo, _ := android.OtherModuleProvider(ctx, importWithImportDeps.Module(), JavaInfoProvider)
1285
1286	// An import with only import deps produces a single jar used as both the header and implementation jar.
1287	android.AssertPathsRelativeToTopEquals(t, "import with import deps implementation jar",
1288		[]string{importWithImportDepsJar.Output.String()}, importWithImportDepsJavaInfo.ImplementationAndResourcesJars)
1289	android.AssertPathsRelativeToTopEquals(t, "import with import deps header jar",
1290		[]string{importWithImportDepsJar.Output.String()}, importWithImportDepsJavaInfo.HeaderJars)
1291	android.AssertPathsRelativeToTopEquals(t, "import with import deps combined implementation jar inputs",
1292		[]string{importWithImportDepsLocalJar.Output.String(), importWithNoDepsLocalJar.Output.String()}, importWithImportDepsJar.Inputs)
1293	android.AssertPathsRelativeToTopEquals(t, "import with import deps local combined implementation jar inputs",
1294		[]string{"import_deps.jar"}, importWithImportDepsLocalJar.Inputs)
1295}
1296
1297var compilerFlagsTestCases = []struct {
1298	in  string
1299	out bool
1300}{
1301	{
1302		in:  "a",
1303		out: false,
1304	},
1305	{
1306		in:  "-a",
1307		out: true,
1308	},
1309	{
1310		in:  "-no-jdk",
1311		out: false,
1312	},
1313	{
1314		in:  "-no-stdlib",
1315		out: false,
1316	},
1317	{
1318		in:  "-kotlin-home",
1319		out: false,
1320	},
1321	{
1322		in:  "-kotlin-home /some/path",
1323		out: false,
1324	},
1325	{
1326		in:  "-include-runtime",
1327		out: false,
1328	},
1329	{
1330		in:  "-Xintellij-plugin-root",
1331		out: false,
1332	},
1333}
1334
1335type mockContext struct {
1336	android.ModuleContext
1337	result bool
1338}
1339
1340func (ctx *mockContext) PropertyErrorf(property, format string, args ...interface{}) {
1341	// CheckBadCompilerFlags calls this function when the flag should be rejected
1342	ctx.result = false
1343}
1344
1345func TestCompilerFlags(t *testing.T) {
1346	t.Parallel()
1347	for _, testCase := range compilerFlagsTestCases {
1348		ctx := &mockContext{result: true}
1349		CheckKotlincFlags(ctx, []string{testCase.in})
1350		if ctx.result != testCase.out {
1351			t.Errorf("incorrect output:")
1352			t.Errorf("     input: %#v", testCase.in)
1353			t.Errorf("  expected: %#v", testCase.out)
1354			t.Errorf("       got: %#v", ctx.result)
1355		}
1356	}
1357}
1358
1359// TODO(jungjw): Consider making this more robust by ignoring path order.
1360func checkPatchModuleFlag(t *testing.T, ctx *android.TestContext, moduleName string, expected string) {
1361	t.Helper()
1362	variables := ctx.ModuleForTests(t, moduleName, "android_common").VariablesForTestsRelativeToTop()
1363	flags := strings.Split(variables["javacFlags"], " ")
1364	got := ""
1365	for _, flag := range flags {
1366		keyEnd := strings.Index(flag, "=")
1367		if keyEnd > -1 && flag[:keyEnd] == "--patch-module" {
1368			got = flag[keyEnd+1:]
1369			break
1370		}
1371	}
1372	if expected != android.StringPathRelativeToTop(ctx.Config().SoongOutDir(), got) {
1373		t.Errorf("Unexpected patch-module flag for module %q - expected %q, but got %q", moduleName, expected, got)
1374	}
1375}
1376
1377func TestPatchModule(t *testing.T) {
1378	t.Parallel()
1379	t.Run("Java language level 8", func(t *testing.T) {
1380		t.Parallel()
1381		// Test with legacy javac -source 1.8 -target 1.8
1382		bp := `
1383			java_library {
1384				name: "foo",
1385				srcs: ["a.java"],
1386				java_version: "1.8",
1387			}
1388
1389			java_library {
1390				name: "bar",
1391				srcs: ["b.java"],
1392				sdk_version: "none",
1393				system_modules: "none",
1394				patch_module: "java.base",
1395				java_version: "1.8",
1396			}
1397
1398			java_library {
1399				name: "baz",
1400				srcs: ["c.java"],
1401				patch_module: "java.base",
1402				java_version: "1.8",
1403			}
1404		`
1405		ctx, _ := testJava(t, bp)
1406
1407		checkPatchModuleFlag(t, ctx, "foo", "")
1408		checkPatchModuleFlag(t, ctx, "bar", "")
1409		checkPatchModuleFlag(t, ctx, "baz", "")
1410	})
1411
1412	t.Run("Java language level 9", func(t *testing.T) {
1413		t.Parallel()
1414		// Test with default javac -source 9 -target 9
1415		bp := `
1416			java_library {
1417				name: "foo",
1418				srcs: ["a.java"],
1419			}
1420
1421			java_library {
1422				name: "bar",
1423				srcs: ["b.java"],
1424				sdk_version: "none",
1425				system_modules: "none",
1426				patch_module: "java.base",
1427			}
1428
1429			java_library {
1430				name: "baz",
1431				srcs: [
1432					"c.java",
1433					// Tests for b/150878007
1434					"dir/d.java",
1435					"dir2/e.java",
1436					"dir2/f.java",
1437					"nested/dir/g.java"
1438				],
1439				patch_module: "java.base",
1440			}
1441		`
1442		ctx, _ := testJava(t, bp)
1443
1444		checkPatchModuleFlag(t, ctx, "foo", "")
1445		expected := "java.base=.:out/soong"
1446		checkPatchModuleFlag(t, ctx, "bar", expected)
1447		expected = "java.base=" + strings.Join([]string{
1448			".", "out/soong", defaultModuleToPath("ext"), defaultModuleToPath("framework")}, ":")
1449		checkPatchModuleFlag(t, ctx, "baz", expected)
1450	})
1451}
1452
1453func TestJavaLibraryWithSystemModules(t *testing.T) {
1454	t.Parallel()
1455	ctx, _ := testJava(t, `
1456		java_library {
1457		    name: "lib-with-source-system-modules",
1458		    srcs: [
1459		        "a.java",
1460		    ],
1461				sdk_version: "none",
1462				system_modules: "source-system-modules",
1463		}
1464
1465		java_library {
1466				name: "source-jar",
1467		    srcs: [
1468		        "a.java",
1469		    ],
1470		}
1471
1472		java_system_modules {
1473				name: "source-system-modules",
1474				libs: ["source-jar"],
1475		}
1476
1477		java_library {
1478		    name: "lib-with-prebuilt-system-modules",
1479		    srcs: [
1480		        "a.java",
1481		    ],
1482				sdk_version: "none",
1483				system_modules: "prebuilt-system-modules",
1484		}
1485
1486		java_import {
1487				name: "prebuilt-jar",
1488				jars: ["a.jar"],
1489		}
1490
1491		java_system_modules_import {
1492				name: "prebuilt-system-modules",
1493				libs: ["prebuilt-jar"],
1494		}
1495		`)
1496
1497	checkBootClasspathForLibWithSystemModule(t, ctx, "lib-with-source-system-modules", "/source-jar.jar")
1498
1499	checkBootClasspathForLibWithSystemModule(t, ctx, "lib-with-prebuilt-system-modules", "/prebuilt-jar.jar")
1500}
1501
1502func checkBootClasspathForLibWithSystemModule(t *testing.T, ctx *android.TestContext, moduleName string, expectedSuffix string) {
1503	javacRule := ctx.ModuleForTests(t, moduleName, "android_common").Rule("javac")
1504	bootClasspath := javacRule.Args["bootClasspath"]
1505	if strings.HasPrefix(bootClasspath, "--system ") && strings.HasSuffix(bootClasspath, expectedSuffix) {
1506		t.Errorf("bootclasspath of %q must start with --system and end with %q, but was %#v.", moduleName, expectedSuffix, bootClasspath)
1507	}
1508}
1509
1510func TestAidlExportIncludeDirsFromImports(t *testing.T) {
1511	t.Parallel()
1512	ctx, _ := testJava(t, `
1513		java_library {
1514			name: "foo",
1515			srcs: ["aidl/foo/IFoo.aidl"],
1516			libs: ["bar"],
1517		}
1518
1519		java_import {
1520			name: "bar",
1521			jars: ["a.jar"],
1522			aidl: {
1523				export_include_dirs: ["aidl/bar"],
1524			},
1525		}
1526	`)
1527
1528	aidlCommand := ctx.ModuleForTests(t, "foo", "android_common").Rule("aidl").RuleParams.Command
1529	expectedAidlFlag := "-Iaidl/bar"
1530	if !strings.Contains(aidlCommand, expectedAidlFlag) {
1531		t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
1532	}
1533}
1534
1535func TestAidlFlagsArePassedToTheAidlCompiler(t *testing.T) {
1536	t.Parallel()
1537	ctx, _ := testJava(t, `
1538		java_library {
1539			name: "foo",
1540			srcs: ["aidl/foo/IFoo.aidl"],
1541			aidl: { flags: ["-Werror"], },
1542		}
1543	`)
1544
1545	aidlCommand := ctx.ModuleForTests(t, "foo", "android_common").Rule("aidl").RuleParams.Command
1546	expectedAidlFlag := "-Werror"
1547	if !strings.Contains(aidlCommand, expectedAidlFlag) {
1548		t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
1549	}
1550}
1551
1552func TestAidlFlagsWithMinSdkVersion(t *testing.T) {
1553	t.Parallel()
1554	fixture := android.GroupFixturePreparers(
1555		prepareForJavaTest, FixtureWithPrebuiltApis(map[string][]string{"14": {"foo"}}))
1556
1557	for _, tc := range []struct {
1558		name       string
1559		sdkVersion string
1560		expected   string
1561	}{
1562		{"default is current", "", "current"},
1563		{"use sdk_version", `sdk_version: "14"`, "14"},
1564		{"system_current", `sdk_version: "system_current"`, "current"},
1565	} {
1566		t.Run(tc.name, func(t *testing.T) {
1567			t.Parallel()
1568			ctx := fixture.RunTestWithBp(t, `
1569				java_library {
1570					name: "foo",
1571					srcs: ["aidl/foo/IFoo.aidl"],
1572					`+tc.sdkVersion+`
1573				}
1574			`)
1575			aidlCommand := ctx.ModuleForTests(t, "foo", "android_common").Rule("aidl").RuleParams.Command
1576			expectedAidlFlag := "--min_sdk_version=" + tc.expected
1577			if !strings.Contains(aidlCommand, expectedAidlFlag) {
1578				t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
1579			}
1580		})
1581	}
1582}
1583
1584func TestAidlFlagsMinSdkVersionDroidstubs(t *testing.T) {
1585	t.Parallel()
1586	bpTemplate := `
1587	droidstubs {
1588		name: "foo-stubs",
1589		srcs: ["foo.aidl"],
1590		%s
1591		system_modules: "none",
1592	}
1593	`
1594	testCases := []struct {
1595		desc                  string
1596		sdkVersionBp          string
1597		minSdkVersionExpected string
1598	}{
1599		{
1600			desc:                  "sdk_version not set, module compiles against private platform APIs",
1601			sdkVersionBp:          ``,
1602			minSdkVersionExpected: "10000",
1603		},
1604		{
1605			desc:                  "sdk_version set to none, module does not build against an SDK",
1606			sdkVersionBp:          `sdk_version: "none",`,
1607			minSdkVersionExpected: "10000",
1608		},
1609	}
1610	for _, tc := range testCases {
1611		ctx := prepareForJavaTest.RunTestWithBp(t, fmt.Sprintf(bpTemplate, tc.sdkVersionBp))
1612		aidlCmd := ctx.ModuleForTests(t, "foo-stubs", "android_common").Rule("aidl").RuleParams.Command
1613		expected := "--min_sdk_version=" + tc.minSdkVersionExpected
1614		android.AssertStringDoesContain(t, "aidl command conatins incorrect min_sdk_version for testCse: "+tc.desc, aidlCmd, expected)
1615	}
1616}
1617
1618func TestAidlEnforcePermissions(t *testing.T) {
1619	t.Parallel()
1620	ctx, _ := testJava(t, `
1621		java_library {
1622			name: "foo",
1623			srcs: ["aidl/foo/IFoo.aidl"],
1624			aidl: { enforce_permissions: true },
1625		}
1626	`)
1627
1628	aidlCommand := ctx.ModuleForTests(t, "foo", "android_common").Rule("aidl").RuleParams.Command
1629	expectedAidlFlag := "-Wmissing-permission-annotation -Werror"
1630	if !strings.Contains(aidlCommand, expectedAidlFlag) {
1631		t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
1632	}
1633}
1634
1635func TestAidlEnforcePermissionsException(t *testing.T) {
1636	t.Parallel()
1637	ctx, _ := testJava(t, `
1638		java_library {
1639			name: "foo",
1640			srcs: ["aidl/foo/IFoo.aidl", "aidl/foo/IFoo2.aidl"],
1641			aidl: { enforce_permissions: true, enforce_permissions_exceptions: ["aidl/foo/IFoo2.aidl"] },
1642		}
1643	`)
1644
1645	aidlCommand := ctx.ModuleForTests(t, "foo", "android_common").Rule("aidl").RuleParams.Command
1646	expectedAidlFlag := "$$FLAGS -Wmissing-permission-annotation -Werror aidl/foo/IFoo.aidl"
1647	if !strings.Contains(aidlCommand, expectedAidlFlag) {
1648		t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
1649	}
1650	expectedAidlFlag = "$$FLAGS  aidl/foo/IFoo2.aidl"
1651	if !strings.Contains(aidlCommand, expectedAidlFlag) {
1652		t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
1653	}
1654}
1655
1656func TestDataNativeBinaries(t *testing.T) {
1657	t.Parallel()
1658	ctx := android.GroupFixturePreparers(
1659		prepareForJavaTest,
1660		android.PrepareForTestWithAllowMissingDependencies).RunTestWithBp(t, `
1661		java_test_host {
1662			name: "foo",
1663			srcs: ["a.java"],
1664			data_native_bins: ["bin"]
1665		}
1666
1667		cc_binary_host {
1668			name: "bin",
1669			srcs: ["bin.cpp"],
1670		}
1671	`).TestContext
1672
1673	buildOS := ctx.Config().BuildOS.String()
1674
1675	test := ctx.ModuleForTests(t, "foo", buildOS+"_common").Module().(*TestHost)
1676	entries := android.AndroidMkEntriesForTest(t, ctx, test)[0]
1677	expected := []string{"out/soong/.intermediates/bin/" + buildOS + "_x86_64/bin:bin"}
1678	actual := entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"]
1679	android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_COMPATIBILITY_SUPPORT_FILES", ctx.Config(), expected, actual)
1680}
1681
1682func TestDefaultInstallable(t *testing.T) {
1683	t.Parallel()
1684	ctx, _ := testJava(t, `
1685		java_test_host {
1686			name: "foo"
1687		}
1688	`)
1689
1690	buildOS := ctx.Config().BuildOS.String()
1691	module := ctx.ModuleForTests(t, "foo", buildOS+"_common").Module().(*TestHost)
1692	assertDeepEquals(t, "Default installable value should be true.", proptools.BoolPtr(true),
1693		module.properties.Installable)
1694}
1695
1696func TestErrorproneEnabled(t *testing.T) {
1697	t.Parallel()
1698	ctx, _ := testJava(t, `
1699		java_library {
1700			name: "foo",
1701			srcs: ["a.java"],
1702			errorprone: {
1703				enabled: true,
1704			},
1705		}
1706	`)
1707
1708	javac := ctx.ModuleForTests(t, "foo", "android_common").Description("javac")
1709
1710	// Test that the errorprone plugins are passed to javac
1711	expectedSubstring := "-Xplugin:ErrorProne"
1712	if !strings.Contains(javac.Args["javacFlags"], expectedSubstring) {
1713		t.Errorf("expected javacFlags to contain %q, got %q", expectedSubstring, javac.Args["javacFlags"])
1714	}
1715
1716	// Modules with errorprone { enabled: true } will include errorprone checks
1717	// in the main javac build rule. Only when RUN_ERROR_PRONE is true will
1718	// the explicit errorprone build rule be created.
1719	errorprone := ctx.ModuleForTests(t, "foo", "android_common").MaybeDescription("errorprone")
1720	if errorprone.RuleParams.Description != "" {
1721		t.Errorf("expected errorprone build rule to not exist, but it did")
1722	}
1723}
1724
1725func TestErrorproneDisabled(t *testing.T) {
1726	t.Parallel()
1727	bp := `
1728		java_library {
1729			name: "foo",
1730			srcs: ["a.java"],
1731			errorprone: {
1732				enabled: false,
1733			},
1734		}
1735	`
1736	ctx := android.GroupFixturePreparers(
1737		PrepareForTestWithJavaDefaultModules,
1738		android.FixtureMergeEnv(map[string]string{
1739			"RUN_ERROR_PRONE": "true",
1740		}),
1741	).RunTestWithBp(t, bp)
1742
1743	javac := ctx.ModuleForTests(t, "foo", "android_common").Description("javac")
1744
1745	// Test that the errorprone plugins are not passed to javac, like they would
1746	// be if enabled was true.
1747	expectedSubstring := "-Xplugin:ErrorProne"
1748	if strings.Contains(javac.Args["javacFlags"], expectedSubstring) {
1749		t.Errorf("expected javacFlags to not contain %q, got %q", expectedSubstring, javac.Args["javacFlags"])
1750	}
1751
1752	// Check that no errorprone build rule is created, like there would be
1753	// if enabled was unset and RUN_ERROR_PRONE was true.
1754	errorprone := ctx.ModuleForTests(t, "foo", "android_common").MaybeDescription("errorprone")
1755	if errorprone.RuleParams.Description != "" {
1756		t.Errorf("expected errorprone build rule to not exist, but it did")
1757	}
1758}
1759
1760func TestErrorproneEnabledOnlyByEnvironmentVariable(t *testing.T) {
1761	t.Parallel()
1762	bp := `
1763		java_library {
1764			name: "foo",
1765			srcs: ["a.java"],
1766		}
1767	`
1768	ctx := android.GroupFixturePreparers(
1769		PrepareForTestWithJavaDefaultModules,
1770		android.FixtureMergeEnv(map[string]string{
1771			"RUN_ERROR_PRONE": "true",
1772		}),
1773	).RunTestWithBp(t, bp)
1774
1775	javac := ctx.ModuleForTests(t, "foo", "android_common").Description("javac")
1776	errorprone := ctx.ModuleForTests(t, "foo", "android_common").Description("errorprone")
1777
1778	// Check that the errorprone plugins are not passed to javac, because they
1779	// will instead be passed to the separate errorprone compilation
1780	expectedSubstring := "-Xplugin:ErrorProne"
1781	if strings.Contains(javac.Args["javacFlags"], expectedSubstring) {
1782		t.Errorf("expected javacFlags to not contain %q, got %q", expectedSubstring, javac.Args["javacFlags"])
1783	}
1784
1785	// Check that the errorprone plugin is enabled
1786	if !strings.Contains(errorprone.Args["javacFlags"], expectedSubstring) {
1787		t.Errorf("expected errorprone to contain %q, got %q", expectedSubstring, javac.Args["javacFlags"])
1788	}
1789}
1790
1791func TestDataDeviceBinsBuildsDeviceBinary(t *testing.T) {
1792	t.Parallel()
1793	testCases := []struct {
1794		dataDeviceBinType  string
1795		depCompileMultilib string
1796		variants           []string
1797		expectedError      string
1798	}{
1799		{
1800			dataDeviceBinType:  "first",
1801			depCompileMultilib: "first",
1802			variants:           []string{"android_arm64_armv8-a"},
1803		},
1804		{
1805			dataDeviceBinType:  "first",
1806			depCompileMultilib: "both",
1807			variants:           []string{"android_arm64_armv8-a"},
1808		},
1809		{
1810			// this is true because our testing framework is set up with
1811			// Targets ~ [<64bit target>, <32bit target>], where 64bit is "first"
1812			dataDeviceBinType:  "first",
1813			depCompileMultilib: "32",
1814			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1815		},
1816		{
1817			dataDeviceBinType:  "first",
1818			depCompileMultilib: "64",
1819			variants:           []string{"android_arm64_armv8-a"},
1820		},
1821		{
1822			dataDeviceBinType:  "both",
1823			depCompileMultilib: "both",
1824			variants: []string{
1825				"android_arm_armv7-a-neon",
1826				"android_arm64_armv8-a",
1827			},
1828		},
1829		{
1830			dataDeviceBinType:  "both",
1831			depCompileMultilib: "32",
1832			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1833		},
1834		{
1835			dataDeviceBinType:  "both",
1836			depCompileMultilib: "64",
1837			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1838		},
1839		{
1840			dataDeviceBinType:  "both",
1841			depCompileMultilib: "first",
1842			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1843		},
1844		{
1845			dataDeviceBinType:  "32",
1846			depCompileMultilib: "32",
1847			variants:           []string{"android_arm_armv7-a-neon"},
1848		},
1849		{
1850			dataDeviceBinType:  "32",
1851			depCompileMultilib: "first",
1852			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1853		},
1854		{
1855			dataDeviceBinType:  "32",
1856			depCompileMultilib: "both",
1857			variants:           []string{"android_arm_armv7-a-neon"},
1858		},
1859		{
1860			dataDeviceBinType:  "32",
1861			depCompileMultilib: "64",
1862			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1863		},
1864		{
1865			dataDeviceBinType:  "64",
1866			depCompileMultilib: "64",
1867			variants:           []string{"android_arm64_armv8-a"},
1868		},
1869		{
1870			dataDeviceBinType:  "64",
1871			depCompileMultilib: "both",
1872			variants:           []string{"android_arm64_armv8-a"},
1873		},
1874		{
1875			dataDeviceBinType:  "64",
1876			depCompileMultilib: "first",
1877			variants:           []string{"android_arm64_armv8-a"},
1878		},
1879		{
1880			dataDeviceBinType:  "64",
1881			depCompileMultilib: "32",
1882			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1883		},
1884		{
1885			dataDeviceBinType:  "prefer32",
1886			depCompileMultilib: "32",
1887			variants:           []string{"android_arm_armv7-a-neon"},
1888		},
1889		{
1890			dataDeviceBinType:  "prefer32",
1891			depCompileMultilib: "both",
1892			variants:           []string{"android_arm_armv7-a-neon"},
1893		},
1894		{
1895			dataDeviceBinType:  "prefer32",
1896			depCompileMultilib: "first",
1897			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1898		},
1899		{
1900			dataDeviceBinType:  "prefer32",
1901			depCompileMultilib: "64",
1902			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1903		},
1904	}
1905
1906	bpTemplate := `
1907		java_test_host {
1908			name: "foo",
1909			srcs: ["test.java"],
1910			data_device_bins_%s: ["bar"],
1911		}
1912
1913		cc_binary {
1914			name: "bar",
1915			compile_multilib: "%s",
1916		}
1917	`
1918
1919	for _, tc := range testCases {
1920		bp := fmt.Sprintf(bpTemplate, tc.dataDeviceBinType, tc.depCompileMultilib)
1921
1922		errorHandler := android.FixtureExpectsNoErrors
1923		if tc.expectedError != "" {
1924			errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(tc.expectedError)
1925		}
1926
1927		testName := fmt.Sprintf(`data_device_bins_%s with compile_multilib:"%s"`, tc.dataDeviceBinType, tc.depCompileMultilib)
1928		t.Run(testName, func(t *testing.T) {
1929			t.Parallel()
1930			ctx := android.GroupFixturePreparers(PrepareForIntegrationTestWithJava).
1931				ExtendWithErrorHandler(errorHandler).
1932				RunTestWithBp(t, bp)
1933			if tc.expectedError != "" {
1934				return
1935			}
1936
1937			buildOS := ctx.Config.BuildOS.String()
1938			fooVariant := ctx.ModuleForTests(t, "foo", buildOS+"_common")
1939			fooMod := fooVariant.Module().(*TestHost)
1940			entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, fooMod)[0]
1941
1942			expectedAutogenConfig := `<option name="push-file" key="bar" value="/data/local/tests/unrestricted/foo/bar" />`
1943			autogen := fooVariant.Rule("autogen")
1944			if !strings.Contains(autogen.Args["extraConfigs"], expectedAutogenConfig) {
1945				t.Errorf("foo extraConfigs %v does not contain %q", autogen.Args["extraConfigs"], expectedAutogenConfig)
1946			}
1947
1948			expectedData := []string{}
1949			for _, variant := range tc.variants {
1950				barVariant := ctx.ModuleForTests(t, "bar", variant)
1951				relocated := barVariant.Output("bar")
1952				expectedInput := fmt.Sprintf("out/soong/.intermediates/bar/%s/unstripped/bar", variant)
1953				android.AssertPathRelativeToTopEquals(t, "relocation input", expectedInput, relocated.Input)
1954
1955				expectedData = append(expectedData, fmt.Sprintf("out/soong/.intermediates/bar/%s/bar:bar", variant))
1956			}
1957
1958			actualData := entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"]
1959			android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_TEST_DATA", ctx.Config, android.SortedUniqueStrings(expectedData), android.SortedUniqueStrings(actualData))
1960		})
1961	}
1962}
1963
1964func TestDeviceBinaryWrapperGeneration(t *testing.T) {
1965	t.Parallel()
1966	// Scenario 1: java_binary has main_class property in its bp
1967	ctx, _ := testJava(t, `
1968		java_binary {
1969			name: "foo",
1970			srcs: ["foo.java"],
1971			main_class: "foo.bar.jb",
1972		}
1973	`)
1974	wrapperPath := fmt.Sprint(ctx.ModuleForTests(t, "foo", "android_common").AllOutputs())
1975	if !strings.Contains(wrapperPath, "foo.sh") {
1976		t.Errorf("wrapper file foo.sh is not generated")
1977	}
1978
1979	// Scenario 2: java_binary has neither wrapper nor main_class, its build
1980	// is expected to be failed.
1981	testJavaError(t, "main_class property is required for device binary if no default wrapper is assigned", `
1982		java_binary {
1983			name: "foo",
1984			srcs: ["foo.java"],
1985		}`)
1986}
1987
1988func TestJavaApiContributionEmptyApiFile(t *testing.T) {
1989	t.Parallel()
1990	android.GroupFixturePreparers(
1991		prepareForJavaTest,
1992		android.FixtureMergeEnv(
1993			map[string]string{
1994				"DISABLE_STUB_VALIDATION": "true",
1995			},
1996		),
1997	).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
1998		"Error: foo has an empty api file.",
1999	)).RunTestWithBp(t, `
2000		java_api_contribution {
2001			name: "foo",
2002		}
2003		java_api_library {
2004			name: "bar",
2005			api_surface: "public",
2006			api_contributions: ["foo"],
2007			stubs_type: "everything",
2008		}
2009	`)
2010}
2011
2012func TestJavaApiLibraryAndProviderLink(t *testing.T) {
2013	t.Parallel()
2014	provider_bp_a := `
2015	java_api_contribution {
2016		name: "foo1",
2017		api_file: "current.txt",
2018		api_surface: "public",
2019	}
2020	`
2021	provider_bp_b := `java_api_contribution {
2022		name: "foo2",
2023		api_file: "current.txt",
2024		api_surface: "public",
2025	}
2026	`
2027	ctx := android.GroupFixturePreparers(
2028		prepareForJavaTest,
2029		android.FixtureMergeMockFs(
2030			map[string][]byte{
2031				"a/Android.bp": []byte(provider_bp_a),
2032				"b/Android.bp": []byte(provider_bp_b),
2033			},
2034		),
2035		android.FixtureMergeEnv(
2036			map[string]string{
2037				"DISABLE_STUB_VALIDATION": "true",
2038			},
2039		),
2040	).RunTestWithBp(t, `
2041		java_api_library {
2042			name: "bar1",
2043			api_surface: "public",
2044			api_contributions: ["foo1"],
2045			stubs_type: "everything",
2046		}
2047
2048		java_api_library {
2049			name: "bar2",
2050			api_surface: "system",
2051			api_contributions: ["foo1", "foo2"],
2052			stubs_type: "everything",
2053		}
2054	`)
2055
2056	testcases := []struct {
2057		moduleName         string
2058		sourceTextFileDirs []string
2059	}{
2060		{
2061			moduleName:         "bar1",
2062			sourceTextFileDirs: []string{"a/current.txt"},
2063		},
2064		{
2065			moduleName:         "bar2",
2066			sourceTextFileDirs: []string{"a/current.txt", "b/current.txt"},
2067		},
2068	}
2069	for _, c := range testcases {
2070		m := ctx.ModuleForTests(t, c.moduleName, "android_common")
2071		manifest := m.Output("metalava.sbox.textproto")
2072		sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, manifest)
2073		manifestCommand := sboxProto.Commands[0].GetCommand()
2074		sourceFilesFlag := "--source-files " + strings.Join(c.sourceTextFileDirs, " ")
2075		android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag)
2076	}
2077}
2078
2079func TestJavaApiLibraryAndDefaultsLink(t *testing.T) {
2080	t.Parallel()
2081	provider_bp_a := `
2082	java_api_contribution {
2083		name: "foo1",
2084		api_file: "current.txt",
2085		api_surface: "public",
2086	}
2087	`
2088	provider_bp_b := `
2089	java_api_contribution {
2090		name: "foo2",
2091		api_file: "current.txt",
2092		api_surface: "public",
2093	}
2094	`
2095	provider_bp_c := `
2096	java_api_contribution {
2097		name: "foo3",
2098		api_file: "system-current.txt",
2099		api_surface: "system",
2100	}
2101	`
2102	provider_bp_d := `
2103	java_api_contribution {
2104		name: "foo4",
2105		api_file: "system-current.txt",
2106		api_surface: "system",
2107	}
2108	`
2109	ctx := android.GroupFixturePreparers(
2110		prepareForJavaTest,
2111		android.FixtureMergeMockFs(
2112			map[string][]byte{
2113				"a/Android.bp": []byte(provider_bp_a),
2114				"b/Android.bp": []byte(provider_bp_b),
2115				"c/Android.bp": []byte(provider_bp_c),
2116				"d/Android.bp": []byte(provider_bp_d),
2117			},
2118		),
2119		android.FixtureMergeEnv(
2120			map[string]string{
2121				"DISABLE_STUB_VALIDATION": "true",
2122			},
2123		),
2124	).RunTestWithBp(t, `
2125		java_defaults {
2126			name: "baz1",
2127			api_surface: "public",
2128			api_contributions: ["foo1", "foo2"],
2129		}
2130
2131		java_defaults {
2132			name: "baz2",
2133			api_surface: "system",
2134			api_contributions: ["foo3"],
2135		}
2136
2137		java_api_library {
2138			name: "bar1",
2139			api_surface: "public",
2140			api_contributions: ["foo1"],
2141			stubs_type: "everything",
2142		}
2143
2144		java_api_library {
2145			name: "bar2",
2146			api_surface: "public",
2147			defaults:["baz1"],
2148			stubs_type: "everything",
2149		}
2150
2151		java_api_library {
2152			name: "bar3",
2153			api_surface: "system",
2154			defaults:["baz1", "baz2"],
2155			api_contributions: ["foo4"],
2156			stubs_type: "everything",
2157		}
2158	`)
2159
2160	testcases := []struct {
2161		moduleName         string
2162		sourceTextFileDirs []string
2163	}{
2164		{
2165			moduleName:         "bar1",
2166			sourceTextFileDirs: []string{"a/current.txt"},
2167		},
2168		{
2169			moduleName:         "bar2",
2170			sourceTextFileDirs: []string{"a/current.txt", "b/current.txt"},
2171		},
2172		{
2173			moduleName: "bar3",
2174			// API text files need to be sorted from the narrower api scope to the wider api scope
2175			sourceTextFileDirs: []string{"a/current.txt", "b/current.txt", "c/system-current.txt", "d/system-current.txt"},
2176		},
2177	}
2178	for _, c := range testcases {
2179		m := ctx.ModuleForTests(t, c.moduleName, "android_common")
2180		manifest := m.Output("metalava.sbox.textproto")
2181		sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, manifest)
2182		manifestCommand := sboxProto.Commands[0].GetCommand()
2183		sourceFilesFlag := "--source-files " + strings.Join(c.sourceTextFileDirs, " ")
2184		android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag)
2185	}
2186}
2187
2188func TestJavaApiLibraryJarGeneration(t *testing.T) {
2189	t.Parallel()
2190	provider_bp_a := `
2191	java_api_contribution {
2192		name: "foo1",
2193		api_file: "current.txt",
2194		api_surface: "public",
2195	}
2196	`
2197	provider_bp_b := `
2198	java_api_contribution {
2199		name: "foo2",
2200		api_file: "current.txt",
2201		api_surface: "public",
2202	}
2203	`
2204	ctx := android.GroupFixturePreparers(
2205		prepareForJavaTest,
2206		android.FixtureMergeMockFs(
2207			map[string][]byte{
2208				"a/Android.bp": []byte(provider_bp_a),
2209				"b/Android.bp": []byte(provider_bp_b),
2210			},
2211		),
2212		android.FixtureMergeEnv(
2213			map[string]string{
2214				"DISABLE_STUB_VALIDATION": "true",
2215			},
2216		),
2217	).RunTestWithBp(t, `
2218		java_api_library {
2219			name: "bar1",
2220			api_surface: "public",
2221			api_contributions: ["foo1"],
2222			stubs_type: "everything",
2223		}
2224
2225		java_api_library {
2226			name: "bar2",
2227			api_surface: "system",
2228			api_contributions: ["foo1", "foo2"],
2229			stubs_type: "everything",
2230		}
2231	`)
2232
2233	testcases := []struct {
2234		moduleName    string
2235		outputJarName string
2236	}{
2237		{
2238			moduleName:    "bar1",
2239			outputJarName: "bar1/bar1.jar",
2240		},
2241		{
2242			moduleName:    "bar2",
2243			outputJarName: "bar2/bar2.jar",
2244		},
2245	}
2246	for _, c := range testcases {
2247		m := ctx.ModuleForTests(t, c.moduleName, "android_common")
2248		outputs := fmt.Sprint(m.AllOutputs())
2249		if !strings.Contains(outputs, c.outputJarName) {
2250			t.Errorf("Module output does not contain expected jar %s", c.outputJarName)
2251		}
2252	}
2253}
2254
2255func TestJavaApiLibraryLibsLink(t *testing.T) {
2256	t.Parallel()
2257	provider_bp_a := `
2258	java_api_contribution {
2259		name: "foo1",
2260		api_file: "current.txt",
2261		api_surface: "public",
2262	}
2263	`
2264	provider_bp_b := `
2265	java_api_contribution {
2266		name: "foo2",
2267		api_file: "current.txt",
2268		api_surface: "public",
2269	}
2270	`
2271	lib_bp_a := `
2272	java_library {
2273		name: "lib1",
2274		srcs: ["Lib.java"],
2275	}
2276	`
2277	lib_bp_b := `
2278	java_library {
2279		name: "lib2",
2280		srcs: ["Lib.java"],
2281	}
2282	`
2283
2284	ctx := android.GroupFixturePreparers(
2285		prepareForJavaTest,
2286		android.FixtureMergeMockFs(
2287			map[string][]byte{
2288				"a/Android.bp": []byte(provider_bp_a),
2289				"b/Android.bp": []byte(provider_bp_b),
2290				"c/Android.bp": []byte(lib_bp_a),
2291				"c/Lib.java":   {},
2292				"d/Android.bp": []byte(lib_bp_b),
2293				"d/Lib.java":   {},
2294			},
2295		),
2296		android.FixtureMergeEnv(
2297			map[string]string{
2298				"DISABLE_STUB_VALIDATION": "true",
2299			},
2300		),
2301	).RunTestWithBp(t, `
2302		java_api_library {
2303			name: "bar1",
2304			api_surface: "public",
2305			api_contributions: ["foo1"],
2306			libs: ["lib1"],
2307			stubs_type: "everything",
2308		}
2309
2310		java_api_library {
2311			name: "bar2",
2312			api_surface: "system",
2313			api_contributions: ["foo1", "foo2"],
2314			libs: ["lib1", "lib2", "bar1"],
2315			stubs_type: "everything",
2316		}
2317	`)
2318
2319	testcases := []struct {
2320		moduleName        string
2321		classPathJarNames []string
2322	}{
2323		{
2324			moduleName:        "bar1",
2325			classPathJarNames: []string{"lib1.jar"},
2326		},
2327		{
2328			moduleName:        "bar2",
2329			classPathJarNames: []string{"lib1.jar", "lib2.jar", "bar1/bar1.jar"},
2330		},
2331	}
2332	for _, c := range testcases {
2333		m := ctx.ModuleForTests(t, c.moduleName, "android_common")
2334		javacRules := m.Rule("javac")
2335		classPathArgs := javacRules.Args["classpath"]
2336		for _, jarName := range c.classPathJarNames {
2337			if !strings.Contains(classPathArgs, jarName) {
2338				t.Errorf("Module output does not contain expected jar %s", jarName)
2339			}
2340		}
2341	}
2342}
2343
2344func TestJavaApiLibraryStaticLibsLink(t *testing.T) {
2345	t.Parallel()
2346	provider_bp_a := `
2347	java_api_contribution {
2348		name: "foo1",
2349		api_file: "current.txt",
2350		api_surface: "public",
2351	}
2352	`
2353	provider_bp_b := `
2354	java_api_contribution {
2355		name: "foo2",
2356		api_file: "current.txt",
2357		api_surface: "public",
2358	}
2359	`
2360	lib_bp_a := `
2361	java_library {
2362		name: "lib1",
2363		srcs: ["Lib.java"],
2364	}
2365	`
2366	lib_bp_b := `
2367	java_library {
2368		name: "lib2",
2369		srcs: ["Lib.java"],
2370	}
2371	`
2372
2373	ctx := android.GroupFixturePreparers(
2374		prepareForJavaTest,
2375		android.FixtureMergeMockFs(
2376			map[string][]byte{
2377				"a/Android.bp": []byte(provider_bp_a),
2378				"b/Android.bp": []byte(provider_bp_b),
2379				"c/Android.bp": []byte(lib_bp_a),
2380				"c/Lib.java":   {},
2381				"d/Android.bp": []byte(lib_bp_b),
2382				"d/Lib.java":   {},
2383			},
2384		),
2385		android.FixtureMergeEnv(
2386			map[string]string{
2387				"DISABLE_STUB_VALIDATION": "true",
2388			},
2389		),
2390	).RunTestWithBp(t, `
2391		java_api_library {
2392			name: "bar1",
2393			api_surface: "public",
2394			api_contributions: ["foo1"],
2395			static_libs: ["lib1"],
2396			stubs_type: "everything",
2397		}
2398
2399		java_api_library {
2400			name: "bar2",
2401			api_surface: "system",
2402			api_contributions: ["foo1", "foo2"],
2403			static_libs: ["lib1", "lib2", "bar1"],
2404			stubs_type: "everything",
2405		}
2406	`)
2407
2408	testcases := []struct {
2409		moduleName        string
2410		staticLibJarNames []string
2411	}{
2412		{
2413			moduleName:        "bar1",
2414			staticLibJarNames: []string{"lib1.jar"},
2415		},
2416		{
2417			moduleName:        "bar2",
2418			staticLibJarNames: []string{"lib1.jar", "lib2.jar", "bar1/bar1.jar"},
2419		},
2420	}
2421	for _, c := range testcases {
2422		m := ctx.ModuleForTests(t, c.moduleName, "android_common")
2423		mergeZipsCommand := m.Rule("merge_zips").RuleParams.Command
2424		for _, jarName := range c.staticLibJarNames {
2425			if !strings.Contains(mergeZipsCommand, jarName) {
2426				t.Errorf("merge_zips command does not contain expected jar %s", jarName)
2427			}
2428		}
2429	}
2430}
2431
2432func TestTransitiveSrcFiles(t *testing.T) {
2433	t.Parallel()
2434	ctx, _ := testJava(t, `
2435		java_library {
2436			name: "a",
2437			srcs: ["a.java"],
2438		}
2439		java_library {
2440			name: "b",
2441			srcs: ["b.java"],
2442		}
2443		java_library {
2444			name: "c",
2445			srcs: ["c.java"],
2446			libs: ["a"],
2447			static_libs: ["b"],
2448		}
2449	`)
2450	c := ctx.ModuleForTests(t, "c", "android_common").Module()
2451	javaInfo, _ := android.OtherModuleProvider(ctx, c, JavaInfoProvider)
2452	transitiveSrcFiles := android.Paths(javaInfo.TransitiveSrcFiles.ToList())
2453	android.AssertArrayString(t, "unexpected jar deps", []string{"b.java", "c.java"}, transitiveSrcFiles.Strings())
2454}
2455
2456func TestTradefedOptions(t *testing.T) {
2457	t.Parallel()
2458	result := PrepareForTestWithJavaBuildComponents.RunTestWithBp(t, `
2459java_test_host {
2460	name: "foo",
2461	test_options: {
2462		tradefed_options: [
2463			{
2464				name: "exclude-path",
2465				value: "org/apache"
2466			}
2467		]
2468	}
2469}
2470`)
2471
2472	buildOS := result.Config.BuildOS.String()
2473	args := result.ModuleForTests(t, "foo", buildOS+"_common").
2474		Output("out/soong/.intermediates/foo/" + buildOS + "_common/foo.config").Args
2475	expected := proptools.NinjaAndShellEscape("<option name=\"exclude-path\" value=\"org/apache\" />")
2476	if args["extraConfigs"] != expected {
2477		t.Errorf("Expected args[\"extraConfigs\"] to equal %q, was %q", expected, args["extraConfigs"])
2478	}
2479}
2480
2481func TestTestRunnerOptions(t *testing.T) {
2482	t.Parallel()
2483	result := PrepareForTestWithJavaBuildComponents.RunTestWithBp(t, `
2484java_test_host {
2485	name: "foo",
2486	test_options: {
2487		test_runner_options: [
2488			{
2489				name: "test-timeout",
2490				value: "10m"
2491			}
2492		]
2493	}
2494}
2495`)
2496
2497	buildOS := result.Config.BuildOS.String()
2498	args := result.ModuleForTests(t, "foo", buildOS+"_common").
2499		Output("out/soong/.intermediates/foo/" + buildOS + "_common/foo.config").Args
2500	expected := proptools.NinjaAndShellEscape("<option name=\"test-timeout\" value=\"10m\" />\\n        ")
2501	if args["extraTestRunnerConfigs"] != expected {
2502		t.Errorf("Expected args[\"extraTestRunnerConfigs\"] to equal %q, was %q", expected, args["extraTestRunnerConfigs"])
2503	}
2504}
2505
2506func TestJavaLibraryWithResourcesStem(t *testing.T) {
2507	t.Parallel()
2508	ctx, _ := testJavaWithFS(t, `
2509    java_library {
2510        name: "foo",
2511        java_resource_dirs: ["test-jar"],
2512        stem: "test",
2513    }
2514    `,
2515		map[string][]byte{
2516			"test-jar/test/resource.txt": nil,
2517		})
2518
2519	m := ctx.ModuleForTests(t, "foo", "android_common")
2520	outputs := fmt.Sprint(m.AllOutputs())
2521	if !strings.Contains(outputs, "test.jar") {
2522		t.Errorf("Module output does not contain expected jar %s", "test.jar")
2523	}
2524}
2525
2526func TestHeadersOnly(t *testing.T) {
2527	t.Parallel()
2528	ctx, _ := testJava(t, `
2529		java_library {
2530			name: "foo",
2531			srcs: ["a.java"],
2532			headers_only: true,
2533		}
2534	`)
2535
2536	turbine := ctx.ModuleForTests(t, "foo", "android_common").Rule("turbine")
2537	if len(turbine.Inputs) != 1 || turbine.Inputs[0].String() != "a.java" {
2538		t.Errorf(`foo inputs %v != ["a.java"]`, turbine.Inputs)
2539	}
2540
2541	javac := ctx.ModuleForTests(t, "foo", "android_common").MaybeRule("javac")
2542	android.AssertDeepEquals(t, "javac rule", nil, javac.Rule)
2543}
2544
2545func TestJavaApiContributionImport(t *testing.T) {
2546	t.Parallel()
2547	ctx := android.GroupFixturePreparers(
2548		prepareForJavaTest,
2549		android.FixtureMergeEnv(
2550			map[string]string{
2551				"DISABLE_STUB_VALIDATION": "true",
2552			},
2553		),
2554	).RunTestWithBp(t, `
2555		java_api_library {
2556			name: "foo",
2557			api_contributions: ["bar"],
2558			stubs_type: "everything",
2559		}
2560		java_api_contribution_import {
2561			name: "bar",
2562			api_file: "current.txt",
2563			api_surface: "public",
2564		}
2565	`)
2566	m := ctx.ModuleForTests(t, "foo", "android_common")
2567	manifest := m.Output("metalava.sbox.textproto")
2568	sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, manifest)
2569	manifestCommand := sboxProto.Commands[0].GetCommand()
2570	sourceFilesFlag := "--source-files current.txt"
2571	android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag)
2572}
2573
2574func TestJavaApiLibraryApiFilesSorting(t *testing.T) {
2575	t.Parallel()
2576	ctx, _ := testJava(t, `
2577		java_api_library {
2578			name: "foo",
2579			api_contributions: [
2580				"system-server-api-stubs-docs-non-updatable.api.contribution",
2581				"test-api-stubs-docs-non-updatable.api.contribution",
2582				"system-api-stubs-docs-non-updatable.api.contribution",
2583				"module-lib-api-stubs-docs-non-updatable.api.contribution",
2584				"api-stubs-docs-non-updatable.api.contribution",
2585			],
2586			stubs_type: "everything",
2587		}
2588	`)
2589	m := ctx.ModuleForTests(t, "foo", "android_common")
2590	manifest := m.Output("metalava.sbox.textproto")
2591	sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx, manifest)
2592	manifestCommand := sboxProto.Commands[0].GetCommand()
2593
2594	// Api files are sorted from the narrowest api scope to the widest api scope.
2595	// test api and module lib api surface do not have subset/superset relationship,
2596	// but they will never be passed as inputs at the same time.
2597	sourceFilesFlag := "--source-files default/java/api/current.txt " +
2598		"default/java/api/system-current.txt default/java/api/test-current.txt " +
2599		"default/java/api/module-lib-current.txt default/java/api/system-server-current.txt"
2600	android.AssertStringDoesContain(t, "source text files not in api scope order", manifestCommand, sourceFilesFlag)
2601}
2602
2603func TestSdkLibraryProvidesSystemModulesToApiLibrary(t *testing.T) {
2604	t.Parallel()
2605	result := android.GroupFixturePreparers(
2606		prepareForJavaTest,
2607		PrepareForTestWithJavaSdkLibraryFiles,
2608		FixtureWithLastReleaseApis("foo"),
2609		android.FixtureMergeMockFs(
2610			map[string][]byte{
2611				"A.java": nil,
2612			},
2613		),
2614	).RunTestWithBp(t, `
2615		java_library {
2616			name: "bar",
2617			srcs: ["a.java"],
2618		}
2619		java_system_modules {
2620			name: "baz",
2621			libs: ["bar"],
2622		}
2623		java_sdk_library {
2624			name: "foo",
2625			srcs: ["A.java"],
2626			system_modules: "baz",
2627		}
2628	`)
2629
2630	checkBootClasspathForLibWithSystemModule(t, result.TestContext, apiScopePublic.apiLibraryModuleName("foo"), "/bar.jar")
2631}
2632
2633func TestApiLibraryDroidstubsDependency(t *testing.T) {
2634	t.Parallel()
2635	result := android.GroupFixturePreparers(
2636		prepareForJavaTest,
2637		PrepareForTestWithJavaSdkLibraryFiles,
2638		FixtureWithLastReleaseApis("foo"),
2639		android.FixtureMergeMockFs(
2640			map[string][]byte{
2641				"A.java": nil,
2642			},
2643		),
2644	).RunTestWithBp(t, `
2645		java_api_library {
2646			name: "foo",
2647			api_contributions: [
2648				"api-stubs-docs-non-updatable.api.contribution",
2649			],
2650			enable_validation: true,
2651			stubs_type: "everything",
2652		}
2653		java_api_library {
2654			name: "bar",
2655			api_contributions: [
2656				"api-stubs-docs-non-updatable.api.contribution",
2657			],
2658			enable_validation: false,
2659			stubs_type: "everything",
2660		}
2661	`)
2662
2663	currentApiTimestampPath := "api-stubs-docs-non-updatable/android_common/everything/check_current_api.timestamp"
2664	foo := result.ModuleForTests(t, "foo", "android_common").Module().(*ApiLibrary)
2665	fooValidationPathsString := strings.Join(foo.validationPaths.Strings(), " ")
2666	bar := result.ModuleForTests(t, "bar", "android_common").Module().(*ApiLibrary)
2667	barValidationPathsString := strings.Join(bar.validationPaths.Strings(), " ")
2668	android.AssertStringDoesContain(t,
2669		"Module expected to have validation",
2670		fooValidationPathsString,
2671		currentApiTimestampPath,
2672	)
2673	android.AssertStringDoesNotContain(t,
2674		"Module expected to not have validation",
2675		barValidationPathsString,
2676		currentApiTimestampPath,
2677	)
2678}
2679
2680func TestDisableFromTextStubForCoverageBuild(t *testing.T) {
2681	t.Parallel()
2682	result := android.GroupFixturePreparers(
2683		prepareForJavaTest,
2684		PrepareForTestWithJavaSdkLibraryFiles,
2685		PrepareForTestWithJacocoInstrumentation,
2686		FixtureWithLastReleaseApis("foo"),
2687		android.FixtureModifyConfig(func(config android.Config) {
2688			config.SetBuildFromTextStub(true)
2689		}),
2690		android.FixtureModifyEnv(func(env map[string]string) {
2691			env["EMMA_INSTRUMENT"] = "true"
2692		}),
2693	).RunTestWithBp(t, `
2694		java_sdk_library {
2695			name: "foo",
2696			srcs: ["A.java"],
2697		}
2698	`)
2699	android.AssertBoolEquals(t, "stub module expected to depend on from-source stub",
2700		true, CheckModuleHasDependency(t, result.TestContext,
2701			apiScopePublic.stubsLibraryModuleName("foo"), "android_common",
2702			apiScopePublic.sourceStubsLibraryModuleName("foo")))
2703
2704	android.AssertBoolEquals(t, "stub module expected to not depend on from-text stub",
2705		false, CheckModuleHasDependency(t, result.TestContext,
2706			apiScopePublic.stubsLibraryModuleName("foo"), "android_common",
2707			apiScopePublic.apiLibraryModuleName("foo")))
2708}
2709
2710func TestMultiplePrebuilts(t *testing.T) {
2711	t.Parallel()
2712	bp := `
2713		// an rdep
2714		java_library {
2715			name: "foo",
2716			libs: ["bar"],
2717		}
2718
2719		// multiple variations of dep
2720		// source
2721		java_library {
2722			name: "bar",
2723			srcs: ["bar.java"],
2724		}
2725		// prebuilt "v1"
2726		java_import {
2727			name: "bar",
2728			jars: ["bar.jar"],
2729		}
2730		// prebuilt "v2"
2731		java_import {
2732			name: "bar.v2",
2733			source_module_name: "bar",
2734			jars: ["bar.v1.jar"],
2735		}
2736
2737		// selectors
2738		apex_contributions {
2739			name: "myapex_contributions",
2740			contents: ["%v"],
2741		}
2742	`
2743	hasDep := func(ctx *android.TestResult, m android.Module, wantDep android.Module) bool {
2744		t.Helper()
2745		var found bool
2746		ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
2747			if dep == wantDep {
2748				found = true
2749			}
2750		})
2751		return found
2752	}
2753
2754	hasFileWithStem := func(m android.TestingModule, stem string) bool {
2755		t.Helper()
2756		for _, o := range m.AllOutputs() {
2757			_, file := filepath.Split(o)
2758			if file == stem+".jar" {
2759				return true
2760			}
2761		}
2762		return false
2763	}
2764
2765	testCases := []struct {
2766		desc                   string
2767		selectedDependencyName string
2768		expectedDependencyName string
2769	}{
2770		{
2771			desc:                   "Source library is selected using apex_contributions",
2772			selectedDependencyName: "bar",
2773			expectedDependencyName: "bar",
2774		},
2775		{
2776			desc:                   "Prebuilt library v1 is selected using apex_contributions",
2777			selectedDependencyName: "prebuilt_bar",
2778			expectedDependencyName: "prebuilt_bar",
2779		},
2780		{
2781			desc:                   "Prebuilt library v2 is selected using apex_contributions",
2782			selectedDependencyName: "prebuilt_bar.v2",
2783			expectedDependencyName: "prebuilt_bar.v2",
2784		},
2785	}
2786
2787	for _, tc := range testCases {
2788		ctx := android.GroupFixturePreparers(
2789			prepareForJavaTest,
2790			android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", "myapex_contributions"),
2791		).RunTestWithBp(t, fmt.Sprintf(bp, tc.selectedDependencyName))
2792
2793		// check that rdep gets the correct variation of dep
2794		foo := ctx.ModuleForTests(t, "foo", "android_common")
2795		expectedDependency := ctx.ModuleForTests(t, tc.expectedDependencyName, "android_common")
2796		android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from %s to %s\n", foo.Module().Name(), tc.expectedDependencyName), true, hasDep(ctx, foo.Module(), expectedDependency.Module()))
2797
2798		// check that output file of dep is always bar.jar
2799		// The filename should be agnostic to source/prebuilt/prebuilt_version
2800		android.AssertBoolEquals(t, fmt.Sprintf("could not find bar.jar in outputs of %s. All Outputs %v\n", tc.expectedDependencyName, expectedDependency.AllOutputs()), true, hasFileWithStem(expectedDependency, "bar"))
2801
2802		// check LOCAL_MODULE of the selected module name
2803		// the prebuilt should have the same LOCAL_MODULE when exported to make
2804		entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, expectedDependency.Module())[0]
2805		android.AssertStringEquals(t, "unexpected LOCAL_MODULE", "bar", entries.EntryMap["LOCAL_MODULE"][0])
2806	}
2807}
2808
2809func TestMultiplePlatformCompatConfigPrebuilts(t *testing.T) {
2810	t.Parallel()
2811	bp := `
2812		// multiple variations of platform_compat_config
2813		// source
2814		platform_compat_config {
2815			name: "myconfig",
2816		}
2817		// prebuilt "v1"
2818		prebuilt_platform_compat_config {
2819			name: "myconfig",
2820			metadata: "myconfig.xml",
2821		}
2822		// prebuilt "v2"
2823		prebuilt_platform_compat_config {
2824			name: "myconfig.v2",
2825			source_module_name: "myconfig", // without source_module_name, the singleton will merge two .xml files
2826			metadata: "myconfig.v2.xml",
2827		}
2828
2829		// selectors
2830		apex_contributions {
2831			name: "myapex_contributions",
2832			contents: ["%v"],
2833		}
2834	`
2835	testCases := []struct {
2836		desc                            string
2837		selectedDependencyName          string
2838		expectedPlatformCompatConfigXml string
2839	}{
2840		{
2841			desc:                            "Source platform_compat_config is selected using apex_contributions",
2842			selectedDependencyName:          "myconfig",
2843			expectedPlatformCompatConfigXml: "out/soong/.intermediates/myconfig/android_common/myconfig_meta.xml",
2844		},
2845		{
2846			desc:                            "Prebuilt platform_compat_config v1 is selected using apex_contributions",
2847			selectedDependencyName:          "prebuilt_myconfig",
2848			expectedPlatformCompatConfigXml: "myconfig.xml",
2849		},
2850		{
2851			desc:                            "Prebuilt platform_compat_config v2 is selected using apex_contributions",
2852			selectedDependencyName:          "prebuilt_myconfig.v2",
2853			expectedPlatformCompatConfigXml: "myconfig.v2.xml",
2854		},
2855	}
2856
2857	for _, tc := range testCases {
2858		ctx := android.GroupFixturePreparers(
2859			prepareForJavaTest,
2860			PrepareForTestWithPlatformCompatConfig,
2861			android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", "myapex_contributions"),
2862		).RunTestWithBp(t, fmt.Sprintf(bp, tc.selectedDependencyName))
2863
2864		mergedGlobalConfig := ctx.SingletonForTests(t, "platform_compat_config_singleton").Output("compat_config/merged_compat_config.xml")
2865		android.AssertIntEquals(t, "The merged compat config file should only have a single dependency", 1, len(mergedGlobalConfig.Implicits))
2866		android.AssertStringEquals(t, "The merged compat config file is missing the appropriate platform compat config", mergedGlobalConfig.Implicits[0].String(), tc.expectedPlatformCompatConfigXml)
2867	}
2868}
2869
2870func TestApiLibraryAconfigDeclarations(t *testing.T) {
2871	t.Parallel()
2872	result := android.GroupFixturePreparers(
2873		prepareForJavaTest,
2874		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
2875		}),
2876		android.FixtureMergeMockFs(map[string][]byte{
2877			"a/A.java":      nil,
2878			"a/current.txt": nil,
2879			"a/removed.txt": nil,
2880		}),
2881	).RunTestWithBp(t, `
2882	aconfig_declarations {
2883		name: "bar",
2884		package: "com.example.package",
2885		container: "com.android.foo",
2886		srcs: [
2887			"bar.aconfig",
2888		],
2889	}
2890	java_api_contribution {
2891		name: "baz",
2892		api_file: "a/current.txt",
2893		api_surface: "public",
2894	}
2895	java_api_library {
2896		name: "foo",
2897		api_surface: "public",
2898		api_contributions: [
2899			"baz",
2900		],
2901		aconfig_declarations: [
2902			"bar",
2903		],
2904		stubs_type: "exportable",
2905		enable_validation: false,
2906	}
2907	`)
2908
2909	// Check if java_api_library depends on aconfig_declarations
2910	android.AssertBoolEquals(t, "foo expected to depend on bar",
2911		CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "bar"), true)
2912
2913	m := result.ModuleForTests(t, "foo", "android_common")
2914	android.AssertStringDoesContain(t, "foo generates revert annotations file",
2915		strings.Join(m.AllOutputs(), ""), "flags-config-exportable.xml")
2916
2917	// revert-annotations.txt passed to exportable stubs generation metalava command
2918	manifest := m.Output("metalava.sbox.textproto")
2919	cmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, manifest).Commands[0].Command)
2920	android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "flags-config-exportable.xml")
2921}
2922
2923func TestTestOnly(t *testing.T) {
2924	t.Parallel()
2925	ctx := android.GroupFixturePreparers(
2926		prepareForJavaTest,
2927	).RunTestWithBp(t, `
2928                // These should be test-only
2929		java_library {
2930			name: "lib1-test-only",
2931                        srcs: ["a.java"],
2932                        test_only: true,
2933		}
2934                java_test {
2935                        name: "java-test",
2936                }
2937                java_test_host {
2938                        name: "java-test-host",
2939                }
2940                java_test_helper_library {
2941                        name: "helper-library",
2942                }
2943                java_binary {
2944                        name: "java-data-binary",
2945			srcs: ["foo.java"],
2946			main_class: "foo.bar.jb",
2947                        test_only: true,
2948                }
2949
2950                // These are NOT
2951		java_library {
2952			name: "lib2-app",
2953                        srcs: ["b.java"],
2954		}
2955		java_import {
2956			name: "bar",
2957			jars: ["bar.jar"],
2958		}
2959                java_binary {
2960                        name: "java-binary",
2961			srcs: ["foo.java"],
2962			main_class: "foo.bar.jb",
2963                }
2964	`)
2965
2966	expectedTestOnlyModules := []string{
2967		"lib1-test-only",
2968		"java-test",
2969		"java-test-host",
2970		"helper-library",
2971		"java-data-binary",
2972	}
2973	expectedTopLevelTests := []string{
2974		"java-test",
2975		"java-test-host",
2976	}
2977	assertTestOnlyAndTopLevel(t, ctx, expectedTestOnlyModules, expectedTopLevelTests)
2978}
2979
2980// Don't allow setting test-only on things that are always tests or never tests.
2981func TestInvalidTestOnlyTargets(t *testing.T) {
2982	t.Parallel()
2983	testCases := []string{
2984		` java_test {  name: "java-test", test_only: true, srcs: ["foo.java"],  } `,
2985		` java_test_host {  name: "java-test-host", test_only: true, srcs: ["foo.java"],  } `,
2986		` java_test_import {  name: "java-test-import", test_only: true, } `,
2987		` java_api_library {  name: "java-api-library", test_only: true, } `,
2988		` java_test_helper_library { name: "test-help-lib", test_only: true, } `,
2989		` java_defaults { name: "java-defaults", test_only: true, } `,
2990	}
2991
2992	for i, bp := range testCases {
2993		android.GroupFixturePreparers(prepareForJavaTest).
2994			ExtendWithErrorHandler(
2995				expectOneError("unrecognized property \"test_only\"",
2996					fmt.Sprintf("testcase: %d", i))).
2997			RunTestWithBp(t, bp)
2998	}
2999}
3000
3001// Expect exactly one that matches 'expected'.
3002// Append 'msg' to the Errorf that printed.
3003func expectOneError(expected string, msg string) android.FixtureErrorHandler {
3004	return android.FixtureCustomErrorHandler(func(t *testing.T, result *android.TestResult) {
3005		t.Helper()
3006		if len(result.Errs) != 1 {
3007			t.Errorf("Expected exactly one error, but found: %d when  setting test_only on: %s", len(result.Errs), msg)
3008			return
3009		}
3010		actualErrMsg := result.Errs[0].Error()
3011		if !strings.Contains(actualErrMsg, expected) {
3012			t.Errorf("Different error than expected.  Received: [%v] on %s expected: %s", actualErrMsg, msg, expected)
3013		}
3014	})
3015}
3016
3017func TestJavaLibHostWithStem(t *testing.T) {
3018	t.Parallel()
3019	ctx, _ := testJava(t, `
3020		java_library_host {
3021			name: "foo",
3022			srcs: ["a.java"],
3023			stem: "foo-new",
3024		}
3025	`)
3026
3027	buildOS := ctx.Config().BuildOS.String()
3028	foo := ctx.ModuleForTests(t, "foo", buildOS+"_common")
3029
3030	outputs := fmt.Sprint(foo.AllOutputs())
3031	if !strings.Contains(outputs, "foo-new.jar") {
3032		t.Errorf("Module output does not contain expected jar %s", "foo-new.jar")
3033	}
3034}
3035
3036func TestJavaLibWithStem(t *testing.T) {
3037	t.Parallel()
3038	ctx, _ := testJava(t, `
3039		java_library {
3040			name: "foo",
3041			srcs: ["a.java"],
3042			stem: "foo-new",
3043		}
3044	`)
3045
3046	foo := ctx.ModuleForTests(t, "foo", "android_common")
3047
3048	outputs := fmt.Sprint(foo.AllOutputs())
3049	if !strings.Contains(outputs, "foo-new.jar") {
3050		t.Errorf("Module output does not contain expected jar %s", "foo-new.jar")
3051	}
3052}
3053
3054func TestJavaLibraryOutputFilesRel(t *testing.T) {
3055	t.Parallel()
3056	result := android.GroupFixturePreparers(
3057		PrepareForTestWithJavaDefaultModules,
3058	).RunTestWithBp(t, `
3059		java_library {
3060			name: "foo",
3061			srcs: ["a.java"],
3062		}
3063
3064		java_import {
3065			name: "bar",
3066			jars: ["bar.aar"],
3067
3068		}
3069
3070		java_import {
3071			name: "baz",
3072			jars: ["baz.aar"],
3073			static_libs: ["bar"],
3074		}
3075	`)
3076
3077	foo := result.ModuleForTests(t, "foo", "android_common")
3078	bar := result.ModuleForTests(t, "bar", "android_common")
3079	baz := result.ModuleForTests(t, "baz", "android_common")
3080
3081	fooOutputPaths := foo.OutputFiles(result.TestContext, t, "")
3082	barOutputPaths := bar.OutputFiles(result.TestContext, t, "")
3083	bazOutputPaths := baz.OutputFiles(result.TestContext, t, "")
3084
3085	android.AssertPathsRelativeToTopEquals(t, "foo output path",
3086		[]string{"out/soong/.intermediates/foo/android_common/javac/foo.jar"}, fooOutputPaths)
3087	android.AssertPathsRelativeToTopEquals(t, "bar output path",
3088		[]string{"out/soong/.intermediates/bar/android_common/combined/bar.jar"}, barOutputPaths)
3089	android.AssertPathsRelativeToTopEquals(t, "baz output path",
3090		[]string{"out/soong/.intermediates/baz/android_common/combined/baz.jar"}, bazOutputPaths)
3091
3092	android.AssertStringEquals(t, "foo relative output path",
3093		"foo.jar", fooOutputPaths[0].Rel())
3094	android.AssertStringEquals(t, "bar relative output path",
3095		"bar.jar", barOutputPaths[0].Rel())
3096	android.AssertStringEquals(t, "baz relative output path",
3097		"baz.jar", bazOutputPaths[0].Rel())
3098}
3099
3100func TestCoverage(t *testing.T) {
3101	t.Parallel()
3102	result := android.GroupFixturePreparers(
3103		PrepareForTestWithJavaDefaultModules,
3104		prepareForTestWithFrameworkJacocoInstrumentation,
3105	).RunTestWithBp(t, `
3106		android_app {
3107			name: "foo",
3108			srcs: ["foo.java"],
3109			static_libs: ["android.car"],
3110			platform_apis: true,
3111		}
3112
3113		// A library in InstrumentFrameworkModules
3114		java_library {
3115			name: "android.car",
3116			srcs: ["android.car.java"],
3117			installable: true,
3118		}
3119	`)
3120
3121	foo := result.ModuleForTests(t, "foo", "android_common")
3122	androidCar := result.ModuleForTests(t, "android.car", "android_common")
3123
3124	fooJacoco := foo.Rule("jacoco")
3125	fooCombine := foo.Description("for javac")
3126
3127	androidCarJacoco := androidCar.Rule("jacoco")
3128	androidCarJavac := androidCar.Rule("javac")
3129
3130	android.AssertStringEquals(t, "foo instrumentation rule inputs", fooJacoco.Input.String(), fooCombine.Output.String())
3131	android.AssertStringEquals(t, "android.car instrumentation rule inputs", androidCarJacoco.Input.String(), androidCarJavac.Output.String())
3132
3133	// The input to instrumentation for the `foo` app contains the non-instrumented android.car classes.
3134	android.AssertStringListContains(t, "foo combined inputs", fooCombine.Inputs.Strings(), androidCarJavac.Output.String())
3135	android.AssertStringListDoesNotContain(t, "foo combined inputs", fooCombine.Inputs.Strings(), androidCarJacoco.Output.String())
3136}
3137
3138func assertTestOnlyAndTopLevel(t *testing.T, ctx *android.TestResult, expectedTestOnly []string, expectedTopLevel []string) {
3139	t.Helper()
3140	actualTrueModules := []string{}
3141	actualTopLevelTests := []string{}
3142	addActuals := func(m blueprint.Module, key blueprint.ProviderKey[android.TestModuleInformation]) {
3143		if provider, ok := android.OtherModuleProvider(ctx.TestContext.OtherModuleProviderAdaptor(), m, key); ok {
3144			if provider.TestOnly {
3145				actualTrueModules = append(actualTrueModules, m.Name())
3146			}
3147			if provider.TopLevelTarget {
3148				actualTopLevelTests = append(actualTopLevelTests, m.Name())
3149			}
3150		}
3151	}
3152
3153	ctx.VisitAllModules(func(m blueprint.Module) {
3154		addActuals(m, android.TestOnlyProviderKey)
3155
3156	})
3157
3158	notEqual, left, right := android.ListSetDifference(expectedTestOnly, actualTrueModules)
3159	if notEqual {
3160		t.Errorf("test-only: Expected but not found: %v, Found but not expected: %v", left, right)
3161	}
3162
3163	notEqual, left, right = android.ListSetDifference(expectedTopLevel, actualTopLevelTests)
3164	if notEqual {
3165		t.Errorf("top-level: Expected but not found: %v, Found but not expected: %v", left, right)
3166	}
3167}
3168
3169// Test that a dependency edge is created to the matching variant of a native library listed in `jni_libs` of java_binary
3170func TestNativeRequiredDepOfJavaBinary(t *testing.T) {
3171	t.Parallel()
3172	findDepsOfModule := func(ctx *android.TestContext, module android.Module, depName string) []blueprint.Module {
3173		var ret []blueprint.Module
3174		ctx.VisitDirectDeps(module, func(dep blueprint.Module) {
3175			if dep.Name() == depName {
3176				ret = append(ret, dep)
3177			}
3178		})
3179		return ret
3180	}
3181
3182	bp := cc.GatherRequiredDepsForTest(android.Android) + `
3183java_binary {
3184	name: "myjavabin",
3185	main_class: "com.android.MyJava",
3186	jni_libs: ["mynativelib"],
3187}
3188cc_library_shared {
3189	name: "mynativelib",
3190}
3191`
3192	res, _ := testJava(t, bp)
3193	deps := findDepsOfModule(res, res.ModuleForTests(t, "myjavabin", "android_common").Module(), "mynativelib")
3194	android.AssertIntEquals(t, "Create a dep on the first variant", 1, len(deps))
3195}
3196
3197func TestBootJarNotInUsesLibs(t *testing.T) {
3198	t.Parallel()
3199	result := android.GroupFixturePreparers(
3200		PrepareForTestWithJavaDefaultModules,
3201		PrepareForTestWithJavaSdkLibraryFiles,
3202		FixtureWithLastReleaseApis("mysdklibrary", "myothersdklibrary"),
3203		FixtureConfigureApexBootJars("myapex:mysdklibrary"),
3204	).RunTestWithBp(t, `
3205		bootclasspath_fragment {
3206			name: "myfragment",
3207			contents: ["mysdklibrary"],
3208			hidden_api: {
3209				split_packages: ["*"],
3210			},
3211		}
3212
3213		java_sdk_library {
3214			name: "mysdklibrary",
3215			srcs: ["Test.java"],
3216			compile_dex: true,
3217			public: {enabled: true},
3218			min_sdk_version: "2",
3219			permitted_packages: ["mysdklibrary"],
3220			sdk_version: "current",
3221		}
3222
3223		java_sdk_library {
3224			name: "myothersdklibrary",
3225			srcs: ["Test.java"],
3226			compile_dex: true,
3227			public: {enabled: true},
3228			min_sdk_version: "2",
3229			permitted_packages: ["myothersdklibrary"],
3230			sdk_version: "current",
3231		}
3232
3233		java_library {
3234			name: "foo",
3235			libs: [
3236				"bar",
3237				"mysdklibrary.stubs",
3238			],
3239			srcs: ["A.java"],
3240		}
3241
3242		java_library {
3243			name: "bar",
3244			libs: [
3245				"myothersdklibrary.stubs"
3246			],
3247		}
3248	`)
3249	ctx := result.TestContext
3250	fooModule := ctx.ModuleForTests(t, "foo", "android_common")
3251
3252	androidMkEntries := android.AndroidMkEntriesForTest(t, ctx, fooModule.Module())[0]
3253	localExportSdkLibraries := androidMkEntries.EntryMap["LOCAL_EXPORT_SDK_LIBRARIES"]
3254	android.AssertStringListDoesNotContain(t,
3255		"boot jar should not be included in uses libs entries",
3256		localExportSdkLibraries,
3257		"mysdklibrary",
3258	)
3259	android.AssertStringListContains(t,
3260		"non boot jar is included in uses libs entries",
3261		localExportSdkLibraries,
3262		"myothersdklibrary",
3263	)
3264}
3265