1// Copyright 2018 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 15package dexpreopt 16 17import ( 18 "android/soong/android" 19 "fmt" 20 "testing" 21) 22 23func testSystemModuleConfig(ctx android.PathContext, name string) *ModuleConfig { 24 return testModuleConfig(ctx, name, "system") 25} 26 27func testSystemProductModuleConfig(ctx android.PathContext, name string) *ModuleConfig { 28 return testModuleConfig(ctx, name, "system/product") 29} 30 31func testProductModuleConfig(ctx android.PathContext, name string) *ModuleConfig { 32 return testModuleConfig(ctx, name, "product") 33} 34 35func testModuleConfig(ctx android.PathContext, name, partition string) *ModuleConfig { 36 return createTestModuleConfig( 37 name, 38 fmt.Sprintf("/%s/app/test/%s.apk", partition, name), 39 android.PathForOutput(ctx, fmt.Sprintf("%s/%s.apk", name, name)), 40 android.PathForOutput(ctx, fmt.Sprintf("%s/dex/%s.jar", name, name)), 41 android.PathForOutput(ctx, fmt.Sprintf("%s/enforce_uses_libraries.status", name))) 42} 43 44func testApexModuleConfig(ctx android.PathContext, name, apexName string) *ModuleConfig { 45 return createTestModuleConfig( 46 name, 47 fmt.Sprintf("/apex/%s/javalib/%s.jar", apexName, name), 48 android.PathForOutput(ctx, fmt.Sprintf("%s/dexpreopt/%s.jar", name, name)), 49 android.PathForOutput(ctx, fmt.Sprintf("%s/aligned/%s.jar", name, name)), 50 android.PathForOutput(ctx, fmt.Sprintf("%s/enforce_uses_libraries.status", name))) 51} 52 53func testPlatformSystemServerModuleConfig(ctx android.PathContext, name string) *ModuleConfig { 54 return createTestModuleConfig( 55 name, 56 fmt.Sprintf("/system/framework/%s.jar", name), 57 android.PathForOutput(ctx, fmt.Sprintf("%s/dexpreopt/%s.jar", name, name)), 58 android.PathForOutput(ctx, fmt.Sprintf("%s/aligned/%s.jar", name, name)), 59 android.PathForOutput(ctx, fmt.Sprintf("%s/enforce_uses_libraries.status", name))) 60} 61 62func createTestModuleConfig(name, dexLocation string, buildPath, dexPath, enforceUsesLibrariesStatusFile android.OutputPath) *ModuleConfig { 63 return &ModuleConfig{ 64 Name: name, 65 DexLocation: dexLocation, 66 BuildPath: buildPath, 67 DexPath: dexPath, 68 UncompressedDex: false, 69 HasApkLibraries: false, 70 PreoptFlags: nil, 71 ProfileClassListing: android.OptionalPath{}, 72 ProfileIsTextListing: false, 73 EnforceUsesLibrariesStatusFile: enforceUsesLibrariesStatusFile, 74 EnforceUsesLibraries: false, 75 ClassLoaderContexts: nil, 76 Archs: []android.ArchType{android.Arm}, 77 DexPreoptImagesDeps: []android.OutputPaths{android.OutputPaths{}}, 78 DexPreoptImageLocationsOnHost: []string{}, 79 PreoptBootClassPathDexFiles: nil, 80 PreoptBootClassPathDexLocations: nil, 81 PreoptExtractedApk: false, 82 NoCreateAppImage: false, 83 ForceCreateAppImage: false, 84 PresignedPrebuilt: false, 85 } 86} 87 88func TestDexPreopt(t *testing.T) { 89 config := android.TestConfig("out", nil, "", nil) 90 ctx := android.BuilderContextForTesting(config) 91 globalSoong := globalSoongConfigForTests() 92 global := GlobalConfigForTests(ctx) 93 module := testSystemModuleConfig(ctx, "test") 94 95 rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module) 96 if err != nil { 97 t.Fatal(err) 98 } 99 100 wantInstalls := android.RuleBuilderInstalls{ 101 {android.PathForOutput(ctx, "test/oat/arm/package.odex"), "/system/app/test/oat/arm/test.odex"}, 102 {android.PathForOutput(ctx, "test/oat/arm/package.vdex"), "/system/app/test/oat/arm/test.vdex"}, 103 } 104 105 if rule.Installs().String() != wantInstalls.String() { 106 t.Errorf("\nwant installs:\n %v\ngot:\n %v", wantInstalls, rule.Installs()) 107 } 108} 109 110func TestDexPreoptSystemOther(t *testing.T) { 111 config := android.TestConfig("out", nil, "", nil) 112 ctx := android.BuilderContextForTesting(config) 113 globalSoong := globalSoongConfigForTests() 114 global := GlobalConfigForTests(ctx) 115 systemModule := testSystemModuleConfig(ctx, "Stest") 116 systemProductModule := testSystemProductModuleConfig(ctx, "SPtest") 117 productModule := testProductModuleConfig(ctx, "Ptest") 118 119 global.HasSystemOther = true 120 121 type moduleTest struct { 122 module *ModuleConfig 123 expectedPartition string 124 } 125 tests := []struct { 126 patterns []string 127 moduleTests []moduleTest 128 }{ 129 { 130 patterns: []string{"app/%"}, 131 moduleTests: []moduleTest{ 132 {module: systemModule, expectedPartition: "system_other/system"}, 133 {module: systemProductModule, expectedPartition: "system/product"}, 134 {module: productModule, expectedPartition: "product"}, 135 }, 136 }, 137 // product/app/% only applies to product apps inside the system partition 138 { 139 patterns: []string{"app/%", "product/app/%"}, 140 moduleTests: []moduleTest{ 141 {module: systemModule, expectedPartition: "system_other/system"}, 142 {module: systemProductModule, expectedPartition: "system_other/system/product"}, 143 {module: productModule, expectedPartition: "product"}, 144 }, 145 }, 146 } 147 148 for _, test := range tests { 149 global.PatternsOnSystemOther = test.patterns 150 for _, mt := range test.moduleTests { 151 rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, mt.module) 152 if err != nil { 153 t.Fatal(err) 154 } 155 156 name := mt.module.Name 157 wantInstalls := android.RuleBuilderInstalls{ 158 {android.PathForOutput(ctx, name+"/oat/arm/package.odex"), fmt.Sprintf("/%s/app/test/oat/arm/%s.odex", mt.expectedPartition, name)}, 159 {android.PathForOutput(ctx, name+"/oat/arm/package.vdex"), fmt.Sprintf("/%s/app/test/oat/arm/%s.vdex", mt.expectedPartition, name)}, 160 } 161 162 if rule.Installs().String() != wantInstalls.String() { 163 t.Errorf("\nwant installs:\n %v\ngot:\n %v", wantInstalls, rule.Installs()) 164 } 165 } 166 } 167 168} 169 170func TestDexPreoptApexSystemServerJars(t *testing.T) { 171 config := android.TestConfig("out", nil, "", nil) 172 ctx := android.BuilderContextForTesting(config) 173 globalSoong := globalSoongConfigForTests() 174 global := GlobalConfigForTests(ctx) 175 module := testApexModuleConfig(ctx, "service-A", "com.android.apex1") 176 177 global.ApexSystemServerJars = android.CreateTestConfiguredJarList( 178 []string{"com.android.apex1:service-A"}) 179 180 rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module) 181 if err != nil { 182 t.Fatal(err) 183 } 184 185 wantInstalls := android.RuleBuilderInstalls{ 186 {android.PathForOutput(ctx, "service-A/dexpreopt/oat/arm/javalib.odex"), "/system/framework/oat/arm/apex@com.android.apex1@javalib@service-A.jar@classes.odex"}, 187 {android.PathForOutput(ctx, "service-A/dexpreopt/oat/arm/javalib.vdex"), "/system/framework/oat/arm/apex@com.android.apex1@javalib@service-A.jar@classes.vdex"}, 188 } 189 190 android.AssertStringEquals(t, "installs", wantInstalls.String(), rule.Installs().String()) 191} 192 193func TestDexPreoptStandaloneSystemServerJars(t *testing.T) { 194 config := android.TestConfig("out", nil, "", nil) 195 ctx := android.BuilderContextForTesting(config) 196 globalSoong := globalSoongConfigForTests() 197 global := GlobalConfigForTests(ctx) 198 module := testPlatformSystemServerModuleConfig(ctx, "service-A") 199 200 global.StandaloneSystemServerJars = android.CreateTestConfiguredJarList( 201 []string{"platform:service-A"}) 202 203 rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module) 204 if err != nil { 205 t.Fatal(err) 206 } 207 208 wantInstalls := android.RuleBuilderInstalls{ 209 {android.PathForOutput(ctx, "service-A/dexpreopt/oat/arm/javalib.odex"), "/system/framework/oat/arm/service-A.odex"}, 210 {android.PathForOutput(ctx, "service-A/dexpreopt/oat/arm/javalib.vdex"), "/system/framework/oat/arm/service-A.vdex"}, 211 } 212 213 android.AssertStringEquals(t, "installs", wantInstalls.String(), rule.Installs().String()) 214} 215 216func TestDexPreoptApexStandaloneSystemServerJars(t *testing.T) { 217 config := android.TestConfig("out", nil, "", nil) 218 ctx := android.BuilderContextForTesting(config) 219 globalSoong := globalSoongConfigForTests() 220 global := GlobalConfigForTests(ctx) 221 module := testApexModuleConfig(ctx, "service-A", "com.android.apex1") 222 223 global.ApexStandaloneSystemServerJars = android.CreateTestConfiguredJarList( 224 []string{"com.android.apex1:service-A"}) 225 226 rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module) 227 if err != nil { 228 t.Fatal(err) 229 } 230 231 wantInstalls := android.RuleBuilderInstalls{ 232 {android.PathForOutput(ctx, "service-A/dexpreopt/oat/arm/javalib.odex"), "/system/framework/oat/arm/apex@com.android.apex1@javalib@service-A.jar@classes.odex"}, 233 {android.PathForOutput(ctx, "service-A/dexpreopt/oat/arm/javalib.vdex"), "/system/framework/oat/arm/apex@com.android.apex1@javalib@service-A.jar@classes.vdex"}, 234 } 235 236 android.AssertStringEquals(t, "installs", wantInstalls.String(), rule.Installs().String()) 237} 238 239func TestDexPreoptProfile(t *testing.T) { 240 config := android.TestConfig("out", nil, "", nil) 241 ctx := android.BuilderContextForTesting(config) 242 globalSoong := globalSoongConfigForTests() 243 global := GlobalConfigForTests(ctx) 244 module := testSystemModuleConfig(ctx, "test") 245 246 module.ProfileClassListing = android.OptionalPathForPath(android.PathForTesting("profile")) 247 248 rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module) 249 if err != nil { 250 t.Fatal(err) 251 } 252 253 wantInstalls := android.RuleBuilderInstalls{ 254 {android.PathForOutput(ctx, "test/profile.prof"), "/system/app/test/test.apk.prof"}, 255 {android.PathForOutput(ctx, "test/oat/arm/package.art"), "/system/app/test/oat/arm/test.art"}, 256 {android.PathForOutput(ctx, "test/oat/arm/package.odex"), "/system/app/test/oat/arm/test.odex"}, 257 {android.PathForOutput(ctx, "test/oat/arm/package.vdex"), "/system/app/test/oat/arm/test.vdex"}, 258 } 259 260 if rule.Installs().String() != wantInstalls.String() { 261 t.Errorf("\nwant installs:\n %v\ngot:\n %v", wantInstalls, rule.Installs()) 262 } 263} 264 265func TestDexPreoptConfigToJson(t *testing.T) { 266 config := android.TestConfig("out", nil, "", nil) 267 ctx := android.BuilderContextForTesting(config) 268 module := testSystemModuleConfig(ctx, "test") 269 data, err := moduleConfigToJSON(module) 270 if err != nil { 271 t.Errorf("Failed to convert module config data to JSON, %v", err) 272 } 273 parsed, err := ParseModuleConfig(ctx, data) 274 if err != nil { 275 t.Errorf("Failed to parse JSON, %v", err) 276 } 277 before := fmt.Sprintf("%v", module) 278 after := fmt.Sprintf("%v", parsed) 279 android.AssertStringEquals(t, "The result must be the same as the original after marshalling and unmarshalling it.", before, after) 280} 281