diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2019-07-16 02:09:29 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2019-07-16 02:09:29 +0000 |
commit | 0f7dbd0d553e7bd5dc09d11464ef2df782822aee (patch) | |
tree | dea0fc501d7dce54d767d4ff0cd162eb44f98528 | |
parent | 34b1b279814b2131ecfa3b4d14fdbae02b391951 (diff) | |
parent | 12df5fb47174ac5a4f365deb99942644092b549b (diff) | |
download | build_soong-0f7dbd0d553e7bd5dc09d11464ef2df782822aee.tar.gz build_soong-0f7dbd0d553e7bd5dc09d11464ef2df782822aee.tar.bz2 build_soong-0f7dbd0d553e7bd5dc09d11464ef2df782822aee.zip |
Merge "soong: Fix AndroidMk with *Required properties"
-rw-r--r-- | Android.bp | 2 | ||||
-rw-r--r-- | android/androidmk.go | 38 | ||||
-rw-r--r-- | android/androidmk_test.go | 82 | ||||
-rw-r--r-- | android/testing.go | 11 | ||||
-rw-r--r-- | android/util.go | 11 | ||||
-rw-r--r-- | java/androidmk_test.go | 184 |
6 files changed, 314 insertions, 14 deletions
@@ -81,6 +81,7 @@ bootstrap_go_package { ], testSrcs: [ "android/android_test.go", + "android/androidmk_test.go", "android/arch_test.go", "android/config_test.go", "android/expand_test.go", @@ -291,6 +292,7 @@ bootstrap_go_package { "java/testing.go", ], testSrcs: [ + "java/androidmk_test.go", "java/app_test.go", "java/device_host_converter_test.go", "java/dexpreopt_test.go", diff --git a/android/androidmk.go b/android/androidmk.go index 9bc26922..c24ac578 100644 --- a/android/androidmk.go +++ b/android/androidmk.go @@ -391,19 +391,7 @@ func translateGoBinaryModule(ctx SingletonContext, w io.Writer, mod blueprint.Mo return nil } -func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Module, - provider AndroidMkDataProvider) error { - - amod := mod.(Module).base() - if shouldSkipAndroidMkProcessing(amod) { - return nil - } - - data := provider.AndroidMk() - if data.Include == "" { - data.Include = "$(BUILD_PREBUILT)" - } - +func (data *AndroidMkData) fillInData(config Config, bpPath string, mod blueprint.Module) { // Get the preamble content through AndroidMkEntries logic. entries := AndroidMkEntries{ Class: data.Class, @@ -416,11 +404,33 @@ func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Mod Host_required: data.Host_required, Target_required: data.Target_required, } - entries.fillInEntries(ctx.Config(), ctx.BlueprintFile(mod), mod) + entries.fillInEntries(config, bpPath, mod) + // preamble doesn't need the footer content. entries.footer = bytes.Buffer{} entries.write(&data.preamble) + // copy entries back to data since it is used in Custom + data.Required = entries.Required + data.Host_required = entries.Host_required + data.Target_required = entries.Target_required +} + +func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Module, + provider AndroidMkDataProvider) error { + + amod := mod.(Module).base() + if shouldSkipAndroidMkProcessing(amod) { + return nil + } + + data := provider.AndroidMk() + if data.Include == "" { + data.Include = "$(BUILD_PREBUILT)" + } + + data.fillInData(ctx.Config(), ctx.BlueprintFile(mod), mod) + prefix := "" if amod.ArchSpecific() { switch amod.Os().Class { diff --git a/android/androidmk_test.go b/android/androidmk_test.go new file mode 100644 index 00000000..0bb455bb --- /dev/null +++ b/android/androidmk_test.go @@ -0,0 +1,82 @@ +// 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 android + +import ( + "io" + "reflect" + "testing" +) + +type customModule struct { + ModuleBase + data AndroidMkData +} + +func (m *customModule) GenerateAndroidBuildActions(ctx ModuleContext) { +} + +func (m *customModule) AndroidMk() AndroidMkData { + return AndroidMkData{ + Custom: func(w io.Writer, name, prefix, moduleDir string, data AndroidMkData) { + m.data = data + }, + } +} + +func customModuleFactory() Module { + module := &customModule{} + InitAndroidModule(module) + return module +} + +func TestAndroidMkSingleton_PassesUpdatedAndroidMkDataToCustomCallback(t *testing.T) { + config := TestConfig(buildDir, nil) + config.inMake = true // Enable androidmk Singleton + + ctx := NewTestContext() + ctx.RegisterSingletonType("androidmk", SingletonFactoryAdaptor(AndroidMkSingleton)) + ctx.RegisterModuleType("custom", ModuleFactoryAdaptor(customModuleFactory)) + ctx.Register() + + bp := ` + custom { + name: "foo", + required: ["bar"], + host_required: ["baz"], + target_required: ["qux"], + } + ` + + ctx.MockFileSystem(map[string][]byte{ + "Android.bp": []byte(bp), + }) + + _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) + FailIfErrored(t, errs) + _, errs = ctx.PrepareBuildActions(config) + FailIfErrored(t, errs) + + m := ctx.ModuleForTests("foo", "").Module().(*customModule) + + assertEqual := func(expected interface{}, actual interface{}) { + if !reflect.DeepEqual(expected, actual) { + t.Errorf("%q expected, but got %q", expected, actual) + } + } + assertEqual([]string{"bar"}, m.data.Required) + assertEqual([]string{"baz"}, m.data.Host_required) + assertEqual([]string{"qux"}, m.data.Target_required) +} diff --git a/android/testing.go b/android/testing.go index 44bee4b7..12e30ec5 100644 --- a/android/testing.go +++ b/android/testing.go @@ -382,3 +382,14 @@ func AndroidMkEntriesForTest(t *testing.T, config Config, bpPath string, mod blu entries.fillInEntries(config, bpPath, mod) return entries } + +func AndroidMkDataForTest(t *testing.T, config Config, bpPath string, mod blueprint.Module) AndroidMkData { + var p AndroidMkDataProvider + var ok bool + if p, ok = mod.(AndroidMkDataProvider); !ok { + t.Errorf("module does not implmement AndroidMkDataProvider: " + mod.Name()) + } + data := p.AndroidMk() + data.fillInData(config, bpPath, mod) + return data +} diff --git a/android/util.go b/android/util.go index 3b8bc783..97bec102 100644 --- a/android/util.go +++ b/android/util.go @@ -115,6 +115,17 @@ func PrefixInList(s string, list []string) bool { return false } +// IndexListPred returns the index of the element which in the given `list` satisfying the predicate, or -1 if there is no such element. +func IndexListPred(pred func(s string) bool, list []string) int { + for i, l := range list { + if pred(l) { + return i + } + } + + return -1 +} + func FilterList(list []string, filter []string) (remainder []string, filtered []string) { for _, l := range list { if InList(l, filter) { diff --git a/java/androidmk_test.go b/java/androidmk_test.go new file mode 100644 index 00000000..107837d0 --- /dev/null +++ b/java/androidmk_test.go @@ -0,0 +1,184 @@ +// 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") +} |