// Copyright 2019 Google Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package java import ( "android/soong/android" "bytes" "io" "io/ioutil" "strings" "testing" ) type testAndroidMk struct { *testing.T body []byte } type testAndroidMkModule struct { *testing.T props map[string]string } func newTestAndroidMk(t *testing.T, r io.Reader) *testAndroidMk { t.Helper() buf, err := ioutil.ReadAll(r) if err != nil { t.Fatal("failed to open read Android.mk.", err) } return &testAndroidMk{ T: t, body: buf, } } func parseAndroidMkProps(lines []string) map[string]string { props := make(map[string]string) for _, line := range lines { line = strings.TrimLeft(line, " ") if line == "" || strings.HasPrefix(line, "#") { continue } tokens := strings.Split(line, " ") if tokens[1] == "+=" { props[tokens[0]] += " " + strings.Join(tokens[2:], " ") } else { props[tokens[0]] = strings.Join(tokens[2:], " ") } } return props } func (t *testAndroidMk) moduleFor(moduleName string) *testAndroidMkModule { t.Helper() lines := strings.Split(string(t.body), "\n") index := android.IndexList("LOCAL_MODULE := "+moduleName, lines) if index == -1 { t.Fatalf("%q is not found.", moduleName) } lines = lines[index:] includeIndex := android.IndexListPred(func(line string) bool { return strings.HasPrefix(line, "include") }, lines) if includeIndex == -1 { t.Fatalf("%q is not properly defined. (\"include\" not found).", moduleName) } props := parseAndroidMkProps(lines[:includeIndex]) return &testAndroidMkModule{ T: t.T, props: props, } } func (t *testAndroidMkModule) hasRequired(dep string) { t.Helper() required, ok := t.props["LOCAL_REQUIRED_MODULES"] if !ok { t.Error("LOCAL_REQUIRED_MODULES is not found.") return } if !android.InList(dep, strings.Split(required, " ")) { t.Errorf("%q is expected in LOCAL_REQUIRED_MODULES, but not found in %q.", dep, required) } } func (t *testAndroidMkModule) hasNoRequired(dep string) { t.Helper() required, ok := t.props["LOCAL_REQUIRED_MODULES"] if !ok { return } if android.InList(dep, strings.Split(required, " ")) { t.Errorf("%q is not expected in LOCAL_REQUIRED_MODULES, but found.", dep) } } func getAndroidMk(t *testing.T, ctx *android.TestContext, config android.Config, name string) *testAndroidMk { t.Helper() lib, _ := ctx.ModuleForTests(name, "android_common").Module().(*Library) data := android.AndroidMkDataForTest(t, config, "", lib) w := &bytes.Buffer{} data.Custom(w, name, "", "", data) return newTestAndroidMk(t, w) } func TestRequired(t *testing.T) { config := testConfig(nil) ctx := testContext(config, ` java_library { name: "foo", srcs: ["a.java"], required: ["libfoo"], } `, nil) run(t, ctx, config) mk := getAndroidMk(t, ctx, config, "foo") mk.moduleFor("foo").hasRequired("libfoo") } func TestHostdex(t *testing.T) { config := testConfig(nil) ctx := testContext(config, ` java_library { name: "foo", srcs: ["a.java"], hostdex: true, } `, nil) run(t, ctx, config) mk := getAndroidMk(t, ctx, config, "foo") mk.moduleFor("foo") mk.moduleFor("foo-hostdex") } func TestHostdexRequired(t *testing.T) { config := testConfig(nil) ctx := testContext(config, ` java_library { name: "foo", srcs: ["a.java"], hostdex: true, required: ["libfoo"], } `, nil) run(t, ctx, config) mk := getAndroidMk(t, ctx, config, "foo") mk.moduleFor("foo").hasRequired("libfoo") mk.moduleFor("foo-hostdex").hasRequired("libfoo") } func TestHostdexSpecificRequired(t *testing.T) { config := testConfig(nil) ctx := testContext(config, ` java_library { name: "foo", srcs: ["a.java"], hostdex: true, target: { hostdex: { required: ["libfoo"], }, }, } `, nil) run(t, ctx, config) mk := getAndroidMk(t, ctx, config, "foo") mk.moduleFor("foo").hasNoRequired("libfoo") mk.moduleFor("foo-hostdex").hasRequired("libfoo") }