1// Copyright 2020 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 bp2build 16 17import ( 18 "fmt" 19 "strings" 20 "testing" 21 22 "android/soong/android" 23 "android/soong/android/allowlists" 24 "android/soong/python" 25) 26 27func TestGenerateSoongModuleTargets(t *testing.T) { 28 testCases := []struct { 29 description string 30 bp string 31 expectedBazelTarget string 32 }{ 33 { 34 description: "only name", 35 bp: `custom { name: "foo" } 36 `, 37 expectedBazelTarget: `soong_module( 38 name = "foo", 39 soong_module_name = "foo", 40 soong_module_type = "custom", 41 soong_module_variant = "", 42 soong_module_deps = [ 43 ], 44 bool_prop = False, 45 string_prop = "", 46)`, 47 }, 48 { 49 description: "handles bool", 50 bp: `custom { 51 name: "foo", 52 bool_prop: true, 53} 54 `, 55 expectedBazelTarget: `soong_module( 56 name = "foo", 57 soong_module_name = "foo", 58 soong_module_type = "custom", 59 soong_module_variant = "", 60 soong_module_deps = [ 61 ], 62 bool_prop = True, 63 string_prop = "", 64)`, 65 }, 66 { 67 description: "string escaping", 68 bp: `custom { 69 name: "foo", 70 owner: "a_string_with\"quotes\"_and_\\backslashes\\\\", 71} 72 `, 73 expectedBazelTarget: `soong_module( 74 name = "foo", 75 soong_module_name = "foo", 76 soong_module_type = "custom", 77 soong_module_variant = "", 78 soong_module_deps = [ 79 ], 80 bool_prop = False, 81 owner = "a_string_with\"quotes\"_and_\\backslashes\\\\", 82 string_prop = "", 83)`, 84 }, 85 { 86 description: "single item string list", 87 bp: `custom { 88 name: "foo", 89 required: ["bar"], 90} 91 `, 92 expectedBazelTarget: `soong_module( 93 name = "foo", 94 soong_module_name = "foo", 95 soong_module_type = "custom", 96 soong_module_variant = "", 97 soong_module_deps = [ 98 ], 99 bool_prop = False, 100 required = ["bar"], 101 string_prop = "", 102)`, 103 }, 104 { 105 description: "list of strings", 106 bp: `custom { 107 name: "foo", 108 target_required: ["qux", "bazqux"], 109} 110 `, 111 expectedBazelTarget: `soong_module( 112 name = "foo", 113 soong_module_name = "foo", 114 soong_module_type = "custom", 115 soong_module_variant = "", 116 soong_module_deps = [ 117 ], 118 bool_prop = False, 119 string_prop = "", 120 target_required = [ 121 "qux", 122 "bazqux", 123 ], 124)`, 125 }, 126 { 127 description: "dist/dists", 128 bp: `custom { 129 name: "foo", 130 dist: { 131 targets: ["goal_foo"], 132 tag: ".foo", 133 }, 134 dists: [{ 135 targets: ["goal_bar"], 136 tag: ".bar", 137 }], 138} 139 `, 140 expectedBazelTarget: `soong_module( 141 name = "foo", 142 soong_module_name = "foo", 143 soong_module_type = "custom", 144 soong_module_variant = "", 145 soong_module_deps = [ 146 ], 147 bool_prop = False, 148 dist = { 149 "tag": ".foo", 150 "targets": ["goal_foo"], 151 }, 152 dists = [{ 153 "tag": ".bar", 154 "targets": ["goal_bar"], 155 }], 156 string_prop = "", 157)`, 158 }, 159 { 160 description: "put it together", 161 bp: `custom { 162 name: "foo", 163 required: ["bar"], 164 target_required: ["qux", "bazqux"], 165 bool_prop: true, 166 owner: "custom_owner", 167 dists: [ 168 { 169 tag: ".tag", 170 targets: ["my_goal"], 171 }, 172 ], 173} 174 `, 175 expectedBazelTarget: `soong_module( 176 name = "foo", 177 soong_module_name = "foo", 178 soong_module_type = "custom", 179 soong_module_variant = "", 180 soong_module_deps = [ 181 ], 182 bool_prop = True, 183 dists = [{ 184 "tag": ".tag", 185 "targets": ["my_goal"], 186 }], 187 owner = "custom_owner", 188 required = ["bar"], 189 string_prop = "", 190 target_required = [ 191 "qux", 192 "bazqux", 193 ], 194)`, 195 }, 196 } 197 198 dir := "." 199 for _, testCase := range testCases { 200 t.Run(testCase.description, func(t *testing.T) { 201 config := android.TestConfig(buildDir, nil, testCase.bp, nil) 202 ctx := android.NewTestContext(config) 203 204 ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice) 205 ctx.Register() 206 207 _, errs := ctx.ParseFileList(dir, []string{"Android.bp"}) 208 android.FailIfErrored(t, errs) 209 _, errs = ctx.PrepareBuildActions(config) 210 android.FailIfErrored(t, errs) 211 212 codegenCtx := NewCodegenContext(config, ctx.Context, QueryView, "") 213 bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir) 214 android.FailIfErrored(t, err) 215 if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount { 216 t.Fatalf("Expected %d bazel target, got %d", expectedCount, actualCount) 217 } 218 219 actualBazelTarget := bazelTargets[0] 220 if actualBazelTarget.content != testCase.expectedBazelTarget { 221 t.Errorf( 222 "Expected generated Bazel target to be '%s', got '%s'", 223 testCase.expectedBazelTarget, 224 actualBazelTarget.content, 225 ) 226 } 227 }) 228 } 229} 230 231func TestGenerateBazelTargetModules(t *testing.T) { 232 testCases := []Bp2buildTestCase{ 233 { 234 Description: "string prop empty", 235 Blueprint: `custom { 236 name: "foo", 237 string_literal_prop: "", 238 bazel_module: { bp2build_available: true }, 239}`, 240 ExpectedBazelTargets: []string{ 241 MakeBazelTarget("custom", "foo", AttrNameToString{ 242 "string_literal_prop": `""`, 243 }), 244 }, 245 }, 246 { 247 Description: `string prop "PROP"`, 248 Blueprint: `custom { 249 name: "foo", 250 string_literal_prop: "PROP", 251 bazel_module: { bp2build_available: true }, 252}`, 253 ExpectedBazelTargets: []string{ 254 MakeBazelTarget("custom", "foo", AttrNameToString{ 255 "string_literal_prop": `"PROP"`, 256 }), 257 }, 258 }, 259 { 260 Description: `string prop arch variant`, 261 Blueprint: `custom { 262 name: "foo", 263 arch: { 264 arm: { string_literal_prop: "ARM" }, 265 arm64: { string_literal_prop: "ARM64" }, 266 }, 267 bazel_module: { bp2build_available: true }, 268}`, 269 ExpectedBazelTargets: []string{ 270 MakeBazelTarget("custom", "foo", AttrNameToString{ 271 "string_literal_prop": `select({ 272 "//build/bazel/platforms/arch:arm": "ARM", 273 "//build/bazel/platforms/arch:arm64": "ARM64", 274 "//conditions:default": None, 275 })`, 276 }), 277 }, 278 }, 279 { 280 Description: "string ptr props", 281 Blueprint: `custom { 282 name: "foo", 283 string_ptr_prop: "", 284 bazel_module: { bp2build_available: true }, 285}`, 286 ExpectedBazelTargets: []string{ 287 MakeBazelTarget("custom", "foo", AttrNameToString{ 288 "string_ptr_prop": `""`, 289 }), 290 }, 291 }, 292 { 293 Description: "string list props", 294 Blueprint: `custom { 295 name: "foo", 296 string_list_prop: ["a", "b"], 297 string_ptr_prop: "a", 298 bazel_module: { bp2build_available: true }, 299}`, 300 ExpectedBazelTargets: []string{ 301 MakeBazelTarget("custom", "foo", AttrNameToString{ 302 "string_list_prop": `[ 303 "a", 304 "b", 305 ]`, 306 "string_ptr_prop": `"a"`, 307 }), 308 }, 309 }, 310 { 311 Description: "control characters", 312 Blueprint: `custom { 313 name: "foo", 314 string_list_prop: ["\t", "\n"], 315 string_ptr_prop: "a\t\n\r", 316 bazel_module: { bp2build_available: true }, 317}`, 318 ExpectedBazelTargets: []string{ 319 MakeBazelTarget("custom", "foo", AttrNameToString{ 320 "string_list_prop": `[ 321 "\t", 322 "\n", 323 ]`, 324 "string_ptr_prop": `"a\t\n\r"`, 325 }), 326 }, 327 }, 328 { 329 Description: "handles dep", 330 Blueprint: `custom { 331 name: "has_dep", 332 arch_paths: [":dep"], 333 bazel_module: { bp2build_available: true }, 334} 335 336custom { 337 name: "dep", 338 arch_paths: ["abc"], 339 bazel_module: { bp2build_available: true }, 340}`, 341 ExpectedBazelTargets: []string{ 342 MakeBazelTarget("custom", "dep", AttrNameToString{ 343 "arch_paths": `["abc"]`, 344 }), 345 MakeBazelTarget("custom", "has_dep", AttrNameToString{ 346 "arch_paths": `[":dep"]`, 347 }), 348 }, 349 }, 350 { 351 Description: "non-existent dep", 352 Blueprint: `custom { 353 name: "has_dep", 354 arch_paths: [":dep"], 355 bazel_module: { bp2build_available: true }, 356}`, 357 ExpectedBazelTargets: []string{ 358 MakeBazelTarget("custom", "has_dep", AttrNameToString{ 359 "arch_paths": `[":dep__BP2BUILD__MISSING__DEP"]`, 360 }), 361 }, 362 }, 363 { 364 Description: "arch-variant srcs", 365 Blueprint: `custom { 366 name: "arch_paths", 367 arch: { 368 x86: { arch_paths: ["x86.txt"] }, 369 x86_64: { arch_paths: ["x86_64.txt"] }, 370 arm: { arch_paths: ["arm.txt"] }, 371 arm64: { arch_paths: ["arm64.txt"] }, 372 riscv64: { arch_paths: ["riscv64.txt"] }, 373 }, 374 target: { 375 linux: { arch_paths: ["linux.txt"] }, 376 bionic: { arch_paths: ["bionic.txt"] }, 377 host: { arch_paths: ["host.txt"] }, 378 not_windows: { arch_paths: ["not_windows.txt"] }, 379 android: { arch_paths: ["android.txt"] }, 380 linux_musl: { arch_paths: ["linux_musl.txt"] }, 381 musl: { arch_paths: ["musl.txt"] }, 382 linux_glibc: { arch_paths: ["linux_glibc.txt"] }, 383 glibc: { arch_paths: ["glibc.txt"] }, 384 linux_bionic: { arch_paths: ["linux_bionic.txt"] }, 385 darwin: { arch_paths: ["darwin.txt"] }, 386 windows: { arch_paths: ["windows.txt"] }, 387 }, 388 multilib: { 389 lib32: { arch_paths: ["lib32.txt"] }, 390 lib64: { arch_paths: ["lib64.txt"] }, 391 }, 392 bazel_module: { bp2build_available: true }, 393}`, 394 ExpectedBazelTargets: []string{ 395 MakeBazelTarget("custom", "arch_paths", AttrNameToString{ 396 "arch_paths": `select({ 397 "//build/bazel/platforms/arch:arm": [ 398 "arm.txt", 399 "lib32.txt", 400 ], 401 "//build/bazel/platforms/arch:arm64": [ 402 "arm64.txt", 403 "lib64.txt", 404 ], 405 "//build/bazel/platforms/arch:riscv64": [ 406 "riscv64.txt", 407 "lib64.txt", 408 ], 409 "//build/bazel/platforms/arch:x86": [ 410 "x86.txt", 411 "lib32.txt", 412 ], 413 "//build/bazel/platforms/arch:x86_64": [ 414 "x86_64.txt", 415 "lib64.txt", 416 ], 417 "//conditions:default": [], 418 }) + select({ 419 "//build/bazel/platforms/os:android": [ 420 "linux.txt", 421 "bionic.txt", 422 "android.txt", 423 ], 424 "//build/bazel/platforms/os:darwin": [ 425 "host.txt", 426 "darwin.txt", 427 "not_windows.txt", 428 ], 429 "//build/bazel/platforms/os:linux_bionic": [ 430 "host.txt", 431 "linux.txt", 432 "bionic.txt", 433 "linux_bionic.txt", 434 "not_windows.txt", 435 ], 436 "//build/bazel/platforms/os:linux_glibc": [ 437 "host.txt", 438 "linux.txt", 439 "glibc.txt", 440 "linux_glibc.txt", 441 "not_windows.txt", 442 ], 443 "//build/bazel/platforms/os:linux_musl": [ 444 "host.txt", 445 "linux.txt", 446 "musl.txt", 447 "linux_musl.txt", 448 "not_windows.txt", 449 ], 450 "//build/bazel/platforms/os:windows": [ 451 "host.txt", 452 "windows.txt", 453 ], 454 "//conditions:default": [], 455 })`, 456 }), 457 }, 458 }, 459 { 460 Description: "arch-variant deps", 461 Blueprint: `custom { 462 name: "has_dep", 463 arch: { 464 x86: { 465 arch_paths: [":dep"], 466 }, 467 }, 468 bazel_module: { bp2build_available: true }, 469} 470 471custom { 472 name: "dep", 473 arch_paths: ["abc"], 474 bazel_module: { bp2build_available: true }, 475}`, 476 ExpectedBazelTargets: []string{ 477 MakeBazelTarget("custom", "dep", AttrNameToString{ 478 "arch_paths": `["abc"]`, 479 }), 480 MakeBazelTarget("custom", "has_dep", AttrNameToString{ 481 "arch_paths": `select({ 482 "//build/bazel/platforms/arch:x86": [":dep"], 483 "//conditions:default": [], 484 })`, 485 }), 486 }, 487 }, 488 { 489 Description: "embedded props", 490 Blueprint: `custom { 491 name: "embedded_props", 492 embedded_prop: "abc", 493 bazel_module: { bp2build_available: true }, 494}`, 495 ExpectedBazelTargets: []string{ 496 MakeBazelTarget("custom", "embedded_props", AttrNameToString{ 497 "embedded_attr": `"abc"`, 498 }), 499 }, 500 }, 501 { 502 Description: "ptr to embedded props", 503 Blueprint: `custom { 504 name: "ptr_to_embedded_props", 505 other_embedded_prop: "abc", 506 bazel_module: { bp2build_available: true }, 507}`, 508 ExpectedBazelTargets: []string{ 509 MakeBazelTarget("custom", "ptr_to_embedded_props", AttrNameToString{ 510 "other_embedded_attr": `"abc"`, 511 }), 512 }, 513 }, 514 } 515 516 dir := "." 517 for _, testCase := range testCases { 518 t.Run(testCase.Description, func(t *testing.T) { 519 config := android.TestConfig(buildDir, nil, testCase.Blueprint, nil) 520 ctx := android.NewTestContext(config) 521 522 registerCustomModuleForBp2buildConversion(ctx) 523 524 _, errs := ctx.ParseFileList(dir, []string{"Android.bp"}) 525 if errored(t, testCase, errs) { 526 return 527 } 528 _, errs = ctx.ResolveDependencies(config) 529 if errored(t, testCase, errs) { 530 return 531 } 532 533 codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "") 534 bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir) 535 android.FailIfErrored(t, err) 536 537 if actualCount, expectedCount := len(bazelTargets), len(testCase.ExpectedBazelTargets); actualCount != expectedCount { 538 t.Errorf("Expected %d bazel target (%s),\ngot %d (%s)", expectedCount, testCase.ExpectedBazelTargets, actualCount, bazelTargets) 539 } else { 540 for i, expectedBazelTarget := range testCase.ExpectedBazelTargets { 541 actualBazelTarget := bazelTargets[i] 542 if actualBazelTarget.content != expectedBazelTarget { 543 t.Errorf( 544 "Expected generated Bazel target to be '%s', got '%s'", 545 expectedBazelTarget, 546 actualBazelTarget.content, 547 ) 548 } 549 } 550 } 551 }) 552 } 553} 554 555func TestBp2buildHostAndDevice(t *testing.T) { 556 testCases := []Bp2buildTestCase{ 557 { 558 Description: "host and device, device only", 559 ModuleTypeUnderTest: "custom", 560 ModuleTypeUnderTestFactory: customModuleFactoryHostAndDevice, 561 Blueprint: `custom { 562 name: "foo", 563 bazel_module: { bp2build_available: true }, 564}`, 565 ExpectedBazelTargets: []string{ 566 makeBazelTargetHostOrDevice("custom", "foo", AttrNameToString{}, android.DeviceSupported), 567 }, 568 }, 569 { 570 Description: "host and device, both", 571 ModuleTypeUnderTest: "custom", 572 ModuleTypeUnderTestFactory: customModuleFactoryHostAndDevice, 573 Blueprint: `custom { 574 name: "foo", 575 host_supported: true, 576 bazel_module: { bp2build_available: true }, 577}`, 578 ExpectedBazelTargets: []string{ 579 MakeBazelTargetNoRestrictions("custom", "foo", AttrNameToString{}), 580 }, 581 }, 582 { 583 Description: "host and device, host explicitly disabled", 584 ModuleTypeUnderTest: "custom", 585 ModuleTypeUnderTestFactory: customModuleFactoryHostAndDevice, 586 Blueprint: `custom { 587 name: "foo", 588 host_supported: false, 589 bazel_module: { bp2build_available: true }, 590}`, 591 ExpectedBazelTargets: []string{ 592 makeBazelTargetHostOrDevice("custom", "foo", AttrNameToString{}, android.DeviceSupported), 593 }, 594 }, 595 { 596 Description: "host and device, neither", 597 ModuleTypeUnderTest: "custom", 598 ModuleTypeUnderTestFactory: customModuleFactoryHostAndDevice, 599 Blueprint: `custom { 600 name: "foo", 601 host_supported: false, 602 device_supported: false, 603 bazel_module: { bp2build_available: true }, 604}`, 605 ExpectedBazelTargets: []string{ 606 MakeBazelTargetNoRestrictions("custom", "foo", AttrNameToString{ 607 "target_compatible_with": `["@platforms//:incompatible"]`, 608 }), 609 }, 610 }, 611 { 612 Description: "host and device, neither, cannot override with product_var", 613 ModuleTypeUnderTest: "custom", 614 ModuleTypeUnderTestFactory: customModuleFactoryHostAndDevice, 615 Blueprint: `custom { 616 name: "foo", 617 host_supported: false, 618 device_supported: false, 619 product_variables: { unbundled_build: { enabled: true } }, 620 bazel_module: { bp2build_available: true }, 621}`, 622 ExpectedBazelTargets: []string{ 623 MakeBazelTargetNoRestrictions("custom", "foo", AttrNameToString{ 624 "target_compatible_with": `["@platforms//:incompatible"]`, 625 }), 626 }, 627 }, 628 { 629 Description: "host and device, both, disabled overrided with product_var", 630 ModuleTypeUnderTest: "custom", 631 ModuleTypeUnderTestFactory: customModuleFactoryHostAndDevice, 632 Blueprint: `custom { 633 name: "foo", 634 host_supported: true, 635 device_supported: true, 636 enabled: false, 637 product_variables: { unbundled_build: { enabled: true } }, 638 bazel_module: { bp2build_available: true }, 639}`, 640 ExpectedBazelTargets: []string{ 641 MakeBazelTargetNoRestrictions("custom", "foo", AttrNameToString{ 642 "target_compatible_with": `["//build/bazel/product_variables:unbundled_build"]`, 643 }), 644 }, 645 }, 646 { 647 Description: "host and device, neither, cannot override with arch enabled", 648 ModuleTypeUnderTest: "custom", 649 ModuleTypeUnderTestFactory: customModuleFactoryHostAndDevice, 650 Blueprint: `custom { 651 name: "foo", 652 host_supported: false, 653 device_supported: false, 654 arch: { x86: { enabled: true } }, 655 bazel_module: { bp2build_available: true }, 656}`, 657 ExpectedBazelTargets: []string{ 658 MakeBazelTargetNoRestrictions("custom", "foo", AttrNameToString{ 659 "target_compatible_with": `["@platforms//:incompatible"]`, 660 }), 661 }, 662 }, 663 { 664 Description: "host and device, host only", 665 ModuleTypeUnderTest: "custom", 666 ModuleTypeUnderTestFactory: customModuleFactoryHostAndDevice, 667 Blueprint: `custom { 668 name: "foo", 669 host_supported: true, 670 device_supported: false, 671 bazel_module: { bp2build_available: true }, 672}`, 673 ExpectedBazelTargets: []string{ 674 makeBazelTargetHostOrDevice("custom", "foo", AttrNameToString{}, android.HostSupported), 675 }, 676 }, 677 { 678 Description: "host only", 679 ModuleTypeUnderTest: "custom", 680 ModuleTypeUnderTestFactory: customModuleFactoryHostSupported, 681 Blueprint: `custom { 682 name: "foo", 683 bazel_module: { bp2build_available: true }, 684}`, 685 ExpectedBazelTargets: []string{ 686 makeBazelTargetHostOrDevice("custom", "foo", AttrNameToString{}, android.HostSupported), 687 }, 688 }, 689 { 690 Description: "device only", 691 ModuleTypeUnderTest: "custom", 692 ModuleTypeUnderTestFactory: customModuleFactoryDeviceSupported, 693 Blueprint: `custom { 694 name: "foo", 695 bazel_module: { bp2build_available: true }, 696}`, 697 ExpectedBazelTargets: []string{ 698 makeBazelTargetHostOrDevice("custom", "foo", AttrNameToString{}, android.DeviceSupported), 699 }, 700 }, 701 { 702 Description: "host and device default, default", 703 ModuleTypeUnderTest: "custom", 704 ModuleTypeUnderTestFactory: customModuleFactoryHostAndDeviceDefault, 705 Blueprint: `custom { 706 name: "foo", 707 bazel_module: { bp2build_available: true }, 708}`, 709 ExpectedBazelTargets: []string{ 710 MakeBazelTargetNoRestrictions("custom", "foo", AttrNameToString{}), 711 }, 712 }, 713 { 714 Description: "host and device default, device only", 715 ModuleTypeUnderTest: "custom", 716 ModuleTypeUnderTestFactory: customModuleFactoryHostAndDeviceDefault, 717 Blueprint: `custom { 718 name: "foo", 719 host_supported: false, 720 bazel_module: { bp2build_available: true }, 721}`, 722 ExpectedBazelTargets: []string{ 723 makeBazelTargetHostOrDevice("custom", "foo", AttrNameToString{}, android.DeviceSupported), 724 }, 725 }, 726 { 727 Description: "host and device default, host only", 728 ModuleTypeUnderTest: "custom", 729 ModuleTypeUnderTestFactory: customModuleFactoryHostAndDeviceDefault, 730 Blueprint: `custom { 731 name: "foo", 732 device_supported: false, 733 bazel_module: { bp2build_available: true }, 734}`, 735 ExpectedBazelTargets: []string{ 736 makeBazelTargetHostOrDevice("custom", "foo", AttrNameToString{}, android.HostSupported), 737 }, 738 }, 739 { 740 Description: "host and device default, neither", 741 ModuleTypeUnderTest: "custom", 742 ModuleTypeUnderTestFactory: customModuleFactoryHostAndDeviceDefault, 743 Blueprint: `custom { 744 name: "foo", 745 host_supported: false, 746 device_supported: false, 747 bazel_module: { bp2build_available: true }, 748}`, 749 ExpectedBazelTargets: []string{ 750 MakeBazelTargetNoRestrictions("custom", "foo", AttrNameToString{ 751 "target_compatible_with": `["@platforms//:incompatible"]`, 752 }), 753 }, 754 }, 755 } 756 757 for _, tc := range testCases { 758 t.Run(tc.Description, func(t *testing.T) { 759 RunBp2BuildTestCaseSimple(t, tc) 760 }) 761 } 762} 763 764func TestLoadStatements(t *testing.T) { 765 testCases := []struct { 766 bazelTargets BazelTargets 767 expectedLoadStatements string 768 }{ 769 { 770 bazelTargets: BazelTargets{ 771 BazelTarget{ 772 name: "foo", 773 ruleClass: "cc_library", 774 bzlLoadLocation: "//build/bazel/rules:cc.bzl", 775 }, 776 }, 777 expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_library")`, 778 }, 779 { 780 bazelTargets: BazelTargets{ 781 BazelTarget{ 782 name: "foo", 783 ruleClass: "cc_library", 784 bzlLoadLocation: "//build/bazel/rules:cc.bzl", 785 }, 786 BazelTarget{ 787 name: "bar", 788 ruleClass: "cc_library", 789 bzlLoadLocation: "//build/bazel/rules:cc.bzl", 790 }, 791 }, 792 expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_library")`, 793 }, 794 { 795 bazelTargets: BazelTargets{ 796 BazelTarget{ 797 name: "foo", 798 ruleClass: "cc_library", 799 bzlLoadLocation: "//build/bazel/rules:cc.bzl", 800 }, 801 BazelTarget{ 802 name: "bar", 803 ruleClass: "cc_binary", 804 bzlLoadLocation: "//build/bazel/rules:cc.bzl", 805 }, 806 }, 807 expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary", "cc_library")`, 808 }, 809 { 810 bazelTargets: BazelTargets{ 811 BazelTarget{ 812 name: "foo", 813 ruleClass: "cc_library", 814 bzlLoadLocation: "//build/bazel/rules:cc.bzl", 815 }, 816 BazelTarget{ 817 name: "bar", 818 ruleClass: "cc_binary", 819 bzlLoadLocation: "//build/bazel/rules:cc.bzl", 820 }, 821 BazelTarget{ 822 name: "baz", 823 ruleClass: "java_binary", 824 bzlLoadLocation: "//build/bazel/rules:java.bzl", 825 }, 826 }, 827 expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary", "cc_library") 828load("//build/bazel/rules:java.bzl", "java_binary")`, 829 }, 830 { 831 bazelTargets: BazelTargets{ 832 BazelTarget{ 833 name: "foo", 834 ruleClass: "cc_binary", 835 bzlLoadLocation: "//build/bazel/rules:cc.bzl", 836 }, 837 BazelTarget{ 838 name: "bar", 839 ruleClass: "java_binary", 840 bzlLoadLocation: "//build/bazel/rules:java.bzl", 841 }, 842 BazelTarget{ 843 name: "baz", 844 ruleClass: "genrule", 845 // Note: no bzlLoadLocation for native rules 846 }, 847 }, 848 expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary") 849load("//build/bazel/rules:java.bzl", "java_binary")`, 850 }, 851 } 852 853 for _, testCase := range testCases { 854 actual := testCase.bazelTargets.LoadStatements() 855 expected := testCase.expectedLoadStatements 856 if actual != expected { 857 t.Fatalf("Expected load statements to be %s, got %s", expected, actual) 858 } 859 } 860 861} 862 863func TestGenerateBazelTargetModules_OneToMany_LoadedFromStarlark(t *testing.T) { 864 testCases := []struct { 865 bp string 866 expectedBazelTarget string 867 expectedBazelTargetCount int 868 expectedLoadStatements string 869 }{ 870 { 871 bp: `custom { 872 name: "bar", 873 host_supported: true, 874 one_to_many_prop: true, 875 bazel_module: { bp2build_available: true }, 876}`, 877 expectedBazelTarget: `my_library( 878 name = "bar", 879) 880 881proto_library( 882 name = "bar_proto_library_deps", 883) 884 885my_proto_library( 886 name = "bar_my_proto_library_deps", 887)`, 888 expectedBazelTargetCount: 3, 889 expectedLoadStatements: `load("//build/bazel/rules:proto.bzl", "my_proto_library", "proto_library") 890load("//build/bazel/rules:rules.bzl", "my_library")`, 891 }, 892 } 893 894 dir := "." 895 for _, testCase := range testCases { 896 config := android.TestConfig(buildDir, nil, testCase.bp, nil) 897 ctx := android.NewTestContext(config) 898 ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice) 899 ctx.RegisterForBazelConversion() 900 901 _, errs := ctx.ParseFileList(dir, []string{"Android.bp"}) 902 android.FailIfErrored(t, errs) 903 _, errs = ctx.ResolveDependencies(config) 904 android.FailIfErrored(t, errs) 905 906 codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "") 907 bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir) 908 android.FailIfErrored(t, err) 909 if actualCount := len(bazelTargets); actualCount != testCase.expectedBazelTargetCount { 910 t.Fatalf("Expected %d bazel target, got %d", testCase.expectedBazelTargetCount, actualCount) 911 } 912 913 actualBazelTargets := bazelTargets.String() 914 if actualBazelTargets != testCase.expectedBazelTarget { 915 t.Errorf( 916 "Expected generated Bazel target to be '%s', got '%s'", 917 testCase.expectedBazelTarget, 918 actualBazelTargets, 919 ) 920 } 921 922 actualLoadStatements := bazelTargets.LoadStatements() 923 if actualLoadStatements != testCase.expectedLoadStatements { 924 t.Errorf( 925 "Expected generated load statements to be '%s', got '%s'", 926 testCase.expectedLoadStatements, 927 actualLoadStatements, 928 ) 929 } 930 } 931} 932 933func TestModuleTypeBp2Build(t *testing.T) { 934 testCases := []Bp2buildTestCase{ 935 { 936 Description: "filegroup with does not specify srcs", 937 ModuleTypeUnderTest: "filegroup", 938 ModuleTypeUnderTestFactory: android.FileGroupFactory, 939 Blueprint: `filegroup { 940 name: "fg_foo", 941 bazel_module: { bp2build_available: true }, 942}`, 943 ExpectedBazelTargets: []string{ 944 MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{}), 945 }, 946 }, 947 { 948 Description: "filegroup with no srcs", 949 ModuleTypeUnderTest: "filegroup", 950 ModuleTypeUnderTestFactory: android.FileGroupFactory, 951 Blueprint: `filegroup { 952 name: "fg_foo", 953 srcs: [], 954 bazel_module: { bp2build_available: true }, 955}`, 956 ExpectedBazelTargets: []string{ 957 MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{}), 958 }, 959 }, 960 { 961 Description: "filegroup with srcs", 962 ModuleTypeUnderTest: "filegroup", 963 ModuleTypeUnderTestFactory: android.FileGroupFactory, 964 Blueprint: `filegroup { 965 name: "fg_foo", 966 srcs: ["a", "b"], 967 bazel_module: { bp2build_available: true }, 968}`, 969 ExpectedBazelTargets: []string{ 970 MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{ 971 "srcs": `[ 972 "a", 973 "b", 974 ]`, 975 }), 976 }, 977 }, 978 { 979 Description: "filegroup with dot-slash-prefixed srcs", 980 ModuleTypeUnderTest: "filegroup", 981 ModuleTypeUnderTestFactory: android.FileGroupFactory, 982 Blueprint: `filegroup { 983 name: "fg_foo", 984 srcs: ["./a", "./b"], 985 bazel_module: { bp2build_available: true }, 986}`, 987 ExpectedBazelTargets: []string{ 988 MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{ 989 "srcs": `[ 990 "a", 991 "b", 992 ]`, 993 }), 994 }, 995 }, 996 { 997 Description: "filegroup with excludes srcs", 998 ModuleTypeUnderTest: "filegroup", 999 ModuleTypeUnderTestFactory: android.FileGroupFactory, 1000 Blueprint: `filegroup { 1001 name: "fg_foo", 1002 srcs: ["a", "b"], 1003 exclude_srcs: ["a"], 1004 bazel_module: { bp2build_available: true }, 1005}`, 1006 ExpectedBazelTargets: []string{ 1007 MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{ 1008 "srcs": `["b"]`, 1009 }), 1010 }, 1011 }, 1012 { 1013 Description: "depends_on_other_dir_module", 1014 ModuleTypeUnderTest: "filegroup", 1015 ModuleTypeUnderTestFactory: android.FileGroupFactory, 1016 Blueprint: `filegroup { 1017 name: "fg_foo", 1018 srcs: [ 1019 ":foo", 1020 "c", 1021 ], 1022 bazel_module: { bp2build_available: true }, 1023}`, 1024 Filesystem: map[string]string{ 1025 "other/Android.bp": `filegroup { 1026 name: "foo", 1027 srcs: ["a", "b"], 1028 bazel_module: { bp2build_available: true }, 1029}`, 1030 }, 1031 ExpectedBazelTargets: []string{ 1032 MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{ 1033 "srcs": `[ 1034 "//other:foo", 1035 "c", 1036 ]`, 1037 }), 1038 }, 1039 }, 1040 { 1041 Description: "depends_on_other_unconverted_module_error", 1042 ModuleTypeUnderTest: "filegroup", 1043 ModuleTypeUnderTestFactory: android.FileGroupFactory, 1044 UnconvertedDepsMode: errorModulesUnconvertedDeps, 1045 Blueprint: `filegroup { 1046 name: "foobar", 1047 srcs: [ 1048 ":foo", 1049 "c", 1050 ], 1051 bazel_module: { bp2build_available: true }, 1052}`, 1053 ExpectedErr: fmt.Errorf(`filegroup .:foobar depends on unconverted modules: foo`), 1054 Filesystem: map[string]string{ 1055 "other/Android.bp": `filegroup { 1056 name: "foo", 1057 srcs: ["a", "b"], 1058}`, 1059 }, 1060 }, 1061 { 1062 Description: "depends_on_other_missing_module_error", 1063 ModuleTypeUnderTest: "filegroup", 1064 ModuleTypeUnderTestFactory: android.FileGroupFactory, 1065 UnconvertedDepsMode: errorModulesUnconvertedDeps, 1066 Blueprint: `filegroup { 1067 name: "foobar", 1068 srcs: [ 1069 "c", 1070 "//other:foo", 1071 "//other:goo", 1072 ], 1073 bazel_module: { bp2build_available: true }, 1074}`, 1075 ExpectedErr: fmt.Errorf(`filegroup .:foobar depends on missing modules: //other:goo`), 1076 Filesystem: map[string]string{"other/Android.bp": `filegroup { 1077 name: "foo", 1078 srcs: ["a"], 1079 bazel_module: { bp2build_available: true }, 1080} 1081`, 1082 }, 1083 }, 1084 } 1085 1086 for _, testCase := range testCases { 1087 t.Run(testCase.Description, func(t *testing.T) { 1088 RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, testCase) 1089 }) 1090 } 1091} 1092 1093func TestAllowlistingBp2buildTargetsExplicitly(t *testing.T) { 1094 testCases := []struct { 1095 moduleTypeUnderTest string 1096 moduleTypeUnderTestFactory android.ModuleFactory 1097 bp string 1098 expectedCount int 1099 description string 1100 }{ 1101 { 1102 description: "explicitly unavailable", 1103 moduleTypeUnderTest: "filegroup", 1104 moduleTypeUnderTestFactory: android.FileGroupFactory, 1105 bp: `filegroup { 1106 name: "foo", 1107 srcs: ["a", "b"], 1108 bazel_module: { bp2build_available: false }, 1109}`, 1110 expectedCount: 0, 1111 }, 1112 { 1113 description: "implicitly unavailable", 1114 moduleTypeUnderTest: "filegroup", 1115 moduleTypeUnderTestFactory: android.FileGroupFactory, 1116 bp: `filegroup { 1117 name: "foo", 1118 srcs: ["a", "b"], 1119}`, 1120 expectedCount: 0, 1121 }, 1122 { 1123 description: "explicitly available", 1124 moduleTypeUnderTest: "filegroup", 1125 moduleTypeUnderTestFactory: android.FileGroupFactory, 1126 bp: `filegroup { 1127 name: "foo", 1128 srcs: ["a", "b"], 1129 bazel_module: { bp2build_available: true }, 1130}`, 1131 expectedCount: 1, 1132 }, 1133 { 1134 description: "generates more than 1 target if needed", 1135 moduleTypeUnderTest: "custom", 1136 moduleTypeUnderTestFactory: customModuleFactoryHostAndDevice, 1137 bp: `custom { 1138 name: "foo", 1139 one_to_many_prop: true, 1140 bazel_module: { bp2build_available: true }, 1141}`, 1142 expectedCount: 3, 1143 }, 1144 } 1145 1146 dir := "." 1147 for _, testCase := range testCases { 1148 t.Run(testCase.description, func(t *testing.T) { 1149 config := android.TestConfig(buildDir, nil, testCase.bp, nil) 1150 ctx := android.NewTestContext(config) 1151 ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory) 1152 ctx.RegisterForBazelConversion() 1153 1154 _, errs := ctx.ParseFileList(dir, []string{"Android.bp"}) 1155 android.FailIfErrored(t, errs) 1156 _, errs = ctx.ResolveDependencies(config) 1157 android.FailIfErrored(t, errs) 1158 1159 codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "") 1160 bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir) 1161 android.FailIfErrored(t, err) 1162 if actualCount := len(bazelTargets); actualCount != testCase.expectedCount { 1163 t.Fatalf("%s: Expected %d bazel target, got %d", testCase.description, testCase.expectedCount, actualCount) 1164 } 1165 }) 1166 } 1167} 1168 1169func TestAllowlistingBp2buildTargetsWithConfig(t *testing.T) { 1170 testCases := []struct { 1171 moduleTypeUnderTest string 1172 moduleTypeUnderTestFactory android.ModuleFactory 1173 expectedCount map[string]int 1174 description string 1175 bp2buildConfig allowlists.Bp2BuildConfig 1176 checkDir string 1177 fs map[string]string 1178 forceEnabledModules []string 1179 expectedErrorMessages []string 1180 }{ 1181 { 1182 description: "test bp2build config package and subpackages config", 1183 moduleTypeUnderTest: "filegroup", 1184 moduleTypeUnderTestFactory: android.FileGroupFactory, 1185 expectedCount: map[string]int{ 1186 "migrated": 1, 1187 "migrated/but_not_really": 0, 1188 "migrated/but_not_really/but_really": 1, 1189 "not_migrated": 0, 1190 "also_not_migrated": 0, 1191 }, 1192 bp2buildConfig: allowlists.Bp2BuildConfig{ 1193 "migrated": allowlists.Bp2BuildDefaultTrueRecursively, 1194 "migrated/but_not_really": allowlists.Bp2BuildDefaultFalse, 1195 "not_migrated": allowlists.Bp2BuildDefaultFalse, 1196 }, 1197 fs: map[string]string{ 1198 "migrated/Android.bp": `filegroup { name: "a" }`, 1199 "migrated/but_not_really/Android.bp": `filegroup { name: "b" }`, 1200 "migrated/but_not_really/but_really/Android.bp": `filegroup { name: "c" }`, 1201 "not_migrated/Android.bp": `filegroup { name: "d" }`, 1202 "also_not_migrated/Android.bp": `filegroup { name: "e" }`, 1203 }, 1204 }, 1205 { 1206 description: "test bp2build config opt-in and opt-out", 1207 moduleTypeUnderTest: "filegroup", 1208 moduleTypeUnderTestFactory: android.FileGroupFactory, 1209 expectedCount: map[string]int{ 1210 "package-opt-in": 2, 1211 "package-opt-in/subpackage": 0, 1212 "package-opt-out": 1, 1213 "package-opt-out/subpackage": 0, 1214 }, 1215 bp2buildConfig: allowlists.Bp2BuildConfig{ 1216 "package-opt-in": allowlists.Bp2BuildDefaultFalse, 1217 "package-opt-out": allowlists.Bp2BuildDefaultTrueRecursively, 1218 }, 1219 fs: map[string]string{ 1220 "package-opt-in/Android.bp": ` 1221filegroup { name: "opt-in-a" } 1222filegroup { name: "opt-in-b", bazel_module: { bp2build_available: true } } 1223filegroup { name: "opt-in-c", bazel_module: { bp2build_available: true } } 1224`, 1225 1226 "package-opt-in/subpackage/Android.bp": ` 1227filegroup { name: "opt-in-d" } // parent package not configured to DefaultTrueRecursively 1228`, 1229 1230 "package-opt-out/Android.bp": ` 1231filegroup { name: "opt-out-a" } 1232filegroup { name: "opt-out-b", bazel_module: { bp2build_available: false } } 1233filegroup { name: "opt-out-c", bazel_module: { bp2build_available: false } } 1234`, 1235 1236 "package-opt-out/subpackage/Android.bp": ` 1237filegroup { name: "opt-out-g", bazel_module: { bp2build_available: false } } 1238filegroup { name: "opt-out-h", bazel_module: { bp2build_available: false } } 1239`, 1240 }, 1241 }, 1242 { 1243 description: "test force-enabled errors out", 1244 moduleTypeUnderTest: "filegroup", 1245 moduleTypeUnderTestFactory: android.FileGroupFactory, 1246 expectedCount: map[string]int{ 1247 "migrated": 0, 1248 "not_migrated": 0, 1249 }, 1250 bp2buildConfig: allowlists.Bp2BuildConfig{ 1251 "migrated/but_not_really": allowlists.Bp2BuildDefaultFalse, 1252 "not_migrated": allowlists.Bp2BuildDefaultFalse, 1253 }, 1254 fs: map[string]string{ 1255 "migrated/Android.bp": `filegroup { name: "a" }`, 1256 }, 1257 forceEnabledModules: []string{"a"}, 1258 expectedErrorMessages: []string{"Force Enabled Module a not converted"}, 1259 }, 1260 } 1261 1262 dir := "." 1263 for _, testCase := range testCases { 1264 fs := make(map[string][]byte) 1265 toParse := []string{ 1266 "Android.bp", 1267 } 1268 for f, content := range testCase.fs { 1269 if strings.HasSuffix(f, "Android.bp") { 1270 toParse = append(toParse, f) 1271 } 1272 fs[f] = []byte(content) 1273 } 1274 config := android.TestConfig(buildDir, nil, "", fs) 1275 config.AddForceEnabledModules(testCase.forceEnabledModules) 1276 ctx := android.NewTestContext(config) 1277 ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory) 1278 allowlist := android.NewBp2BuildAllowlist().SetDefaultConfig(testCase.bp2buildConfig) 1279 ctx.RegisterBp2BuildConfig(allowlist) 1280 ctx.RegisterForBazelConversion() 1281 1282 _, errs := ctx.ParseFileList(dir, toParse) 1283 android.FailIfErrored(t, errs) 1284 _, errs = ctx.ResolveDependencies(config) 1285 android.FailIfErrored(t, errs) 1286 1287 codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "") 1288 1289 // For each directory, test that the expected number of generated targets is correct. 1290 for dir, expectedCount := range testCase.expectedCount { 1291 bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir) 1292 android.CheckErrorsAgainstExpectations(t, err, testCase.expectedErrorMessages) 1293 if actualCount := len(bazelTargets); actualCount != expectedCount { 1294 t.Fatalf( 1295 "%s: Expected %d bazel target for %s package, got %d", 1296 testCase.description, 1297 expectedCount, 1298 dir, 1299 actualCount) 1300 } 1301 1302 } 1303 } 1304} 1305 1306func TestCombineBuildFilesBp2buildTargets(t *testing.T) { 1307 testCases := []Bp2buildTestCase{ 1308 { 1309 Description: "filegroup bazel_module.label", 1310 ModuleTypeUnderTest: "filegroup", 1311 ModuleTypeUnderTestFactory: android.FileGroupFactory, 1312 Blueprint: `filegroup { 1313 name: "fg_foo", 1314 bazel_module: { label: "//other:fg_foo" }, 1315}`, 1316 ExpectedBazelTargets: []string{}, 1317 Filesystem: map[string]string{ 1318 "other/BUILD.bazel": `// BUILD file`, 1319 }, 1320 }, 1321 { 1322 Description: "multiple bazel_module.label same BUILD", 1323 ModuleTypeUnderTest: "filegroup", 1324 ModuleTypeUnderTestFactory: android.FileGroupFactory, 1325 Blueprint: `filegroup { 1326 name: "fg_foo", 1327 bazel_module: { label: "//other:fg_foo" }, 1328 } 1329 1330 filegroup { 1331 name: "foo", 1332 bazel_module: { label: "//other:foo" }, 1333 }`, 1334 ExpectedBazelTargets: []string{}, 1335 Filesystem: map[string]string{ 1336 "other/BUILD.bazel": `// BUILD file`, 1337 }, 1338 }, 1339 { 1340 Description: "filegroup bazel_module.label and bp2build in subdir", 1341 ModuleTypeUnderTest: "filegroup", 1342 ModuleTypeUnderTestFactory: android.FileGroupFactory, 1343 Dir: "other", 1344 Blueprint: ``, 1345 Filesystem: map[string]string{ 1346 "other/Android.bp": `filegroup { 1347 name: "fg_foo", 1348 bazel_module: { 1349 bp2build_available: true, 1350 }, 1351 } 1352 filegroup { 1353 name: "fg_bar", 1354 bazel_module: { 1355 label: "//other:fg_bar" 1356 }, 1357 }`, 1358 "other/BUILD.bazel": `// definition for fg_bar`, 1359 }, 1360 ExpectedBazelTargets: []string{ 1361 MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{}), 1362 }, 1363 }, 1364 { 1365 Description: "filegroup bazel_module.label and filegroup bp2build", 1366 ModuleTypeUnderTest: "filegroup", 1367 ModuleTypeUnderTestFactory: android.FileGroupFactory, 1368 1369 Filesystem: map[string]string{ 1370 "other/BUILD.bazel": `// BUILD file`, 1371 }, 1372 Blueprint: `filegroup { 1373 name: "fg_foo", 1374 bazel_module: { 1375 label: "//other:fg_foo", 1376 }, 1377 } 1378 1379 filegroup { 1380 name: "fg_bar", 1381 bazel_module: { 1382 bp2build_available: true, 1383 }, 1384 }`, 1385 ExpectedBazelTargets: []string{ 1386 MakeBazelTargetNoRestrictions("filegroup", "fg_bar", map[string]string{}), 1387 }, 1388 }, 1389 } 1390 1391 dir := "." 1392 for _, testCase := range testCases { 1393 t.Run(testCase.Description, func(t *testing.T) { 1394 fs := make(map[string][]byte) 1395 toParse := []string{ 1396 "Android.bp", 1397 } 1398 for f, content := range testCase.Filesystem { 1399 if strings.HasSuffix(f, "Android.bp") { 1400 toParse = append(toParse, f) 1401 } 1402 fs[f] = []byte(content) 1403 } 1404 config := android.TestConfig(buildDir, nil, testCase.Blueprint, fs) 1405 ctx := android.NewTestContext(config) 1406 ctx.RegisterModuleType(testCase.ModuleTypeUnderTest, testCase.ModuleTypeUnderTestFactory) 1407 ctx.RegisterForBazelConversion() 1408 1409 _, errs := ctx.ParseFileList(dir, toParse) 1410 if errored(t, testCase, errs) { 1411 return 1412 } 1413 _, errs = ctx.ResolveDependencies(config) 1414 if errored(t, testCase, errs) { 1415 return 1416 } 1417 1418 checkDir := dir 1419 if testCase.Dir != "" { 1420 checkDir = testCase.Dir 1421 } 1422 codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "") 1423 bazelTargets, err := generateBazelTargetsForDir(codegenCtx, checkDir) 1424 android.FailIfErrored(t, err) 1425 bazelTargets.sort() 1426 actualCount := len(bazelTargets) 1427 expectedCount := len(testCase.ExpectedBazelTargets) 1428 if actualCount != expectedCount { 1429 t.Errorf("Expected %d bazel target, got %d\n%s", expectedCount, actualCount, bazelTargets) 1430 } 1431 for i, target := range bazelTargets { 1432 actualContent := target.content 1433 expectedContent := testCase.ExpectedBazelTargets[i] 1434 if expectedContent != actualContent { 1435 t.Errorf( 1436 "Expected generated Bazel target to be '%s', got '%s'", 1437 expectedContent, 1438 actualContent, 1439 ) 1440 } 1441 } 1442 }) 1443 } 1444} 1445 1446func TestGlob(t *testing.T) { 1447 testCases := []Bp2buildTestCase{ 1448 { 1449 Description: "filegroup with glob", 1450 ModuleTypeUnderTest: "filegroup", 1451 ModuleTypeUnderTestFactory: android.FileGroupFactory, 1452 Blueprint: `filegroup { 1453 name: "fg_foo", 1454 srcs: ["**/*.txt"], 1455 bazel_module: { bp2build_available: true }, 1456}`, 1457 ExpectedBazelTargets: []string{ 1458 MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{ 1459 "srcs": `[ 1460 "other/a.txt", 1461 "other/b.txt", 1462 "other/subdir/a.txt", 1463 ]`, 1464 }), 1465 }, 1466 Filesystem: map[string]string{ 1467 "other/a.txt": "", 1468 "other/b.txt": "", 1469 "other/subdir/a.txt": "", 1470 "other/file": "", 1471 }, 1472 }, 1473 { 1474 Description: "filegroup with glob in subdir", 1475 ModuleTypeUnderTest: "filegroup", 1476 ModuleTypeUnderTestFactory: android.FileGroupFactory, 1477 Dir: "other", 1478 Filesystem: map[string]string{ 1479 "other/Android.bp": `filegroup { 1480 name: "fg_foo", 1481 srcs: ["**/*.txt"], 1482 bazel_module: { bp2build_available: true }, 1483}`, 1484 "other/a.txt": "", 1485 "other/b.txt": "", 1486 "other/subdir/a.txt": "", 1487 "other/file": "", 1488 }, 1489 ExpectedBazelTargets: []string{ 1490 MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{ 1491 "srcs": `[ 1492 "a.txt", 1493 "b.txt", 1494 "subdir/a.txt", 1495 ]`, 1496 }), 1497 }, 1498 }, 1499 { 1500 Description: "filegroup with glob with no kept BUILD files", 1501 ModuleTypeUnderTest: "filegroup", 1502 ModuleTypeUnderTestFactory: android.FileGroupFactory, 1503 KeepBuildFileForDirs: []string{ 1504 // empty 1505 }, 1506 Blueprint: `filegroup { 1507 name: "fg_foo", 1508 srcs: ["**/*.txt"], 1509 bazel_module: { bp2build_available: true }, 1510}`, 1511 Filesystem: map[string]string{ 1512 "a.txt": "", 1513 "b.txt": "", 1514 "foo/BUILD": "", 1515 "foo/a.txt": "", 1516 "foo/bar/BUILD": "", 1517 "foo/bar/b.txt": "", 1518 }, 1519 ExpectedBazelTargets: []string{ 1520 MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{ 1521 "srcs": `[ 1522 "a.txt", 1523 "b.txt", 1524 "foo/a.txt", 1525 "foo/bar/b.txt", 1526 ]`, 1527 }), 1528 }, 1529 }, 1530 { 1531 Description: "filegroup with glob with kept BUILD file", 1532 ModuleTypeUnderTest: "filegroup", 1533 ModuleTypeUnderTestFactory: android.FileGroupFactory, 1534 KeepBuildFileForDirs: []string{ 1535 "foo", 1536 }, 1537 Blueprint: `filegroup { 1538 name: "fg_foo", 1539 srcs: ["**/*.txt"], 1540 bazel_module: { bp2build_available: true }, 1541}`, 1542 Filesystem: map[string]string{ 1543 "a.txt": "", 1544 "b.txt": "", 1545 "foo/BUILD": "", 1546 "foo/a.txt": "", 1547 "foo/bar/BUILD": "", 1548 "foo/bar/b.txt": "", 1549 }, 1550 ExpectedBazelTargets: []string{ 1551 MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{ 1552 "srcs": `[ 1553 "a.txt", 1554 "b.txt", 1555 "//foo:a.txt", 1556 "//foo:bar/b.txt", 1557 ]`, 1558 }), 1559 }, 1560 }, 1561 { 1562 Description: "filegroup with glob with kept BUILD.bazel file", 1563 ModuleTypeUnderTest: "filegroup", 1564 ModuleTypeUnderTestFactory: android.FileGroupFactory, 1565 KeepBuildFileForDirs: []string{ 1566 "foo", 1567 }, 1568 Blueprint: `filegroup { 1569 name: "fg_foo", 1570 srcs: ["**/*.txt"], 1571 bazel_module: { bp2build_available: true }, 1572}`, 1573 Filesystem: map[string]string{ 1574 "a.txt": "", 1575 "b.txt": "", 1576 "foo/BUILD.bazel": "", 1577 "foo/a.txt": "", 1578 "foo/bar/BUILD.bazel": "", 1579 "foo/bar/b.txt": "", 1580 }, 1581 ExpectedBazelTargets: []string{ 1582 MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{ 1583 "srcs": `[ 1584 "a.txt", 1585 "b.txt", 1586 "//foo:a.txt", 1587 "//foo:bar/b.txt", 1588 ]`, 1589 }), 1590 }, 1591 }, 1592 { 1593 Description: "filegroup with glob with Android.bp file as boundary", 1594 ModuleTypeUnderTest: "filegroup", 1595 ModuleTypeUnderTestFactory: android.FileGroupFactory, 1596 Blueprint: `filegroup { 1597 name: "fg_foo", 1598 srcs: ["**/*.txt"], 1599 bazel_module: { bp2build_available: true }, 1600}`, 1601 Filesystem: map[string]string{ 1602 "a.txt": "", 1603 "b.txt": "", 1604 "foo/Android.bp": "", 1605 "foo/a.txt": "", 1606 "foo/bar/Android.bp": "", 1607 "foo/bar/b.txt": "", 1608 }, 1609 ExpectedBazelTargets: []string{ 1610 MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{ 1611 "srcs": `[ 1612 "a.txt", 1613 "b.txt", 1614 "//foo:a.txt", 1615 "//foo/bar:b.txt", 1616 ]`, 1617 }), 1618 }, 1619 }, 1620 { 1621 Description: "filegroup with glob in subdir with kept BUILD and BUILD.bazel file", 1622 ModuleTypeUnderTest: "filegroup", 1623 ModuleTypeUnderTestFactory: android.FileGroupFactory, 1624 Dir: "other", 1625 KeepBuildFileForDirs: []string{ 1626 "other/foo", 1627 "other/foo/bar", 1628 // deliberately not other/foo/baz/BUILD. 1629 }, 1630 Filesystem: map[string]string{ 1631 "other/Android.bp": `filegroup { 1632 name: "fg_foo", 1633 srcs: ["**/*.txt"], 1634 bazel_module: { bp2build_available: true }, 1635}`, 1636 "other/a.txt": "", 1637 "other/b.txt": "", 1638 "other/foo/BUILD": "", 1639 "other/foo/a.txt": "", 1640 "other/foo/bar/BUILD.bazel": "", 1641 "other/foo/bar/b.txt": "", 1642 "other/foo/baz/BUILD": "", 1643 "other/foo/baz/c.txt": "", 1644 }, 1645 ExpectedBazelTargets: []string{ 1646 MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{ 1647 "srcs": `[ 1648 "a.txt", 1649 "b.txt", 1650 "//other/foo:a.txt", 1651 "//other/foo/bar:b.txt", 1652 "//other/foo:baz/c.txt", 1653 ]`, 1654 }), 1655 }, 1656 }, 1657 } 1658 1659 for _, testCase := range testCases { 1660 t.Run(testCase.Description, func(t *testing.T) { 1661 RunBp2BuildTestCaseSimple(t, testCase) 1662 }) 1663 } 1664} 1665 1666func TestGlobExcludeSrcs(t *testing.T) { 1667 testCases := []Bp2buildTestCase{ 1668 { 1669 Description: "filegroup top level exclude_srcs", 1670 ModuleTypeUnderTest: "filegroup", 1671 ModuleTypeUnderTestFactory: android.FileGroupFactory, 1672 Blueprint: `filegroup { 1673 name: "fg_foo", 1674 srcs: ["**/*.txt"], 1675 exclude_srcs: ["c.txt"], 1676 bazel_module: { bp2build_available: true }, 1677}`, 1678 Filesystem: map[string]string{ 1679 "a.txt": "", 1680 "b.txt": "", 1681 "c.txt": "", 1682 "dir/Android.bp": "", 1683 "dir/e.txt": "", 1684 "dir/f.txt": "", 1685 }, 1686 ExpectedBazelTargets: []string{ 1687 MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{ 1688 "srcs": `[ 1689 "a.txt", 1690 "b.txt", 1691 "//dir:e.txt", 1692 "//dir:f.txt", 1693 ]`, 1694 }), 1695 }, 1696 }, 1697 { 1698 Description: "filegroup in subdir exclude_srcs", 1699 ModuleTypeUnderTest: "filegroup", 1700 ModuleTypeUnderTestFactory: android.FileGroupFactory, 1701 Blueprint: "", 1702 Dir: "dir", 1703 Filesystem: map[string]string{ 1704 "dir/Android.bp": `filegroup { 1705 name: "fg_foo", 1706 srcs: ["**/*.txt"], 1707 exclude_srcs: ["b.txt"], 1708 bazel_module: { bp2build_available: true }, 1709} 1710`, 1711 "dir/a.txt": "", 1712 "dir/b.txt": "", 1713 "dir/subdir/Android.bp": "", 1714 "dir/subdir/e.txt": "", 1715 "dir/subdir/f.txt": "", 1716 }, 1717 ExpectedBazelTargets: []string{ 1718 MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{ 1719 "srcs": `[ 1720 "a.txt", 1721 "//dir/subdir:e.txt", 1722 "//dir/subdir:f.txt", 1723 ]`, 1724 }), 1725 }, 1726 }, 1727 } 1728 1729 for _, testCase := range testCases { 1730 t.Run(testCase.Description, func(t *testing.T) { 1731 RunBp2BuildTestCaseSimple(t, testCase) 1732 }) 1733 } 1734} 1735 1736func TestCommonBp2BuildModuleAttrs(t *testing.T) { 1737 testCases := []Bp2buildTestCase{ 1738 { 1739 Description: "Required into data test", 1740 ModuleTypeUnderTest: "filegroup", 1741 ModuleTypeUnderTestFactory: android.FileGroupFactory, 1742 Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "reqd") + ` 1743filegroup { 1744 name: "fg_foo", 1745 required: ["reqd"], 1746 bazel_module: { bp2build_available: true }, 1747}`, 1748 ExpectedBazelTargets: []string{ 1749 MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{ 1750 "data": `[":reqd"]`, 1751 }), 1752 }, 1753 }, 1754 { 1755 Description: "Required into data test, cyclic self reference is filtered out", 1756 ModuleTypeUnderTest: "filegroup", 1757 ModuleTypeUnderTestFactory: android.FileGroupFactory, 1758 Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "reqd") + ` 1759filegroup { 1760 name: "fg_foo", 1761 required: ["reqd", "fg_foo"], 1762 bazel_module: { bp2build_available: true }, 1763}`, 1764 ExpectedBazelTargets: []string{ 1765 MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{ 1766 "data": `[":reqd"]`, 1767 }), 1768 }, 1769 }, 1770 { 1771 Description: "Required via arch into data test", 1772 ModuleTypeUnderTest: "python_library", 1773 ModuleTypeUnderTestFactory: python.PythonLibraryFactory, 1774 Blueprint: simpleModuleDoNotConvertBp2build("python_library", "reqdx86") + 1775 simpleModuleDoNotConvertBp2build("python_library", "reqdarm") + ` 1776python_library { 1777 name: "fg_foo", 1778 arch: { 1779 arm: { 1780 required: ["reqdarm"], 1781 }, 1782 x86: { 1783 required: ["reqdx86"], 1784 }, 1785 }, 1786 bazel_module: { bp2build_available: true }, 1787}`, 1788 ExpectedBazelTargets: []string{ 1789 MakeBazelTarget("py_library", "fg_foo", map[string]string{ 1790 "data": `select({ 1791 "//build/bazel/platforms/arch:arm": [":reqdarm"], 1792 "//build/bazel/platforms/arch:x86": [":reqdx86"], 1793 "//conditions:default": [], 1794 })`, 1795 "srcs_version": `"PY3"`, 1796 "imports": `["."]`, 1797 }), 1798 }, 1799 }, 1800 { 1801 Description: "Required appended to data test", 1802 ModuleTypeUnderTest: "python_library", 1803 ModuleTypeUnderTestFactory: python.PythonLibraryFactory, 1804 Filesystem: map[string]string{ 1805 "data.bin": "", 1806 "src.py": "", 1807 }, 1808 Blueprint: simpleModuleDoNotConvertBp2build("python_library", "reqd") + ` 1809python_library { 1810 name: "fg_foo", 1811 data: ["data.bin"], 1812 required: ["reqd"], 1813 bazel_module: { bp2build_available: true }, 1814}`, 1815 ExpectedBazelTargets: []string{ 1816 MakeBazelTarget("py_library", "fg_foo", map[string]string{ 1817 "data": `[ 1818 "data.bin", 1819 ":reqd", 1820 ]`, 1821 "srcs_version": `"PY3"`, 1822 "imports": `["."]`, 1823 }), 1824 }, 1825 }, 1826 { 1827 Description: "All props-to-attrs at once together test", 1828 ModuleTypeUnderTest: "filegroup", 1829 ModuleTypeUnderTestFactory: android.FileGroupFactory, 1830 Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "reqd") + ` 1831filegroup { 1832 name: "fg_foo", 1833 required: ["reqd"], 1834 bazel_module: { bp2build_available: true }, 1835}`, 1836 ExpectedBazelTargets: []string{ 1837 MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{ 1838 "data": `[":reqd"]`, 1839 }), 1840 }, 1841 }, 1842 } 1843 1844 for _, tc := range testCases { 1845 t.Run(tc.Description, func(t *testing.T) { 1846 RunBp2BuildTestCaseSimple(t, tc) 1847 }) 1848 } 1849} 1850 1851func TestLicensesAttrConversion(t *testing.T) { 1852 RunBp2BuildTestCase(t, 1853 func(ctx android.RegistrationContext) { 1854 ctx.RegisterModuleType("license", android.LicenseFactory) 1855 }, 1856 Bp2buildTestCase{ 1857 Description: "Test that licenses: attribute is converted", 1858 ModuleTypeUnderTest: "filegroup", 1859 ModuleTypeUnderTestFactory: android.FileGroupFactory, 1860 Blueprint: ` 1861license { 1862 name: "my_license", 1863} 1864filegroup { 1865 name: "my_filegroup", 1866 licenses: ["my_license"], 1867} 1868`, 1869 ExpectedBazelTargets: []string{ 1870 MakeBazelTargetNoRestrictions("filegroup", "my_filegroup", AttrNameToString{ 1871 "applicable_licenses": `[":my_license"]`, 1872 }), 1873 MakeBazelTargetNoRestrictions("android_license", "my_license", AttrNameToString{}), 1874 }, 1875 }) 1876} 1877 1878func TestGenerateApiBazelTargets(t *testing.T) { 1879 bp := ` 1880 custom { 1881 name: "foo", 1882 api: "foo.txt", 1883 } 1884 ` 1885 expectedBazelTarget := MakeBazelTarget( 1886 "custom_api_contribution", 1887 "foo", 1888 AttrNameToString{ 1889 "api": `"foo.txt"`, 1890 }, 1891 ) 1892 registerCustomModule := func(ctx android.RegistrationContext) { 1893 ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice) 1894 } 1895 RunApiBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{ 1896 Blueprint: bp, 1897 ExpectedBazelTargets: []string{expectedBazelTarget}, 1898 Description: "Generating API contribution Bazel targets for custom module", 1899 }) 1900} 1901