• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2017 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package java
16
17import (
18	"fmt"
19	"os"
20	"path/filepath"
21	"reflect"
22	"runtime"
23	"strconv"
24	"strings"
25	"testing"
26
27	"github.com/google/blueprint/proptools"
28
29	"android/soong/android"
30	"android/soong/cc"
31	"android/soong/dexpreopt"
32	"android/soong/genrule"
33)
34
35// Legacy preparer used for running tests within the java package.
36//
37// This includes everything that was needed to run any test in the java package prior to the
38// introduction of the test fixtures. Tests that are being converted to use fixtures directly
39// rather than through the testJava...() methods should avoid using this and instead use the
40// various preparers directly, using android.GroupFixturePreparers(...) to group them when
41// necessary.
42//
43// deprecated
44var prepareForJavaTest = android.GroupFixturePreparers(
45	genrule.PrepareForTestWithGenRuleBuildComponents,
46	// Get the CC build components but not default modules.
47	cc.PrepareForTestWithCcBuildComponents,
48	// Include all the default java modules.
49	PrepareForTestWithDexpreopt,
50	PrepareForTestWithOverlayBuildComponents,
51	android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
52		ctx.RegisterPreSingletonType("sdk_versions", sdkPreSingletonFactory)
53	}),
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
532func TestPrebuilts(t *testing.T) {
533	ctx, _ := testJava(t, `
534		java_library {
535			name: "foo",
536			srcs: ["a.java", ":stubs-source"],
537			libs: ["bar", "sdklib"],
538			static_libs: ["baz"],
539		}
540
541		java_import {
542			name: "bar",
543			jars: ["a.jar"],
544		}
545
546		java_import {
547			name: "baz",
548			jars: ["b.jar"],
549			sdk_version: "current",
550			compile_dex: true,
551		}
552
553		dex_import {
554			name: "qux",
555			jars: ["b.jar"],
556		}
557
558		java_sdk_library_import {
559			name: "sdklib",
560			public: {
561				jars: ["c.jar"],
562			},
563		}
564
565		prebuilt_stubs_sources {
566			name: "stubs-source",
567			srcs: ["stubs/sources"],
568		}
569
570		java_test_import {
571			name: "test",
572			jars: ["a.jar"],
573			test_suites: ["cts"],
574			test_config: "AndroidTest.xml",
575		}
576		`)
577
578	fooModule := ctx.ModuleForTests("foo", "android_common")
579	javac := fooModule.Rule("javac")
580	combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac")
581	barModule := ctx.ModuleForTests("bar", "android_common")
582	barJar := barModule.Rule("combineJar").Output
583	bazModule := ctx.ModuleForTests("baz", "android_common")
584	bazJar := bazModule.Rule("combineJar").Output
585	sdklibStubsJar := ctx.ModuleForTests("sdklib.stubs", "android_common").Rule("combineJar").Output
586
587	fooLibrary := fooModule.Module().(*Library)
588	assertDeepEquals(t, "foo unique sources incorrect",
589		[]string{"a.java"}, fooLibrary.uniqueSrcFiles.Strings())
590
591	assertDeepEquals(t, "foo java source jars incorrect",
592		[]string{".intermediates/stubs-source/android_common/stubs-source-stubs.srcjar"},
593		android.NormalizePathsForTesting(fooLibrary.compiledSrcJars))
594
595	if !strings.Contains(javac.Args["classpath"], barJar.String()) {
596		t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barJar.String())
597	}
598
599	barDexJar := barModule.Module().(*Import).DexJarBuildPath()
600	if barDexJar.IsSet() {
601		t.Errorf("bar dex jar build path expected to be set, got %s", barDexJar)
602	}
603
604	if !strings.Contains(javac.Args["classpath"], sdklibStubsJar.String()) {
605		t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], sdklibStubsJar.String())
606	}
607
608	if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != bazJar.String() {
609		t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, bazJar.String())
610	}
611
612	bazDexJar := bazModule.Module().(*Import).DexJarBuildPath().Path()
613	expectedDexJar := "out/soong/.intermediates/baz/android_common/dex/baz.jar"
614	android.AssertPathRelativeToTopEquals(t, "baz dex jar build path", expectedDexJar, bazDexJar)
615
616	ctx.ModuleForTests("qux", "android_common").Rule("Cp")
617
618	entries := android.AndroidMkEntriesForTest(t, ctx, fooModule.Module())[0]
619	android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "java_library", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
620	entries = android.AndroidMkEntriesForTest(t, ctx, barModule.Module())[0]
621	android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "java_import", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
622	entries = android.AndroidMkEntriesForTest(t, ctx, ctx.ModuleForTests("sdklib", "android_common").Module())[0]
623	android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "java_sdk_library_import", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
624}
625
626func assertDeepEquals(t *testing.T, message string, expected interface{}, actual interface{}) {
627	if !reflect.DeepEqual(expected, actual) {
628		t.Errorf("%s: expected %q, found %q", message, expected, actual)
629	}
630}
631
632func TestPrebuiltStubsSources(t *testing.T) {
633	test := func(t *testing.T, sourcesPath string, expectedInputs []string) {
634		ctx, _ := testJavaWithFS(t, fmt.Sprintf(`
635prebuilt_stubs_sources {
636  name: "stubs-source",
637	srcs: ["%s"],
638}`, sourcesPath), map[string][]byte{
639			"stubs/sources/pkg/A.java": nil,
640			"stubs/sources/pkg/B.java": nil,
641		})
642
643		zipSrc := ctx.ModuleForTests("stubs-source", "android_common").Rule("zip_src")
644		if expected, actual := expectedInputs, zipSrc.Inputs.Strings(); !reflect.DeepEqual(expected, actual) {
645			t.Errorf("mismatch of inputs to soong_zip: expected %q, actual %q", expected, actual)
646		}
647	}
648
649	t.Run("empty/missing directory", func(t *testing.T) {
650		test(t, "empty-directory", nil)
651	})
652
653	t.Run("non-empty set of sources", func(t *testing.T) {
654		test(t, "stubs/sources", []string{
655			"stubs/sources/pkg/A.java",
656			"stubs/sources/pkg/B.java",
657		})
658	})
659}
660
661func TestDefaults(t *testing.T) {
662	ctx, _ := testJava(t, `
663		java_defaults {
664			name: "defaults",
665			srcs: ["a.java"],
666			libs: ["bar"],
667			static_libs: ["baz"],
668			optimize: {enabled: false},
669		}
670
671		java_library {
672			name: "foo",
673			defaults: ["defaults"],
674		}
675
676		java_library {
677			name: "bar",
678			srcs: ["b.java"],
679		}
680
681		java_library {
682			name: "baz",
683			srcs: ["c.java"],
684		}
685
686		android_test {
687			name: "atestOptimize",
688			defaults: ["defaults"],
689			optimize: {enabled: true},
690		}
691
692		android_test {
693			name: "atestNoOptimize",
694			defaults: ["defaults"],
695		}
696
697		android_test {
698			name: "atestDefault",
699			srcs: ["a.java"],
700		}
701		`)
702
703	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
704	combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac")
705
706	if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
707		t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
708	}
709
710	barTurbine := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine-combined", "bar.jar")
711	if !strings.Contains(javac.Args["classpath"], barTurbine) {
712		t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barTurbine)
713	}
714
715	baz := ctx.ModuleForTests("baz", "android_common").Rule("javac").Output.String()
716	if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != baz {
717		t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, baz)
718	}
719
720	atestOptimize := ctx.ModuleForTests("atestOptimize", "android_common").MaybeRule("r8")
721	if atestOptimize.Output == nil {
722		t.Errorf("atestOptimize should optimize APK")
723	}
724
725	atestNoOptimize := ctx.ModuleForTests("atestNoOptimize", "android_common").MaybeRule("d8")
726	if atestNoOptimize.Output == nil {
727		t.Errorf("atestNoOptimize should not optimize APK")
728	}
729
730	atestDefault := ctx.ModuleForTests("atestDefault", "android_common").MaybeRule("d8")
731	if atestDefault.Output == nil {
732		t.Errorf("atestDefault should not optimize APK")
733	}
734}
735
736func TestResources(t *testing.T) {
737	var table = []struct {
738		name  string
739		prop  string
740		extra string
741		args  string
742	}{
743		{
744			// Test that a module with java_resource_dirs includes the files
745			name: "resource dirs",
746			prop: `java_resource_dirs: ["java-res"]`,
747			args: "-C java-res -f java-res/a/a -f java-res/b/b",
748		},
749		{
750			// Test that a module with java_resources includes the files
751			name: "resource files",
752			prop: `java_resources: ["java-res/a/a", "java-res/b/b"]`,
753			args: "-C . -f java-res/a/a -f java-res/b/b",
754		},
755		{
756			// Test that a module with a filegroup in java_resources includes the files with the
757			// path prefix
758			name: "resource filegroup",
759			prop: `java_resources: [":foo-res"]`,
760			extra: `
761				filegroup {
762					name: "foo-res",
763					path: "java-res",
764					srcs: ["java-res/a/a", "java-res/b/b"],
765				}`,
766			args: "-C java-res -f java-res/a/a -f java-res/b/b",
767		},
768		{
769			// Test that a module with wildcards in java_resource_dirs has the correct path prefixes
770			name: "wildcard dirs",
771			prop: `java_resource_dirs: ["java-res/*"]`,
772			args: "-C java-res/a -f java-res/a/a -C java-res/b -f java-res/b/b",
773		},
774		{
775			// Test that a module exclude_java_resource_dirs excludes the files
776			name: "wildcard dirs",
777			prop: `java_resource_dirs: ["java-res/*"], exclude_java_resource_dirs: ["java-res/b"]`,
778			args: "-C java-res/a -f java-res/a/a",
779		},
780		{
781			// Test wildcards in java_resources
782			name: "wildcard files",
783			prop: `java_resources: ["java-res/**/*"]`,
784			args: "-C . -f java-res/a/a -f java-res/b/b",
785		},
786		{
787			// Test exclude_java_resources with java_resources
788			name: "wildcard files with exclude",
789			prop: `java_resources: ["java-res/**/*"], exclude_java_resources: ["java-res/b/*"]`,
790			args: "-C . -f java-res/a/a",
791		},
792		{
793			// Test exclude_java_resources with java_resource_dirs
794			name: "resource dirs with exclude files",
795			prop: `java_resource_dirs: ["java-res"], exclude_java_resources: ["java-res/b/b"]`,
796			args: "-C java-res -f java-res/a/a",
797		},
798		{
799			// Test exclude_java_resource_dirs with java_resource_dirs
800			name: "resource dirs with exclude files",
801			prop: `java_resource_dirs: ["java-res", "java-res2"], exclude_java_resource_dirs: ["java-res2"]`,
802			args: "-C java-res -f java-res/a/a -f java-res/b/b",
803		},
804	}
805
806	for _, test := range table {
807		t.Run(test.name, func(t *testing.T) {
808			ctx, _ := testJavaWithFS(t, `
809				java_library {
810					name: "foo",
811					srcs: [
812						"a.java",
813						"b.java",
814						"c.java",
815					],
816					`+test.prop+`,
817				}
818			`+test.extra,
819				map[string][]byte{
820					"java-res/a/a": nil,
821					"java-res/b/b": nil,
822					"java-res2/a":  nil,
823				},
824			)
825
826			foo := ctx.ModuleForTests("foo", "android_common").Output("withres/foo.jar")
827			fooRes := ctx.ModuleForTests("foo", "android_common").Output("res/foo.jar")
828
829			if !inList(fooRes.Output.String(), foo.Inputs.Strings()) {
830				t.Errorf("foo combined jars %v does not contain %q",
831					foo.Inputs.Strings(), fooRes.Output.String())
832			}
833
834			if fooRes.Args["jarArgs"] != test.args {
835				t.Errorf("foo resource jar args %q is not %q",
836					fooRes.Args["jarArgs"], test.args)
837			}
838		})
839	}
840}
841
842func TestIncludeSrcs(t *testing.T) {
843	ctx, _ := testJavaWithFS(t, `
844		java_library {
845			name: "foo",
846			srcs: [
847				"a.java",
848				"b.java",
849				"c.java",
850			],
851			include_srcs: true,
852		}
853
854		java_library {
855			name: "bar",
856			srcs: [
857				"a.java",
858				"b.java",
859				"c.java",
860			],
861			java_resource_dirs: ["java-res"],
862			include_srcs: true,
863		}
864	`, map[string][]byte{
865		"java-res/a/a": nil,
866		"java-res/b/b": nil,
867		"java-res2/a":  nil,
868	})
869
870	// Test a library with include_srcs: true
871	foo := ctx.ModuleForTests("foo", "android_common").Output("withres/foo.jar")
872	fooSrcJar := ctx.ModuleForTests("foo", "android_common").Output("foo.srcjar")
873
874	if g, w := fooSrcJar.Output.String(), foo.Inputs.Strings(); !inList(g, w) {
875		t.Errorf("foo combined jars %v does not contain %q", w, g)
876	}
877
878	if g, w := fooSrcJar.Args["jarArgs"], "-C . -f a.java -f b.java -f c.java"; g != w {
879		t.Errorf("foo source jar args %q is not %q", w, g)
880	}
881
882	// Test a library with include_srcs: true and resources
883	bar := ctx.ModuleForTests("bar", "android_common").Output("withres/bar.jar")
884	barResCombined := ctx.ModuleForTests("bar", "android_common").Output("res-combined/bar.jar")
885	barRes := ctx.ModuleForTests("bar", "android_common").Output("res/bar.jar")
886	barSrcJar := ctx.ModuleForTests("bar", "android_common").Output("bar.srcjar")
887
888	if g, w := barSrcJar.Output.String(), barResCombined.Inputs.Strings(); !inList(g, w) {
889		t.Errorf("bar combined resource jars %v does not contain %q", w, g)
890	}
891
892	if g, w := barRes.Output.String(), barResCombined.Inputs.Strings(); !inList(g, w) {
893		t.Errorf("bar combined resource jars %v does not contain %q", w, g)
894	}
895
896	if g, w := barResCombined.Output.String(), bar.Inputs.Strings(); !inList(g, w) {
897		t.Errorf("bar combined jars %v does not contain %q", w, g)
898	}
899
900	if g, w := barSrcJar.Args["jarArgs"], "-C . -f a.java -f b.java -f c.java"; g != w {
901		t.Errorf("bar source jar args %q is not %q", w, g)
902	}
903
904	if g, w := barRes.Args["jarArgs"], "-C java-res -f java-res/a/a -f java-res/b/b"; g != w {
905		t.Errorf("bar resource jar args %q is not %q", w, g)
906	}
907}
908
909func TestGeneratedSources(t *testing.T) {
910	ctx, _ := testJavaWithFS(t, `
911		java_library {
912			name: "foo",
913			srcs: [
914				"a*.java",
915				":gen",
916				"b*.java",
917			],
918		}
919
920		genrule {
921			name: "gen",
922			tool_files: ["java-res/a"],
923			out: ["gen.java"],
924		}
925	`, map[string][]byte{
926		"a.java": nil,
927		"b.java": nil,
928	})
929
930	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
931	genrule := ctx.ModuleForTests("gen", "").Rule("generator")
932
933	if filepath.Base(genrule.Output.String()) != "gen.java" {
934		t.Fatalf(`gen output file %v is not ".../gen.java"`, genrule.Output.String())
935	}
936
937	if len(javac.Inputs) != 3 ||
938		javac.Inputs[0].String() != "a.java" ||
939		javac.Inputs[1].String() != genrule.Output.String() ||
940		javac.Inputs[2].String() != "b.java" {
941		t.Errorf(`foo inputs %v != ["a.java", ".../gen.java", "b.java"]`, javac.Inputs)
942	}
943}
944
945func TestTurbine(t *testing.T) {
946	result := android.GroupFixturePreparers(
947		prepareForJavaTest, FixtureWithPrebuiltApis(map[string][]string{"14": {"foo"}})).
948		RunTestWithBp(t, `
949		java_library {
950			name: "foo",
951			srcs: ["a.java"],
952			sdk_version: "14",
953		}
954
955		java_library {
956			name: "bar",
957			srcs: ["b.java"],
958			static_libs: ["foo"],
959			sdk_version: "14",
960		}
961
962		java_library {
963			name: "baz",
964			srcs: ["c.java"],
965			libs: ["bar"],
966			sdk_version: "14",
967		}
968		`)
969
970	fooTurbine := result.ModuleForTests("foo", "android_common").Rule("turbine")
971	barTurbine := result.ModuleForTests("bar", "android_common").Rule("turbine")
972	barJavac := result.ModuleForTests("bar", "android_common").Rule("javac")
973	barTurbineCombined := result.ModuleForTests("bar", "android_common").Description("for turbine")
974	bazJavac := result.ModuleForTests("baz", "android_common").Rule("javac")
975
976	android.AssertPathsRelativeToTopEquals(t, "foo inputs", []string{"a.java"}, fooTurbine.Inputs)
977
978	fooHeaderJar := filepath.Join("out", "soong", ".intermediates", "foo", "android_common", "turbine-combined", "foo.jar")
979	barTurbineJar := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine", "bar.jar")
980	android.AssertStringDoesContain(t, "bar turbine classpath", barTurbine.Args["turbineFlags"], fooHeaderJar)
981	android.AssertStringDoesContain(t, "bar javac classpath", barJavac.Args["classpath"], fooHeaderJar)
982	android.AssertPathsRelativeToTopEquals(t, "bar turbine combineJar", []string{barTurbineJar, fooHeaderJar}, barTurbineCombined.Inputs)
983	android.AssertStringDoesContain(t, "baz javac classpath", bazJavac.Args["classpath"], "prebuilts/sdk/14/public/android.jar")
984}
985
986func TestSharding(t *testing.T) {
987	ctx, _ := testJava(t, `
988		java_library {
989			name: "bar",
990			srcs: ["a.java","b.java","c.java"],
991			javac_shard_size: 1
992		}
993		`)
994
995	barHeaderJar := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine", "bar.jar")
996	for i := 0; i < 3; i++ {
997		barJavac := ctx.ModuleForTests("bar", "android_common").Description("javac" + strconv.Itoa(i))
998		if !strings.HasPrefix(barJavac.Args["classpath"], "-classpath "+barHeaderJar+":") {
999			t.Errorf("bar javac classpath %v does start with %q", barJavac.Args["classpath"], barHeaderJar)
1000		}
1001	}
1002}
1003
1004func TestExcludeFileGroupInSrcs(t *testing.T) {
1005	ctx, _ := testJava(t, `
1006		java_library {
1007			name: "foo",
1008			srcs: ["a.java", ":foo-srcs"],
1009			exclude_srcs: ["a.java", ":foo-excludes"],
1010		}
1011
1012		filegroup {
1013			name: "foo-srcs",
1014			srcs: ["java-fg/a.java", "java-fg/b.java", "java-fg/c.java"],
1015		}
1016
1017		filegroup {
1018			name: "foo-excludes",
1019			srcs: ["java-fg/a.java", "java-fg/b.java"],
1020		}
1021	`)
1022
1023	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
1024
1025	if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "java-fg/c.java" {
1026		t.Errorf(`foo inputs %v != ["java-fg/c.java"]`, javac.Inputs)
1027	}
1028}
1029
1030func TestJavaLibrary(t *testing.T) {
1031	testJavaWithFS(t, "", map[string][]byte{
1032		"libcore/Android.bp": []byte(`
1033				java_library {
1034						name: "core",
1035						sdk_version: "none",
1036						system_modules: "none",
1037				}
1038
1039				filegroup {
1040					name: "core-jar",
1041					srcs: [":core{.jar}"],
1042				}
1043		`),
1044	})
1045}
1046
1047func TestJavaImport(t *testing.T) {
1048	testJavaWithFS(t, "", map[string][]byte{
1049		"libcore/Android.bp": []byte(`
1050				java_import {
1051						name: "core",
1052						sdk_version: "none",
1053				}
1054
1055				filegroup {
1056					name: "core-jar",
1057					srcs: [":core{.jar}"],
1058				}
1059		`),
1060	})
1061}
1062
1063var compilerFlagsTestCases = []struct {
1064	in  string
1065	out bool
1066}{
1067	{
1068		in:  "a",
1069		out: false,
1070	},
1071	{
1072		in:  "-a",
1073		out: true,
1074	},
1075	{
1076		in:  "-no-jdk",
1077		out: false,
1078	},
1079	{
1080		in:  "-no-stdlib",
1081		out: false,
1082	},
1083	{
1084		in:  "-kotlin-home",
1085		out: false,
1086	},
1087	{
1088		in:  "-kotlin-home /some/path",
1089		out: false,
1090	},
1091	{
1092		in:  "-include-runtime",
1093		out: false,
1094	},
1095	{
1096		in:  "-Xintellij-plugin-root",
1097		out: false,
1098	},
1099}
1100
1101type mockContext struct {
1102	android.ModuleContext
1103	result bool
1104}
1105
1106func (ctx *mockContext) PropertyErrorf(property, format string, args ...interface{}) {
1107	// CheckBadCompilerFlags calls this function when the flag should be rejected
1108	ctx.result = false
1109}
1110
1111func TestCompilerFlags(t *testing.T) {
1112	for _, testCase := range compilerFlagsTestCases {
1113		ctx := &mockContext{result: true}
1114		CheckKotlincFlags(ctx, []string{testCase.in})
1115		if ctx.result != testCase.out {
1116			t.Errorf("incorrect output:")
1117			t.Errorf("     input: %#v", testCase.in)
1118			t.Errorf("  expected: %#v", testCase.out)
1119			t.Errorf("       got: %#v", ctx.result)
1120		}
1121	}
1122}
1123
1124// TODO(jungjw): Consider making this more robust by ignoring path order.
1125func checkPatchModuleFlag(t *testing.T, ctx *android.TestContext, moduleName string, expected string) {
1126	variables := ctx.ModuleForTests(moduleName, "android_common").VariablesForTestsRelativeToTop()
1127	flags := strings.Split(variables["javacFlags"], " ")
1128	got := ""
1129	for _, flag := range flags {
1130		keyEnd := strings.Index(flag, "=")
1131		if keyEnd > -1 && flag[:keyEnd] == "--patch-module" {
1132			got = flag[keyEnd+1:]
1133			break
1134		}
1135	}
1136	if expected != android.StringPathRelativeToTop(ctx.Config().SoongOutDir(), got) {
1137		t.Errorf("Unexpected patch-module flag for module %q - expected %q, but got %q", moduleName, expected, got)
1138	}
1139}
1140
1141func TestPatchModule(t *testing.T) {
1142	t.Run("Java language level 8", func(t *testing.T) {
1143		// Test with legacy javac -source 1.8 -target 1.8
1144		bp := `
1145			java_library {
1146				name: "foo",
1147				srcs: ["a.java"],
1148				java_version: "1.8",
1149			}
1150
1151			java_library {
1152				name: "bar",
1153				srcs: ["b.java"],
1154				sdk_version: "none",
1155				system_modules: "none",
1156				patch_module: "java.base",
1157				java_version: "1.8",
1158			}
1159
1160			java_library {
1161				name: "baz",
1162				srcs: ["c.java"],
1163				patch_module: "java.base",
1164				java_version: "1.8",
1165			}
1166		`
1167		ctx, _ := testJava(t, bp)
1168
1169		checkPatchModuleFlag(t, ctx, "foo", "")
1170		checkPatchModuleFlag(t, ctx, "bar", "")
1171		checkPatchModuleFlag(t, ctx, "baz", "")
1172	})
1173
1174	t.Run("Java language level 9", func(t *testing.T) {
1175		// Test with default javac -source 9 -target 9
1176		bp := `
1177			java_library {
1178				name: "foo",
1179				srcs: ["a.java"],
1180			}
1181
1182			java_library {
1183				name: "bar",
1184				srcs: ["b.java"],
1185				sdk_version: "none",
1186				system_modules: "none",
1187				patch_module: "java.base",
1188			}
1189
1190			java_library {
1191				name: "baz",
1192				srcs: [
1193					"c.java",
1194					// Tests for b/150878007
1195					"dir/d.java",
1196					"dir2/e.java",
1197					"dir2/f.java",
1198					"nested/dir/g.java"
1199				],
1200				patch_module: "java.base",
1201			}
1202		`
1203		ctx, _ := testJava(t, bp)
1204
1205		checkPatchModuleFlag(t, ctx, "foo", "")
1206		expected := "java.base=.:out/soong"
1207		checkPatchModuleFlag(t, ctx, "bar", expected)
1208		expected = "java.base=" + strings.Join([]string{
1209			".", "out/soong", "dir", "dir2", "nested", defaultModuleToPath("ext"), defaultModuleToPath("framework")}, ":")
1210		checkPatchModuleFlag(t, ctx, "baz", expected)
1211	})
1212}
1213
1214func TestJavaLibraryWithSystemModules(t *testing.T) {
1215	ctx, _ := testJava(t, `
1216		java_library {
1217		    name: "lib-with-source-system-modules",
1218		    srcs: [
1219		        "a.java",
1220		    ],
1221				sdk_version: "none",
1222				system_modules: "source-system-modules",
1223		}
1224
1225		java_library {
1226				name: "source-jar",
1227		    srcs: [
1228		        "a.java",
1229		    ],
1230		}
1231
1232		java_system_modules {
1233				name: "source-system-modules",
1234				libs: ["source-jar"],
1235		}
1236
1237		java_library {
1238		    name: "lib-with-prebuilt-system-modules",
1239		    srcs: [
1240		        "a.java",
1241		    ],
1242				sdk_version: "none",
1243				system_modules: "prebuilt-system-modules",
1244		}
1245
1246		java_import {
1247				name: "prebuilt-jar",
1248				jars: ["a.jar"],
1249		}
1250
1251		java_system_modules_import {
1252				name: "prebuilt-system-modules",
1253				libs: ["prebuilt-jar"],
1254		}
1255		`)
1256
1257	checkBootClasspathForSystemModule(t, ctx, "lib-with-source-system-modules", "/source-jar.jar")
1258
1259	checkBootClasspathForSystemModule(t, ctx, "lib-with-prebuilt-system-modules", "/prebuilt-jar.jar")
1260}
1261
1262func checkBootClasspathForSystemModule(t *testing.T, ctx *android.TestContext, moduleName string, expectedSuffix string) {
1263	javacRule := ctx.ModuleForTests(moduleName, "android_common").Rule("javac")
1264	bootClasspath := javacRule.Args["bootClasspath"]
1265	if strings.HasPrefix(bootClasspath, "--system ") && strings.HasSuffix(bootClasspath, expectedSuffix) {
1266		t.Errorf("bootclasspath of %q must start with --system and end with %q, but was %#v.", moduleName, expectedSuffix, bootClasspath)
1267	}
1268}
1269
1270func TestAidlExportIncludeDirsFromImports(t *testing.T) {
1271	ctx, _ := testJava(t, `
1272		java_library {
1273			name: "foo",
1274			srcs: ["aidl/foo/IFoo.aidl"],
1275			libs: ["bar"],
1276		}
1277
1278		java_import {
1279			name: "bar",
1280			jars: ["a.jar"],
1281			aidl: {
1282				export_include_dirs: ["aidl/bar"],
1283			},
1284		}
1285	`)
1286
1287	aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command
1288	expectedAidlFlag := "-Iaidl/bar"
1289	if !strings.Contains(aidlCommand, expectedAidlFlag) {
1290		t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
1291	}
1292}
1293
1294func TestAidlIncludeDirFromConvertedFileGroupWithPathPropInMixedBuilds(t *testing.T) {
1295	// TODO(b/247782695), TODO(b/242847534) Fix mixed builds for filegroups
1296	t.Skip("Re-enable once filegroups are corrected for mixed builds")
1297	bp := `
1298	filegroup {
1299		name: "foo_aidl",
1300		srcs: ["aidl/foo/IFoo.aidl"],
1301		path: "aidl/foo",
1302		bazel_module: { label: "//:foo_aidl" },
1303	}
1304	java_library {
1305		name: "foo",
1306		srcs: [":foo_aidl"],
1307	}
1308`
1309
1310	outBaseDir := "out/bazel/output"
1311	result := android.GroupFixturePreparers(
1312		prepareForJavaTest,
1313		android.PrepareForTestWithFilegroup,
1314		android.FixtureModifyConfig(func(config android.Config) {
1315			config.BazelContext = android.MockBazelContext{
1316				OutputBaseDir: outBaseDir,
1317				LabelToOutputFiles: map[string][]string{
1318					"//:foo_aidl": []string{"aidl/foo/IFoo.aidl"},
1319				},
1320			}
1321		}),
1322	).RunTestWithBp(t, bp)
1323
1324	aidlCommand := result.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command
1325	expectedAidlFlag := "-I" + outBaseDir + "/execroot/__main__/aidl/foo"
1326	if !strings.Contains(aidlCommand, expectedAidlFlag) {
1327		t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
1328	}
1329}
1330
1331func TestAidlFlagsArePassedToTheAidlCompiler(t *testing.T) {
1332	ctx, _ := testJava(t, `
1333		java_library {
1334			name: "foo",
1335			srcs: ["aidl/foo/IFoo.aidl"],
1336			aidl: { flags: ["-Werror"], },
1337		}
1338	`)
1339
1340	aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command
1341	expectedAidlFlag := "-Werror"
1342	if !strings.Contains(aidlCommand, expectedAidlFlag) {
1343		t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
1344	}
1345}
1346
1347func TestAidlFlagsWithMinSdkVersion(t *testing.T) {
1348	fixture := android.GroupFixturePreparers(
1349		prepareForJavaTest, FixtureWithPrebuiltApis(map[string][]string{"14": {"foo"}}))
1350
1351	for _, tc := range []struct {
1352		name       string
1353		sdkVersion string
1354		expected   string
1355	}{
1356		{"default is current", "", "current"},
1357		{"use sdk_version", `sdk_version: "14"`, "14"},
1358		{"system_current", `sdk_version: "system_current"`, "current"},
1359	} {
1360		t.Run(tc.name, func(t *testing.T) {
1361			ctx := fixture.RunTestWithBp(t, `
1362				java_library {
1363					name: "foo",
1364					srcs: ["aidl/foo/IFoo.aidl"],
1365					`+tc.sdkVersion+`
1366				}
1367			`)
1368			aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command
1369			expectedAidlFlag := "--min_sdk_version=" + tc.expected
1370			if !strings.Contains(aidlCommand, expectedAidlFlag) {
1371				t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
1372			}
1373		})
1374	}
1375}
1376
1377func TestAidlFlagsMinSdkVersionDroidstubs(t *testing.T) {
1378	bpTemplate := `
1379	droidstubs {
1380		name: "foo-stubs",
1381		srcs: ["foo.aidl"],
1382		%s
1383		system_modules: "none",
1384	}
1385	`
1386	testCases := []struct {
1387		desc                  string
1388		sdkVersionBp          string
1389		minSdkVersionExpected string
1390	}{
1391		{
1392			desc:                  "sdk_version not set, module compiles against private platform APIs",
1393			sdkVersionBp:          ``,
1394			minSdkVersionExpected: "10000",
1395		},
1396		{
1397			desc:                  "sdk_version set to none, module does not build against an SDK",
1398			sdkVersionBp:          `sdk_version: "none",`,
1399			minSdkVersionExpected: "10000",
1400		},
1401	}
1402	for _, tc := range testCases {
1403		ctx := prepareForJavaTest.RunTestWithBp(t, fmt.Sprintf(bpTemplate, tc.sdkVersionBp))
1404		aidlCmd := ctx.ModuleForTests("foo-stubs", "android_common").Rule("aidl").RuleParams.Command
1405		expected := "--min_sdk_version=" + tc.minSdkVersionExpected
1406		android.AssertStringDoesContain(t, "aidl command conatins incorrect min_sdk_version for testCse: "+tc.desc, aidlCmd, expected)
1407	}
1408}
1409
1410func TestAidlEnforcePermissions(t *testing.T) {
1411	ctx, _ := testJava(t, `
1412		java_library {
1413			name: "foo",
1414			srcs: ["aidl/foo/IFoo.aidl"],
1415			aidl: { enforce_permissions: true },
1416		}
1417	`)
1418
1419	aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command
1420	expectedAidlFlag := "-Wmissing-permission-annotation -Werror"
1421	if !strings.Contains(aidlCommand, expectedAidlFlag) {
1422		t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
1423	}
1424}
1425
1426func TestAidlEnforcePermissionsException(t *testing.T) {
1427	ctx, _ := testJava(t, `
1428		java_library {
1429			name: "foo",
1430			srcs: ["aidl/foo/IFoo.aidl", "aidl/foo/IFoo2.aidl"],
1431			aidl: { enforce_permissions: true, enforce_permissions_exceptions: ["aidl/foo/IFoo2.aidl"] },
1432		}
1433	`)
1434
1435	aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command
1436	expectedAidlFlag := "$$FLAGS -Wmissing-permission-annotation -Werror aidl/foo/IFoo.aidl"
1437	if !strings.Contains(aidlCommand, expectedAidlFlag) {
1438		t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
1439	}
1440	expectedAidlFlag = "$$FLAGS  aidl/foo/IFoo2.aidl"
1441	if !strings.Contains(aidlCommand, expectedAidlFlag) {
1442		t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
1443	}
1444}
1445
1446func TestDataNativeBinaries(t *testing.T) {
1447	ctx := android.GroupFixturePreparers(
1448		prepareForJavaTest,
1449		android.PrepareForTestWithAllowMissingDependencies).RunTestWithBp(t, `
1450		java_test_host {
1451			name: "foo",
1452			srcs: ["a.java"],
1453			data_native_bins: ["bin"]
1454		}
1455
1456		cc_binary_host {
1457			name: "bin",
1458			srcs: ["bin.cpp"],
1459		}
1460	`).TestContext
1461
1462	buildOS := ctx.Config().BuildOS.String()
1463
1464	test := ctx.ModuleForTests("foo", buildOS+"_common").Module().(*TestHost)
1465	entries := android.AndroidMkEntriesForTest(t, ctx, test)[0]
1466	expected := []string{"out/soong/.intermediates/bin/" + buildOS + "_x86_64/bin:bin"}
1467	actual := entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"]
1468	android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_COMPATIBILITY_SUPPORT_FILES", ctx.Config(), expected, actual)
1469}
1470
1471func TestDefaultInstallable(t *testing.T) {
1472	ctx, _ := testJava(t, `
1473		java_test_host {
1474			name: "foo"
1475		}
1476	`)
1477
1478	buildOS := ctx.Config().BuildOS.String()
1479	module := ctx.ModuleForTests("foo", buildOS+"_common").Module().(*TestHost)
1480	assertDeepEquals(t, "Default installable value should be true.", proptools.BoolPtr(true),
1481		module.properties.Installable)
1482}
1483
1484func TestErrorproneEnabled(t *testing.T) {
1485	ctx, _ := testJava(t, `
1486		java_library {
1487			name: "foo",
1488			srcs: ["a.java"],
1489			errorprone: {
1490				enabled: true,
1491			},
1492		}
1493	`)
1494
1495	javac := ctx.ModuleForTests("foo", "android_common").Description("javac")
1496
1497	// Test that the errorprone plugins are passed to javac
1498	expectedSubstring := "-Xplugin:ErrorProne"
1499	if !strings.Contains(javac.Args["javacFlags"], expectedSubstring) {
1500		t.Errorf("expected javacFlags to contain %q, got %q", expectedSubstring, javac.Args["javacFlags"])
1501	}
1502
1503	// Modules with errorprone { enabled: true } will include errorprone checks
1504	// in the main javac build rule. Only when RUN_ERROR_PRONE is true will
1505	// the explicit errorprone build rule be created.
1506	errorprone := ctx.ModuleForTests("foo", "android_common").MaybeDescription("errorprone")
1507	if errorprone.RuleParams.Description != "" {
1508		t.Errorf("expected errorprone build rule to not exist, but it did")
1509	}
1510}
1511
1512func TestErrorproneDisabled(t *testing.T) {
1513	bp := `
1514		java_library {
1515			name: "foo",
1516			srcs: ["a.java"],
1517			errorprone: {
1518				enabled: false,
1519			},
1520		}
1521	`
1522	ctx := android.GroupFixturePreparers(
1523		PrepareForTestWithJavaDefaultModules,
1524		android.FixtureMergeEnv(map[string]string{
1525			"RUN_ERROR_PRONE": "true",
1526		}),
1527	).RunTestWithBp(t, bp)
1528
1529	javac := ctx.ModuleForTests("foo", "android_common").Description("javac")
1530
1531	// Test that the errorprone plugins are not passed to javac, like they would
1532	// be if enabled was true.
1533	expectedSubstring := "-Xplugin:ErrorProne"
1534	if strings.Contains(javac.Args["javacFlags"], expectedSubstring) {
1535		t.Errorf("expected javacFlags to not contain %q, got %q", expectedSubstring, javac.Args["javacFlags"])
1536	}
1537
1538	// Check that no errorprone build rule is created, like there would be
1539	// if enabled was unset and RUN_ERROR_PRONE was true.
1540	errorprone := ctx.ModuleForTests("foo", "android_common").MaybeDescription("errorprone")
1541	if errorprone.RuleParams.Description != "" {
1542		t.Errorf("expected errorprone build rule to not exist, but it did")
1543	}
1544}
1545
1546func TestErrorproneEnabledOnlyByEnvironmentVariable(t *testing.T) {
1547	bp := `
1548		java_library {
1549			name: "foo",
1550			srcs: ["a.java"],
1551		}
1552	`
1553	ctx := android.GroupFixturePreparers(
1554		PrepareForTestWithJavaDefaultModules,
1555		android.FixtureMergeEnv(map[string]string{
1556			"RUN_ERROR_PRONE": "true",
1557		}),
1558	).RunTestWithBp(t, bp)
1559
1560	javac := ctx.ModuleForTests("foo", "android_common").Description("javac")
1561	errorprone := ctx.ModuleForTests("foo", "android_common").Description("errorprone")
1562
1563	// Check that the errorprone plugins are not passed to javac, because they
1564	// will instead be passed to the separate errorprone compilation
1565	expectedSubstring := "-Xplugin:ErrorProne"
1566	if strings.Contains(javac.Args["javacFlags"], expectedSubstring) {
1567		t.Errorf("expected javacFlags to not contain %q, got %q", expectedSubstring, javac.Args["javacFlags"])
1568	}
1569
1570	// Check that the errorprone plugin is enabled
1571	if !strings.Contains(errorprone.Args["javacFlags"], expectedSubstring) {
1572		t.Errorf("expected errorprone to contain %q, got %q", expectedSubstring, javac.Args["javacFlags"])
1573	}
1574}
1575
1576func TestDataDeviceBinsBuildsDeviceBinary(t *testing.T) {
1577	testCases := []struct {
1578		dataDeviceBinType  string
1579		depCompileMultilib string
1580		variants           []string
1581		expectedError      string
1582	}{
1583		{
1584			dataDeviceBinType:  "first",
1585			depCompileMultilib: "first",
1586			variants:           []string{"android_arm64_armv8-a"},
1587		},
1588		{
1589			dataDeviceBinType:  "first",
1590			depCompileMultilib: "both",
1591			variants:           []string{"android_arm64_armv8-a"},
1592		},
1593		{
1594			// this is true because our testing framework is set up with
1595			// Targets ~ [<64bit target>, <32bit target>], where 64bit is "first"
1596			dataDeviceBinType:  "first",
1597			depCompileMultilib: "32",
1598			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1599		},
1600		{
1601			dataDeviceBinType:  "first",
1602			depCompileMultilib: "64",
1603			variants:           []string{"android_arm64_armv8-a"},
1604		},
1605		{
1606			dataDeviceBinType:  "both",
1607			depCompileMultilib: "both",
1608			variants: []string{
1609				"android_arm_armv7-a-neon",
1610				"android_arm64_armv8-a",
1611			},
1612		},
1613		{
1614			dataDeviceBinType:  "both",
1615			depCompileMultilib: "32",
1616			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1617		},
1618		{
1619			dataDeviceBinType:  "both",
1620			depCompileMultilib: "64",
1621			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1622		},
1623		{
1624			dataDeviceBinType:  "both",
1625			depCompileMultilib: "first",
1626			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1627		},
1628		{
1629			dataDeviceBinType:  "32",
1630			depCompileMultilib: "32",
1631			variants:           []string{"android_arm_armv7-a-neon"},
1632		},
1633		{
1634			dataDeviceBinType:  "32",
1635			depCompileMultilib: "first",
1636			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1637		},
1638		{
1639			dataDeviceBinType:  "32",
1640			depCompileMultilib: "both",
1641			variants:           []string{"android_arm_armv7-a-neon"},
1642		},
1643		{
1644			dataDeviceBinType:  "32",
1645			depCompileMultilib: "64",
1646			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1647		},
1648		{
1649			dataDeviceBinType:  "64",
1650			depCompileMultilib: "64",
1651			variants:           []string{"android_arm64_armv8-a"},
1652		},
1653		{
1654			dataDeviceBinType:  "64",
1655			depCompileMultilib: "both",
1656			variants:           []string{"android_arm64_armv8-a"},
1657		},
1658		{
1659			dataDeviceBinType:  "64",
1660			depCompileMultilib: "first",
1661			variants:           []string{"android_arm64_armv8-a"},
1662		},
1663		{
1664			dataDeviceBinType:  "64",
1665			depCompileMultilib: "32",
1666			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1667		},
1668		{
1669			dataDeviceBinType:  "prefer32",
1670			depCompileMultilib: "32",
1671			variants:           []string{"android_arm_armv7-a-neon"},
1672		},
1673		{
1674			dataDeviceBinType:  "prefer32",
1675			depCompileMultilib: "both",
1676			variants:           []string{"android_arm_armv7-a-neon"},
1677		},
1678		{
1679			dataDeviceBinType:  "prefer32",
1680			depCompileMultilib: "first",
1681			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1682		},
1683		{
1684			dataDeviceBinType:  "prefer32",
1685			depCompileMultilib: "64",
1686			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1687		},
1688	}
1689
1690	bpTemplate := `
1691		java_test_host {
1692			name: "foo",
1693			srcs: ["test.java"],
1694			data_device_bins_%s: ["bar"],
1695		}
1696
1697		cc_binary {
1698			name: "bar",
1699			compile_multilib: "%s",
1700		}
1701	`
1702
1703	for _, tc := range testCases {
1704		bp := fmt.Sprintf(bpTemplate, tc.dataDeviceBinType, tc.depCompileMultilib)
1705
1706		errorHandler := android.FixtureExpectsNoErrors
1707		if tc.expectedError != "" {
1708			errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(tc.expectedError)
1709		}
1710
1711		testName := fmt.Sprintf(`data_device_bins_%s with compile_multilib:"%s"`, tc.dataDeviceBinType, tc.depCompileMultilib)
1712		t.Run(testName, func(t *testing.T) {
1713			ctx := android.GroupFixturePreparers(PrepareForIntegrationTestWithJava).
1714				ExtendWithErrorHandler(errorHandler).
1715				RunTestWithBp(t, bp)
1716			if tc.expectedError != "" {
1717				return
1718			}
1719
1720			buildOS := ctx.Config.BuildOS.String()
1721			fooVariant := ctx.ModuleForTests("foo", buildOS+"_common")
1722			fooMod := fooVariant.Module().(*TestHost)
1723			entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, fooMod)[0]
1724
1725			expectedAutogenConfig := `<option name="push-file" key="bar" value="/data/local/tests/unrestricted/foo/bar" />`
1726			autogen := fooVariant.Rule("autogen")
1727			if !strings.Contains(autogen.Args["extraConfigs"], expectedAutogenConfig) {
1728				t.Errorf("foo extraConfigs %v does not contain %q", autogen.Args["extraConfigs"], expectedAutogenConfig)
1729			}
1730
1731			expectedData := []string{}
1732			for _, variant := range tc.variants {
1733				barVariant := ctx.ModuleForTests("bar", variant)
1734				relocated := barVariant.Output("bar")
1735				expectedInput := fmt.Sprintf("out/soong/.intermediates/bar/%s/unstripped/bar", variant)
1736				android.AssertPathRelativeToTopEquals(t, "relocation input", expectedInput, relocated.Input)
1737
1738				expectedData = append(expectedData, fmt.Sprintf("out/soong/.intermediates/bar/%s/bar:bar", variant))
1739			}
1740
1741			actualData := entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"]
1742			android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_TEST_DATA", ctx.Config, expectedData, actualData)
1743		})
1744	}
1745}
1746
1747func TestImportMixedBuild(t *testing.T) {
1748	bp := `
1749		java_import {
1750			name: "baz",
1751			jars: [
1752				"test1.jar",
1753				"test2.jar",
1754			],
1755			bazel_module: { label: "//foo/bar:baz" },
1756		}
1757	`
1758
1759	ctx := android.GroupFixturePreparers(
1760		prepareForJavaTest,
1761		android.FixtureModifyConfig(func(config android.Config) {
1762			config.BazelContext = android.MockBazelContext{
1763				OutputBaseDir: "outputbase",
1764				LabelToOutputFiles: map[string][]string{
1765					"//foo/bar:baz": []string{"test1.jar", "test2.jar"},
1766				},
1767			}
1768		}),
1769	).RunTestWithBp(t, bp)
1770
1771	bazMod := ctx.ModuleForTests("baz", "android_common").Module()
1772	producer := bazMod.(android.OutputFileProducer)
1773	expectedOutputFiles := []string{".intermediates/baz/android_common/bazelCombined/baz.jar"}
1774
1775	outputFiles, err := producer.OutputFiles("")
1776	if err != nil {
1777		t.Errorf("Unexpected error getting java_import outputfiles %s", err)
1778	}
1779	actualOutputFiles := android.NormalizePathsForTesting(outputFiles)
1780	android.AssertDeepEquals(t, "Output files are produced", expectedOutputFiles, actualOutputFiles)
1781
1782	javaInfoProvider := ctx.ModuleProvider(bazMod, JavaInfoProvider)
1783	javaInfo, ok := javaInfoProvider.(JavaInfo)
1784	if !ok {
1785		t.Error("could not get JavaInfo from java_import module")
1786	}
1787	android.AssertDeepEquals(t, "Header JARs are produced", expectedOutputFiles, android.NormalizePathsForTesting(javaInfo.HeaderJars))
1788	android.AssertDeepEquals(t, "Implementation/Resources JARs are produced", expectedOutputFiles, android.NormalizePathsForTesting(javaInfo.ImplementationAndResourcesJars))
1789	android.AssertDeepEquals(t, "Implementation JARs are produced", expectedOutputFiles, android.NormalizePathsForTesting(javaInfo.ImplementationJars))
1790}
1791
1792func TestGenAidlIncludeFlagsForMixedBuilds(t *testing.T) {
1793	bazelOutputBaseDir := filepath.Join("out", "bazel")
1794	result := android.GroupFixturePreparers(
1795		PrepareForIntegrationTestWithJava,
1796		android.FixtureModifyConfig(func(config android.Config) {
1797			config.BazelContext = android.MockBazelContext{
1798				OutputBaseDir: bazelOutputBaseDir,
1799			}
1800		}),
1801	).RunTest(t)
1802
1803	ctx := &android.TestPathContext{TestResult: result}
1804
1805	srcDirectory := filepath.Join("frameworks", "base")
1806	srcDirectoryAlreadyIncluded := filepath.Join("frameworks", "base", "core", "java")
1807	bazelSrcDirectory := android.PathForBazelOut(ctx, srcDirectory)
1808	bazelSrcDirectoryAlreadyIncluded := android.PathForBazelOut(ctx, srcDirectoryAlreadyIncluded)
1809	srcs := android.Paths{
1810		android.PathForTestingWithRel(bazelSrcDirectory.String(), "bazelAidl.aidl"),
1811		android.PathForTestingWithRel(bazelSrcDirectory.String(), "bazelAidl2.aidl"),
1812		android.PathForTestingWithRel(bazelSrcDirectoryAlreadyIncluded.String(), "bazelAidlExclude.aidl"),
1813		android.PathForTestingWithRel(bazelSrcDirectoryAlreadyIncluded.String(), "bazelAidl2Exclude.aidl"),
1814	}
1815	dirsAlreadyIncluded := android.Paths{
1816		android.PathForTesting(srcDirectoryAlreadyIncluded),
1817	}
1818
1819	expectedFlags := " -Iout/bazel/execroot/__main__/frameworks/base"
1820	flags := genAidlIncludeFlags(ctx, srcs, dirsAlreadyIncluded)
1821	if flags != expectedFlags {
1822		t.Errorf("expected flags to be %q; was %q", expectedFlags, flags)
1823	}
1824}
1825
1826func TestDeviceBinaryWrapperGeneration(t *testing.T) {
1827	// Scenario 1: java_binary has main_class property in its bp
1828	ctx, _ := testJava(t, `
1829		java_binary {
1830			name: "foo",
1831			srcs: ["foo.java"],
1832			main_class: "foo.bar.jb",
1833		}
1834	`)
1835	wrapperPath := fmt.Sprint(ctx.ModuleForTests("foo", "android_arm64_armv8-a").AllOutputs())
1836	if !strings.Contains(wrapperPath, "foo.sh") {
1837		t.Errorf("wrapper file foo.sh is not generated")
1838	}
1839
1840	// Scenario 2: java_binary has neither wrapper nor main_class, its build
1841	// is expected to be failed.
1842	testJavaError(t, "main_class property is required for device binary if no default wrapper is assigned", `
1843		java_binary {
1844			name: "foo",
1845			srcs: ["foo.java"],
1846		}`)
1847}
1848
1849func TestJavaApiContributionEmptyApiFile(t *testing.T) {
1850	testJavaError(t,
1851		"Error: foo has an empty api file.",
1852		`java_api_contribution {
1853			name: "foo",
1854		}
1855		java_api_library {
1856			name: "bar",
1857			api_surface: "public",
1858			api_contributions: ["foo"],
1859		}
1860	`)
1861}
1862
1863func TestJavaApiLibraryAndProviderLink(t *testing.T) {
1864	provider_bp_a := `
1865	java_api_contribution {
1866		name: "foo1",
1867		api_file: "foo1.txt",
1868	}
1869	`
1870	provider_bp_b := `java_api_contribution {
1871		name: "foo2",
1872		api_file: "foo2.txt",
1873	}
1874	`
1875	ctx, _ := testJavaWithFS(t, `
1876		java_api_library {
1877			name: "bar1",
1878			api_surface: "public",
1879			api_contributions: ["foo1"],
1880		}
1881
1882		java_api_library {
1883			name: "bar2",
1884			api_surface: "system",
1885			api_contributions: ["foo1", "foo2"],
1886			api_files: ["api1/current.txt", "api2/current.txt"]
1887		}
1888		`,
1889		map[string][]byte{
1890			"a/Android.bp": []byte(provider_bp_a),
1891			"b/Android.bp": []byte(provider_bp_b),
1892		})
1893
1894	testcases := []struct {
1895		moduleName         string
1896		sourceTextFileDirs []string
1897	}{
1898		{
1899			moduleName:         "bar1",
1900			sourceTextFileDirs: []string{"a/foo1.txt"},
1901		},
1902		{
1903			moduleName:         "bar2",
1904			sourceTextFileDirs: []string{"a/foo1.txt", "b/foo2.txt", "api1/current.txt", "api2/current.txt"},
1905		},
1906	}
1907	for _, c := range testcases {
1908		m := ctx.ModuleForTests(c.moduleName, "android_common")
1909		manifest := m.Output("metalava.sbox.textproto")
1910		sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
1911		manifestCommand := sboxProto.Commands[0].GetCommand()
1912		sourceFilesFlag := "--source-files " + strings.Join(c.sourceTextFileDirs, " ")
1913		android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag)
1914	}
1915}
1916
1917func TestJavaApiLibraryAndDefaultsLink(t *testing.T) {
1918	provider_bp_a := `
1919	java_api_contribution {
1920		name: "foo1",
1921		api_file: "foo1.txt",
1922	}
1923	`
1924	provider_bp_b := `
1925	java_api_contribution {
1926		name: "foo2",
1927		api_file: "foo2.txt",
1928	}
1929	`
1930	provider_bp_c := `
1931	java_api_contribution {
1932		name: "foo3",
1933		api_file: "foo3.txt",
1934	}
1935	`
1936	provider_bp_d := `
1937	java_api_contribution {
1938		name: "foo4",
1939		api_file: "foo4.txt",
1940	}
1941	`
1942	ctx, _ := testJavaWithFS(t, `
1943		java_defaults {
1944			name: "baz1",
1945			api_surface: "public",
1946			api_contributions: ["foo1", "foo2"],
1947		}
1948
1949		java_defaults {
1950			name: "baz2",
1951			api_surface: "system",
1952			api_contributions: ["foo3"],
1953		}
1954
1955		java_api_library {
1956			name: "bar1",
1957			api_surface: "public",
1958			api_contributions: ["foo1"],
1959		}
1960
1961		java_api_library {
1962			name: "bar2",
1963			api_surface: "public",
1964			defaults:["baz1"],
1965		}
1966
1967		java_api_library {
1968			name: "bar3",
1969			api_surface: "system",
1970			defaults:["baz1", "baz2"],
1971			api_contributions: ["foo4"],
1972			api_files: ["api1/current.txt", "api2/current.txt"]
1973		}
1974		`,
1975		map[string][]byte{
1976			"a/Android.bp": []byte(provider_bp_a),
1977			"b/Android.bp": []byte(provider_bp_b),
1978			"c/Android.bp": []byte(provider_bp_c),
1979			"d/Android.bp": []byte(provider_bp_d),
1980		})
1981
1982	testcases := []struct {
1983		moduleName         string
1984		sourceTextFileDirs []string
1985	}{
1986		{
1987			moduleName:         "bar1",
1988			sourceTextFileDirs: []string{"a/foo1.txt"},
1989		},
1990		{
1991			moduleName:         "bar2",
1992			sourceTextFileDirs: []string{"a/foo1.txt", "b/foo2.txt"},
1993		},
1994		{
1995			moduleName:         "bar3",
1996			sourceTextFileDirs: []string{"c/foo3.txt", "a/foo1.txt", "b/foo2.txt", "d/foo4.txt", "api1/current.txt", "api2/current.txt"},
1997		},
1998	}
1999	for _, c := range testcases {
2000		m := ctx.ModuleForTests(c.moduleName, "android_common")
2001		manifest := m.Output("metalava.sbox.textproto")
2002		sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
2003		manifestCommand := sboxProto.Commands[0].GetCommand()
2004		sourceFilesFlag := "--source-files " + strings.Join(c.sourceTextFileDirs, " ")
2005		android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag)
2006	}
2007}
2008
2009func TestJavaApiLibraryJarGeneration(t *testing.T) {
2010	provider_bp_a := `
2011	java_api_contribution {
2012		name: "foo1",
2013		api_file: "foo1.txt",
2014	}
2015	`
2016	provider_bp_b := `
2017	java_api_contribution {
2018		name: "foo2",
2019		api_file: "foo2.txt",
2020	}
2021	`
2022	ctx, _ := testJavaWithFS(t, `
2023		java_api_library {
2024			name: "bar1",
2025			api_surface: "public",
2026			api_contributions: ["foo1"],
2027		}
2028
2029		java_api_library {
2030			name: "bar2",
2031			api_surface: "system",
2032			api_contributions: ["foo1", "foo2"],
2033		}
2034		`,
2035		map[string][]byte{
2036			"a/Android.bp": []byte(provider_bp_a),
2037			"b/Android.bp": []byte(provider_bp_b),
2038		})
2039
2040	testcases := []struct {
2041		moduleName    string
2042		outputJarName string
2043	}{
2044		{
2045			moduleName:    "bar1",
2046			outputJarName: "bar1/bar1.jar",
2047		},
2048		{
2049			moduleName:    "bar2",
2050			outputJarName: "bar2/bar2.jar",
2051		},
2052	}
2053	for _, c := range testcases {
2054		m := ctx.ModuleForTests(c.moduleName, "android_common")
2055		outputs := fmt.Sprint(m.AllOutputs())
2056		if !strings.Contains(outputs, c.outputJarName) {
2057			t.Errorf("Module output does not contain expected jar %s", c.outputJarName)
2058		}
2059	}
2060}
2061
2062func TestJavaApiLibraryLibsLink(t *testing.T) {
2063	provider_bp_a := `
2064	java_api_contribution {
2065		name: "foo1",
2066		api_file: "foo1.txt",
2067	}
2068	`
2069	provider_bp_b := `
2070	java_api_contribution {
2071		name: "foo2",
2072		api_file: "foo2.txt",
2073	}
2074	`
2075	lib_bp_a := `
2076	java_library {
2077		name: "lib1",
2078		srcs: ["Lib.java"],
2079	}
2080	`
2081	lib_bp_b := `
2082	java_library {
2083		name: "lib2",
2084		srcs: ["Lib.java"],
2085	}
2086	`
2087
2088	ctx, _ := testJavaWithFS(t, `
2089		java_api_library {
2090			name: "bar1",
2091			api_surface: "public",
2092			api_contributions: ["foo1"],
2093			libs: ["lib1"],
2094		}
2095
2096		java_api_library {
2097			name: "bar2",
2098			api_surface: "system",
2099			api_contributions: ["foo1", "foo2"],
2100			libs: ["lib1", "lib2", "bar1"],
2101		}
2102		`,
2103		map[string][]byte{
2104			"a/Android.bp": []byte(provider_bp_a),
2105			"b/Android.bp": []byte(provider_bp_b),
2106			"c/Android.bp": []byte(lib_bp_a),
2107			"c/Lib.java":   {},
2108			"d/Android.bp": []byte(lib_bp_b),
2109			"d/Lib.java":   {},
2110		})
2111
2112	testcases := []struct {
2113		moduleName        string
2114		classPathJarNames []string
2115	}{
2116		{
2117			moduleName:        "bar1",
2118			classPathJarNames: []string{"lib1.jar"},
2119		},
2120		{
2121			moduleName:        "bar2",
2122			classPathJarNames: []string{"lib1.jar", "lib2.jar", "bar1/bar1.jar"},
2123		},
2124	}
2125	for _, c := range testcases {
2126		m := ctx.ModuleForTests(c.moduleName, "android_common")
2127		javacRules := m.Rule("javac")
2128		classPathArgs := javacRules.Args["classpath"]
2129		for _, jarName := range c.classPathJarNames {
2130			if !strings.Contains(classPathArgs, jarName) {
2131				t.Errorf("Module output does not contain expected jar %s", jarName)
2132			}
2133		}
2134	}
2135}
2136
2137func TestJavaApiLibraryStaticLibsLink(t *testing.T) {
2138	provider_bp_a := `
2139	java_api_contribution {
2140		name: "foo1",
2141		api_file: "foo1.txt",
2142	}
2143	`
2144	provider_bp_b := `
2145	java_api_contribution {
2146		name: "foo2",
2147		api_file: "foo2.txt",
2148	}
2149	`
2150	lib_bp_a := `
2151	java_library {
2152		name: "lib1",
2153		srcs: ["Lib.java"],
2154	}
2155	`
2156	lib_bp_b := `
2157	java_library {
2158		name: "lib2",
2159		srcs: ["Lib.java"],
2160	}
2161	`
2162
2163	ctx, _ := testJavaWithFS(t, `
2164		java_api_library {
2165			name: "bar1",
2166			api_surface: "public",
2167			api_contributions: ["foo1"],
2168			static_libs: ["lib1"],
2169		}
2170
2171		java_api_library {
2172			name: "bar2",
2173			api_surface: "system",
2174			api_contributions: ["foo1", "foo2"],
2175			static_libs: ["lib1", "lib2", "bar1"],
2176		}
2177		`,
2178		map[string][]byte{
2179			"a/Android.bp": []byte(provider_bp_a),
2180			"b/Android.bp": []byte(provider_bp_b),
2181			"c/Android.bp": []byte(lib_bp_a),
2182			"c/Lib.java":   {},
2183			"d/Android.bp": []byte(lib_bp_b),
2184			"d/Lib.java":   {},
2185		})
2186
2187	testcases := []struct {
2188		moduleName        string
2189		staticLibJarNames []string
2190	}{
2191		{
2192			moduleName:        "bar1",
2193			staticLibJarNames: []string{"lib1.jar"},
2194		},
2195		{
2196			moduleName:        "bar2",
2197			staticLibJarNames: []string{"lib1.jar", "lib2.jar", "bar1/bar1.jar"},
2198		},
2199	}
2200	for _, c := range testcases {
2201		m := ctx.ModuleForTests(c.moduleName, "android_common")
2202		mergeZipsCommand := m.Rule("merge_zips").RuleParams.Command
2203		for _, jarName := range c.staticLibJarNames {
2204			if !strings.Contains(mergeZipsCommand, jarName) {
2205				t.Errorf("merge_zips command does not contain expected jar %s", jarName)
2206			}
2207		}
2208	}
2209}
2210
2211func TestJavaApiLibraryDepApiSrcs(t *testing.T) {
2212	provider_bp_a := `
2213	java_api_contribution {
2214		name: "foo1",
2215		api_file: "foo1.txt",
2216	}
2217	`
2218	provider_bp_b := `
2219	java_api_contribution {
2220		name: "foo2",
2221		api_file: "foo2.txt",
2222	}
2223	`
2224	lib_bp_a := `
2225	java_api_library {
2226		name: "lib1",
2227		api_surface: "public",
2228		api_contributions: ["foo1", "foo2"],
2229	}
2230	`
2231
2232	ctx, _ := testJavaWithFS(t, `
2233		java_api_library {
2234			name: "bar1",
2235			api_surface: "public",
2236			api_contributions: ["foo1"],
2237			dep_api_srcs: "lib1",
2238		}
2239		`,
2240		map[string][]byte{
2241			"a/Android.bp": []byte(provider_bp_a),
2242			"b/Android.bp": []byte(provider_bp_b),
2243			"c/Android.bp": []byte(lib_bp_a),
2244		})
2245
2246	m := ctx.ModuleForTests("bar1", "android_common")
2247	manifest := m.Output("metalava.sbox.textproto")
2248	sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
2249	manifestCommand := sboxProto.Commands[0].GetCommand()
2250
2251	android.AssertStringDoesContain(t, "Command expected to contain module srcjar file", manifestCommand, "bar1-stubs.srcjar")
2252	android.AssertStringDoesContain(t, "Command expected to contain output files list text file flag", manifestCommand, "--out __SBOX_SANDBOX_DIR__/out/sources.txt")
2253}
2254
2255func TestTradefedOptions(t *testing.T) {
2256	result := PrepareForTestWithJavaBuildComponents.RunTestWithBp(t, `
2257java_test_host {
2258	name: "foo",
2259	test_options: {
2260		tradefed_options: [
2261			{
2262				name: "exclude-path",
2263				value: "org/apache"
2264			}
2265		]
2266	}
2267}
2268`)
2269
2270	buildOS := result.Config.BuildOS.String()
2271	args := result.ModuleForTests("foo", buildOS+"_common").
2272		Output("out/soong/.intermediates/foo/" + buildOS + "_common/foo.config").Args
2273	expected := proptools.NinjaAndShellEscape("<option name=\"exclude-path\" value=\"org/apache\" />")
2274	if args["extraConfigs"] != expected {
2275		t.Errorf("Expected args[\"extraConfigs\"] to equal %q, was %q", expected, args["extraConfigs"])
2276	}
2277}
2278