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 etc 16 17import ( 18 "os" 19 "path/filepath" 20 "testing" 21 22 "github.com/google/blueprint/proptools" 23 24 "android/soong/android" 25) 26 27func TestMain(m *testing.M) { 28 os.Exit(m.Run()) 29} 30 31var prepareForPrebuiltEtcTest = android.GroupFixturePreparers( 32 android.PrepareForTestWithArchMutator, 33 PrepareForTestWithPrebuiltEtc, 34 android.FixtureMergeMockFs(android.MockFS{ 35 "foo.conf": nil, 36 "bar.conf": nil, 37 "baz.conf": nil, 38 }), 39) 40 41func TestPrebuiltEtcVariants(t *testing.T) { 42 result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` 43 prebuilt_etc { 44 name: "foo.conf", 45 src: "foo.conf", 46 } 47 prebuilt_etc { 48 name: "bar.conf", 49 src: "bar.conf", 50 recovery_available: true, 51 } 52 prebuilt_etc { 53 name: "baz.conf", 54 src: "baz.conf", 55 recovery: true, 56 } 57 `) 58 59 foo_variants := result.ModuleVariantsForTests("foo.conf") 60 if len(foo_variants) != 1 { 61 t.Errorf("expected 1, got %#v", foo_variants) 62 } 63 64 bar_variants := result.ModuleVariantsForTests("bar.conf") 65 if len(bar_variants) != 2 { 66 t.Errorf("expected 2, got %#v", bar_variants) 67 } 68 69 baz_variants := result.ModuleVariantsForTests("baz.conf") 70 if len(baz_variants) != 1 { 71 t.Errorf("expected 1, got %#v", baz_variants) 72 } 73} 74 75func TestPrebuiltEtcOutputPath(t *testing.T) { 76 result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` 77 prebuilt_etc { 78 name: "foo.conf", 79 src: "foo.conf", 80 filename: "foo.installed.conf", 81 } 82 `) 83 84 p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) 85 android.AssertStringEquals(t, "output file path", "foo.installed.conf", p.outputFilePaths[0].Base()) 86} 87 88func TestPrebuiltEtcGlob(t *testing.T) { 89 result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` 90 prebuilt_etc { 91 name: "my_foo", 92 src: "foo.*", 93 } 94 prebuilt_etc { 95 name: "my_bar", 96 src: "bar.*", 97 filename_from_src: true, 98 } 99 `) 100 101 p := result.Module("my_foo", "android_arm64_armv8-a").(*PrebuiltEtc) 102 android.AssertStringEquals(t, "my_foo output file path", "my_foo", p.outputFilePaths[0].Base()) 103 104 p = result.Module("my_bar", "android_arm64_armv8-a").(*PrebuiltEtc) 105 android.AssertStringEquals(t, "my_bar output file path", "bar.conf", p.outputFilePaths[0].Base()) 106} 107 108func TestPrebuiltEtcMultipleSrcs(t *testing.T) { 109 result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` 110 prebuilt_etc { 111 name: "foo", 112 srcs: ["*.conf"], 113 } 114 `) 115 116 p := result.Module("foo", "android_arm64_armv8-a").(*PrebuiltEtc) 117 android.AssertStringEquals(t, "output file path", "bar.conf", p.outputFilePaths[0].Base()) 118 android.AssertStringEquals(t, "output file path", "baz.conf", p.outputFilePaths[1].Base()) 119 android.AssertStringEquals(t, "output file path", "foo.conf", p.outputFilePaths[2].Base()) 120} 121 122func TestPrebuiltEtcDsts(t *testing.T) { 123 result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` 124 prebuilt_etc { 125 name: "foo", 126 srcs: ["foo.conf", "bar.conf"], 127 dsts: ["foodir/foo.conf", "bardir/extradir/different.name"], 128 } 129 `) 130 131 p := result.Module("foo", "android_arm64_armv8-a").(*PrebuiltEtc) 132 android.AssertStringEquals(t, "output file path", "foo.conf", p.outputFilePaths[0].Base()) 133 android.AssertStringEquals(t, "output file path", "different.name", p.outputFilePaths[1].Base()) 134 135 expectedPaths := [...]string{ 136 "out/soong/target/product/test_device/system/etc/foodir", 137 "out/soong/target/product/test_device/system/etc/bardir/extradir", 138 } 139 android.AssertPathRelativeToTopEquals(t, "install dir", expectedPaths[0], p.installDirPaths[0]) 140 android.AssertPathRelativeToTopEquals(t, "install dir", expectedPaths[1], p.installDirPaths[1]) 141} 142 143func TestPrebuiltEtcDstsPlusRelativeInstallPath(t *testing.T) { 144 result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` 145 prebuilt_etc { 146 name: "foo", 147 srcs: ["foo.conf", "bar.conf"], 148 dsts: ["foodir/foo.conf", "bardir/extradir/different.name"], 149 relative_install_path: "somewhere", 150 } 151 `) 152 153 p := result.Module("foo", "android_arm64_armv8-a").(*PrebuiltEtc) 154 android.AssertStringEquals(t, "output file path", "foo.conf", p.outputFilePaths[0].Base()) 155 android.AssertStringEquals(t, "output file path", "different.name", p.outputFilePaths[1].Base()) 156 157 expectedPaths := [...]string{ 158 "out/soong/target/product/test_device/system/etc/somewhere/foodir", 159 "out/soong/target/product/test_device/system/etc/somewhere/bardir/extradir", 160 } 161 android.AssertPathRelativeToTopEquals(t, "install dir", expectedPaths[0], p.installDirPaths[0]) 162 android.AssertPathRelativeToTopEquals(t, "install dir", expectedPaths[1], p.installDirPaths[1]) 163} 164 165func TestPrebuiltEtcDstsSrcGlob(t *testing.T) { 166 result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` 167 prebuilt_etc { 168 name: "foo", 169 srcs: ["*.conf"], 170 dsts: ["a.conf", "b.conf", "c.conf"], 171 } 172 `) 173 174 p := result.Module("foo", "android_arm64_armv8-a").(*PrebuiltEtc) 175 android.AssertStringEquals(t, "output file path", "a.conf", p.outputFilePaths[0].Base()) 176 android.AssertStringEquals(t, "output file path", "b.conf", p.outputFilePaths[1].Base()) 177 android.AssertStringEquals(t, "output file path", "c.conf", p.outputFilePaths[2].Base()) 178} 179 180func TestPrebuiltEtcDstsSrcGlobDstsTooShort(t *testing.T) { 181 prepareForPrebuiltEtcTest. 182 ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("Must have one entry in dsts per source file")). 183 RunTestWithBp(t, ` 184 prebuilt_etc { 185 name: "foo", 186 srcs: ["*.conf"], 187 dsts: ["a.conf", "b.conf"], 188 } 189 `) 190} 191 192func TestPrebuiltEtcDstsSrcGlobDstsTooLong(t *testing.T) { 193 prepareForPrebuiltEtcTest. 194 ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("Must have one entry in dsts per source file")). 195 RunTestWithBp(t, ` 196 prebuilt_etc { 197 name: "foo", 198 srcs: ["*.conf"], 199 dsts: ["a.conf", "b.conf", "c.conf", "d.conf"], 200 } 201 `) 202} 203 204func TestPrebuiltEtcCannotDstsWithSrc(t *testing.T) { 205 prepareForPrebuiltEtcTest. 206 ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("dsts is set. Must use srcs")). 207 RunTestWithBp(t, ` 208 prebuilt_etc { 209 name: "foo.conf", 210 src: "foo.conf", 211 dsts: ["a.conf"], 212 } 213 `) 214} 215 216func TestPrebuiltEtcCannotDstsWithFilenameFromSrc(t *testing.T) { 217 prepareForPrebuiltEtcTest. 218 ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("dsts is set. Cannot set filename_from_src")). 219 RunTestWithBp(t, ` 220 prebuilt_etc { 221 name: "foo.conf", 222 srcs: ["foo.conf"], 223 dsts: ["a.conf"], 224 filename_from_src: true, 225 } 226 `) 227} 228 229func TestPrebuiltEtcAndroidMk(t *testing.T) { 230 result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` 231 prebuilt_etc { 232 name: "foo", 233 src: "foo.conf", 234 owner: "abc", 235 filename_from_src: true, 236 required: ["modA", "moduleB"], 237 host_required: ["hostModA", "hostModB"], 238 target_required: ["targetModA"], 239 } 240 `) 241 242 expected := map[string][]string{ 243 "LOCAL_MODULE": {"foo"}, 244 "LOCAL_MODULE_CLASS": {"ETC"}, 245 "LOCAL_MODULE_OWNER": {"abc"}, 246 "LOCAL_INSTALLED_MODULE_STEM": {"foo.conf"}, 247 "LOCAL_REQUIRED_MODULES": {"modA", "moduleB"}, 248 "LOCAL_HOST_REQUIRED_MODULES": {"hostModA", "hostModB"}, 249 "LOCAL_TARGET_REQUIRED_MODULES": {"targetModA"}, 250 "LOCAL_SOONG_MODULE_TYPE": {"prebuilt_etc"}, 251 } 252 253 mod := result.Module("foo", "android_arm64_armv8-a").(*PrebuiltEtc) 254 entries := android.AndroidMkEntriesForTest(t, result.TestContext, mod)[0] 255 for k, expectedValue := range expected { 256 if value, ok := entries.EntryMap[k]; ok { 257 android.AssertDeepEquals(t, k, expectedValue, value) 258 } else { 259 t.Errorf("No %s defined, saw %q", k, entries.EntryMap) 260 } 261 } 262} 263 264func TestPrebuiltEtcRelativeInstallPathInstallDirPath(t *testing.T) { 265 result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` 266 prebuilt_etc { 267 name: "foo.conf", 268 src: "foo.conf", 269 relative_install_path: "bar", 270 } 271 `) 272 273 p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) 274 expected := "out/soong/target/product/test_device/system/etc/bar" 275 android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0]) 276} 277 278func TestPrebuiltEtcCannotSetRelativeInstallPathAndSubDir(t *testing.T) { 279 prepareForPrebuiltEtcTest. 280 ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("relative_install_path is set. Cannot set sub_dir")). 281 RunTestWithBp(t, ` 282 prebuilt_etc { 283 name: "foo.conf", 284 src: "foo.conf", 285 sub_dir: "bar", 286 relative_install_path: "bar", 287 } 288 `) 289} 290 291func TestPrebuiltEtcHost(t *testing.T) { 292 result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` 293 prebuilt_etc_host { 294 name: "foo.conf", 295 src: "foo.conf", 296 } 297 `) 298 299 buildOS := result.Config.BuildOS.String() 300 p := result.Module("foo.conf", buildOS+"_common").(*PrebuiltEtc) 301 if !p.Host() { 302 t.Errorf("host bit is not set for a prebuilt_etc_host module.") 303 } 304} 305 306func TestPrebuiltEtcAllowMissingDependencies(t *testing.T) { 307 result := android.GroupFixturePreparers( 308 prepareForPrebuiltEtcTest, 309 android.PrepareForTestDisallowNonExistentPaths, 310 android.FixtureModifyConfig( 311 func(config android.Config) { 312 config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true) 313 }), 314 ).RunTestWithBp(t, ` 315 prebuilt_etc { 316 name: "foo.conf", 317 filename_from_src: true, 318 arch: { 319 x86: { 320 src: "x86.conf", 321 }, 322 }, 323 } 324 `) 325 326 android.AssertStringEquals(t, "expected error rule", "android/soong/android.Error", 327 result.ModuleForTests("foo.conf", "android_arm64_armv8-a").Output("foo.conf").Rule.String()) 328} 329 330func TestPrebuiltRootInstallDirPath(t *testing.T) { 331 result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` 332 prebuilt_root { 333 name: "foo.conf", 334 src: "foo.conf", 335 filename: "foo.conf", 336 } 337 `) 338 339 p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) 340 expected := "out/soong/target/product/test_device/system" 341 android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0]) 342} 343 344func TestPrebuiltRootInstallDirPathValidate(t *testing.T) { 345 prepareForPrebuiltEtcTest.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("filename cannot contain separator")).RunTestWithBp(t, ` 346 prebuilt_root { 347 name: "foo.conf", 348 src: "foo.conf", 349 filename: "foo/bar.conf", 350 } 351 `) 352} 353 354func TestPrebuiltAvbInstallDirPath(t *testing.T) { 355 result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` 356 prebuilt_avb { 357 name: "foo.conf", 358 src: "foo.conf", 359 filename: "foo.conf", 360 //recovery: true, 361 } 362 `) 363 364 p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) 365 expected := "out/soong/target/product/test_device/root/avb" 366 android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0]) 367} 368 369func TestPrebuiltAvdInstallDirPathValidate(t *testing.T) { 370 prepareForPrebuiltEtcTest.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("filename cannot contain separator")).RunTestWithBp(t, ` 371 prebuilt_avb { 372 name: "foo.conf", 373 src: "foo.conf", 374 filename: "foo/bar.conf", 375 } 376 `) 377} 378 379func TestPrebuiltUserShareInstallDirPath(t *testing.T) { 380 result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` 381 prebuilt_usr_share { 382 name: "foo.conf", 383 src: "foo.conf", 384 sub_dir: "bar", 385 } 386 `) 387 388 p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) 389 expected := "out/soong/target/product/test_device/system/usr/share/bar" 390 android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0]) 391} 392 393func TestPrebuiltUserShareHostInstallDirPath(t *testing.T) { 394 result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` 395 prebuilt_usr_share_host { 396 name: "foo.conf", 397 src: "foo.conf", 398 sub_dir: "bar", 399 } 400 `) 401 402 buildOS := result.Config.BuildOS.String() 403 p := result.Module("foo.conf", buildOS+"_common").(*PrebuiltEtc) 404 expected := filepath.Join("out/soong/host", result.Config.PrebuiltOS(), "usr", "share", "bar") 405 android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0]) 406} 407 408func TestPrebuiltPrebuiltUserHyphenDataInstallDirPath(t *testing.T) { 409 result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` 410 prebuilt_usr_hyphendata { 411 name: "foo.conf", 412 src: "foo.conf", 413 sub_dir: "bar", 414 } 415 `) 416 417 p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) 418 expected := "out/soong/target/product/test_device/system/usr/hyphen-data/bar" 419 android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0]) 420} 421 422func TestPrebuiltPrebuiltUserKeyLayoutInstallDirPath(t *testing.T) { 423 result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` 424 prebuilt_usr_keylayout { 425 name: "foo.conf", 426 src: "foo.conf", 427 sub_dir: "bar", 428 } 429 `) 430 431 p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) 432 expected := "out/soong/target/product/test_device/system/usr/keylayout/bar" 433 android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0]) 434} 435 436func TestPrebuiltPrebuiltUserKeyCharsInstallDirPath(t *testing.T) { 437 result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` 438 prebuilt_usr_keychars { 439 name: "foo.conf", 440 src: "foo.conf", 441 sub_dir: "bar", 442 } 443 `) 444 445 p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) 446 expected := "out/soong/target/product/test_device/system/usr/keychars/bar" 447 android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0]) 448} 449 450func TestPrebuiltPrebuiltUserIdcInstallDirPath(t *testing.T) { 451 result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` 452 prebuilt_usr_idc { 453 name: "foo.conf", 454 src: "foo.conf", 455 sub_dir: "bar", 456 } 457 `) 458 459 p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) 460 expected := "out/soong/target/product/test_device/system/usr/idc/bar" 461 android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0]) 462} 463 464func TestPrebuiltFontInstallDirPath(t *testing.T) { 465 result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` 466 prebuilt_font { 467 name: "foo.conf", 468 src: "foo.conf", 469 } 470 `) 471 472 p := result.Module("foo.conf", "android_common").(*PrebuiltEtc) 473 expected := "out/soong/target/product/test_device/system/fonts" 474 android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0]) 475} 476 477func TestPrebuiltOverlayInstallDirPath(t *testing.T) { 478 result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` 479 prebuilt_overlay { 480 name: "foo.conf", 481 src: "foo.conf", 482 } 483 `) 484 485 p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) 486 expected := "out/soong/target/product/test_device/system/overlay" 487 android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0]) 488} 489 490func TestPrebuiltFirmwareDirPath(t *testing.T) { 491 targetPath := "out/soong/target/product/test_device" 492 tests := []struct { 493 description string 494 config string 495 expectedPath string 496 }{{ 497 description: "prebuilt: system firmware", 498 config: ` 499 prebuilt_firmware { 500 name: "foo.conf", 501 src: "foo.conf", 502 }`, 503 expectedPath: filepath.Join(targetPath, "system/etc/firmware"), 504 }, { 505 description: "prebuilt: vendor firmware", 506 config: ` 507 prebuilt_firmware { 508 name: "foo.conf", 509 src: "foo.conf", 510 soc_specific: true, 511 sub_dir: "sub_dir", 512 }`, 513 expectedPath: filepath.Join(targetPath, "vendor/firmware/sub_dir"), 514 }} 515 for _, tt := range tests { 516 t.Run(tt.description, func(t *testing.T) { 517 result := prepareForPrebuiltEtcTest.RunTestWithBp(t, tt.config) 518 p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) 519 android.AssertPathRelativeToTopEquals(t, "install dir", tt.expectedPath, p.installDirPaths[0]) 520 }) 521 } 522} 523 524func TestPrebuiltDSPDirPath(t *testing.T) { 525 targetPath := "out/soong/target/product/test_device" 526 tests := []struct { 527 description string 528 config string 529 expectedPath string 530 }{{ 531 description: "prebuilt: system dsp", 532 config: ` 533 prebuilt_dsp { 534 name: "foo.conf", 535 src: "foo.conf", 536 }`, 537 expectedPath: filepath.Join(targetPath, "system/etc/dsp"), 538 }, { 539 description: "prebuilt: vendor dsp", 540 config: ` 541 prebuilt_dsp { 542 name: "foo.conf", 543 src: "foo.conf", 544 soc_specific: true, 545 sub_dir: "sub_dir", 546 }`, 547 expectedPath: filepath.Join(targetPath, "vendor/dsp/sub_dir"), 548 }} 549 for _, tt := range tests { 550 t.Run(tt.description, func(t *testing.T) { 551 result := prepareForPrebuiltEtcTest.RunTestWithBp(t, tt.config) 552 p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) 553 android.AssertPathRelativeToTopEquals(t, "install dir", tt.expectedPath, p.installDirPaths[0]) 554 }) 555 } 556} 557 558func TestPrebuiltRFSADirPath(t *testing.T) { 559 targetPath := "out/soong/target/product/test_device" 560 tests := []struct { 561 description string 562 config string 563 expectedPath string 564 }{{ 565 description: "prebuilt: system rfsa", 566 config: ` 567 prebuilt_rfsa { 568 name: "foo.conf", 569 src: "foo.conf", 570 }`, 571 expectedPath: filepath.Join(targetPath, "system/lib/rfsa"), 572 }, { 573 description: "prebuilt: vendor rfsa", 574 config: ` 575 prebuilt_rfsa { 576 name: "foo.conf", 577 src: "foo.conf", 578 soc_specific: true, 579 sub_dir: "sub_dir", 580 }`, 581 expectedPath: filepath.Join(targetPath, "vendor/lib/rfsa/sub_dir"), 582 }} 583 for _, tt := range tests { 584 t.Run(tt.description, func(t *testing.T) { 585 result := prepareForPrebuiltEtcTest.RunTestWithBp(t, tt.config) 586 p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) 587 android.AssertPathRelativeToTopEquals(t, "install dir", tt.expectedPath, p.installDirPaths[0]) 588 }) 589 } 590} 591 592func TestPrebuiltMediaAutoDirPath(t *testing.T) { 593 result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` 594 prebuilt_media { 595 name: "foo", 596 src: "Alarm_Beep_01.ogg", 597 product_specific: true, 598 relative_install_path: "alarms" 599 } 600 `) 601 602 p := result.Module("foo", "android_common").(*PrebuiltEtc) 603 expected := "out/soong/target/product/test_device/product/media/alarms" 604 android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0]) 605} 606