diff options
Diffstat (limited to 'java/rro_test.go')
-rw-r--r-- | java/rro_test.go | 399 |
1 files changed, 399 insertions, 0 deletions
diff --git a/java/rro_test.go b/java/rro_test.go new file mode 100644 index 000000000..27abbe4f3 --- /dev/null +++ b/java/rro_test.go @@ -0,0 +1,399 @@ +// Copyright 2020 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 ( + "reflect" + "strings" + "testing" + + "android/soong/android" + "android/soong/shared" +) + +func TestRuntimeResourceOverlay(t *testing.T) { + fs := android.MockFS{ + "baz/res/res/values/strings.xml": nil, + "bar/res/res/values/strings.xml": nil, + } + bp := ` + runtime_resource_overlay { + name: "foo", + certificate: "platform", + lineage: "lineage.bin", + product_specific: true, + static_libs: ["bar"], + resource_libs: ["baz"], + aaptflags: ["--keep-raw-values"], + } + + runtime_resource_overlay { + name: "foo_themed", + certificate: "platform", + product_specific: true, + theme: "faza", + overrides: ["foo"], + } + + android_library { + name: "bar", + resource_dirs: ["bar/res"], + } + + android_app { + name: "baz", + sdk_version: "current", + resource_dirs: ["baz/res"], + } + ` + + result := android.GroupFixturePreparers( + PrepareForTestWithJavaDefaultModules, + PrepareForTestWithOverlayBuildComponents, + fs.AddToFixture(), + ).RunTestWithBp(t, bp) + + m := result.ModuleForTests("foo", "android_common") + + // Check AAPT2 link flags. + aapt2Flags := m.Output("package-res.apk").Args["flags"] + expectedFlags := []string{"--keep-raw-values", "--no-resource-deduping", "--no-resource-removal"} + absentFlags := android.RemoveListFromList(expectedFlags, strings.Split(aapt2Flags, " ")) + if len(absentFlags) > 0 { + t.Errorf("expected values, %q are missing in aapt2 link flags, %q", absentFlags, aapt2Flags) + } + + // Check overlay.list output for static_libs dependency. + overlayList := android.PathsRelativeToTop(m.Output("aapt2/overlay.list").Inputs) + staticLibPackage := "out/soong/.intermediates/bar/android_common/package-res.apk" + if !inList(staticLibPackage, overlayList) { + t.Errorf("Stactic lib res package %q missing in overlay list: %q", staticLibPackage, overlayList) + } + + // Check AAPT2 link flags for resource_libs dependency. + resourceLibFlag := "-I " + "out/soong/.intermediates/baz/android_common/package-res.apk" + if !strings.Contains(aapt2Flags, resourceLibFlag) { + t.Errorf("Resource lib flag %q missing in aapt2 link flags: %q", resourceLibFlag, aapt2Flags) + } + + // Check cert signing flag. + signedApk := m.Output("signed/foo.apk") + lineageFlag := signedApk.Args["flags"] + expectedLineageFlag := "--lineage lineage.bin" + if expectedLineageFlag != lineageFlag { + t.Errorf("Incorrect signing lineage flags, expected: %q, got: %q", expectedLineageFlag, lineageFlag) + } + signingFlag := signedApk.Args["certificates"] + expected := "build/make/target/product/security/platform.x509.pem build/make/target/product/security/platform.pk8" + if expected != signingFlag { + t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag) + } + androidMkEntries := android.AndroidMkEntriesForTest(t, result.TestContext, m.Module())[0] + path := androidMkEntries.EntryMap["LOCAL_CERTIFICATE"] + expectedPath := []string{"build/make/target/product/security/platform.x509.pem"} + if !reflect.DeepEqual(path, expectedPath) { + t.Errorf("Unexpected LOCAL_CERTIFICATE value: %v, expected: %v", path, expectedPath) + } + + // Check device location. + path = androidMkEntries.EntryMap["LOCAL_MODULE_PATH"] + expectedPath = []string{shared.JoinPath("out/target/product/test_device/product/overlay")} + android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_MODULE_PATH", result.Config, expectedPath, path) + + // A themed module has a different device location + m = result.ModuleForTests("foo_themed", "android_common") + androidMkEntries = android.AndroidMkEntriesForTest(t, result.TestContext, m.Module())[0] + path = androidMkEntries.EntryMap["LOCAL_MODULE_PATH"] + expectedPath = []string{shared.JoinPath("out/target/product/test_device/product/overlay/faza")} + android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_MODULE_PATH", result.Config, expectedPath, path) + + overrides := androidMkEntries.EntryMap["LOCAL_OVERRIDES_PACKAGES"] + expectedOverrides := []string{"foo"} + if !reflect.DeepEqual(overrides, expectedOverrides) { + t.Errorf("Unexpected LOCAL_OVERRIDES_PACKAGES value: %v, expected: %v", overrides, expectedOverrides) + } +} + +func TestRuntimeResourceOverlay_JavaDefaults(t *testing.T) { + ctx, config := testJava(t, ` + java_defaults { + name: "rro_defaults", + theme: "default_theme", + product_specific: true, + aaptflags: ["--keep-raw-values"], + } + + runtime_resource_overlay { + name: "foo_with_defaults", + defaults: ["rro_defaults"], + } + + runtime_resource_overlay { + name: "foo_barebones", + } + `) + + // + // RRO module with defaults + // + m := ctx.ModuleForTests("foo_with_defaults", "android_common") + + // Check AAPT2 link flags. + aapt2Flags := strings.Split(m.Output("package-res.apk").Args["flags"], " ") + expectedFlags := []string{"--keep-raw-values", "--no-resource-deduping", "--no-resource-removal"} + absentFlags := android.RemoveListFromList(expectedFlags, aapt2Flags) + if len(absentFlags) > 0 { + t.Errorf("expected values, %q are missing in aapt2 link flags, %q", absentFlags, aapt2Flags) + } + + // Check device location. + path := android.AndroidMkEntriesForTest(t, ctx, m.Module())[0].EntryMap["LOCAL_MODULE_PATH"] + expectedPath := []string{shared.JoinPath("out/target/product/test_device/product/overlay/default_theme")} + android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_MODULE_PATH", config, expectedPath, path) + + // + // RRO module without defaults + // + m = ctx.ModuleForTests("foo_barebones", "android_common") + + // Check AAPT2 link flags. + aapt2Flags = strings.Split(m.Output("package-res.apk").Args["flags"], " ") + unexpectedFlags := "--keep-raw-values" + if inList(unexpectedFlags, aapt2Flags) { + t.Errorf("unexpected value, %q is present in aapt2 link flags, %q", unexpectedFlags, aapt2Flags) + } + + // Check device location. + path = android.AndroidMkEntriesForTest(t, ctx, m.Module())[0].EntryMap["LOCAL_MODULE_PATH"] + expectedPath = []string{shared.JoinPath("out/target/product/test_device/product/overlay")} + android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_MODULE_PATH", config, expectedPath, path) +} + +func TestOverrideRuntimeResourceOverlay(t *testing.T) { + ctx, _ := testJava(t, ` + runtime_resource_overlay { + name: "foo_overlay", + certificate: "platform", + product_specific: true, + sdk_version: "current", + } + + override_runtime_resource_overlay { + name: "bar_overlay", + base: "foo_overlay", + package_name: "com.android.bar.overlay", + target_package_name: "com.android.bar", + } + `) + + expectedVariants := []struct { + moduleName string + variantName string + apkPath string + overrides []string + targetVariant string + packageFlag string + targetPackageFlag string + }{ + { + variantName: "android_common", + apkPath: "out/soong/target/product/test_device/product/overlay/foo_overlay.apk", + overrides: nil, + targetVariant: "android_common", + packageFlag: "", + targetPackageFlag: "", + }, + { + variantName: "android_common_bar_overlay", + apkPath: "out/soong/target/product/test_device/product/overlay/bar_overlay.apk", + overrides: []string{"foo_overlay"}, + targetVariant: "android_common_bar", + packageFlag: "com.android.bar.overlay", + targetPackageFlag: "com.android.bar", + }, + } + for _, expected := range expectedVariants { + variant := ctx.ModuleForTests("foo_overlay", expected.variantName) + + // Check the final apk name + variant.Output(expected.apkPath) + + // Check if the overrides field values are correctly aggregated. + mod := variant.Module().(*RuntimeResourceOverlay) + if !reflect.DeepEqual(expected.overrides, mod.properties.Overrides) { + t.Errorf("Incorrect overrides property value, expected: %q, got: %q", + expected.overrides, mod.properties.Overrides) + } + + // Check aapt2 flags. + res := variant.Output("package-res.apk") + aapt2Flags := res.Args["flags"] + checkAapt2LinkFlag(t, aapt2Flags, "rename-manifest-package", expected.packageFlag) + checkAapt2LinkFlag(t, aapt2Flags, "rename-resources-package", "") + checkAapt2LinkFlag(t, aapt2Flags, "rename-overlay-target-package", expected.targetPackageFlag) + } +} + +func TestEnforceRRO_propagatesToDependencies(t *testing.T) { + testCases := []struct { + name string + enforceRROTargets []string + rroDirs map[string][]string + }{ + { + name: "no RRO", + enforceRROTargets: nil, + rroDirs: map[string][]string{ + "foo": nil, + "bar": nil, + }, + }, + { + name: "enforce RRO on all", + enforceRROTargets: []string{"*"}, + rroDirs: map[string][]string{ + "foo": {"product/vendor/blah/overlay/lib2/res"}, + "bar": {"product/vendor/blah/overlay/lib2/res"}, + }, + }, + { + name: "enforce RRO on foo", + enforceRROTargets: []string{"foo"}, + rroDirs: map[string][]string{ + "foo": {"product/vendor/blah/overlay/lib2/res"}, + "bar": {"product/vendor/blah/overlay/lib2/res"}, + }, + }, + } + + productResourceOverlays := []string{ + "product/vendor/blah/overlay", + } + + fs := android.MockFS{ + "lib2/res/values/strings.xml": nil, + "product/vendor/blah/overlay/lib2/res/values/strings.xml": nil, + } + + bp := ` + android_app { + name: "foo", + sdk_version: "current", + resource_dirs: [], + static_libs: ["lib"], + } + + android_app { + name: "bar", + sdk_version: "current", + resource_dirs: [], + static_libs: ["lib"], + } + + android_library { + name: "lib", + sdk_version: "current", + resource_dirs: [], + static_libs: ["lib2"], + } + + android_library { + name: "lib2", + sdk_version: "current", + resource_dirs: ["lib2/res"], + } + ` + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + result := android.GroupFixturePreparers( + PrepareForTestWithJavaDefaultModules, + PrepareForTestWithOverlayBuildComponents, + fs.AddToFixture(), + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + variables.ProductResourceOverlays = productResourceOverlays + if testCase.enforceRROTargets != nil { + variables.EnforceRROTargets = testCase.enforceRROTargets + } + }), + ).RunTestWithBp(t, bp) + + modules := []string{"foo", "bar"} + for _, moduleName := range modules { + module := result.ModuleForTests(moduleName, "android_common") + mkEntries := android.AndroidMkEntriesForTest(t, result.TestContext, module.Module())[0] + actualRRODirs := mkEntries.EntryMap["LOCAL_SOONG_PRODUCT_RRO_DIRS"] + if !reflect.DeepEqual(actualRRODirs, testCase.rroDirs[moduleName]) { + t.Errorf("exected %s LOCAL_SOONG_PRODUCT_RRO_DIRS entry: %v\ngot:%q", + moduleName, testCase.rroDirs[moduleName], actualRRODirs) + } + } + }) + } +} + +func TestRuntimeResourceOverlayPartition(t *testing.T) { + bp := ` + runtime_resource_overlay { + name: "device_specific", + device_specific: true, + } + runtime_resource_overlay { + name: "soc_specific", + soc_specific: true, + } + runtime_resource_overlay { + name: "system_ext_specific", + system_ext_specific: true, + } + runtime_resource_overlay { + name: "product_specific", + product_specific: true, + } + runtime_resource_overlay { + name: "default" + } + ` + testCases := []struct { + name string + expectedPath string + }{ + { + name: "device_specific", + expectedPath: "out/soong/target/product/test_device/odm/overlay", + }, + { + name: "soc_specific", + expectedPath: "out/soong/target/product/test_device/vendor/overlay", + }, + { + name: "system_ext_specific", + expectedPath: "out/soong/target/product/test_device/system_ext/overlay", + }, + { + name: "product_specific", + expectedPath: "out/soong/target/product/test_device/product/overlay", + }, + { + name: "default", + expectedPath: "out/soong/target/product/test_device/product/overlay", + }, + } + for _, testCase := range testCases { + ctx, _ := testJava(t, bp) + mod := ctx.ModuleForTests(testCase.name, "android_common").Module().(*RuntimeResourceOverlay) + android.AssertPathRelativeToTopEquals(t, "Install dir is not correct for "+testCase.name, testCase.expectedPath, mod.installDir) + } +} |