• 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	"android/soong/python"
34)
35
36// Legacy preparer used for running tests within the java package.
37//
38// This includes everything that was needed to run any test in the java package prior to the
39// introduction of the test fixtures. Tests that are being converted to use fixtures directly
40// rather than through the testJava...() methods should avoid using this and instead use the
41// various preparers directly, using android.GroupFixturePreparers(...) to group them when
42// necessary.
43//
44// deprecated
45var prepareForJavaTest = android.GroupFixturePreparers(
46	genrule.PrepareForTestWithGenRuleBuildComponents,
47	// Get the CC build components but not default modules.
48	cc.PrepareForTestWithCcBuildComponents,
49	// Include all the default java modules.
50	PrepareForTestWithJavaDefaultModules,
51	PrepareForTestWithOverlayBuildComponents,
52	python.PrepareForTestWithPythonBuildComponents,
53	android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
54		ctx.RegisterPreSingletonType("sdk_versions", sdkPreSingletonFactory)
55	}),
56	PrepareForTestWithDexpreopt,
57)
58
59func TestMain(m *testing.M) {
60	os.Exit(m.Run())
61}
62
63// testJavaError is a legacy way of running tests of java modules that expect errors.
64//
65// See testJava for an explanation as to how to stop using this deprecated method.
66//
67// deprecated
68func testJavaError(t *testing.T, pattern string, bp string) (*android.TestContext, android.Config) {
69	t.Helper()
70	result := android.GroupFixturePreparers(
71		prepareForJavaTest, dexpreopt.PrepareForTestByEnablingDexpreopt).
72		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)).
73		RunTestWithBp(t, bp)
74	return result.TestContext, result.Config
75}
76
77// testJavaWithFS runs tests using the prepareForJavaTest
78//
79// See testJava for an explanation as to how to stop using this deprecated method.
80//
81// deprecated
82func testJavaWithFS(t *testing.T, bp string, fs android.MockFS) (*android.TestContext, android.Config) {
83	t.Helper()
84	result := android.GroupFixturePreparers(
85		prepareForJavaTest, fs.AddToFixture()).RunTestWithBp(t, bp)
86	return result.TestContext, result.Config
87}
88
89// testJava runs tests using the prepareForJavaTest
90//
91// Do not add any new usages of this, instead use the prepareForJavaTest directly as it makes it
92// much easier to customize the test behavior.
93//
94// If it is necessary to customize the behavior of an existing test that uses this then please first
95// convert the test to using prepareForJavaTest first and then in a following change add the
96// appropriate fixture preparers. Keeping the conversion change separate makes it easy to verify
97// that it did not change the test behavior unexpectedly.
98//
99// deprecated
100func testJava(t *testing.T, bp string) (*android.TestContext, android.Config) {
101	t.Helper()
102	result := prepareForJavaTest.RunTestWithBp(t, bp)
103	return result.TestContext, result.Config
104}
105
106// defaultModuleToPath constructs a path to the turbine generate jar for a default test module that
107// is defined in PrepareForIntegrationTestWithJava
108func defaultModuleToPath(name string) string {
109	switch {
110	case name == `""`:
111		return name
112	case strings.HasSuffix(name, ".jar"):
113		return name
114	default:
115		return filepath.Join("out", "soong", ".intermediates", defaultJavaDir, name, "android_common", "turbine-combined", name+".jar")
116	}
117}
118
119// Test that the PrepareForTestWithJavaDefaultModules provides all the files that it uses by
120// running it in a fixture that requires all source files to exist.
121func TestPrepareForTestWithJavaDefaultModules(t *testing.T) {
122	android.GroupFixturePreparers(
123		PrepareForTestWithJavaDefaultModules,
124		android.PrepareForTestDisallowNonExistentPaths,
125	).RunTest(t)
126}
127
128func TestJavaLinkType(t *testing.T) {
129	testJava(t, `
130		java_library {
131			name: "foo",
132			srcs: ["a.java"],
133			libs: ["bar"],
134			static_libs: ["baz"],
135		}
136
137		java_library {
138			name: "bar",
139			sdk_version: "current",
140			srcs: ["b.java"],
141		}
142
143		java_library {
144			name: "baz",
145			sdk_version: "system_current",
146			srcs: ["c.java"],
147		}
148	`)
149
150	testJavaError(t, "consider adjusting sdk_version: OR platform_apis:", `
151		java_library {
152			name: "foo",
153			srcs: ["a.java"],
154			libs: ["bar"],
155			sdk_version: "current",
156			static_libs: ["baz"],
157		}
158
159		java_library {
160			name: "bar",
161			sdk_version: "current",
162			srcs: ["b.java"],
163		}
164
165		java_library {
166			name: "baz",
167			sdk_version: "system_current",
168			srcs: ["c.java"],
169		}
170	`)
171
172	testJava(t, `
173		java_library {
174			name: "foo",
175			srcs: ["a.java"],
176			libs: ["bar"],
177			sdk_version: "system_current",
178			static_libs: ["baz"],
179		}
180
181		java_library {
182			name: "bar",
183			sdk_version: "current",
184			srcs: ["b.java"],
185		}
186
187		java_library {
188			name: "baz",
189			sdk_version: "system_current",
190			srcs: ["c.java"],
191		}
192	`)
193
194	testJavaError(t, "consider adjusting sdk_version: OR platform_apis:", `
195		java_library {
196			name: "foo",
197			srcs: ["a.java"],
198			libs: ["bar"],
199			sdk_version: "system_current",
200			static_libs: ["baz"],
201		}
202
203		java_library {
204			name: "bar",
205			sdk_version: "current",
206			srcs: ["b.java"],
207		}
208
209		java_library {
210			name: "baz",
211			srcs: ["c.java"],
212		}
213	`)
214}
215
216func TestSimple(t *testing.T) {
217	ctx, _ := testJava(t, `
218		java_library {
219			name: "foo",
220			srcs: ["a.java"],
221			libs: ["bar"],
222			static_libs: ["baz"],
223		}
224
225		java_library {
226			name: "bar",
227			srcs: ["b.java"],
228		}
229
230		java_library {
231			name: "baz",
232			srcs: ["c.java"],
233		}
234	`)
235
236	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
237	combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac")
238
239	if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
240		t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
241	}
242
243	baz := ctx.ModuleForTests("baz", "android_common").Rule("javac").Output.String()
244	barTurbine := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine-combined", "bar.jar")
245	bazTurbine := filepath.Join("out", "soong", ".intermediates", "baz", "android_common", "turbine-combined", "baz.jar")
246
247	android.AssertStringDoesContain(t, "foo classpath", javac.Args["classpath"], barTurbine)
248
249	android.AssertStringDoesContain(t, "foo classpath", javac.Args["classpath"], bazTurbine)
250
251	if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != baz {
252		t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, baz)
253	}
254}
255
256func TestExportedPlugins(t *testing.T) {
257	type Result struct {
258		library        string
259		processors     string
260		disableTurbine bool
261	}
262	var tests = []struct {
263		name    string
264		extra   string
265		results []Result
266	}{
267		{
268			name:    "Exported plugin is not a direct plugin",
269			extra:   `java_library { name: "exports", srcs: ["a.java"], exported_plugins: ["plugin"] }`,
270			results: []Result{{library: "exports", processors: "-proc:none"}},
271		},
272		{
273			name: "Exports plugin to dependee",
274			extra: `
275				java_library{name: "exports", exported_plugins: ["plugin"]}
276				java_library{name: "foo", srcs: ["a.java"], libs: ["exports"]}
277				java_library{name: "bar", srcs: ["a.java"], static_libs: ["exports"]}
278			`,
279			results: []Result{
280				{library: "foo", processors: "-processor com.android.TestPlugin"},
281				{library: "bar", processors: "-processor com.android.TestPlugin"},
282			},
283		},
284		{
285			name: "Exports plugin to android_library",
286			extra: `
287				java_library{name: "exports", exported_plugins: ["plugin"]}
288				android_library{name: "foo", srcs: ["a.java"],  libs: ["exports"]}
289				android_library{name: "bar", srcs: ["a.java"], static_libs: ["exports"]}
290			`,
291			results: []Result{
292				{library: "foo", processors: "-processor com.android.TestPlugin"},
293				{library: "bar", processors: "-processor com.android.TestPlugin"},
294			},
295		},
296		{
297			name: "Exports plugin is not propagated via transitive deps",
298			extra: `
299				java_library{name: "exports", exported_plugins: ["plugin"]}
300				java_library{name: "foo", srcs: ["a.java"], libs: ["exports"]}
301				java_library{name: "bar", srcs: ["a.java"], static_libs: ["foo"]}
302			`,
303			results: []Result{
304				{library: "foo", processors: "-processor com.android.TestPlugin"},
305				{library: "bar", processors: "-proc:none"},
306			},
307		},
308		{
309			name: "Exports plugin appends to plugins",
310			extra: `
311                java_plugin{name: "plugin2", processor_class: "com.android.TestPlugin2"}
312				java_library{name: "exports", exported_plugins: ["plugin"]}
313				java_library{name: "foo", srcs: ["a.java"], libs: ["exports"], plugins: ["plugin2"]}
314			`,
315			results: []Result{
316				{library: "foo", processors: "-processor com.android.TestPlugin,com.android.TestPlugin2"},
317			},
318		},
319		{
320			name: "Exports plugin to with generates_api to dependee",
321			extra: `
322				java_library{name: "exports", exported_plugins: ["plugin_generates_api"]}
323				java_library{name: "foo", srcs: ["a.java"], libs: ["exports"]}
324				java_library{name: "bar", srcs: ["a.java"], static_libs: ["exports"]}
325			`,
326			results: []Result{
327				{library: "foo", processors: "-processor com.android.TestPlugin", disableTurbine: true},
328				{library: "bar", processors: "-processor com.android.TestPlugin", disableTurbine: true},
329			},
330		},
331	}
332
333	for _, test := range tests {
334		t.Run(test.name, func(t *testing.T) {
335			ctx, _ := testJava(t, `
336				java_plugin {
337					name: "plugin",
338					processor_class: "com.android.TestPlugin",
339				}
340				java_plugin {
341					name: "plugin_generates_api",
342					generates_api: true,
343					processor_class: "com.android.TestPlugin",
344				}
345			`+test.extra)
346
347			for _, want := range test.results {
348				javac := ctx.ModuleForTests(want.library, "android_common").Rule("javac")
349				if javac.Args["processor"] != want.processors {
350					t.Errorf("For library %v, expected %v, found %v", want.library, want.processors, javac.Args["processor"])
351				}
352				turbine := ctx.ModuleForTests(want.library, "android_common").MaybeRule("turbine")
353				disableTurbine := turbine.BuildParams.Rule == nil
354				if disableTurbine != want.disableTurbine {
355					t.Errorf("For library %v, expected disableTurbine %v, found %v", want.library, want.disableTurbine, disableTurbine)
356				}
357			}
358		})
359	}
360}
361
362func TestSdkVersionByPartition(t *testing.T) {
363	testJavaError(t, "sdk_version must have a value when the module is located at vendor or product", `
364		java_library {
365			name: "foo",
366			srcs: ["a.java"],
367			vendor: true,
368		}
369	`)
370
371	testJava(t, `
372		java_library {
373			name: "bar",
374			srcs: ["b.java"],
375		}
376	`)
377
378	for _, enforce := range []bool{true, false} {
379		bp := `
380			java_library {
381				name: "foo",
382				srcs: ["a.java"],
383				product_specific: true,
384			}
385		`
386
387		errorHandler := android.FixtureExpectsNoErrors
388		if enforce {
389			errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern("sdk_version must have a value when the module is located at vendor or product")
390		}
391
392		android.GroupFixturePreparers(
393			PrepareForTestWithJavaDefaultModules,
394			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
395				variables.EnforceProductPartitionInterface = proptools.BoolPtr(enforce)
396			}),
397		).
398			ExtendWithErrorHandler(errorHandler).
399			RunTestWithBp(t, bp)
400	}
401}
402
403func TestArchSpecific(t *testing.T) {
404	ctx, _ := testJava(t, `
405		java_library {
406			name: "foo",
407			srcs: ["a.java"],
408			target: {
409				android: {
410					srcs: ["b.java"],
411				},
412			},
413		}
414	`)
415
416	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
417	if len(javac.Inputs) != 2 || javac.Inputs[0].String() != "a.java" || javac.Inputs[1].String() != "b.java" {
418		t.Errorf(`foo inputs %v != ["a.java", "b.java"]`, javac.Inputs)
419	}
420}
421
422func TestBinary(t *testing.T) {
423	ctx, _ := testJava(t, `
424		java_library_host {
425			name: "foo",
426			srcs: ["a.java"],
427		}
428
429		java_binary_host {
430			name: "bar",
431			srcs: ["b.java"],
432			static_libs: ["foo"],
433			jni_libs: ["libjni"],
434		}
435
436		cc_library_shared {
437			name: "libjni",
438			host_supported: true,
439			device_supported: false,
440			stl: "none",
441		}
442	`)
443
444	buildOS := ctx.Config().BuildOS.String()
445
446	bar := ctx.ModuleForTests("bar", buildOS+"_common")
447	barJar := bar.Output("bar.jar").Output.String()
448	barWrapper := ctx.ModuleForTests("bar", buildOS+"_x86_64")
449	barWrapperDeps := barWrapper.Output("bar").Implicits.Strings()
450
451	libjni := ctx.ModuleForTests("libjni", buildOS+"_x86_64_shared")
452	libjniSO := libjni.Rule("Cp").Output.String()
453
454	// Test that the install binary wrapper depends on the installed jar file
455	if g, w := barWrapperDeps, barJar; !android.InList(w, g) {
456		t.Errorf("expected binary wrapper implicits to contain %q, got %q", w, g)
457	}
458
459	// Test that the install binary wrapper depends on the installed JNI libraries
460	if g, w := barWrapperDeps, libjniSO; !android.InList(w, g) {
461		t.Errorf("expected binary wrapper implicits to contain %q, got %q", w, g)
462	}
463}
464
465func TestTest(t *testing.T) {
466	ctx, _ := testJava(t, `
467		java_test_host {
468			name: "foo",
469			srcs: ["a.java"],
470			jni_libs: ["libjni"],
471		}
472
473		cc_library_shared {
474			name: "libjni",
475			host_supported: true,
476			device_supported: false,
477			stl: "none",
478		}
479	`)
480
481	buildOS := ctx.Config().BuildOS.String()
482
483	foo := ctx.ModuleForTests("foo", buildOS+"_common").Module().(*TestHost)
484
485	expected := "lib64/libjni.so"
486	if runtime.GOOS == "darwin" {
487		expected = "lib64/libjni.dylib"
488	}
489
490	fooTestData := foo.data
491	if len(fooTestData) != 1 || fooTestData[0].Rel() != expected {
492		t.Errorf(`expected foo test data relative path [%q], got %q`,
493			expected, fooTestData.Strings())
494	}
495}
496
497func TestHostBinaryNoJavaDebugInfoOverride(t *testing.T) {
498	bp := `
499		java_library {
500			name: "target_library",
501			srcs: ["a.java"],
502		}
503
504		java_binary_host {
505			name: "host_binary",
506			srcs: ["b.java"],
507		}
508	`
509
510	result := android.GroupFixturePreparers(
511		PrepareForTestWithJavaDefaultModules,
512		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
513			variables.MinimizeJavaDebugInfo = proptools.BoolPtr(true)
514		}),
515	).RunTestWithBp(t, bp)
516
517	// first, check that the -g flag is added to target modules
518	targetLibrary := result.ModuleForTests("target_library", "android_common")
519	targetJavaFlags := targetLibrary.Module().VariablesForTests()["javacFlags"]
520	if !strings.Contains(targetJavaFlags, "-g:source,lines") {
521		t.Errorf("target library javac flags %v should contain "+
522			"-g:source,lines override with MinimizeJavaDebugInfo", targetJavaFlags)
523	}
524
525	// check that -g is not overridden for host modules
526	buildOS := result.Config.BuildOS.String()
527	hostBinary := result.ModuleForTests("host_binary", buildOS+"_common")
528	hostJavaFlags := hostBinary.Module().VariablesForTests()["javacFlags"]
529	if strings.Contains(hostJavaFlags, "-g:source,lines") {
530		t.Errorf("java_binary_host javac flags %v should not have "+
531			"-g:source,lines override with MinimizeJavaDebugInfo", hostJavaFlags)
532	}
533}
534
535func TestPrebuilts(t *testing.T) {
536	ctx, _ := testJava(t, `
537		java_library {
538			name: "foo",
539			srcs: ["a.java", ":stubs-source"],
540			libs: ["bar", "sdklib"],
541			static_libs: ["baz"],
542		}
543
544		java_import {
545			name: "bar",
546			jars: ["a.jar"],
547		}
548
549		java_import {
550			name: "baz",
551			jars: ["b.jar"],
552			sdk_version: "current",
553			compile_dex: true,
554		}
555
556		dex_import {
557			name: "qux",
558			jars: ["b.jar"],
559		}
560
561		java_sdk_library_import {
562			name: "sdklib",
563			public: {
564				jars: ["c.jar"],
565			},
566		}
567
568		prebuilt_stubs_sources {
569			name: "stubs-source",
570			srcs: ["stubs/sources"],
571		}
572
573		java_test_import {
574			name: "test",
575			jars: ["a.jar"],
576			test_suites: ["cts"],
577			test_config: "AndroidTest.xml",
578		}
579		`)
580
581	fooModule := ctx.ModuleForTests("foo", "android_common")
582	javac := fooModule.Rule("javac")
583	combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac")
584	barModule := ctx.ModuleForTests("bar", "android_common")
585	barJar := barModule.Rule("combineJar").Output
586	bazModule := ctx.ModuleForTests("baz", "android_common")
587	bazJar := bazModule.Rule("combineJar").Output
588	sdklibStubsJar := ctx.ModuleForTests("sdklib.stubs", "android_common").Rule("combineJar").Output
589
590	fooLibrary := fooModule.Module().(*Library)
591	assertDeepEquals(t, "foo java sources incorrect",
592		[]string{"a.java"}, fooLibrary.compiledJavaSrcs.Strings())
593
594	assertDeepEquals(t, "foo java source jars incorrect",
595		[]string{".intermediates/stubs-source/android_common/stubs-source-stubs.srcjar"},
596		android.NormalizePathsForTesting(fooLibrary.compiledSrcJars))
597
598	if !strings.Contains(javac.Args["classpath"], barJar.String()) {
599		t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barJar.String())
600	}
601
602	barDexJar := barModule.Module().(*Import).DexJarBuildPath()
603	if barDexJar.IsSet() {
604		t.Errorf("bar dex jar build path expected to be set, got %s", barDexJar)
605	}
606
607	if !strings.Contains(javac.Args["classpath"], sdklibStubsJar.String()) {
608		t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], sdklibStubsJar.String())
609	}
610
611	if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != bazJar.String() {
612		t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, bazJar.String())
613	}
614
615	bazDexJar := bazModule.Module().(*Import).DexJarBuildPath().Path()
616	expectedDexJar := "out/soong/.intermediates/baz/android_common/dex/baz.jar"
617	android.AssertPathRelativeToTopEquals(t, "baz dex jar build path", expectedDexJar, bazDexJar)
618
619	ctx.ModuleForTests("qux", "android_common").Rule("Cp")
620}
621
622func assertDeepEquals(t *testing.T, message string, expected interface{}, actual interface{}) {
623	if !reflect.DeepEqual(expected, actual) {
624		t.Errorf("%s: expected %q, found %q", message, expected, actual)
625	}
626}
627
628func TestPrebuiltStubsSources(t *testing.T) {
629	test := func(t *testing.T, sourcesPath string, expectedInputs []string) {
630		ctx, _ := testJavaWithFS(t, fmt.Sprintf(`
631prebuilt_stubs_sources {
632  name: "stubs-source",
633	srcs: ["%s"],
634}`, sourcesPath), map[string][]byte{
635			"stubs/sources/pkg/A.java": nil,
636			"stubs/sources/pkg/B.java": nil,
637		})
638
639		zipSrc := ctx.ModuleForTests("stubs-source", "android_common").Rule("zip_src")
640		if expected, actual := expectedInputs, zipSrc.Inputs.Strings(); !reflect.DeepEqual(expected, actual) {
641			t.Errorf("mismatch of inputs to soong_zip: expected %q, actual %q", expected, actual)
642		}
643	}
644
645	t.Run("empty/missing directory", func(t *testing.T) {
646		test(t, "empty-directory", nil)
647	})
648
649	t.Run("non-empty set of sources", func(t *testing.T) {
650		test(t, "stubs/sources", []string{
651			"stubs/sources/pkg/A.java",
652			"stubs/sources/pkg/B.java",
653		})
654	})
655}
656
657func TestDefaults(t *testing.T) {
658	ctx, _ := testJava(t, `
659		java_defaults {
660			name: "defaults",
661			srcs: ["a.java"],
662			libs: ["bar"],
663			static_libs: ["baz"],
664			optimize: {enabled: false},
665		}
666
667		java_library {
668			name: "foo",
669			defaults: ["defaults"],
670		}
671
672		java_library {
673			name: "bar",
674			srcs: ["b.java"],
675		}
676
677		java_library {
678			name: "baz",
679			srcs: ["c.java"],
680		}
681
682		android_test {
683			name: "atestOptimize",
684			defaults: ["defaults"],
685			optimize: {enabled: true},
686		}
687
688		android_test {
689			name: "atestNoOptimize",
690			defaults: ["defaults"],
691		}
692
693		android_test {
694			name: "atestDefault",
695			srcs: ["a.java"],
696		}
697		`)
698
699	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
700	combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac")
701
702	if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
703		t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
704	}
705
706	barTurbine := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine-combined", "bar.jar")
707	if !strings.Contains(javac.Args["classpath"], barTurbine) {
708		t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barTurbine)
709	}
710
711	baz := ctx.ModuleForTests("baz", "android_common").Rule("javac").Output.String()
712	if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != baz {
713		t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, baz)
714	}
715
716	atestOptimize := ctx.ModuleForTests("atestOptimize", "android_common").MaybeRule("r8")
717	if atestOptimize.Output == nil {
718		t.Errorf("atestOptimize should optimize APK")
719	}
720
721	atestNoOptimize := ctx.ModuleForTests("atestNoOptimize", "android_common").MaybeRule("d8")
722	if atestNoOptimize.Output == nil {
723		t.Errorf("atestNoOptimize should not optimize APK")
724	}
725
726	atestDefault := ctx.ModuleForTests("atestDefault", "android_common").MaybeRule("r8")
727	if atestDefault.Output == nil {
728		t.Errorf("atestDefault should optimize APK")
729	}
730}
731
732func TestResources(t *testing.T) {
733	var table = []struct {
734		name  string
735		prop  string
736		extra string
737		args  string
738	}{
739		{
740			// Test that a module with java_resource_dirs includes the files
741			name: "resource dirs",
742			prop: `java_resource_dirs: ["java-res"]`,
743			args: "-C java-res -f java-res/a/a -f java-res/b/b",
744		},
745		{
746			// Test that a module with java_resources includes the files
747			name: "resource files",
748			prop: `java_resources: ["java-res/a/a", "java-res/b/b"]`,
749			args: "-C . -f java-res/a/a -f java-res/b/b",
750		},
751		{
752			// Test that a module with a filegroup in java_resources includes the files with the
753			// path prefix
754			name: "resource filegroup",
755			prop: `java_resources: [":foo-res"]`,
756			extra: `
757				filegroup {
758					name: "foo-res",
759					path: "java-res",
760					srcs: ["java-res/a/a", "java-res/b/b"],
761				}`,
762			args: "-C java-res -f java-res/a/a -f java-res/b/b",
763		},
764		{
765			// Test that a module with wildcards in java_resource_dirs has the correct path prefixes
766			name: "wildcard dirs",
767			prop: `java_resource_dirs: ["java-res/*"]`,
768			args: "-C java-res/a -f java-res/a/a -C java-res/b -f java-res/b/b",
769		},
770		{
771			// Test that a module exclude_java_resource_dirs excludes the files
772			name: "wildcard dirs",
773			prop: `java_resource_dirs: ["java-res/*"], exclude_java_resource_dirs: ["java-res/b"]`,
774			args: "-C java-res/a -f java-res/a/a",
775		},
776		{
777			// Test wildcards in java_resources
778			name: "wildcard files",
779			prop: `java_resources: ["java-res/**/*"]`,
780			args: "-C . -f java-res/a/a -f java-res/b/b",
781		},
782		{
783			// Test exclude_java_resources with java_resources
784			name: "wildcard files with exclude",
785			prop: `java_resources: ["java-res/**/*"], exclude_java_resources: ["java-res/b/*"]`,
786			args: "-C . -f java-res/a/a",
787		},
788		{
789			// Test exclude_java_resources with java_resource_dirs
790			name: "resource dirs with exclude files",
791			prop: `java_resource_dirs: ["java-res"], exclude_java_resources: ["java-res/b/b"]`,
792			args: "-C java-res -f java-res/a/a",
793		},
794		{
795			// Test exclude_java_resource_dirs with java_resource_dirs
796			name: "resource dirs with exclude files",
797			prop: `java_resource_dirs: ["java-res", "java-res2"], exclude_java_resource_dirs: ["java-res2"]`,
798			args: "-C java-res -f java-res/a/a -f java-res/b/b",
799		},
800	}
801
802	for _, test := range table {
803		t.Run(test.name, func(t *testing.T) {
804			ctx, _ := testJavaWithFS(t, `
805				java_library {
806					name: "foo",
807					srcs: [
808						"a.java",
809						"b.java",
810						"c.java",
811					],
812					`+test.prop+`,
813				}
814			`+test.extra,
815				map[string][]byte{
816					"java-res/a/a": nil,
817					"java-res/b/b": nil,
818					"java-res2/a":  nil,
819				},
820			)
821
822			foo := ctx.ModuleForTests("foo", "android_common").Output("withres/foo.jar")
823			fooRes := ctx.ModuleForTests("foo", "android_common").Output("res/foo.jar")
824
825			if !inList(fooRes.Output.String(), foo.Inputs.Strings()) {
826				t.Errorf("foo combined jars %v does not contain %q",
827					foo.Inputs.Strings(), fooRes.Output.String())
828			}
829
830			if fooRes.Args["jarArgs"] != test.args {
831				t.Errorf("foo resource jar args %q is not %q",
832					fooRes.Args["jarArgs"], test.args)
833			}
834		})
835	}
836}
837
838func TestIncludeSrcs(t *testing.T) {
839	ctx, _ := testJavaWithFS(t, `
840		java_library {
841			name: "foo",
842			srcs: [
843				"a.java",
844				"b.java",
845				"c.java",
846			],
847			include_srcs: true,
848		}
849
850		java_library {
851			name: "bar",
852			srcs: [
853				"a.java",
854				"b.java",
855				"c.java",
856			],
857			java_resource_dirs: ["java-res"],
858			include_srcs: true,
859		}
860	`, map[string][]byte{
861		"java-res/a/a": nil,
862		"java-res/b/b": nil,
863		"java-res2/a":  nil,
864	})
865
866	// Test a library with include_srcs: true
867	foo := ctx.ModuleForTests("foo", "android_common").Output("withres/foo.jar")
868	fooSrcJar := ctx.ModuleForTests("foo", "android_common").Output("foo.srcjar")
869
870	if g, w := fooSrcJar.Output.String(), foo.Inputs.Strings(); !inList(g, w) {
871		t.Errorf("foo combined jars %v does not contain %q", w, g)
872	}
873
874	if g, w := fooSrcJar.Args["jarArgs"], "-C . -f a.java -f b.java -f c.java"; g != w {
875		t.Errorf("foo source jar args %q is not %q", w, g)
876	}
877
878	// Test a library with include_srcs: true and resources
879	bar := ctx.ModuleForTests("bar", "android_common").Output("withres/bar.jar")
880	barResCombined := ctx.ModuleForTests("bar", "android_common").Output("res-combined/bar.jar")
881	barRes := ctx.ModuleForTests("bar", "android_common").Output("res/bar.jar")
882	barSrcJar := ctx.ModuleForTests("bar", "android_common").Output("bar.srcjar")
883
884	if g, w := barSrcJar.Output.String(), barResCombined.Inputs.Strings(); !inList(g, w) {
885		t.Errorf("bar combined resource jars %v does not contain %q", w, g)
886	}
887
888	if g, w := barRes.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 := barResCombined.Output.String(), bar.Inputs.Strings(); !inList(g, w) {
893		t.Errorf("bar combined jars %v does not contain %q", w, g)
894	}
895
896	if g, w := barSrcJar.Args["jarArgs"], "-C . -f a.java -f b.java -f c.java"; g != w {
897		t.Errorf("bar source jar args %q is not %q", w, g)
898	}
899
900	if g, w := barRes.Args["jarArgs"], "-C java-res -f java-res/a/a -f java-res/b/b"; g != w {
901		t.Errorf("bar resource jar args %q is not %q", w, g)
902	}
903}
904
905func TestGeneratedSources(t *testing.T) {
906	ctx, _ := testJavaWithFS(t, `
907		java_library {
908			name: "foo",
909			srcs: [
910				"a*.java",
911				":gen",
912				"b*.java",
913			],
914		}
915
916		genrule {
917			name: "gen",
918			tool_files: ["java-res/a"],
919			out: ["gen.java"],
920		}
921	`, map[string][]byte{
922		"a.java": nil,
923		"b.java": nil,
924	})
925
926	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
927	genrule := ctx.ModuleForTests("gen", "").Rule("generator")
928
929	if filepath.Base(genrule.Output.String()) != "gen.java" {
930		t.Fatalf(`gen output file %v is not ".../gen.java"`, genrule.Output.String())
931	}
932
933	if len(javac.Inputs) != 3 ||
934		javac.Inputs[0].String() != "a.java" ||
935		javac.Inputs[1].String() != genrule.Output.String() ||
936		javac.Inputs[2].String() != "b.java" {
937		t.Errorf(`foo inputs %v != ["a.java", ".../gen.java", "b.java"]`, javac.Inputs)
938	}
939}
940
941func TestTurbine(t *testing.T) {
942	result := android.GroupFixturePreparers(
943		prepareForJavaTest, FixtureWithPrebuiltApis(map[string][]string{"14": {"foo"}})).
944		RunTestWithBp(t, `
945		java_library {
946			name: "foo",
947			srcs: ["a.java"],
948			sdk_version: "14",
949		}
950
951		java_library {
952			name: "bar",
953			srcs: ["b.java"],
954			static_libs: ["foo"],
955			sdk_version: "14",
956		}
957
958		java_library {
959			name: "baz",
960			srcs: ["c.java"],
961			libs: ["bar"],
962			sdk_version: "14",
963		}
964		`)
965
966	fooTurbine := result.ModuleForTests("foo", "android_common").Rule("turbine")
967	barTurbine := result.ModuleForTests("bar", "android_common").Rule("turbine")
968	barJavac := result.ModuleForTests("bar", "android_common").Rule("javac")
969	barTurbineCombined := result.ModuleForTests("bar", "android_common").Description("for turbine")
970	bazJavac := result.ModuleForTests("baz", "android_common").Rule("javac")
971
972	android.AssertPathsRelativeToTopEquals(t, "foo inputs", []string{"a.java"}, fooTurbine.Inputs)
973
974	fooHeaderJar := filepath.Join("out", "soong", ".intermediates", "foo", "android_common", "turbine-combined", "foo.jar")
975	barTurbineJar := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine", "bar.jar")
976	android.AssertStringDoesContain(t, "bar turbine classpath", barTurbine.Args["turbineFlags"], fooHeaderJar)
977	android.AssertStringDoesContain(t, "bar javac classpath", barJavac.Args["classpath"], fooHeaderJar)
978	android.AssertPathsRelativeToTopEquals(t, "bar turbine combineJar", []string{barTurbineJar, fooHeaderJar}, barTurbineCombined.Inputs)
979	android.AssertStringDoesContain(t, "baz javac classpath", bazJavac.Args["classpath"], "prebuilts/sdk/14/public/android.jar")
980}
981
982func TestSharding(t *testing.T) {
983	ctx, _ := testJava(t, `
984		java_library {
985			name: "bar",
986			srcs: ["a.java","b.java","c.java"],
987			javac_shard_size: 1
988		}
989		`)
990
991	barHeaderJar := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine", "bar.jar")
992	for i := 0; i < 3; i++ {
993		barJavac := ctx.ModuleForTests("bar", "android_common").Description("javac" + strconv.Itoa(i))
994		if !strings.HasPrefix(barJavac.Args["classpath"], "-classpath "+barHeaderJar+":") {
995			t.Errorf("bar javac classpath %v does start with %q", barJavac.Args["classpath"], barHeaderJar)
996		}
997	}
998}
999
1000func TestExcludeFileGroupInSrcs(t *testing.T) {
1001	ctx, _ := testJava(t, `
1002		java_library {
1003			name: "foo",
1004			srcs: ["a.java", ":foo-srcs"],
1005			exclude_srcs: ["a.java", ":foo-excludes"],
1006		}
1007
1008		filegroup {
1009			name: "foo-srcs",
1010			srcs: ["java-fg/a.java", "java-fg/b.java", "java-fg/c.java"],
1011		}
1012
1013		filegroup {
1014			name: "foo-excludes",
1015			srcs: ["java-fg/a.java", "java-fg/b.java"],
1016		}
1017	`)
1018
1019	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
1020
1021	if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "java-fg/c.java" {
1022		t.Errorf(`foo inputs %v != ["java-fg/c.java"]`, javac.Inputs)
1023	}
1024}
1025
1026func TestJavaLibrary(t *testing.T) {
1027	testJavaWithFS(t, "", map[string][]byte{
1028		"libcore/Android.bp": []byte(`
1029				java_library {
1030						name: "core",
1031						sdk_version: "none",
1032						system_modules: "none",
1033				}
1034
1035				filegroup {
1036					name: "core-jar",
1037					srcs: [":core{.jar}"],
1038				}
1039		`),
1040	})
1041}
1042
1043func TestJavaImport(t *testing.T) {
1044	testJavaWithFS(t, "", map[string][]byte{
1045		"libcore/Android.bp": []byte(`
1046				java_import {
1047						name: "core",
1048						sdk_version: "none",
1049				}
1050
1051				filegroup {
1052					name: "core-jar",
1053					srcs: [":core{.jar}"],
1054				}
1055		`),
1056	})
1057}
1058
1059var compilerFlagsTestCases = []struct {
1060	in  string
1061	out bool
1062}{
1063	{
1064		in:  "a",
1065		out: false,
1066	},
1067	{
1068		in:  "-a",
1069		out: true,
1070	},
1071	{
1072		in:  "-no-jdk",
1073		out: false,
1074	},
1075	{
1076		in:  "-no-stdlib",
1077		out: false,
1078	},
1079	{
1080		in:  "-kotlin-home",
1081		out: false,
1082	},
1083	{
1084		in:  "-kotlin-home /some/path",
1085		out: false,
1086	},
1087	{
1088		in:  "-include-runtime",
1089		out: false,
1090	},
1091	{
1092		in:  "-Xintellij-plugin-root",
1093		out: false,
1094	},
1095}
1096
1097type mockContext struct {
1098	android.ModuleContext
1099	result bool
1100}
1101
1102func (ctx *mockContext) PropertyErrorf(property, format string, args ...interface{}) {
1103	// CheckBadCompilerFlags calls this function when the flag should be rejected
1104	ctx.result = false
1105}
1106
1107func TestCompilerFlags(t *testing.T) {
1108	for _, testCase := range compilerFlagsTestCases {
1109		ctx := &mockContext{result: true}
1110		CheckKotlincFlags(ctx, []string{testCase.in})
1111		if ctx.result != testCase.out {
1112			t.Errorf("incorrect output:")
1113			t.Errorf("     input: %#v", testCase.in)
1114			t.Errorf("  expected: %#v", testCase.out)
1115			t.Errorf("       got: %#v", ctx.result)
1116		}
1117	}
1118}
1119
1120// TODO(jungjw): Consider making this more robust by ignoring path order.
1121func checkPatchModuleFlag(t *testing.T, ctx *android.TestContext, moduleName string, expected string) {
1122	variables := ctx.ModuleForTests(moduleName, "android_common").VariablesForTestsRelativeToTop()
1123	flags := strings.Split(variables["javacFlags"], " ")
1124	got := ""
1125	for _, flag := range flags {
1126		keyEnd := strings.Index(flag, "=")
1127		if keyEnd > -1 && flag[:keyEnd] == "--patch-module" {
1128			got = flag[keyEnd+1:]
1129			break
1130		}
1131	}
1132	if expected != android.StringPathRelativeToTop(ctx.Config().SoongOutDir(), got) {
1133		t.Errorf("Unexpected patch-module flag for module %q - expected %q, but got %q", moduleName, expected, got)
1134	}
1135}
1136
1137func TestPatchModule(t *testing.T) {
1138	t.Run("Java language level 8", func(t *testing.T) {
1139		// Test with legacy javac -source 1.8 -target 1.8
1140		bp := `
1141			java_library {
1142				name: "foo",
1143				srcs: ["a.java"],
1144				java_version: "1.8",
1145			}
1146
1147			java_library {
1148				name: "bar",
1149				srcs: ["b.java"],
1150				sdk_version: "none",
1151				system_modules: "none",
1152				patch_module: "java.base",
1153				java_version: "1.8",
1154			}
1155
1156			java_library {
1157				name: "baz",
1158				srcs: ["c.java"],
1159				patch_module: "java.base",
1160				java_version: "1.8",
1161			}
1162		`
1163		ctx, _ := testJava(t, bp)
1164
1165		checkPatchModuleFlag(t, ctx, "foo", "")
1166		checkPatchModuleFlag(t, ctx, "bar", "")
1167		checkPatchModuleFlag(t, ctx, "baz", "")
1168	})
1169
1170	t.Run("Java language level 9", func(t *testing.T) {
1171		// Test with default javac -source 9 -target 9
1172		bp := `
1173			java_library {
1174				name: "foo",
1175				srcs: ["a.java"],
1176			}
1177
1178			java_library {
1179				name: "bar",
1180				srcs: ["b.java"],
1181				sdk_version: "none",
1182				system_modules: "none",
1183				patch_module: "java.base",
1184			}
1185
1186			java_library {
1187				name: "baz",
1188				srcs: [
1189					"c.java",
1190					// Tests for b/150878007
1191					"dir/d.java",
1192					"dir2/e.java",
1193					"dir2/f.java",
1194					"nested/dir/g.java"
1195				],
1196				patch_module: "java.base",
1197			}
1198		`
1199		ctx, _ := testJava(t, bp)
1200
1201		checkPatchModuleFlag(t, ctx, "foo", "")
1202		expected := "java.base=.:out/soong"
1203		checkPatchModuleFlag(t, ctx, "bar", expected)
1204		expected = "java.base=" + strings.Join([]string{
1205			".", "out/soong", "dir", "dir2", "nested", defaultModuleToPath("ext"), defaultModuleToPath("framework")}, ":")
1206		checkPatchModuleFlag(t, ctx, "baz", expected)
1207	})
1208}
1209
1210func TestJavaLibraryWithSystemModules(t *testing.T) {
1211	ctx, _ := testJava(t, `
1212		java_library {
1213		    name: "lib-with-source-system-modules",
1214		    srcs: [
1215		        "a.java",
1216		    ],
1217				sdk_version: "none",
1218				system_modules: "source-system-modules",
1219		}
1220
1221		java_library {
1222				name: "source-jar",
1223		    srcs: [
1224		        "a.java",
1225		    ],
1226		}
1227
1228		java_system_modules {
1229				name: "source-system-modules",
1230				libs: ["source-jar"],
1231		}
1232
1233		java_library {
1234		    name: "lib-with-prebuilt-system-modules",
1235		    srcs: [
1236		        "a.java",
1237		    ],
1238				sdk_version: "none",
1239				system_modules: "prebuilt-system-modules",
1240		}
1241
1242		java_import {
1243				name: "prebuilt-jar",
1244				jars: ["a.jar"],
1245		}
1246
1247		java_system_modules_import {
1248				name: "prebuilt-system-modules",
1249				libs: ["prebuilt-jar"],
1250		}
1251		`)
1252
1253	checkBootClasspathForSystemModule(t, ctx, "lib-with-source-system-modules", "/source-jar.jar")
1254
1255	checkBootClasspathForSystemModule(t, ctx, "lib-with-prebuilt-system-modules", "/prebuilt-jar.jar")
1256}
1257
1258func checkBootClasspathForSystemModule(t *testing.T, ctx *android.TestContext, moduleName string, expectedSuffix string) {
1259	javacRule := ctx.ModuleForTests(moduleName, "android_common").Rule("javac")
1260	bootClasspath := javacRule.Args["bootClasspath"]
1261	if strings.HasPrefix(bootClasspath, "--system ") && strings.HasSuffix(bootClasspath, expectedSuffix) {
1262		t.Errorf("bootclasspath of %q must start with --system and end with %q, but was %#v.", moduleName, expectedSuffix, bootClasspath)
1263	}
1264}
1265
1266func TestAidlExportIncludeDirsFromImports(t *testing.T) {
1267	ctx, _ := testJava(t, `
1268		java_library {
1269			name: "foo",
1270			srcs: ["aidl/foo/IFoo.aidl"],
1271			libs: ["bar"],
1272		}
1273
1274		java_import {
1275			name: "bar",
1276			jars: ["a.jar"],
1277			aidl: {
1278				export_include_dirs: ["aidl/bar"],
1279			},
1280		}
1281	`)
1282
1283	aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command
1284	expectedAidlFlag := "-Iaidl/bar"
1285	if !strings.Contains(aidlCommand, expectedAidlFlag) {
1286		t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
1287	}
1288}
1289
1290func TestAidlFlagsArePassedToTheAidlCompiler(t *testing.T) {
1291	ctx, _ := testJava(t, `
1292		java_library {
1293			name: "foo",
1294			srcs: ["aidl/foo/IFoo.aidl"],
1295			aidl: { flags: ["-Werror"], },
1296		}
1297	`)
1298
1299	aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command
1300	expectedAidlFlag := "-Werror"
1301	if !strings.Contains(aidlCommand, expectedAidlFlag) {
1302		t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
1303	}
1304}
1305
1306func TestAidlFlagsWithMinSdkVersion(t *testing.T) {
1307	fixture := android.GroupFixturePreparers(
1308		prepareForJavaTest, FixtureWithPrebuiltApis(map[string][]string{"14": {"foo"}}))
1309
1310	for _, tc := range []struct {
1311		name       string
1312		sdkVersion string
1313		expected   string
1314	}{
1315		{"default is current", "", "current"},
1316		{"use sdk_version", `sdk_version: "14"`, "14"},
1317		{"system_current", `sdk_version: "system_current"`, "current"},
1318	} {
1319		t.Run(tc.name, func(t *testing.T) {
1320			ctx := fixture.RunTestWithBp(t, `
1321				java_library {
1322					name: "foo",
1323					srcs: ["aidl/foo/IFoo.aidl"],
1324					`+tc.sdkVersion+`
1325				}
1326			`)
1327			aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command
1328			expectedAidlFlag := "--min_sdk_version=" + tc.expected
1329			if !strings.Contains(aidlCommand, expectedAidlFlag) {
1330				t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
1331			}
1332		})
1333	}
1334}
1335
1336func TestAidlEnforcePermissions(t *testing.T) {
1337	ctx, _ := testJava(t, `
1338		java_library {
1339			name: "foo",
1340			srcs: ["aidl/foo/IFoo.aidl"],
1341			aidl: { enforce_permissions: true },
1342		}
1343	`)
1344
1345	aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command
1346	expectedAidlFlag := "-Wmissing-permission-annotation -Werror"
1347	if !strings.Contains(aidlCommand, expectedAidlFlag) {
1348		t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
1349	}
1350}
1351
1352func TestAidlEnforcePermissionsException(t *testing.T) {
1353	ctx, _ := testJava(t, `
1354		java_library {
1355			name: "foo",
1356			srcs: ["aidl/foo/IFoo.aidl", "aidl/foo/IFoo2.aidl"],
1357			aidl: { enforce_permissions: true, enforce_permissions_exceptions: ["aidl/foo/IFoo2.aidl"] },
1358		}
1359	`)
1360
1361	aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command
1362	expectedAidlFlag := "$$FLAGS -Wmissing-permission-annotation -Werror aidl/foo/IFoo.aidl"
1363	if !strings.Contains(aidlCommand, expectedAidlFlag) {
1364		t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
1365	}
1366	expectedAidlFlag = "$$FLAGS  aidl/foo/IFoo2.aidl"
1367	if !strings.Contains(aidlCommand, expectedAidlFlag) {
1368		t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
1369	}
1370}
1371
1372func TestDataNativeBinaries(t *testing.T) {
1373	ctx, _ := testJava(t, `
1374		java_test_host {
1375			name: "foo",
1376			srcs: ["a.java"],
1377			data_native_bins: ["bin"]
1378		}
1379
1380		python_binary_host {
1381			name: "bin",
1382			srcs: ["bin.py"],
1383		}
1384	`)
1385
1386	buildOS := ctx.Config().BuildOS.String()
1387
1388	test := ctx.ModuleForTests("foo", buildOS+"_common").Module().(*TestHost)
1389	entries := android.AndroidMkEntriesForTest(t, ctx, test)[0]
1390	expected := []string{"out/soong/.intermediates/bin/" + buildOS + "_x86_64_PY3/bin:bin"}
1391	actual := entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"]
1392	android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_COMPATIBILITY_SUPPORT_FILES", ctx.Config(), expected, actual)
1393}
1394
1395func TestDefaultInstallable(t *testing.T) {
1396	ctx, _ := testJava(t, `
1397		java_test_host {
1398			name: "foo"
1399		}
1400	`)
1401
1402	buildOS := ctx.Config().BuildOS.String()
1403	module := ctx.ModuleForTests("foo", buildOS+"_common").Module().(*TestHost)
1404	assertDeepEquals(t, "Default installable value should be true.", proptools.BoolPtr(true),
1405		module.properties.Installable)
1406}
1407
1408func TestErrorproneEnabled(t *testing.T) {
1409	ctx, _ := testJava(t, `
1410		java_library {
1411			name: "foo",
1412			srcs: ["a.java"],
1413			errorprone: {
1414				enabled: true,
1415			},
1416		}
1417	`)
1418
1419	javac := ctx.ModuleForTests("foo", "android_common").Description("javac")
1420
1421	// Test that the errorprone plugins are passed to javac
1422	expectedSubstring := "-Xplugin:ErrorProne"
1423	if !strings.Contains(javac.Args["javacFlags"], expectedSubstring) {
1424		t.Errorf("expected javacFlags to contain %q, got %q", expectedSubstring, javac.Args["javacFlags"])
1425	}
1426
1427	// Modules with errorprone { enabled: true } will include errorprone checks
1428	// in the main javac build rule. Only when RUN_ERROR_PRONE is true will
1429	// the explicit errorprone build rule be created.
1430	errorprone := ctx.ModuleForTests("foo", "android_common").MaybeDescription("errorprone")
1431	if errorprone.RuleParams.Description != "" {
1432		t.Errorf("expected errorprone build rule to not exist, but it did")
1433	}
1434}
1435
1436func TestErrorproneDisabled(t *testing.T) {
1437	bp := `
1438		java_library {
1439			name: "foo",
1440			srcs: ["a.java"],
1441			errorprone: {
1442				enabled: false,
1443			},
1444		}
1445	`
1446	ctx := android.GroupFixturePreparers(
1447		PrepareForTestWithJavaDefaultModules,
1448		android.FixtureMergeEnv(map[string]string{
1449			"RUN_ERROR_PRONE": "true",
1450		}),
1451	).RunTestWithBp(t, bp)
1452
1453	javac := ctx.ModuleForTests("foo", "android_common").Description("javac")
1454
1455	// Test that the errorprone plugins are not passed to javac, like they would
1456	// be if enabled was true.
1457	expectedSubstring := "-Xplugin:ErrorProne"
1458	if strings.Contains(javac.Args["javacFlags"], expectedSubstring) {
1459		t.Errorf("expected javacFlags to not contain %q, got %q", expectedSubstring, javac.Args["javacFlags"])
1460	}
1461
1462	// Check that no errorprone build rule is created, like there would be
1463	// if enabled was unset and RUN_ERROR_PRONE was true.
1464	errorprone := ctx.ModuleForTests("foo", "android_common").MaybeDescription("errorprone")
1465	if errorprone.RuleParams.Description != "" {
1466		t.Errorf("expected errorprone build rule to not exist, but it did")
1467	}
1468}
1469
1470func TestErrorproneEnabledOnlyByEnvironmentVariable(t *testing.T) {
1471	bp := `
1472		java_library {
1473			name: "foo",
1474			srcs: ["a.java"],
1475		}
1476	`
1477	ctx := android.GroupFixturePreparers(
1478		PrepareForTestWithJavaDefaultModules,
1479		android.FixtureMergeEnv(map[string]string{
1480			"RUN_ERROR_PRONE": "true",
1481		}),
1482	).RunTestWithBp(t, bp)
1483
1484	javac := ctx.ModuleForTests("foo", "android_common").Description("javac")
1485	errorprone := ctx.ModuleForTests("foo", "android_common").Description("errorprone")
1486
1487	// Check that the errorprone plugins are not passed to javac, because they
1488	// will instead be passed to the separate errorprone compilation
1489	expectedSubstring := "-Xplugin:ErrorProne"
1490	if strings.Contains(javac.Args["javacFlags"], expectedSubstring) {
1491		t.Errorf("expected javacFlags to not contain %q, got %q", expectedSubstring, javac.Args["javacFlags"])
1492	}
1493
1494	// Check that the errorprone plugin is enabled
1495	if !strings.Contains(errorprone.Args["javacFlags"], expectedSubstring) {
1496		t.Errorf("expected errorprone to contain %q, got %q", expectedSubstring, javac.Args["javacFlags"])
1497	}
1498}
1499
1500func TestDataDeviceBinsBuildsDeviceBinary(t *testing.T) {
1501	testCases := []struct {
1502		dataDeviceBinType  string
1503		depCompileMultilib string
1504		variants           []string
1505		expectedError      string
1506	}{
1507		{
1508			dataDeviceBinType:  "first",
1509			depCompileMultilib: "first",
1510			variants:           []string{"android_arm64_armv8-a"},
1511		},
1512		{
1513			dataDeviceBinType:  "first",
1514			depCompileMultilib: "both",
1515			variants:           []string{"android_arm64_armv8-a"},
1516		},
1517		{
1518			// this is true because our testing framework is set up with
1519			// Targets ~ [<64bit target>, <32bit target>], where 64bit is "first"
1520			dataDeviceBinType:  "first",
1521			depCompileMultilib: "32",
1522			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1523		},
1524		{
1525			dataDeviceBinType:  "first",
1526			depCompileMultilib: "64",
1527			variants:           []string{"android_arm64_armv8-a"},
1528		},
1529		{
1530			dataDeviceBinType:  "both",
1531			depCompileMultilib: "both",
1532			variants: []string{
1533				"android_arm_armv7-a-neon",
1534				"android_arm64_armv8-a",
1535			},
1536		},
1537		{
1538			dataDeviceBinType:  "both",
1539			depCompileMultilib: "32",
1540			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1541		},
1542		{
1543			dataDeviceBinType:  "both",
1544			depCompileMultilib: "64",
1545			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1546		},
1547		{
1548			dataDeviceBinType:  "both",
1549			depCompileMultilib: "first",
1550			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1551		},
1552		{
1553			dataDeviceBinType:  "32",
1554			depCompileMultilib: "32",
1555			variants:           []string{"android_arm_armv7-a-neon"},
1556		},
1557		{
1558			dataDeviceBinType:  "32",
1559			depCompileMultilib: "first",
1560			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1561		},
1562		{
1563			dataDeviceBinType:  "32",
1564			depCompileMultilib: "both",
1565			variants:           []string{"android_arm_armv7-a-neon"},
1566		},
1567		{
1568			dataDeviceBinType:  "32",
1569			depCompileMultilib: "64",
1570			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1571		},
1572		{
1573			dataDeviceBinType:  "64",
1574			depCompileMultilib: "64",
1575			variants:           []string{"android_arm64_armv8-a"},
1576		},
1577		{
1578			dataDeviceBinType:  "64",
1579			depCompileMultilib: "both",
1580			variants:           []string{"android_arm64_armv8-a"},
1581		},
1582		{
1583			dataDeviceBinType:  "64",
1584			depCompileMultilib: "first",
1585			variants:           []string{"android_arm64_armv8-a"},
1586		},
1587		{
1588			dataDeviceBinType:  "64",
1589			depCompileMultilib: "32",
1590			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1591		},
1592		{
1593			dataDeviceBinType:  "prefer32",
1594			depCompileMultilib: "32",
1595			variants:           []string{"android_arm_armv7-a-neon"},
1596		},
1597		{
1598			dataDeviceBinType:  "prefer32",
1599			depCompileMultilib: "both",
1600			variants:           []string{"android_arm_armv7-a-neon"},
1601		},
1602		{
1603			dataDeviceBinType:  "prefer32",
1604			depCompileMultilib: "first",
1605			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1606		},
1607		{
1608			dataDeviceBinType:  "prefer32",
1609			depCompileMultilib: "64",
1610			expectedError:      `Android.bp:2:3: dependency "bar" of "foo" missing variant`,
1611		},
1612	}
1613
1614	bpTemplate := `
1615		java_test_host {
1616			name: "foo",
1617			srcs: ["test.java"],
1618			data_device_bins_%s: ["bar"],
1619		}
1620
1621		cc_binary {
1622			name: "bar",
1623			compile_multilib: "%s",
1624		}
1625	`
1626
1627	for _, tc := range testCases {
1628		bp := fmt.Sprintf(bpTemplate, tc.dataDeviceBinType, tc.depCompileMultilib)
1629
1630		errorHandler := android.FixtureExpectsNoErrors
1631		if tc.expectedError != "" {
1632			errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(tc.expectedError)
1633		}
1634
1635		testName := fmt.Sprintf(`data_device_bins_%s with compile_multilib:"%s"`, tc.dataDeviceBinType, tc.depCompileMultilib)
1636		t.Run(testName, func(t *testing.T) {
1637			ctx := android.GroupFixturePreparers(PrepareForIntegrationTestWithJava).
1638				ExtendWithErrorHandler(errorHandler).
1639				RunTestWithBp(t, bp)
1640			if tc.expectedError != "" {
1641				return
1642			}
1643
1644			buildOS := ctx.Config.BuildOS.String()
1645			fooVariant := ctx.ModuleForTests("foo", buildOS+"_common")
1646			fooMod := fooVariant.Module().(*TestHost)
1647			entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, fooMod)[0]
1648
1649			expectedAutogenConfig := `<option name="push-file" key="bar" value="/data/local/tests/unrestricted/foo/bar" />`
1650			autogen := fooVariant.Rule("autogen")
1651			if !strings.Contains(autogen.Args["extraConfigs"], expectedAutogenConfig) {
1652				t.Errorf("foo extraConfigs %v does not contain %q", autogen.Args["extraConfigs"], expectedAutogenConfig)
1653			}
1654
1655			expectedData := []string{}
1656			for _, variant := range tc.variants {
1657				barVariant := ctx.ModuleForTests("bar", variant)
1658				relocated := barVariant.Output("bar")
1659				expectedInput := fmt.Sprintf("out/soong/.intermediates/bar/%s/unstripped/bar", variant)
1660				android.AssertPathRelativeToTopEquals(t, "relocation input", expectedInput, relocated.Input)
1661
1662				expectedData = append(expectedData, fmt.Sprintf("out/soong/.intermediates/bar/%s/bar:bar", variant))
1663			}
1664
1665			actualData := entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"]
1666			android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_TEST_DATA", ctx.Config, expectedData, actualData)
1667		})
1668	}
1669}
1670