platform_build_soong/java/app_test.go
Colin Cross b69301ee96 Sort compiled resources by output path
Soong was keeping the compiled resources in the same order as the
input resources, which are sorted lexicographically. Converting the
path names in pathsToAapt2Paths results in a list that is no longer
lexicographically sorted.

Make sorts the inputs to aapt2 link by compiled resource name, so
do the same in Soong.

Bug: 69917341
Test: no change to framework-res.apk when converting to Soong
Change-Id: I29e8339b9969b0d323d469dac140c7e172b7ebfa
2017-12-01 19:16:42 +00:00

239 lines
7.1 KiB
Go

// Copyright 2017 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"
"reflect"
"sort"
"testing"
)
var (
resourceFiles = []string{
"res/layout/layout.xml",
"res/values/strings.xml",
"res/values-en-rUS/strings.xml",
}
compiledResourceFiles = []string{
"aapt2/res/layout_layout.xml.flat",
"aapt2/res/values_strings.arsc.flat",
"aapt2/res/values-en-rUS_strings.arsc.flat",
}
)
func testAppContext(config android.Config, bp string, fs map[string][]byte) *android.TestContext {
appFS := map[string][]byte{}
for k, v := range fs {
appFS[k] = v
}
for _, file := range resourceFiles {
appFS[file] = nil
}
return testContext(config, bp, appFS)
}
func testApp(t *testing.T, bp string) *android.TestContext {
config := testConfig(nil)
ctx := testAppContext(config, bp, nil)
run(t, ctx, config)
return ctx
}
func TestApp(t *testing.T) {
ctx := testApp(t, `
android_app {
name: "foo",
srcs: ["a.java"],
}
`)
foo := ctx.ModuleForTests("foo", "android_common")
expectedLinkImplicits := []string{"AndroidManifest.xml"}
frameworkRes := ctx.ModuleForTests("framework-res", "android_common")
expectedLinkImplicits = append(expectedLinkImplicits,
frameworkRes.Output("package-res.apk").Output.String())
// Test the mapping from input files to compiled output file names
compile := foo.Output(compiledResourceFiles[0])
if !reflect.DeepEqual(resourceFiles, compile.Inputs.Strings()) {
t.Errorf("expected aapt2 compile inputs expected:\n %#v\n got:\n %#v",
resourceFiles, compile.Inputs.Strings())
}
compiledResourceOutputs := compile.Outputs.Strings()
sort.Strings(compiledResourceOutputs)
expectedLinkImplicits = append(expectedLinkImplicits, compiledResourceOutputs...)
list := foo.Output("aapt2/res.list")
expectedLinkImplicits = append(expectedLinkImplicits, list.Output.String())
// Check that the link rule uses
res := ctx.ModuleForTests("foo", "android_common").Output("package-res.apk")
if !reflect.DeepEqual(expectedLinkImplicits, res.Implicits.Strings()) {
t.Errorf("expected aapt2 link implicits expected:\n %#v\n got:\n %#v",
expectedLinkImplicits, res.Implicits.Strings())
}
}
var testEnforceRROTests = []struct {
name string
enforceRROTargets []string
enforceRROExcludedOverlays []string
fooOverlayFiles []string
fooRRODirs []string
barOverlayFiles []string
barRRODirs []string
}{
{
name: "no RRO",
enforceRROTargets: nil,
enforceRROExcludedOverlays: nil,
fooOverlayFiles: []string{
"device/vendor/blah/overlay/foo/res/values/strings.xml",
"device/vendor/blah/static_overlay/foo/res/values/strings.xml",
},
fooRRODirs: nil,
barOverlayFiles: []string{
"device/vendor/blah/overlay/bar/res/values/strings.xml",
"device/vendor/blah/static_overlay/bar/res/values/strings.xml",
},
barRRODirs: nil,
},
{
name: "enforce RRO on foo",
enforceRROTargets: []string{"foo"},
enforceRROExcludedOverlays: []string{"device/vendor/blah/static_overlay"},
fooOverlayFiles: []string{
"device/vendor/blah/static_overlay/foo/res/values/strings.xml",
},
fooRRODirs: []string{
"device/vendor/blah/overlay/foo/res",
},
barOverlayFiles: []string{
"device/vendor/blah/overlay/bar/res/values/strings.xml",
"device/vendor/blah/static_overlay/bar/res/values/strings.xml",
},
barRRODirs: nil,
},
{
name: "enforce RRO on all",
enforceRROTargets: []string{"*"},
enforceRROExcludedOverlays: []string{"device/vendor/blah/static_overlay"},
fooOverlayFiles: []string{
"device/vendor/blah/static_overlay/foo/res/values/strings.xml",
},
fooRRODirs: []string{
"device/vendor/blah/overlay/foo/res",
},
barOverlayFiles: []string{
"device/vendor/blah/static_overlay/bar/res/values/strings.xml",
},
barRRODirs: []string{
"device/vendor/blah/overlay/bar/res",
},
},
}
func TestEnforceRRO(t *testing.T) {
resourceOverlays := []string{
"device/vendor/blah/overlay",
"device/vendor/blah/overlay2",
"device/vendor/blah/static_overlay",
}
fs := map[string][]byte{
"foo/res/res/values/strings.xml": nil,
"bar/res/res/values/strings.xml": nil,
"device/vendor/blah/overlay/foo/res/values/strings.xml": nil,
"device/vendor/blah/overlay/bar/res/values/strings.xml": nil,
"device/vendor/blah/static_overlay/foo/res/values/strings.xml": nil,
"device/vendor/blah/static_overlay/bar/res/values/strings.xml": nil,
"device/vendor/blah/overlay2/res/values/strings.xml": nil,
}
bp := `
android_app {
name: "foo",
resource_dirs: ["foo/res"],
}
android_app {
name: "bar",
resource_dirs: ["bar/res"],
}
`
for _, testCase := range testEnforceRROTests {
t.Run(testCase.name, func(t *testing.T) {
config := testConfig(nil)
config.ProductVariables.ResourceOverlays = &resourceOverlays
if testCase.enforceRROTargets != nil {
config.ProductVariables.EnforceRROTargets = &testCase.enforceRROTargets
}
if testCase.enforceRROExcludedOverlays != nil {
config.ProductVariables.EnforceRROExcludedOverlays = &testCase.enforceRROExcludedOverlays
}
ctx := testAppContext(config, bp, fs)
run(t, ctx, config)
getOverlays := func(moduleName string) ([]string, []string) {
module := ctx.ModuleForTests(moduleName, "android_common")
overlayCompiledPaths := module.Output("aapt2/overlay.list").Inputs.Strings()
var overlayFiles []string
for _, o := range overlayCompiledPaths {
overlayFiles = append(overlayFiles, module.Output(o).Inputs.Strings()...)
}
rroDirs := module.Module().(*AndroidApp).rroDirs.Strings()
return overlayFiles, rroDirs
}
fooOverlayFiles, fooRRODirs := getOverlays("foo")
barOverlayFiles, barRRODirs := getOverlays("bar")
if !reflect.DeepEqual(fooOverlayFiles, testCase.fooOverlayFiles) {
t.Errorf("expected foo overlay files:\n %#v\n got:\n %#v",
testCase.fooOverlayFiles, fooOverlayFiles)
}
if !reflect.DeepEqual(fooRRODirs, testCase.fooRRODirs) {
t.Errorf("expected foo rroDirs: %#v\n got:\n %#v",
testCase.fooRRODirs, fooRRODirs)
}
if !reflect.DeepEqual(barOverlayFiles, testCase.barOverlayFiles) {
t.Errorf("expected bar overlay files:\n %#v\n got:\n %#v",
testCase.barOverlayFiles, barOverlayFiles)
}
if !reflect.DeepEqual(barRRODirs, testCase.barRRODirs) {
t.Errorf("expected bar rroDirs: %#v\n got:\n %#v",
testCase.barRRODirs, barRRODirs)
}
})
}
}