1// Copyright 2022 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. 14package apex 15 16import ( 17 "android/soong/android" 18 "android/soong/bazel/cquery" 19 "strings" 20 "testing" 21) 22 23func TestApexImageInMixedBuilds(t *testing.T) { 24 bp := ` 25apex_key{ 26 name: "foo_key", 27} 28 29apex { 30 name: "foo", 31 key: "foo_key", 32 updatable: true, 33 min_sdk_version: "31", 34 file_contexts: ":myapex-file_contexts", 35 bazel_module: { label: "//:foo" }, 36}` 37 38 outputBaseDir := "out/bazel" 39 result := android.GroupFixturePreparers( 40 prepareForApexTest, 41 android.FixtureModifyConfig(func(config android.Config) { 42 config.BazelContext = android.MockBazelContext{ 43 OutputBaseDir: outputBaseDir, 44 LabelToApexInfo: map[string]cquery.ApexInfo{ 45 "//:foo": cquery.ApexInfo{ 46 // ApexInfo Starlark provider. 47 SignedOutput: "signed_out.apex", 48 SignedCompressedOutput: "signed_out.capex", 49 UnsignedOutput: "unsigned_out.apex", 50 BundleKeyInfo: []string{"public_key", "private_key"}, 51 ContainerKeyInfo: []string{"container_cert", "container_private"}, 52 SymbolsUsedByApex: "foo_using.txt", 53 JavaSymbolsUsedByApex: "foo_using.xml", 54 BundleFile: "apex_bundle.zip", 55 InstalledFiles: "installed-files.txt", 56 RequiresLibs: []string{"//path/c:c", "//path/d:d"}, 57 58 // unused 59 PackageName: "pkg_name", 60 ProvidesLibs: []string{"a", "b"}, 61 62 // ApexMkInfo Starlark provider 63 PayloadFilesInfo: []map[string]string{ 64 { 65 "built_file": "bazel-out/adbd", 66 "install_dir": "bin", 67 "class": "nativeExecutable", 68 "make_module_name": "adbd", 69 "basename": "adbd", 70 "package": "foo", 71 }, 72 }, 73 MakeModulesToInstall: []string{"c"}, // d deliberately omitted 74 }, 75 }, 76 } 77 }), 78 ).RunTestWithBp(t, bp) 79 80 m := result.ModuleForTests("foo", "android_common_foo_image").Module() 81 ab, ok := m.(*apexBundle) 82 83 if !ok { 84 t.Fatalf("Expected module to be an apexBundle, was not") 85 } 86 87 // TODO: refactor to android.AssertStringEquals 88 if w, g := "out/bazel/execroot/__main__/public_key", ab.publicKeyFile.String(); w != g { 89 t.Errorf("Expected public key %q, got %q", w, g) 90 } 91 92 if w, g := "out/bazel/execroot/__main__/private_key", ab.privateKeyFile.String(); w != g { 93 t.Errorf("Expected private key %q, got %q", w, g) 94 } 95 96 if w, g := "out/bazel/execroot/__main__/container_cert", ab.containerCertificateFile.String(); w != g { 97 t.Errorf("Expected public container key %q, got %q", w, g) 98 } 99 100 if w, g := "out/bazel/execroot/__main__/container_private", ab.containerPrivateKeyFile.String(); w != g { 101 t.Errorf("Expected private container key %q, got %q", w, g) 102 } 103 104 if w, g := "out/bazel/execroot/__main__/signed_out.apex", ab.outputFile.String(); w != g { 105 t.Errorf("Expected output file %q, got %q", w, g) 106 } 107 108 if w, g := "out/bazel/execroot/__main__/foo_using.txt", ab.nativeApisUsedByModuleFile.String(); w != g { 109 t.Errorf("Expected output file %q, got %q", w, g) 110 } 111 112 if w, g := "out/bazel/execroot/__main__/foo_using.xml", ab.javaApisUsedByModuleFile.String(); w != g { 113 t.Errorf("Expected output file %q, got %q", w, g) 114 } 115 116 if w, g := "out/bazel/execroot/__main__/installed-files.txt", ab.installedFilesFile.String(); w != g { 117 t.Errorf("Expected installed-files.txt %q, got %q", w, g) 118 } 119 120 mkData := android.AndroidMkDataForTest(t, result.TestContext, m) 121 var builder strings.Builder 122 mkData.Custom(&builder, "foo", "BAZEL_TARGET_", "", mkData) 123 124 data := builder.String() 125 if w := "ALL_MODULES.$(my_register_name).BUNDLE := out/bazel/execroot/__main__/apex_bundle.zip"; !strings.Contains(data, w) { 126 t.Errorf("Expected %q in androidmk data, but did not find %q", w, data) 127 } 128 if w := "$(call dist-for-goals,checkbuild,out/bazel/execroot/__main__/installed-files.txt:foo-installed-files.txt)"; !strings.Contains(data, w) { 129 t.Errorf("Expected %q in androidmk data, but did not find %q", w, data) 130 } 131 132 // make modules to be installed to system 133 if len(ab.makeModulesToInstall) != 1 && ab.makeModulesToInstall[0] != "c" { 134 t.Errorf("Expected makeModulesToInstall slice to only contain 'c', got %q", ab.makeModulesToInstall) 135 } 136 if w := "LOCAL_REQUIRED_MODULES := adbd.foo c"; !strings.Contains(data, w) { 137 t.Errorf("Expected %q in androidmk data, but did not find it in %q", w, data) 138 } 139} 140 141func TestApexImageCreatesFilesInfoForMake(t *testing.T) { 142 bp := ` 143apex_key{ 144 name: "foo_key", 145} 146 147apex { 148 name: "foo", 149 key: "foo_key", 150 updatable: true, 151 min_sdk_version: "31", 152 file_contexts: ":myapex-file_contexts", 153 bazel_module: { label: "//:foo" }, 154}` 155 156 outputBaseDir := "out/bazel" 157 result := android.GroupFixturePreparers( 158 prepareForApexTest, 159 android.FixtureModifyConfig(func(config android.Config) { 160 config.BazelContext = android.MockBazelContext{ 161 OutputBaseDir: outputBaseDir, 162 LabelToApexInfo: map[string]cquery.ApexInfo{ 163 "//:foo": { 164 // ApexInfo Starlark provider. Necessary for the test. 165 SignedOutput: "signed_out.apex", 166 BundleKeyInfo: []string{"public_key", "private_key"}, 167 ContainerKeyInfo: []string{"container_cert", "container_private"}, 168 169 // ApexMkInfo Starlark provider 170 PayloadFilesInfo: []map[string]string{ 171 { 172 "arch": "arm64", 173 "basename": "libcrypto.so", 174 "built_file": "bazel-out/64/libcrypto.so", 175 "class": "nativeSharedLib", 176 "install_dir": "lib64", 177 "make_module_name": "libcrypto", 178 "package": "foo/bar", 179 "unstripped_built_file": "bazel-out/64/unstripped_libcrypto.so", 180 }, 181 { 182 "arch": "arm", 183 "basename": "libcrypto.so", 184 "built_file": "bazel-out/32/libcrypto.so", 185 "class": "nativeSharedLib", 186 "install_dir": "lib", 187 "make_module_name": "libcrypto", 188 "package": "foo/bar", 189 }, 190 { 191 "arch": "arm64", 192 "basename": "adbd", 193 "built_file": "bazel-out/adbd", 194 "class": "nativeExecutable", 195 "install_dir": "bin", 196 "make_module_name": "adbd", 197 "package": "foo", 198 }, 199 }, 200 }, 201 }, 202 } 203 }), 204 ).RunTestWithBp(t, bp) 205 206 m := result.ModuleForTests("foo", "android_common_foo_image").Module() 207 ab, ok := m.(*apexBundle) 208 209 if !ok { 210 t.Fatalf("Expected module to be an apexBundle, was not") 211 } 212 213 expectedFilesInfo := []apexFile{ 214 { 215 androidMkModuleName: "libcrypto", 216 builtFile: android.PathForTesting("out/bazel/execroot/__main__/bazel-out/64/libcrypto.so"), 217 class: nativeSharedLib, 218 customStem: "libcrypto.so", 219 installDir: "lib64", 220 moduleDir: "foo/bar", 221 arch: "arm64", 222 unstrippedBuiltFile: android.PathForTesting("out/bazel/execroot/__main__/bazel-out/64/unstripped_libcrypto.so"), 223 }, 224 { 225 androidMkModuleName: "libcrypto", 226 builtFile: android.PathForTesting("out/bazel/execroot/__main__/bazel-out/32/libcrypto.so"), 227 class: nativeSharedLib, 228 customStem: "libcrypto.so", 229 installDir: "lib", 230 moduleDir: "foo/bar", 231 arch: "arm", 232 }, 233 { 234 androidMkModuleName: "adbd", 235 builtFile: android.PathForTesting("out/bazel/execroot/__main__/bazel-out/adbd"), 236 class: nativeExecutable, 237 customStem: "adbd", 238 installDir: "bin", 239 moduleDir: "foo", 240 arch: "arm64", 241 }, 242 } 243 244 if len(ab.filesInfo) != len(expectedFilesInfo) { 245 t.Errorf("Expected %d entries in ab.filesInfo, but got %d", len(ab.filesInfo), len(expectedFilesInfo)) 246 } 247 248 for idx, f := range ab.filesInfo { 249 expected := expectedFilesInfo[idx] 250 android.AssertSame(t, "different class", expected.class, f.class) 251 android.AssertStringEquals(t, "different built file", expected.builtFile.String(), f.builtFile.String()) 252 android.AssertStringEquals(t, "different custom stem", expected.customStem, f.customStem) 253 android.AssertStringEquals(t, "different install dir", expected.installDir, f.installDir) 254 android.AssertStringEquals(t, "different make module name", expected.androidMkModuleName, f.androidMkModuleName) 255 android.AssertStringEquals(t, "different moduleDir", expected.moduleDir, f.moduleDir) 256 android.AssertStringEquals(t, "different arch", expected.arch, f.arch) 257 if expected.unstrippedBuiltFile != nil { 258 if f.unstrippedBuiltFile == nil { 259 t.Errorf("expected an unstripped built file path.") 260 } 261 android.AssertStringEquals(t, "different unstripped built file", expected.unstrippedBuiltFile.String(), f.unstrippedBuiltFile.String()) 262 } 263 } 264} 265 266func TestCompressedApexImageInMixedBuilds(t *testing.T) { 267 bp := ` 268apex_key{ 269 name: "foo_key", 270} 271apex { 272 name: "foo", 273 key: "foo_key", 274 updatable: true, 275 min_sdk_version: "31", 276 file_contexts: ":myapex-file_contexts", 277 bazel_module: { label: "//:foo" }, 278 test_only_force_compression: true, // force compression 279}` 280 281 outputBaseDir := "out/bazel" 282 result := android.GroupFixturePreparers( 283 prepareForApexTest, 284 android.FixtureModifyConfig(func(config android.Config) { 285 config.BazelContext = android.MockBazelContext{ 286 OutputBaseDir: outputBaseDir, 287 LabelToApexInfo: map[string]cquery.ApexInfo{ 288 "//:foo": cquery.ApexInfo{ 289 SignedOutput: "signed_out.apex", 290 SignedCompressedOutput: "signed_out.capex", 291 BundleKeyInfo: []string{"public_key", "private_key"}, 292 ContainerKeyInfo: []string{"container_cert", "container_private"}, 293 }, 294 }, 295 } 296 }), 297 ).RunTestWithBp(t, bp) 298 299 m := result.ModuleForTests("foo", "android_common_foo_image").Module() 300 ab, ok := m.(*apexBundle) 301 if !ok { 302 t.Fatalf("Expected module to be an apexBundle, was not") 303 } 304 305 if w, g := "out/bazel/execroot/__main__/signed_out.capex", ab.outputFile.String(); w != g { 306 t.Errorf("Expected output file to be compressed apex %q, got %q", w, g) 307 } 308 309 mkData := android.AndroidMkDataForTest(t, result.TestContext, m) 310 var builder strings.Builder 311 mkData.Custom(&builder, "foo", "BAZEL_TARGET_", "", mkData) 312 313 data := builder.String() 314 315 expectedAndroidMk := []string{ 316 "LOCAL_PREBUILT_MODULE_FILE := out/bazel/execroot/__main__/signed_out.capex", 317 318 // Check that the source install file is the capex. The dest is not important. 319 "LOCAL_SOONG_INSTALL_PAIRS := out/bazel/execroot/__main__/signed_out.capex:", 320 } 321 for _, androidMk := range expectedAndroidMk { 322 if !strings.Contains(data, androidMk) { 323 t.Errorf("Expected %q in androidmk data, but did not find %q", androidMk, data) 324 } 325 } 326} 327 328func TestOverrideApexImageInMixedBuilds(t *testing.T) { 329 bp := ` 330apex_key{ 331 name: "foo_key", 332} 333apex_key{ 334 name: "override_foo_key", 335} 336apex { 337 name: "foo", 338 key: "foo_key", 339 updatable: true, 340 min_sdk_version: "31", 341 package_name: "pkg_name", 342 file_contexts: ":myapex-file_contexts", 343 bazel_module: { label: "//:foo" }, 344} 345override_apex { 346 name: "override_foo", 347 key: "override_foo_key", 348 package_name: "override_pkg_name", 349 base: "foo", 350 bazel_module: { label: "//:override_foo" }, 351} 352` 353 354 outputBaseDir := "out/bazel" 355 result := android.GroupFixturePreparers( 356 prepareForApexTest, 357 android.FixtureModifyConfig(func(config android.Config) { 358 config.BazelContext = android.MockBazelContext{ 359 OutputBaseDir: outputBaseDir, 360 LabelToApexInfo: map[string]cquery.ApexInfo{ 361 "//:foo": cquery.ApexInfo{ 362 // ApexInfo Starlark provider 363 SignedOutput: "signed_out.apex", 364 UnsignedOutput: "unsigned_out.apex", 365 BundleKeyInfo: []string{"public_key", "private_key"}, 366 ContainerKeyInfo: []string{"container_cert", "container_private"}, 367 SymbolsUsedByApex: "foo_using.txt", 368 JavaSymbolsUsedByApex: "foo_using.xml", 369 BundleFile: "apex_bundle.zip", 370 InstalledFiles: "installed-files.txt", 371 RequiresLibs: []string{"//path/c:c", "//path/d:d"}, 372 373 // unused 374 PackageName: "pkg_name", 375 ProvidesLibs: []string{"a", "b"}, 376 377 // ApexMkInfo Starlark provider 378 MakeModulesToInstall: []string{"c"}, // d deliberately omitted 379 }, 380 "//:override_foo": cquery.ApexInfo{ 381 // ApexInfo Starlark provider 382 SignedOutput: "override_signed_out.apex", 383 UnsignedOutput: "override_unsigned_out.apex", 384 BundleKeyInfo: []string{"override_public_key", "override_private_key"}, 385 ContainerKeyInfo: []string{"override_container_cert", "override_container_private"}, 386 SymbolsUsedByApex: "override_foo_using.txt", 387 JavaSymbolsUsedByApex: "override_foo_using.xml", 388 BundleFile: "override_apex_bundle.zip", 389 InstalledFiles: "override_installed-files.txt", 390 RequiresLibs: []string{"//path/c:c", "//path/d:d"}, 391 392 // unused 393 PackageName: "override_pkg_name", 394 ProvidesLibs: []string{"a", "b"}, 395 396 // ApexMkInfo Starlark provider 397 MakeModulesToInstall: []string{"c"}, // d deliberately omitted 398 }, 399 }, 400 } 401 }), 402 ).RunTestWithBp(t, bp) 403 404 m := result.ModuleForTests("foo", "android_common_override_foo_foo_image").Module() 405 ab, ok := m.(*apexBundle) 406 if !ok { 407 t.Fatalf("Expected module to be an apexBundle, was not") 408 } 409 410 if w, g := "out/bazel/execroot/__main__/override_public_key", ab.publicKeyFile.String(); w != g { 411 t.Errorf("Expected public key %q, got %q", w, g) 412 } 413 414 if w, g := "out/bazel/execroot/__main__/override_private_key", ab.privateKeyFile.String(); w != g { 415 t.Errorf("Expected private key %q, got %q", w, g) 416 } 417 418 if w, g := "out/bazel/execroot/__main__/override_container_cert", ab.containerCertificateFile.String(); w != g { 419 t.Errorf("Expected public container key %q, got %q", w, g) 420 } 421 422 if w, g := "out/bazel/execroot/__main__/override_container_private", ab.containerPrivateKeyFile.String(); w != g { 423 t.Errorf("Expected private container key %q, got %q", w, g) 424 } 425 426 if w, g := "out/bazel/execroot/__main__/override_signed_out.apex", ab.outputFile.String(); w != g { 427 t.Errorf("Expected output file %q, got %q", w, g) 428 } 429 430 if w, g := "out/bazel/execroot/__main__/override_foo_using.txt", ab.nativeApisUsedByModuleFile.String(); w != g { 431 t.Errorf("Expected output file %q, got %q", w, g) 432 } 433 434 if w, g := "out/bazel/execroot/__main__/override_foo_using.xml", ab.javaApisUsedByModuleFile.String(); w != g { 435 t.Errorf("Expected output file %q, got %q", w, g) 436 } 437 438 if w, g := "out/bazel/execroot/__main__/override_installed-files.txt", ab.installedFilesFile.String(); w != g { 439 t.Errorf("Expected installed-files.txt %q, got %q", w, g) 440 } 441 442 mkData := android.AndroidMkDataForTest(t, result.TestContext, m) 443 var builder strings.Builder 444 mkData.Custom(&builder, "override_foo", "BAZEL_TARGET_", "", mkData) 445 446 data := builder.String() 447 if w := "ALL_MODULES.$(my_register_name).BUNDLE := out/bazel/execroot/__main__/override_apex_bundle.zip"; !strings.Contains(data, w) { 448 t.Errorf("Expected %q in androidmk data, but did not find %q", w, data) 449 } 450 if w := "$(call dist-for-goals,checkbuild,out/bazel/execroot/__main__/override_installed-files.txt:override_foo-installed-files.txt)"; !strings.Contains(data, w) { 451 t.Errorf("Expected %q in androidmk data, but did not find %q", w, data) 452 } 453 454 // make modules to be installed to system 455 if len(ab.makeModulesToInstall) != 1 && ab.makeModulesToInstall[0] != "c" { 456 t.Errorf("Expected makeModulestoInstall slice to only contain 'c', got %q", ab.makeModulesToInstall) 457 } 458 if w := "LOCAL_REQUIRED_MODULES := c"; !strings.Contains(data, w) { 459 t.Errorf("Expected %q in androidmk data, but did not find it in %q", w, data) 460 } 461} 462