• 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	"io/ioutil"
19	"os"
20	"path/filepath"
21	"strconv"
22	"strings"
23	"testing"
24
25	"android/soong/android"
26	"android/soong/cc"
27	"android/soong/dexpreopt"
28	"android/soong/genrule"
29)
30
31var buildDir string
32
33func setUp() {
34	var err error
35	buildDir, err = ioutil.TempDir("", "soong_java_test")
36	if err != nil {
37		panic(err)
38	}
39}
40
41func tearDown() {
42	os.RemoveAll(buildDir)
43}
44
45func TestMain(m *testing.M) {
46	run := func() int {
47		setUp()
48		defer tearDown()
49
50		return m.Run()
51	}
52
53	os.Exit(run())
54}
55
56func testConfig(env map[string]string) android.Config {
57	return TestConfig(buildDir, env)
58}
59
60func testContext(config android.Config, bp string,
61	fs map[string][]byte) *android.TestContext {
62
63	ctx := android.NewTestArchContext()
64	ctx.RegisterModuleType("android_app", android.ModuleFactoryAdaptor(AndroidAppFactory))
65	ctx.RegisterModuleType("android_app_certificate", android.ModuleFactoryAdaptor(AndroidAppCertificateFactory))
66	ctx.RegisterModuleType("android_library", android.ModuleFactoryAdaptor(AndroidLibraryFactory))
67	ctx.RegisterModuleType("android_test", android.ModuleFactoryAdaptor(AndroidTestFactory))
68	ctx.RegisterModuleType("android_test_helper_app", android.ModuleFactoryAdaptor(AndroidTestHelperAppFactory))
69	ctx.RegisterModuleType("java_binary", android.ModuleFactoryAdaptor(BinaryFactory))
70	ctx.RegisterModuleType("java_binary_host", android.ModuleFactoryAdaptor(BinaryHostFactory))
71	ctx.RegisterModuleType("java_device_for_host", android.ModuleFactoryAdaptor(DeviceForHostFactory))
72	ctx.RegisterModuleType("java_host_for_device", android.ModuleFactoryAdaptor(HostForDeviceFactory))
73	ctx.RegisterModuleType("java_library", android.ModuleFactoryAdaptor(LibraryFactory))
74	ctx.RegisterModuleType("java_library_host", android.ModuleFactoryAdaptor(LibraryHostFactory))
75	ctx.RegisterModuleType("java_test", android.ModuleFactoryAdaptor(TestFactory))
76	ctx.RegisterModuleType("java_import", android.ModuleFactoryAdaptor(ImportFactory))
77	ctx.RegisterModuleType("java_import_host", android.ModuleFactoryAdaptor(ImportFactoryHost))
78	ctx.RegisterModuleType("java_defaults", android.ModuleFactoryAdaptor(defaultsFactory))
79	ctx.RegisterModuleType("java_system_modules", android.ModuleFactoryAdaptor(SystemModulesFactory))
80	ctx.RegisterModuleType("java_genrule", android.ModuleFactoryAdaptor(genRuleFactory))
81	ctx.RegisterModuleType("java_plugin", android.ModuleFactoryAdaptor(PluginFactory))
82	ctx.RegisterModuleType("dex_import", android.ModuleFactoryAdaptor(DexImportFactory))
83	ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(android.FileGroupFactory))
84	ctx.RegisterModuleType("genrule", android.ModuleFactoryAdaptor(genrule.GenRuleFactory))
85	ctx.RegisterModuleType("droiddoc", android.ModuleFactoryAdaptor(DroiddocFactory))
86	ctx.RegisterModuleType("droiddoc_host", android.ModuleFactoryAdaptor(DroiddocHostFactory))
87	ctx.RegisterModuleType("droiddoc_template", android.ModuleFactoryAdaptor(ExportedDroiddocDirFactory))
88	ctx.RegisterModuleType("java_sdk_library", android.ModuleFactoryAdaptor(SdkLibraryFactory))
89	ctx.RegisterModuleType("override_android_app", android.ModuleFactoryAdaptor(OverrideAndroidAppModuleFactory))
90	ctx.RegisterModuleType("prebuilt_apis", android.ModuleFactoryAdaptor(PrebuiltApisFactory))
91	ctx.PreArchMutators(android.RegisterPrebuiltsPreArchMutators)
92	ctx.PreArchMutators(android.RegisterPrebuiltsPostDepsMutators)
93	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
94	ctx.PreArchMutators(android.RegisterOverridePreArchMutators)
95	ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
96		ctx.TopDown("prebuilt_apis", PrebuiltApisMutator).Parallel()
97		ctx.TopDown("java_sdk_library", SdkLibraryMutator).Parallel()
98	})
99	ctx.RegisterPreSingletonType("overlay", android.SingletonFactoryAdaptor(OverlaySingletonFactory))
100	ctx.RegisterPreSingletonType("sdk_versions", android.SingletonFactoryAdaptor(sdkPreSingletonFactory))
101
102	// Register module types and mutators from cc needed for JNI testing
103	ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
104	ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(cc.ObjectFactory))
105	ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(cc.ToolchainLibraryFactory))
106	ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(cc.LlndkLibraryFactory))
107	ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
108		ctx.BottomUp("link", cc.LinkageMutator).Parallel()
109		ctx.BottomUp("begin", cc.BeginMutator).Parallel()
110	})
111
112	bp += GatherRequiredDepsForTest()
113
114	mockFS := map[string][]byte{
115		"Android.bp":             []byte(bp),
116		"a.java":                 nil,
117		"b.java":                 nil,
118		"c.java":                 nil,
119		"b.kt":                   nil,
120		"a.jar":                  nil,
121		"b.jar":                  nil,
122		"APP_NOTICE":             nil,
123		"GENRULE_NOTICE":         nil,
124		"LIB_NOTICE":             nil,
125		"TOOL_NOTICE":            nil,
126		"java-res/a/a":           nil,
127		"java-res/b/b":           nil,
128		"java-res2/a":            nil,
129		"java-fg/a.java":         nil,
130		"java-fg/b.java":         nil,
131		"java-fg/c.java":         nil,
132		"api/current.txt":        nil,
133		"api/removed.txt":        nil,
134		"api/system-current.txt": nil,
135		"api/system-removed.txt": nil,
136		"api/test-current.txt":   nil,
137		"api/test-removed.txt":   nil,
138		"framework/aidl/a.aidl":  nil,
139
140		"prebuilts/sdk/14/public/android.jar":         nil,
141		"prebuilts/sdk/14/public/framework.aidl":      nil,
142		"prebuilts/sdk/14/system/android.jar":         nil,
143		"prebuilts/sdk/17/public/android.jar":         nil,
144		"prebuilts/sdk/17/public/framework.aidl":      nil,
145		"prebuilts/sdk/17/system/android.jar":         nil,
146		"prebuilts/sdk/25/public/android.jar":         nil,
147		"prebuilts/sdk/25/public/framework.aidl":      nil,
148		"prebuilts/sdk/25/system/android.jar":         nil,
149		"prebuilts/sdk/current/core/android.jar":      nil,
150		"prebuilts/sdk/current/public/android.jar":    nil,
151		"prebuilts/sdk/current/public/framework.aidl": nil,
152		"prebuilts/sdk/current/public/core.jar":       nil,
153		"prebuilts/sdk/current/system/android.jar":    nil,
154		"prebuilts/sdk/current/test/android.jar":      nil,
155		"prebuilts/sdk/28/public/api/foo.txt":         nil,
156		"prebuilts/sdk/28/system/api/foo.txt":         nil,
157		"prebuilts/sdk/28/test/api/foo.txt":           nil,
158		"prebuilts/sdk/28/public/api/foo-removed.txt": nil,
159		"prebuilts/sdk/28/system/api/foo-removed.txt": nil,
160		"prebuilts/sdk/28/test/api/foo-removed.txt":   nil,
161		"prebuilts/sdk/28/public/api/bar.txt":         nil,
162		"prebuilts/sdk/28/system/api/bar.txt":         nil,
163		"prebuilts/sdk/28/test/api/bar.txt":           nil,
164		"prebuilts/sdk/28/public/api/bar-removed.txt": nil,
165		"prebuilts/sdk/28/system/api/bar-removed.txt": nil,
166		"prebuilts/sdk/28/test/api/bar-removed.txt":   nil,
167		"prebuilts/sdk/tools/core-lambda-stubs.jar":   nil,
168		"prebuilts/sdk/Android.bp":                    []byte(`prebuilt_apis { name: "sdk", api_dirs: ["14", "28", "current"],}`),
169
170		// For framework-res, which is an implicit dependency for framework
171		"AndroidManifest.xml":                   nil,
172		"build/target/product/security/testkey": nil,
173
174		"build/soong/scripts/jar-wrapper.sh": nil,
175
176		"build/make/core/proguard.flags":             nil,
177		"build/make/core/proguard_basic_keeps.flags": nil,
178
179		"jdk8/jre/lib/jce.jar": nil,
180		"jdk8/jre/lib/rt.jar":  nil,
181		"jdk8/lib/tools.jar":   nil,
182
183		"bar-doc/a.java":                 nil,
184		"bar-doc/b.java":                 nil,
185		"bar-doc/IFoo.aidl":              nil,
186		"bar-doc/known_oj_tags.txt":      nil,
187		"external/doclava/templates-sdk": nil,
188
189		"cert/new_cert.x509.pem": nil,
190		"cert/new_cert.pk8":      nil,
191	}
192
193	for k, v := range fs {
194		mockFS[k] = v
195	}
196
197	ctx.MockFileSystem(mockFS)
198
199	return ctx
200}
201
202func run(t *testing.T, ctx *android.TestContext, config android.Config) {
203	t.Helper()
204
205	pathCtx := android.PathContextForTesting(config, nil)
206	setDexpreoptTestGlobalConfig(config, dexpreopt.GlobalConfigForTests(pathCtx))
207
208	ctx.Register()
209	_, errs := ctx.ParseFileList(".", []string{"Android.bp", "prebuilts/sdk/Android.bp"})
210	android.FailIfErrored(t, errs)
211	_, errs = ctx.PrepareBuildActions(config)
212	android.FailIfErrored(t, errs)
213}
214
215func testJava(t *testing.T, bp string) *android.TestContext {
216	t.Helper()
217	config := testConfig(nil)
218	ctx := testContext(config, bp, nil)
219	run(t, ctx, config)
220
221	return ctx
222}
223
224func moduleToPath(name string) string {
225	switch {
226	case name == `""`:
227		return name
228	case strings.HasSuffix(name, ".jar"):
229		return name
230	default:
231		return filepath.Join(buildDir, ".intermediates", name, "android_common", "turbine-combined", name+".jar")
232	}
233}
234
235func TestSimple(t *testing.T) {
236	ctx := testJava(t, `
237		java_library {
238			name: "foo",
239			srcs: ["a.java"],
240			libs: ["bar"],
241			static_libs: ["baz"],
242		}
243
244		java_library {
245			name: "bar",
246			srcs: ["b.java"],
247		}
248
249		java_library {
250			name: "baz",
251			srcs: ["c.java"],
252		}
253	`)
254
255	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
256	combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac")
257
258	if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
259		t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
260	}
261
262	baz := ctx.ModuleForTests("baz", "android_common").Rule("javac").Output.String()
263	barTurbine := filepath.Join(buildDir, ".intermediates", "bar", "android_common", "turbine-combined", "bar.jar")
264	bazTurbine := filepath.Join(buildDir, ".intermediates", "baz", "android_common", "turbine-combined", "baz.jar")
265
266	if !strings.Contains(javac.Args["classpath"], barTurbine) {
267		t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barTurbine)
268	}
269
270	if !strings.Contains(javac.Args["classpath"], bazTurbine) {
271		t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], bazTurbine)
272	}
273
274	if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != baz {
275		t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, baz)
276	}
277}
278
279func TestArchSpecific(t *testing.T) {
280	ctx := testJava(t, `
281		java_library {
282			name: "foo",
283			srcs: ["a.java"],
284			target: {
285				android: {
286					srcs: ["b.java"],
287				},
288			},
289		}
290	`)
291
292	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
293	if len(javac.Inputs) != 2 || javac.Inputs[0].String() != "a.java" || javac.Inputs[1].String() != "b.java" {
294		t.Errorf(`foo inputs %v != ["a.java", "b.java"]`, javac.Inputs)
295	}
296}
297
298func TestBinary(t *testing.T) {
299	ctx := testJava(t, `
300		java_library_host {
301			name: "foo",
302			srcs: ["a.java"],
303		}
304
305		java_binary_host {
306			name: "bar",
307			srcs: ["b.java"],
308			static_libs: ["foo"],
309		}
310	`)
311
312	buildOS := android.BuildOs.String()
313
314	bar := ctx.ModuleForTests("bar", buildOS+"_common")
315	barJar := bar.Output("bar.jar").Output.String()
316	barWrapper := ctx.ModuleForTests("bar", buildOS+"_x86_64")
317	barWrapperDeps := barWrapper.Output("bar").Implicits.Strings()
318
319	// Test that the install binary wrapper depends on the installed jar file
320	if len(barWrapperDeps) != 1 || barWrapperDeps[0] != barJar {
321		t.Errorf("expected binary wrapper implicits [%q], got %v",
322			barJar, barWrapperDeps)
323	}
324
325}
326
327func TestPrebuilts(t *testing.T) {
328	ctx := testJava(t, `
329		java_library {
330			name: "foo",
331			srcs: ["a.java"],
332			libs: ["bar"],
333			static_libs: ["baz"],
334		}
335
336		java_import {
337			name: "bar",
338			jars: ["a.jar"],
339		}
340
341		java_import {
342			name: "baz",
343			jars: ["b.jar"],
344		}
345
346		dex_import {
347			name: "qux",
348			jars: ["b.jar"],
349		}
350		`)
351
352	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
353	combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac")
354	barJar := ctx.ModuleForTests("bar", "android_common").Rule("combineJar").Output
355	bazJar := ctx.ModuleForTests("baz", "android_common").Rule("combineJar").Output
356
357	if !strings.Contains(javac.Args["classpath"], barJar.String()) {
358		t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barJar.String())
359	}
360
361	if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != bazJar.String() {
362		t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, bazJar.String())
363	}
364
365	ctx.ModuleForTests("qux", "android_common").Rule("Cp")
366}
367
368func TestDefaults(t *testing.T) {
369	ctx := testJava(t, `
370		java_defaults {
371			name: "defaults",
372			srcs: ["a.java"],
373			libs: ["bar"],
374			static_libs: ["baz"],
375			optimize: {enabled: false},
376		}
377
378		java_library {
379			name: "foo",
380			defaults: ["defaults"],
381		}
382
383		java_library {
384			name: "bar",
385			srcs: ["b.java"],
386		}
387
388		java_library {
389			name: "baz",
390			srcs: ["c.java"],
391		}
392
393		android_test {
394			name: "atestOptimize",
395			defaults: ["defaults"],
396			optimize: {enabled: true},
397		}
398
399		android_test {
400			name: "atestNoOptimize",
401			defaults: ["defaults"],
402		}
403
404		android_test {
405			name: "atestDefault",
406			srcs: ["a.java"],
407		}
408		`)
409
410	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
411	combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac")
412
413	if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
414		t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
415	}
416
417	barTurbine := filepath.Join(buildDir, ".intermediates", "bar", "android_common", "turbine-combined", "bar.jar")
418	if !strings.Contains(javac.Args["classpath"], barTurbine) {
419		t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barTurbine)
420	}
421
422	baz := ctx.ModuleForTests("baz", "android_common").Rule("javac").Output.String()
423	if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != baz {
424		t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, baz)
425	}
426
427	atestOptimize := ctx.ModuleForTests("atestOptimize", "android_common").MaybeRule("r8")
428	if atestOptimize.Output == nil {
429		t.Errorf("atestOptimize should optimize APK")
430	}
431
432	atestNoOptimize := ctx.ModuleForTests("atestNoOptimize", "android_common").MaybeRule("d8")
433	if atestNoOptimize.Output == nil {
434		t.Errorf("atestNoOptimize should not optimize APK")
435	}
436
437	atestDefault := ctx.ModuleForTests("atestDefault", "android_common").MaybeRule("r8")
438	if atestDefault.Output == nil {
439		t.Errorf("atestDefault should optimize APK")
440	}
441}
442
443func TestResources(t *testing.T) {
444	var table = []struct {
445		name  string
446		prop  string
447		extra string
448		args  string
449	}{
450		{
451			// Test that a module with java_resource_dirs includes the files
452			name: "resource dirs",
453			prop: `java_resource_dirs: ["java-res"]`,
454			args: "-C java-res -f java-res/a/a -f java-res/b/b",
455		},
456		{
457			// Test that a module with java_resources includes the files
458			name: "resource files",
459			prop: `java_resources: ["java-res/a/a", "java-res/b/b"]`,
460			args: "-C . -f java-res/a/a -f java-res/b/b",
461		},
462		{
463			// Test that a module with a filegroup in java_resources includes the files with the
464			// path prefix
465			name: "resource filegroup",
466			prop: `java_resources: [":foo-res"]`,
467			extra: `
468				filegroup {
469					name: "foo-res",
470					path: "java-res",
471					srcs: ["java-res/a/a", "java-res/b/b"],
472				}`,
473			args: "-C java-res -f java-res/a/a -f java-res/b/b",
474		},
475		{
476			// Test that a module with "include_srcs: true" includes its source files in the resources jar
477			name: "include sources",
478			prop: `include_srcs: true`,
479			args: "-C . -f a.java -f b.java -f c.java",
480		},
481		{
482			// Test that a module with wildcards in java_resource_dirs has the correct path prefixes
483			name: "wildcard dirs",
484			prop: `java_resource_dirs: ["java-res/*"]`,
485			args: "-C java-res/a -f java-res/a/a -C java-res/b -f java-res/b/b",
486		},
487		{
488			// Test that a module exclude_java_resource_dirs excludes the files
489			name: "wildcard dirs",
490			prop: `java_resource_dirs: ["java-res/*"], exclude_java_resource_dirs: ["java-res/b"]`,
491			args: "-C java-res/a -f java-res/a/a",
492		},
493		{
494			// Test wildcards in java_resources
495			name: "wildcard files",
496			prop: `java_resources: ["java-res/**/*"]`,
497			args: "-C . -f java-res/a/a -f java-res/b/b",
498		},
499		{
500			// Test exclude_java_resources with java_resources
501			name: "wildcard files with exclude",
502			prop: `java_resources: ["java-res/**/*"], exclude_java_resources: ["java-res/b/*"]`,
503			args: "-C . -f java-res/a/a",
504		},
505		{
506			// Test exclude_java_resources with java_resource_dirs
507			name: "resource dirs with exclude files",
508			prop: `java_resource_dirs: ["java-res"], exclude_java_resources: ["java-res/b/b"]`,
509			args: "-C java-res -f java-res/a/a",
510		},
511		{
512			// Test exclude_java_resource_dirs with java_resource_dirs
513			name: "resource dirs with exclude files",
514			prop: `java_resource_dirs: ["java-res", "java-res2"], exclude_java_resource_dirs: ["java-res2"]`,
515			args: "-C java-res -f java-res/a/a -f java-res/b/b",
516		},
517	}
518
519	for _, test := range table {
520		t.Run(test.name, func(t *testing.T) {
521			ctx := testJava(t, `
522				java_library {
523					name: "foo",
524					srcs: [
525						"a.java",
526						"b.java",
527						"c.java",
528					],
529					`+test.prop+`,
530				}
531			`+test.extra)
532
533			foo := ctx.ModuleForTests("foo", "android_common").Output("withres/foo.jar")
534			fooRes := ctx.ModuleForTests("foo", "android_common").Output("res/foo.jar")
535
536			if !inList(fooRes.Output.String(), foo.Inputs.Strings()) {
537				t.Errorf("foo combined jars %v does not contain %q",
538					foo.Inputs.Strings(), fooRes.Output.String())
539			}
540
541			if fooRes.Args["jarArgs"] != test.args {
542				t.Errorf("foo resource jar args %q is not %q",
543					fooRes.Args["jarArgs"], test.args)
544			}
545		})
546	}
547}
548
549func TestGeneratedSources(t *testing.T) {
550	ctx := testJava(t, `
551		java_library {
552			name: "foo",
553			srcs: [
554				"a*.java",
555				":gen",
556				"b*.java",
557			],
558		}
559
560		genrule {
561			name: "gen",
562			tool_files: ["java-res/a"],
563			out: ["gen.java"],
564		}
565	`)
566
567	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
568	genrule := ctx.ModuleForTests("gen", "").Rule("generator")
569
570	if filepath.Base(genrule.Output.String()) != "gen.java" {
571		t.Fatalf(`gen output file %v is not ".../gen.java"`, genrule.Output.String())
572	}
573
574	if len(javac.Inputs) != 3 ||
575		javac.Inputs[0].String() != "a.java" ||
576		javac.Inputs[1].String() != genrule.Output.String() ||
577		javac.Inputs[2].String() != "b.java" {
578		t.Errorf(`foo inputs %v != ["a.java", ".../gen.java", "b.java"]`, javac.Inputs)
579	}
580}
581
582func TestTurbine(t *testing.T) {
583	ctx := testJava(t, `
584		java_library {
585			name: "foo",
586			srcs: ["a.java"],
587			sdk_version: "14",
588		}
589
590		java_library {
591			name: "bar",
592			srcs: ["b.java"],
593			static_libs: ["foo"],
594			sdk_version: "14",
595		}
596
597		java_library {
598			name: "baz",
599			srcs: ["c.java"],
600			libs: ["bar"],
601			sdk_version: "14",
602		}
603		`)
604
605	fooTurbine := ctx.ModuleForTests("foo", "android_common").Rule("turbine")
606	barTurbine := ctx.ModuleForTests("bar", "android_common").Rule("turbine")
607	barJavac := ctx.ModuleForTests("bar", "android_common").Rule("javac")
608	barTurbineCombined := ctx.ModuleForTests("bar", "android_common").Description("for turbine")
609	bazJavac := ctx.ModuleForTests("baz", "android_common").Rule("javac")
610
611	if len(fooTurbine.Inputs) != 1 || fooTurbine.Inputs[0].String() != "a.java" {
612		t.Errorf(`foo inputs %v != ["a.java"]`, fooTurbine.Inputs)
613	}
614
615	fooHeaderJar := filepath.Join(buildDir, ".intermediates", "foo", "android_common", "turbine-combined", "foo.jar")
616	if !strings.Contains(barTurbine.Args["classpath"], fooHeaderJar) {
617		t.Errorf("bar turbine classpath %v does not contain %q", barTurbine.Args["classpath"], fooHeaderJar)
618	}
619	if !strings.Contains(barJavac.Args["classpath"], fooHeaderJar) {
620		t.Errorf("bar javac classpath %v does not contain %q", barJavac.Args["classpath"], fooHeaderJar)
621	}
622	if len(barTurbineCombined.Inputs) != 2 || barTurbineCombined.Inputs[1].String() != fooHeaderJar {
623		t.Errorf("bar turbine combineJar inputs %v does not contain %q", barTurbineCombined.Inputs, fooHeaderJar)
624	}
625	if !strings.Contains(bazJavac.Args["classpath"], "prebuilts/sdk/14/public/android.jar") {
626		t.Errorf("baz javac classpath %v does not contain %q", bazJavac.Args["classpath"],
627			"prebuilts/sdk/14/public/android.jar")
628	}
629}
630
631func TestSharding(t *testing.T) {
632	ctx := testJava(t, `
633		java_library {
634			name: "bar",
635			srcs: ["a.java","b.java","c.java"],
636			javac_shard_size: 1
637		}
638		`)
639
640	barHeaderJar := filepath.Join(buildDir, ".intermediates", "bar", "android_common", "turbine-combined", "bar.jar")
641	for i := 0; i < 3; i++ {
642		barJavac := ctx.ModuleForTests("bar", "android_common").Description("javac" + strconv.Itoa(i))
643		if !strings.Contains(barJavac.Args["classpath"], barHeaderJar) {
644			t.Errorf("bar javac classpath %v does not contain %q", barJavac.Args["classpath"], barHeaderJar)
645		}
646	}
647}
648
649func TestDroiddoc(t *testing.T) {
650	ctx := testJava(t, `
651		droiddoc_template {
652		    name: "droiddoc-templates-sdk",
653		    path: ".",
654		}
655		droiddoc {
656		    name: "bar-doc",
657		    srcs: [
658		        "bar-doc/*.java",
659		        "bar-doc/IFoo.aidl",
660		    ],
661		    exclude_srcs: [
662		        "bar-doc/b.java"
663		    ],
664		    custom_template: "droiddoc-templates-sdk",
665		    hdf: [
666		        "android.whichdoc offline",
667		    ],
668		    knowntags: [
669		        "bar-doc/known_oj_tags.txt",
670		    ],
671		    proofread_file: "libcore-proofread.txt",
672		    todo_file: "libcore-docs-todo.html",
673		    args: "-offlinemode -title \"libcore\"",
674		}
675		`)
676
677	stubsJar := filepath.Join(buildDir, ".intermediates", "bar-doc", "android_common", "bar-doc-stubs.srcjar")
678	barDoc := ctx.ModuleForTests("bar-doc", "android_common").Output("bar-doc-stubs.srcjar")
679	if stubsJar != barDoc.Output.String() {
680		t.Errorf("expected stubs Jar [%q], got %q", stubsJar, barDoc.Output.String())
681	}
682	inputs := ctx.ModuleForTests("bar-doc", "android_common").Rule("javadoc").Inputs
683	var javaSrcs []string
684	for _, i := range inputs {
685		javaSrcs = append(javaSrcs, i.Base())
686	}
687	if len(javaSrcs) != 2 || javaSrcs[0] != "a.java" || javaSrcs[1] != "IFoo.java" {
688		t.Errorf("inputs of bar-doc must be []string{\"a.java\", \"IFoo.java\", but was %#v.", javaSrcs)
689	}
690}
691
692func TestJarGenrules(t *testing.T) {
693	ctx := testJava(t, `
694		java_library {
695			name: "foo",
696			srcs: ["a.java"],
697		}
698
699		java_genrule {
700			name: "jargen",
701			tool_files: ["b.java"],
702			cmd: "$(location b.java) $(in) $(out)",
703			out: ["jargen.jar"],
704			srcs: [":foo"],
705		}
706
707		java_library {
708			name: "bar",
709			static_libs: ["jargen"],
710			srcs: ["c.java"],
711		}
712
713		java_library {
714			name: "baz",
715			libs: ["jargen"],
716			srcs: ["c.java"],
717		}
718	`)
719
720	foo := ctx.ModuleForTests("foo", "android_common").Output("javac/foo.jar")
721	jargen := ctx.ModuleForTests("jargen", "android_common").Output("jargen.jar")
722	bar := ctx.ModuleForTests("bar", "android_common").Output("javac/bar.jar")
723	baz := ctx.ModuleForTests("baz", "android_common").Output("javac/baz.jar")
724	barCombined := ctx.ModuleForTests("bar", "android_common").Output("combined/bar.jar")
725
726	if len(jargen.Inputs) != 1 || jargen.Inputs[0].String() != foo.Output.String() {
727		t.Errorf("expected jargen inputs [%q], got %q", foo.Output.String(), jargen.Inputs.Strings())
728	}
729
730	if !strings.Contains(bar.Args["classpath"], jargen.Output.String()) {
731		t.Errorf("bar classpath %v does not contain %q", bar.Args["classpath"], jargen.Output.String())
732	}
733
734	if !strings.Contains(baz.Args["classpath"], jargen.Output.String()) {
735		t.Errorf("baz classpath %v does not contain %q", baz.Args["classpath"], jargen.Output.String())
736	}
737
738	if len(barCombined.Inputs) != 2 ||
739		barCombined.Inputs[0].String() != bar.Output.String() ||
740		barCombined.Inputs[1].String() != jargen.Output.String() {
741		t.Errorf("bar combined jar inputs %v is not [%q, %q]",
742			barCombined.Inputs.Strings(), bar.Output.String(), jargen.Output.String())
743	}
744}
745
746func TestExcludeFileGroupInSrcs(t *testing.T) {
747	ctx := testJava(t, `
748		java_library {
749			name: "foo",
750			srcs: ["a.java", ":foo-srcs"],
751			exclude_srcs: ["a.java", ":foo-excludes"],
752		}
753
754		filegroup {
755			name: "foo-srcs",
756			srcs: ["java-fg/a.java", "java-fg/b.java", "java-fg/c.java"],
757		}
758
759		filegroup {
760			name: "foo-excludes",
761			srcs: ["java-fg/a.java", "java-fg/b.java"],
762		}
763	`)
764
765	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
766
767	if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "java-fg/c.java" {
768		t.Errorf(`foo inputs %v != ["java-fg/c.java"]`, javac.Inputs)
769	}
770}
771
772func TestJavaSdkLibrary(t *testing.T) {
773	ctx := testJava(t, `
774		droiddoc_template {
775			name: "droiddoc-templates-sdk",
776			path: ".",
777		}
778		java_sdk_library {
779			name: "foo",
780			srcs: ["a.java", "b.java"],
781			api_packages: ["foo"],
782		}
783		java_sdk_library {
784			name: "bar",
785			srcs: ["a.java", "b.java"],
786			api_packages: ["bar"],
787		}
788		java_library {
789			name: "baz",
790			srcs: ["c.java"],
791			libs: ["foo", "bar"],
792			sdk_version: "system_current",
793		}
794		java_library {
795		    name: "qux",
796		    srcs: ["c.java"],
797		    libs: ["baz"],
798		    sdk_version: "system_current",
799		}
800		`)
801
802	// check the existence of the internal modules
803	ctx.ModuleForTests("foo", "android_common")
804	ctx.ModuleForTests("foo"+sdkStubsLibrarySuffix, "android_common")
805	ctx.ModuleForTests("foo"+sdkStubsLibrarySuffix+sdkSystemApiSuffix, "android_common")
806	ctx.ModuleForTests("foo"+sdkStubsLibrarySuffix+sdkTestApiSuffix, "android_common")
807	ctx.ModuleForTests("foo"+sdkDocsSuffix, "android_common")
808	ctx.ModuleForTests("foo"+sdkDocsSuffix+sdkSystemApiSuffix, "android_common")
809	ctx.ModuleForTests("foo"+sdkDocsSuffix+sdkTestApiSuffix, "android_common")
810	ctx.ModuleForTests("foo"+sdkXmlFileSuffix, "android_arm64_armv8-a")
811	ctx.ModuleForTests("foo.api.public.28", "")
812	ctx.ModuleForTests("foo.api.system.28", "")
813	ctx.ModuleForTests("foo.api.test.28", "")
814
815	bazJavac := ctx.ModuleForTests("baz", "android_common").Rule("javac")
816	// tests if baz is actually linked to the stubs lib
817	if !strings.Contains(bazJavac.Args["classpath"], "foo.stubs.system.jar") {
818		t.Errorf("baz javac classpath %v does not contain %q", bazJavac.Args["classpath"],
819			"foo.stubs.system.jar")
820	}
821	// ... and not to the impl lib
822	if strings.Contains(bazJavac.Args["classpath"], "foo.jar") {
823		t.Errorf("baz javac classpath %v should not contain %q", bazJavac.Args["classpath"],
824			"foo.jar")
825	}
826	// test if baz is not linked to the system variant of foo
827	if strings.Contains(bazJavac.Args["classpath"], "foo.stubs.jar") {
828		t.Errorf("baz javac classpath %v should not contain %q", bazJavac.Args["classpath"],
829			"foo.stubs.jar")
830	}
831
832	// test if baz has exported SDK lib names foo and bar to qux
833	qux := ctx.ModuleForTests("qux", "android_common")
834	if quxLib, ok := qux.Module().(*Library); ok {
835		sdkLibs := quxLib.ExportedSdkLibs()
836		if len(sdkLibs) != 2 || !android.InList("foo", sdkLibs) || !android.InList("bar", sdkLibs) {
837			t.Errorf("qux should export \"foo\" and \"bar\" but exports %v", sdkLibs)
838		}
839	}
840}
841
842var compilerFlagsTestCases = []struct {
843	in  string
844	out bool
845}{
846	{
847		in:  "a",
848		out: false,
849	},
850	{
851		in:  "-a",
852		out: true,
853	},
854	{
855		in:  "-no-jdk",
856		out: false,
857	},
858	{
859		in:  "-no-stdlib",
860		out: false,
861	},
862	{
863		in:  "-kotlin-home",
864		out: false,
865	},
866	{
867		in:  "-kotlin-home /some/path",
868		out: false,
869	},
870	{
871		in:  "-include-runtime",
872		out: false,
873	},
874	{
875		in:  "-Xintellij-plugin-root",
876		out: false,
877	},
878}
879
880type mockContext struct {
881	android.ModuleContext
882	result bool
883}
884
885func (ctx *mockContext) PropertyErrorf(property, format string, args ...interface{}) {
886	// CheckBadCompilerFlags calls this function when the flag should be rejected
887	ctx.result = false
888}
889
890func TestCompilerFlags(t *testing.T) {
891	for _, testCase := range compilerFlagsTestCases {
892		ctx := &mockContext{result: true}
893		CheckKotlincFlags(ctx, []string{testCase.in})
894		if ctx.result != testCase.out {
895			t.Errorf("incorrect output:")
896			t.Errorf("     input: %#v", testCase.in)
897			t.Errorf("  expected: %#v", testCase.out)
898			t.Errorf("       got: %#v", ctx.result)
899		}
900	}
901}
902
903// TODO(jungjw): Consider making this more robust by ignoring path order.
904func checkPatchModuleFlag(t *testing.T, ctx *android.TestContext, moduleName string, expected string) {
905	variables := ctx.ModuleForTests(moduleName, "android_common").Module().VariablesForTests()
906	flags := strings.Split(variables["javacFlags"], " ")
907	got := ""
908	for _, flag := range flags {
909		keyEnd := strings.Index(flag, "=")
910		if keyEnd > -1 && flag[:keyEnd] == "--patch-module" {
911			got = flag[keyEnd+1:]
912			break
913		}
914	}
915	if expected != got {
916		t.Errorf("Unexpected patch-module flag for module %q - expected %q, but got %q", moduleName, expected, got)
917	}
918}
919
920func TestPatchModule(t *testing.T) {
921	bp := `
922		java_library {
923			name: "foo",
924			srcs: ["a.java"],
925		}
926
927		java_library {
928			name: "bar",
929			srcs: ["b.java"],
930			no_standard_libs: true,
931			system_modules: "none",
932			patch_module: "java.base",
933		}
934
935		java_library {
936			name: "baz",
937			srcs: ["c.java"],
938			patch_module: "java.base",
939		}
940	`
941
942	t.Run("1.8", func(t *testing.T) {
943		// Test default javac 1.8
944		ctx := testJava(t, bp)
945
946		checkPatchModuleFlag(t, ctx, "foo", "")
947		checkPatchModuleFlag(t, ctx, "bar", "")
948		checkPatchModuleFlag(t, ctx, "baz", "")
949	})
950
951	t.Run("1.9", func(t *testing.T) {
952		// Test again with javac 1.9
953		config := testConfig(map[string]string{"EXPERIMENTAL_USE_OPENJDK9": "true"})
954		ctx := testContext(config, bp, nil)
955		run(t, ctx, config)
956
957		checkPatchModuleFlag(t, ctx, "foo", "")
958		expected := "java.base=.:" + buildDir
959		checkPatchModuleFlag(t, ctx, "bar", expected)
960		expected = "java.base=" + strings.Join([]string{".", buildDir, moduleToPath("ext"), moduleToPath("framework"), moduleToPath("updatable_media_stubs")}, ":")
961		checkPatchModuleFlag(t, ctx, "baz", expected)
962	})
963}
964