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