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