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 "android/soong/android" 19 "android/soong/genrule" 20 "strings" 21 "testing" 22) 23 24func TestGenerateSoongModuleTargets(t *testing.T) { 25 testCases := []struct { 26 bp string 27 expectedBazelTarget string 28 }{ 29 { 30 bp: `custom { name: "foo" } 31 `, 32 expectedBazelTarget: `soong_module( 33 name = "foo", 34 soong_module_name = "foo", 35 soong_module_type = "custom", 36 soong_module_variant = "", 37 soong_module_deps = [ 38 ], 39)`, 40 }, 41 { 42 bp: `custom { 43 name: "foo", 44 ramdisk: true, 45} 46 `, 47 expectedBazelTarget: `soong_module( 48 name = "foo", 49 soong_module_name = "foo", 50 soong_module_type = "custom", 51 soong_module_variant = "", 52 soong_module_deps = [ 53 ], 54 ramdisk = True, 55)`, 56 }, 57 { 58 bp: `custom { 59 name: "foo", 60 owner: "a_string_with\"quotes\"_and_\\backslashes\\\\", 61} 62 `, 63 expectedBazelTarget: `soong_module( 64 name = "foo", 65 soong_module_name = "foo", 66 soong_module_type = "custom", 67 soong_module_variant = "", 68 soong_module_deps = [ 69 ], 70 owner = "a_string_with\"quotes\"_and_\\backslashes\\\\", 71)`, 72 }, 73 { 74 bp: `custom { 75 name: "foo", 76 required: ["bar"], 77} 78 `, 79 expectedBazelTarget: `soong_module( 80 name = "foo", 81 soong_module_name = "foo", 82 soong_module_type = "custom", 83 soong_module_variant = "", 84 soong_module_deps = [ 85 ], 86 required = ["bar"], 87)`, 88 }, 89 { 90 bp: `custom { 91 name: "foo", 92 target_required: ["qux", "bazqux"], 93} 94 `, 95 expectedBazelTarget: `soong_module( 96 name = "foo", 97 soong_module_name = "foo", 98 soong_module_type = "custom", 99 soong_module_variant = "", 100 soong_module_deps = [ 101 ], 102 target_required = [ 103 "qux", 104 "bazqux", 105 ], 106)`, 107 }, 108 { 109 bp: `custom { 110 name: "foo", 111 dist: { 112 targets: ["goal_foo"], 113 tag: ".foo", 114 }, 115 dists: [{ 116 targets: ["goal_bar"], 117 tag: ".bar", 118 }], 119} 120 `, 121 expectedBazelTarget: `soong_module( 122 name = "foo", 123 soong_module_name = "foo", 124 soong_module_type = "custom", 125 soong_module_variant = "", 126 soong_module_deps = [ 127 ], 128 dist = { 129 "tag": ".foo", 130 "targets": ["goal_foo"], 131 }, 132 dists = [{ 133 "tag": ".bar", 134 "targets": ["goal_bar"], 135 }], 136)`, 137 }, 138 { 139 bp: `custom { 140 name: "foo", 141 required: ["bar"], 142 target_required: ["qux", "bazqux"], 143 ramdisk: true, 144 owner: "custom_owner", 145 dists: [ 146 { 147 tag: ".tag", 148 targets: ["my_goal"], 149 }, 150 ], 151} 152 `, 153 expectedBazelTarget: `soong_module( 154 name = "foo", 155 soong_module_name = "foo", 156 soong_module_type = "custom", 157 soong_module_variant = "", 158 soong_module_deps = [ 159 ], 160 dists = [{ 161 "tag": ".tag", 162 "targets": ["my_goal"], 163 }], 164 owner = "custom_owner", 165 ramdisk = True, 166 required = ["bar"], 167 target_required = [ 168 "qux", 169 "bazqux", 170 ], 171)`, 172 }, 173 } 174 175 dir := "." 176 for _, testCase := range testCases { 177 config := android.TestConfig(buildDir, nil, testCase.bp, nil) 178 ctx := android.NewTestContext(config) 179 180 ctx.RegisterModuleType("custom", customModuleFactory) 181 ctx.Register() 182 183 _, errs := ctx.ParseFileList(dir, []string{"Android.bp"}) 184 android.FailIfErrored(t, errs) 185 _, errs = ctx.PrepareBuildActions(config) 186 android.FailIfErrored(t, errs) 187 188 codegenCtx := NewCodegenContext(config, *ctx.Context, QueryView) 189 bazelTargets := generateBazelTargetsForDir(codegenCtx, dir) 190 if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount { 191 t.Fatalf("Expected %d bazel target, got %d", expectedCount, actualCount) 192 } 193 194 actualBazelTarget := bazelTargets[0] 195 if actualBazelTarget.content != testCase.expectedBazelTarget { 196 t.Errorf( 197 "Expected generated Bazel target to be '%s', got '%s'", 198 testCase.expectedBazelTarget, 199 actualBazelTarget.content, 200 ) 201 } 202 } 203} 204 205func TestGenerateBazelTargetModules(t *testing.T) { 206 testCases := []struct { 207 name string 208 bp string 209 expectedBazelTargets []string 210 }{ 211 { 212 bp: `custom { 213 name: "foo", 214 string_list_prop: ["a", "b"], 215 string_prop: "a", 216 bazel_module: { bp2build_available: true }, 217}`, 218 expectedBazelTargets: []string{`custom( 219 name = "foo", 220 string_list_prop = [ 221 "a", 222 "b", 223 ], 224 string_prop = "a", 225)`, 226 }, 227 }, 228 { 229 bp: `custom { 230 name: "control_characters", 231 string_list_prop: ["\t", "\n"], 232 string_prop: "a\t\n\r", 233 bazel_module: { bp2build_available: true }, 234}`, 235 expectedBazelTargets: []string{`custom( 236 name = "control_characters", 237 string_list_prop = [ 238 "\t", 239 "\n", 240 ], 241 string_prop = "a\t\n\r", 242)`, 243 }, 244 }, 245 { 246 bp: `custom { 247 name: "has_dep", 248 arch_paths: [":dep"], 249 bazel_module: { bp2build_available: true }, 250} 251 252custom { 253 name: "dep", 254 arch_paths: ["abc"], 255 bazel_module: { bp2build_available: true }, 256}`, 257 expectedBazelTargets: []string{`custom( 258 name = "dep", 259 arch_paths = ["abc"], 260)`, 261 `custom( 262 name = "has_dep", 263 arch_paths = [":dep"], 264)`, 265 }, 266 }, 267 { 268 bp: `custom { 269 name: "arch_paths", 270 arch: { 271 x86: { 272 arch_paths: ["abc"], 273 }, 274 }, 275 bazel_module: { bp2build_available: true }, 276}`, 277 expectedBazelTargets: []string{`custom( 278 name = "arch_paths", 279 arch_paths = select({ 280 "//build/bazel/platforms/arch:x86": ["abc"], 281 "//conditions:default": [], 282 }), 283)`, 284 }, 285 }, 286 { 287 bp: `custom { 288 name: "has_dep", 289 arch: { 290 x86: { 291 arch_paths: [":dep"], 292 }, 293 }, 294 bazel_module: { bp2build_available: true }, 295} 296 297custom { 298 name: "dep", 299 arch_paths: ["abc"], 300 bazel_module: { bp2build_available: true }, 301}`, 302 expectedBazelTargets: []string{`custom( 303 name = "dep", 304 arch_paths = ["abc"], 305)`, 306 `custom( 307 name = "has_dep", 308 arch_paths = select({ 309 "//build/bazel/platforms/arch:x86": [":dep"], 310 "//conditions:default": [], 311 }), 312)`, 313 }, 314 }, 315 } 316 317 dir := "." 318 for _, testCase := range testCases { 319 config := android.TestConfig(buildDir, nil, testCase.bp, nil) 320 ctx := android.NewTestContext(config) 321 322 ctx.RegisterModuleType("custom", customModuleFactory) 323 ctx.RegisterBp2BuildMutator("custom", customBp2BuildMutator) 324 ctx.RegisterForBazelConversion() 325 326 _, errs := ctx.ParseFileList(dir, []string{"Android.bp"}) 327 if Errored(t, "", errs) { 328 continue 329 } 330 _, errs = ctx.ResolveDependencies(config) 331 if Errored(t, "", errs) { 332 continue 333 } 334 335 codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build) 336 bazelTargets := generateBazelTargetsForDir(codegenCtx, dir) 337 338 if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount { 339 t.Errorf("Expected %d bazel target, got %d", expectedCount, actualCount) 340 } else { 341 for i, expectedBazelTarget := range testCase.expectedBazelTargets { 342 actualBazelTarget := bazelTargets[i] 343 if actualBazelTarget.content != expectedBazelTarget { 344 t.Errorf( 345 "Expected generated Bazel target to be '%s', got '%s'", 346 expectedBazelTarget, 347 actualBazelTarget.content, 348 ) 349 } 350 } 351 } 352 } 353} 354 355func TestLoadStatements(t *testing.T) { 356 testCases := []struct { 357 bazelTargets BazelTargets 358 expectedLoadStatements string 359 }{ 360 { 361 bazelTargets: BazelTargets{ 362 BazelTarget{ 363 name: "foo", 364 ruleClass: "cc_library", 365 bzlLoadLocation: "//build/bazel/rules:cc.bzl", 366 }, 367 }, 368 expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_library")`, 369 }, 370 { 371 bazelTargets: BazelTargets{ 372 BazelTarget{ 373 name: "foo", 374 ruleClass: "cc_library", 375 bzlLoadLocation: "//build/bazel/rules:cc.bzl", 376 }, 377 BazelTarget{ 378 name: "bar", 379 ruleClass: "cc_library", 380 bzlLoadLocation: "//build/bazel/rules:cc.bzl", 381 }, 382 }, 383 expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_library")`, 384 }, 385 { 386 bazelTargets: BazelTargets{ 387 BazelTarget{ 388 name: "foo", 389 ruleClass: "cc_library", 390 bzlLoadLocation: "//build/bazel/rules:cc.bzl", 391 }, 392 BazelTarget{ 393 name: "bar", 394 ruleClass: "cc_binary", 395 bzlLoadLocation: "//build/bazel/rules:cc.bzl", 396 }, 397 }, 398 expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary", "cc_library")`, 399 }, 400 { 401 bazelTargets: BazelTargets{ 402 BazelTarget{ 403 name: "foo", 404 ruleClass: "cc_library", 405 bzlLoadLocation: "//build/bazel/rules:cc.bzl", 406 }, 407 BazelTarget{ 408 name: "bar", 409 ruleClass: "cc_binary", 410 bzlLoadLocation: "//build/bazel/rules:cc.bzl", 411 }, 412 BazelTarget{ 413 name: "baz", 414 ruleClass: "java_binary", 415 bzlLoadLocation: "//build/bazel/rules:java.bzl", 416 }, 417 }, 418 expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary", "cc_library") 419load("//build/bazel/rules:java.bzl", "java_binary")`, 420 }, 421 { 422 bazelTargets: BazelTargets{ 423 BazelTarget{ 424 name: "foo", 425 ruleClass: "cc_binary", 426 bzlLoadLocation: "//build/bazel/rules:cc.bzl", 427 }, 428 BazelTarget{ 429 name: "bar", 430 ruleClass: "java_binary", 431 bzlLoadLocation: "//build/bazel/rules:java.bzl", 432 }, 433 BazelTarget{ 434 name: "baz", 435 ruleClass: "genrule", 436 // Note: no bzlLoadLocation for native rules 437 }, 438 }, 439 expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary") 440load("//build/bazel/rules:java.bzl", "java_binary")`, 441 }, 442 } 443 444 for _, testCase := range testCases { 445 actual := testCase.bazelTargets.LoadStatements() 446 expected := testCase.expectedLoadStatements 447 if actual != expected { 448 t.Fatalf("Expected load statements to be %s, got %s", expected, actual) 449 } 450 } 451 452} 453 454func TestGenerateBazelTargetModules_OneToMany_LoadedFromStarlark(t *testing.T) { 455 testCases := []struct { 456 bp string 457 expectedBazelTarget string 458 expectedBazelTargetCount int 459 expectedLoadStatements string 460 }{ 461 { 462 bp: `custom { 463 name: "bar", 464 bazel_module: { bp2build_available: true }, 465}`, 466 expectedBazelTarget: `my_library( 467 name = "bar", 468) 469 470my_proto_library( 471 name = "bar_my_proto_library_deps", 472) 473 474proto_library( 475 name = "bar_proto_library_deps", 476)`, 477 expectedBazelTargetCount: 3, 478 expectedLoadStatements: `load("//build/bazel/rules:proto.bzl", "my_proto_library", "proto_library") 479load("//build/bazel/rules:rules.bzl", "my_library")`, 480 }, 481 } 482 483 dir := "." 484 for _, testCase := range testCases { 485 config := android.TestConfig(buildDir, nil, testCase.bp, nil) 486 ctx := android.NewTestContext(config) 487 ctx.RegisterModuleType("custom", customModuleFactory) 488 ctx.RegisterBp2BuildMutator("custom", customBp2BuildMutatorFromStarlark) 489 ctx.RegisterForBazelConversion() 490 491 _, errs := ctx.ParseFileList(dir, []string{"Android.bp"}) 492 android.FailIfErrored(t, errs) 493 _, errs = ctx.ResolveDependencies(config) 494 android.FailIfErrored(t, errs) 495 496 codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build) 497 bazelTargets := generateBazelTargetsForDir(codegenCtx, dir) 498 if actualCount := len(bazelTargets); actualCount != testCase.expectedBazelTargetCount { 499 t.Fatalf("Expected %d bazel target, got %d", testCase.expectedBazelTargetCount, actualCount) 500 } 501 502 actualBazelTargets := bazelTargets.String() 503 if actualBazelTargets != testCase.expectedBazelTarget { 504 t.Errorf( 505 "Expected generated Bazel target to be '%s', got '%s'", 506 testCase.expectedBazelTarget, 507 actualBazelTargets, 508 ) 509 } 510 511 actualLoadStatements := bazelTargets.LoadStatements() 512 if actualLoadStatements != testCase.expectedLoadStatements { 513 t.Errorf( 514 "Expected generated load statements to be '%s', got '%s'", 515 testCase.expectedLoadStatements, 516 actualLoadStatements, 517 ) 518 } 519 } 520} 521 522func TestModuleTypeBp2Build(t *testing.T) { 523 otherGenruleBp := map[string]string{ 524 "other/Android.bp": `genrule { 525 name: "foo.tool", 526 out: ["foo_tool.out"], 527 srcs: ["foo_tool.in"], 528 cmd: "cp $(in) $(out)", 529} 530genrule { 531 name: "other.tool", 532 out: ["other_tool.out"], 533 srcs: ["other_tool.in"], 534 cmd: "cp $(in) $(out)", 535}`, 536 } 537 538 testCases := []struct { 539 description string 540 moduleTypeUnderTest string 541 moduleTypeUnderTestFactory android.ModuleFactory 542 moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext) 543 preArchMutators []android.RegisterMutatorFunc 544 depsMutators []android.RegisterMutatorFunc 545 bp string 546 expectedBazelTargets []string 547 fs map[string]string 548 dir string 549 }{ 550 { 551 description: "filegroup with does not specify srcs", 552 moduleTypeUnderTest: "filegroup", 553 moduleTypeUnderTestFactory: android.FileGroupFactory, 554 moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build, 555 bp: `filegroup { 556 name: "fg_foo", 557 bazel_module: { bp2build_available: true }, 558}`, 559 expectedBazelTargets: []string{ 560 `filegroup( 561 name = "fg_foo", 562)`, 563 }, 564 }, 565 { 566 description: "filegroup with no srcs", 567 moduleTypeUnderTest: "filegroup", 568 moduleTypeUnderTestFactory: android.FileGroupFactory, 569 moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build, 570 bp: `filegroup { 571 name: "fg_foo", 572 srcs: [], 573 bazel_module: { bp2build_available: true }, 574}`, 575 expectedBazelTargets: []string{ 576 `filegroup( 577 name = "fg_foo", 578)`, 579 }, 580 }, 581 { 582 description: "filegroup with srcs", 583 moduleTypeUnderTest: "filegroup", 584 moduleTypeUnderTestFactory: android.FileGroupFactory, 585 moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build, 586 bp: `filegroup { 587 name: "fg_foo", 588 srcs: ["a", "b"], 589 bazel_module: { bp2build_available: true }, 590}`, 591 expectedBazelTargets: []string{`filegroup( 592 name = "fg_foo", 593 srcs = [ 594 "a", 595 "b", 596 ], 597)`, 598 }, 599 }, 600 { 601 description: "filegroup with excludes srcs", 602 moduleTypeUnderTest: "filegroup", 603 moduleTypeUnderTestFactory: android.FileGroupFactory, 604 moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build, 605 bp: `filegroup { 606 name: "fg_foo", 607 srcs: ["a", "b"], 608 exclude_srcs: ["a"], 609 bazel_module: { bp2build_available: true }, 610}`, 611 expectedBazelTargets: []string{`filegroup( 612 name = "fg_foo", 613 srcs = ["b"], 614)`, 615 }, 616 }, 617 { 618 description: "filegroup with glob", 619 moduleTypeUnderTest: "filegroup", 620 moduleTypeUnderTestFactory: android.FileGroupFactory, 621 moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build, 622 bp: `filegroup { 623 name: "foo", 624 srcs: ["**/*.txt"], 625 bazel_module: { bp2build_available: true }, 626}`, 627 expectedBazelTargets: []string{`filegroup( 628 name = "foo", 629 srcs = [ 630 "other/a.txt", 631 "other/b.txt", 632 "other/subdir/a.txt", 633 ], 634)`, 635 }, 636 fs: map[string]string{ 637 "other/a.txt": "", 638 "other/b.txt": "", 639 "other/subdir/a.txt": "", 640 "other/file": "", 641 }, 642 }, 643 { 644 description: "filegroup with glob in subdir", 645 moduleTypeUnderTest: "filegroup", 646 moduleTypeUnderTestFactory: android.FileGroupFactory, 647 moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build, 648 bp: `filegroup { 649 name: "foo", 650 srcs: ["a.txt"], 651 bazel_module: { bp2build_available: true }, 652}`, 653 dir: "other", 654 expectedBazelTargets: []string{`filegroup( 655 name = "fg_foo", 656 srcs = [ 657 "a.txt", 658 "b.txt", 659 "subdir/a.txt", 660 ], 661)`, 662 }, 663 fs: map[string]string{ 664 "other/Android.bp": `filegroup { 665 name: "fg_foo", 666 srcs: ["**/*.txt"], 667 bazel_module: { bp2build_available: true }, 668}`, 669 "other/a.txt": "", 670 "other/b.txt": "", 671 "other/subdir/a.txt": "", 672 "other/file": "", 673 }, 674 }, 675 { 676 description: "depends_on_other_dir_module", 677 moduleTypeUnderTest: "filegroup", 678 moduleTypeUnderTestFactory: android.FileGroupFactory, 679 moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build, 680 bp: `filegroup { 681 name: "foobar", 682 srcs: [ 683 ":foo", 684 "c", 685 ], 686 bazel_module: { bp2build_available: true }, 687}`, 688 expectedBazelTargets: []string{`filegroup( 689 name = "foobar", 690 srcs = [ 691 "//other:foo", 692 "c", 693 ], 694)`, 695 }, 696 fs: map[string]string{ 697 "other/Android.bp": `filegroup { 698 name: "foo", 699 srcs: ["a", "b"], 700}`, 701 }, 702 }, 703 { 704 description: "genrule with command line variable replacements", 705 moduleTypeUnderTest: "genrule", 706 moduleTypeUnderTestFactory: genrule.GenRuleFactory, 707 moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build, 708 depsMutators: []android.RegisterMutatorFunc{genrule.RegisterGenruleBp2BuildDeps}, 709 bp: `genrule { 710 name: "foo.tool", 711 out: ["foo_tool.out"], 712 srcs: ["foo_tool.in"], 713 cmd: "cp $(in) $(out)", 714 bazel_module: { bp2build_available: true }, 715} 716 717genrule { 718 name: "foo", 719 out: ["foo.out"], 720 srcs: ["foo.in"], 721 tools: [":foo.tool"], 722 cmd: "$(location :foo.tool) --genDir=$(genDir) arg $(in) $(out)", 723 bazel_module: { bp2build_available: true }, 724}`, 725 expectedBazelTargets: []string{ 726 `genrule( 727 name = "foo", 728 cmd = "$(location :foo.tool) --genDir=$(GENDIR) arg $(SRCS) $(OUTS)", 729 outs = ["foo.out"], 730 srcs = ["foo.in"], 731 tools = [":foo.tool"], 732)`, 733 `genrule( 734 name = "foo.tool", 735 cmd = "cp $(SRCS) $(OUTS)", 736 outs = ["foo_tool.out"], 737 srcs = ["foo_tool.in"], 738)`, 739 }, 740 }, 741 { 742 description: "genrule using $(locations :label)", 743 moduleTypeUnderTest: "genrule", 744 moduleTypeUnderTestFactory: genrule.GenRuleFactory, 745 moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build, 746 depsMutators: []android.RegisterMutatorFunc{genrule.RegisterGenruleBp2BuildDeps}, 747 bp: `genrule { 748 name: "foo.tools", 749 out: ["foo_tool.out", "foo_tool2.out"], 750 srcs: ["foo_tool.in"], 751 cmd: "cp $(in) $(out)", 752 bazel_module: { bp2build_available: true }, 753} 754 755genrule { 756 name: "foo", 757 out: ["foo.out"], 758 srcs: ["foo.in"], 759 tools: [":foo.tools"], 760 cmd: "$(locations :foo.tools) -s $(out) $(in)", 761 bazel_module: { bp2build_available: true }, 762}`, 763 expectedBazelTargets: []string{`genrule( 764 name = "foo", 765 cmd = "$(locations :foo.tools) -s $(OUTS) $(SRCS)", 766 outs = ["foo.out"], 767 srcs = ["foo.in"], 768 tools = [":foo.tools"], 769)`, 770 `genrule( 771 name = "foo.tools", 772 cmd = "cp $(SRCS) $(OUTS)", 773 outs = [ 774 "foo_tool.out", 775 "foo_tool2.out", 776 ], 777 srcs = ["foo_tool.in"], 778)`, 779 }, 780 }, 781 { 782 description: "genrule using $(locations //absolute:label)", 783 moduleTypeUnderTest: "genrule", 784 moduleTypeUnderTestFactory: genrule.GenRuleFactory, 785 moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build, 786 depsMutators: []android.RegisterMutatorFunc{genrule.RegisterGenruleBp2BuildDeps}, 787 bp: `genrule { 788 name: "foo", 789 out: ["foo.out"], 790 srcs: ["foo.in"], 791 tool_files: [":foo.tool"], 792 cmd: "$(locations :foo.tool) -s $(out) $(in)", 793 bazel_module: { bp2build_available: true }, 794}`, 795 expectedBazelTargets: []string{`genrule( 796 name = "foo", 797 cmd = "$(locations //other:foo.tool) -s $(OUTS) $(SRCS)", 798 outs = ["foo.out"], 799 srcs = ["foo.in"], 800 tools = ["//other:foo.tool"], 801)`, 802 }, 803 fs: otherGenruleBp, 804 }, 805 { 806 description: "genrule srcs using $(locations //absolute:label)", 807 moduleTypeUnderTest: "genrule", 808 moduleTypeUnderTestFactory: genrule.GenRuleFactory, 809 moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build, 810 depsMutators: []android.RegisterMutatorFunc{genrule.RegisterGenruleBp2BuildDeps}, 811 bp: `genrule { 812 name: "foo", 813 out: ["foo.out"], 814 srcs: [":other.tool"], 815 tool_files: [":foo.tool"], 816 cmd: "$(locations :foo.tool) -s $(out) $(location :other.tool)", 817 bazel_module: { bp2build_available: true }, 818}`, 819 expectedBazelTargets: []string{`genrule( 820 name = "foo", 821 cmd = "$(locations //other:foo.tool) -s $(OUTS) $(location //other:other.tool)", 822 outs = ["foo.out"], 823 srcs = ["//other:other.tool"], 824 tools = ["//other:foo.tool"], 825)`, 826 }, 827 fs: otherGenruleBp, 828 }, 829 { 830 description: "genrule using $(location) label should substitute first tool label automatically", 831 moduleTypeUnderTest: "genrule", 832 moduleTypeUnderTestFactory: genrule.GenRuleFactory, 833 moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build, 834 depsMutators: []android.RegisterMutatorFunc{genrule.RegisterGenruleBp2BuildDeps}, 835 bp: `genrule { 836 name: "foo", 837 out: ["foo.out"], 838 srcs: ["foo.in"], 839 tool_files: [":foo.tool", ":other.tool"], 840 cmd: "$(location) -s $(out) $(in)", 841 bazel_module: { bp2build_available: true }, 842}`, 843 expectedBazelTargets: []string{`genrule( 844 name = "foo", 845 cmd = "$(location //other:foo.tool) -s $(OUTS) $(SRCS)", 846 outs = ["foo.out"], 847 srcs = ["foo.in"], 848 tools = [ 849 "//other:foo.tool", 850 "//other:other.tool", 851 ], 852)`, 853 }, 854 fs: otherGenruleBp, 855 }, 856 { 857 description: "genrule using $(locations) label should substitute first tool label automatically", 858 moduleTypeUnderTest: "genrule", 859 moduleTypeUnderTestFactory: genrule.GenRuleFactory, 860 moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build, 861 depsMutators: []android.RegisterMutatorFunc{genrule.RegisterGenruleBp2BuildDeps}, 862 bp: `genrule { 863 name: "foo", 864 out: ["foo.out"], 865 srcs: ["foo.in"], 866 tools: [":foo.tool", ":other.tool"], 867 cmd: "$(locations) -s $(out) $(in)", 868 bazel_module: { bp2build_available: true }, 869}`, 870 expectedBazelTargets: []string{`genrule( 871 name = "foo", 872 cmd = "$(locations //other:foo.tool) -s $(OUTS) $(SRCS)", 873 outs = ["foo.out"], 874 srcs = ["foo.in"], 875 tools = [ 876 "//other:foo.tool", 877 "//other:other.tool", 878 ], 879)`, 880 }, 881 fs: otherGenruleBp, 882 }, 883 { 884 description: "genrule without tools or tool_files can convert successfully", 885 moduleTypeUnderTest: "genrule", 886 moduleTypeUnderTestFactory: genrule.GenRuleFactory, 887 moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build, 888 depsMutators: []android.RegisterMutatorFunc{genrule.RegisterGenruleBp2BuildDeps}, 889 bp: `genrule { 890 name: "foo", 891 out: ["foo.out"], 892 srcs: ["foo.in"], 893 cmd: "cp $(in) $(out)", 894 bazel_module: { bp2build_available: true }, 895}`, 896 expectedBazelTargets: []string{`genrule( 897 name = "foo", 898 cmd = "cp $(SRCS) $(OUTS)", 899 outs = ["foo.out"], 900 srcs = ["foo.in"], 901)`, 902 }, 903 }, 904 } 905 906 dir := "." 907 for _, testCase := range testCases { 908 fs := make(map[string][]byte) 909 toParse := []string{ 910 "Android.bp", 911 } 912 for f, content := range testCase.fs { 913 if strings.HasSuffix(f, "Android.bp") { 914 toParse = append(toParse, f) 915 } 916 fs[f] = []byte(content) 917 } 918 config := android.TestConfig(buildDir, nil, testCase.bp, fs) 919 ctx := android.NewTestContext(config) 920 ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory) 921 for _, m := range testCase.depsMutators { 922 ctx.DepsBp2BuildMutators(m) 923 } 924 ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator) 925 ctx.RegisterForBazelConversion() 926 927 _, errs := ctx.ParseFileList(dir, toParse) 928 if Errored(t, testCase.description, errs) { 929 continue 930 } 931 _, errs = ctx.ResolveDependencies(config) 932 if Errored(t, testCase.description, errs) { 933 continue 934 } 935 936 checkDir := dir 937 if testCase.dir != "" { 938 checkDir = testCase.dir 939 } 940 941 codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build) 942 bazelTargets := generateBazelTargetsForDir(codegenCtx, checkDir) 943 if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount { 944 t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount) 945 } else { 946 for i, target := range bazelTargets { 947 if w, g := testCase.expectedBazelTargets[i], target.content; w != g { 948 t.Errorf( 949 "%s: Expected generated Bazel target to be '%s', got '%s'", 950 testCase.description, 951 w, 952 g, 953 ) 954 } 955 } 956 } 957 } 958} 959 960func Errored(t *testing.T, desc string, errs []error) bool { 961 t.Helper() 962 if len(errs) > 0 { 963 for _, err := range errs { 964 t.Errorf("%s: %s", desc, err) 965 } 966 return true 967 } 968 return false 969} 970 971type bp2buildMutator = func(android.TopDownMutatorContext) 972 973func TestBp2BuildInlinesDefaults(t *testing.T) { 974 testCases := []struct { 975 moduleTypesUnderTest map[string]android.ModuleFactory 976 bp2buildMutatorsUnderTest map[string]bp2buildMutator 977 bp string 978 expectedBazelTarget string 979 description string 980 }{ 981 { 982 moduleTypesUnderTest: map[string]android.ModuleFactory{ 983 "genrule": genrule.GenRuleFactory, 984 "genrule_defaults": func() android.Module { return genrule.DefaultsFactory() }, 985 }, 986 bp2buildMutatorsUnderTest: map[string]bp2buildMutator{ 987 "genrule": genrule.GenruleBp2Build, 988 }, 989 bp: `genrule_defaults { 990 name: "gen_defaults", 991 cmd: "do-something $(in) $(out)", 992} 993genrule { 994 name: "gen", 995 out: ["out"], 996 srcs: ["in1"], 997 defaults: ["gen_defaults"], 998 bazel_module: { bp2build_available: true }, 999} 1000`, 1001 expectedBazelTarget: `genrule( 1002 name = "gen", 1003 cmd = "do-something $(SRCS) $(OUTS)", 1004 outs = ["out"], 1005 srcs = ["in1"], 1006)`, 1007 description: "genrule applies properties from a genrule_defaults dependency if not specified", 1008 }, 1009 { 1010 moduleTypesUnderTest: map[string]android.ModuleFactory{ 1011 "genrule": genrule.GenRuleFactory, 1012 "genrule_defaults": func() android.Module { return genrule.DefaultsFactory() }, 1013 }, 1014 bp2buildMutatorsUnderTest: map[string]bp2buildMutator{ 1015 "genrule": genrule.GenruleBp2Build, 1016 }, 1017 bp: `genrule_defaults { 1018 name: "gen_defaults", 1019 out: ["out-from-defaults"], 1020 srcs: ["in-from-defaults"], 1021 cmd: "cmd-from-defaults", 1022} 1023genrule { 1024 name: "gen", 1025 out: ["out"], 1026 srcs: ["in1"], 1027 defaults: ["gen_defaults"], 1028 cmd: "do-something $(in) $(out)", 1029 bazel_module: { bp2build_available: true }, 1030} 1031`, 1032 expectedBazelTarget: `genrule( 1033 name = "gen", 1034 cmd = "do-something $(SRCS) $(OUTS)", 1035 outs = [ 1036 "out-from-defaults", 1037 "out", 1038 ], 1039 srcs = [ 1040 "in-from-defaults", 1041 "in1", 1042 ], 1043)`, 1044 description: "genrule does merges properties from a genrule_defaults dependency, latest-first", 1045 }, 1046 { 1047 moduleTypesUnderTest: map[string]android.ModuleFactory{ 1048 "genrule": genrule.GenRuleFactory, 1049 "genrule_defaults": func() android.Module { return genrule.DefaultsFactory() }, 1050 }, 1051 bp2buildMutatorsUnderTest: map[string]bp2buildMutator{ 1052 "genrule": genrule.GenruleBp2Build, 1053 }, 1054 bp: `genrule_defaults { 1055 name: "gen_defaults1", 1056 cmd: "cp $(in) $(out)", 1057} 1058 1059genrule_defaults { 1060 name: "gen_defaults2", 1061 srcs: ["in1"], 1062} 1063 1064genrule { 1065 name: "gen", 1066 out: ["out"], 1067 defaults: ["gen_defaults1", "gen_defaults2"], 1068 bazel_module: { bp2build_available: true }, 1069} 1070`, 1071 expectedBazelTarget: `genrule( 1072 name = "gen", 1073 cmd = "cp $(SRCS) $(OUTS)", 1074 outs = ["out"], 1075 srcs = ["in1"], 1076)`, 1077 description: "genrule applies properties from list of genrule_defaults", 1078 }, 1079 { 1080 moduleTypesUnderTest: map[string]android.ModuleFactory{ 1081 "genrule": genrule.GenRuleFactory, 1082 "genrule_defaults": func() android.Module { return genrule.DefaultsFactory() }, 1083 }, 1084 bp2buildMutatorsUnderTest: map[string]bp2buildMutator{ 1085 "genrule": genrule.GenruleBp2Build, 1086 }, 1087 bp: `genrule_defaults { 1088 name: "gen_defaults1", 1089 defaults: ["gen_defaults2"], 1090 cmd: "cmd1 $(in) $(out)", // overrides gen_defaults2's cmd property value. 1091} 1092 1093genrule_defaults { 1094 name: "gen_defaults2", 1095 defaults: ["gen_defaults3"], 1096 cmd: "cmd2 $(in) $(out)", 1097 out: ["out-from-2"], 1098 srcs: ["in1"], 1099} 1100 1101genrule_defaults { 1102 name: "gen_defaults3", 1103 out: ["out-from-3"], 1104 srcs: ["srcs-from-3"], 1105} 1106 1107genrule { 1108 name: "gen", 1109 out: ["out"], 1110 defaults: ["gen_defaults1"], 1111 bazel_module: { bp2build_available: true }, 1112} 1113`, 1114 expectedBazelTarget: `genrule( 1115 name = "gen", 1116 cmd = "cmd1 $(SRCS) $(OUTS)", 1117 outs = [ 1118 "out-from-3", 1119 "out-from-2", 1120 "out", 1121 ], 1122 srcs = [ 1123 "in1", 1124 "srcs-from-3", 1125 ], 1126)`, 1127 description: "genrule applies properties from genrule_defaults transitively", 1128 }, 1129 } 1130 1131 dir := "." 1132 for _, testCase := range testCases { 1133 config := android.TestConfig(buildDir, nil, testCase.bp, nil) 1134 ctx := android.NewTestContext(config) 1135 for m, factory := range testCase.moduleTypesUnderTest { 1136 ctx.RegisterModuleType(m, factory) 1137 } 1138 for mutator, f := range testCase.bp2buildMutatorsUnderTest { 1139 ctx.RegisterBp2BuildMutator(mutator, f) 1140 } 1141 ctx.RegisterForBazelConversion() 1142 1143 _, errs := ctx.ParseFileList(dir, []string{"Android.bp"}) 1144 android.FailIfErrored(t, errs) 1145 _, errs = ctx.ResolveDependencies(config) 1146 android.FailIfErrored(t, errs) 1147 1148 codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build) 1149 bazelTargets := generateBazelTargetsForDir(codegenCtx, dir) 1150 if actualCount := len(bazelTargets); actualCount != 1 { 1151 t.Fatalf("%s: Expected 1 bazel target, got %d", testCase.description, actualCount) 1152 } 1153 1154 actualBazelTarget := bazelTargets[0] 1155 if actualBazelTarget.content != testCase.expectedBazelTarget { 1156 t.Errorf( 1157 "%s: Expected generated Bazel target to be '%s', got '%s'", 1158 testCase.description, 1159 testCase.expectedBazelTarget, 1160 actualBazelTarget.content, 1161 ) 1162 } 1163 } 1164} 1165 1166func TestAllowlistingBp2buildTargetsExplicitly(t *testing.T) { 1167 testCases := []struct { 1168 moduleTypeUnderTest string 1169 moduleTypeUnderTestFactory android.ModuleFactory 1170 moduleTypeUnderTestBp2BuildMutator bp2buildMutator 1171 bp string 1172 expectedCount int 1173 description string 1174 }{ 1175 { 1176 description: "explicitly unavailable", 1177 moduleTypeUnderTest: "filegroup", 1178 moduleTypeUnderTestFactory: android.FileGroupFactory, 1179 moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build, 1180 bp: `filegroup { 1181 name: "foo", 1182 srcs: ["a", "b"], 1183 bazel_module: { bp2build_available: false }, 1184}`, 1185 expectedCount: 0, 1186 }, 1187 { 1188 description: "implicitly unavailable", 1189 moduleTypeUnderTest: "filegroup", 1190 moduleTypeUnderTestFactory: android.FileGroupFactory, 1191 moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build, 1192 bp: `filegroup { 1193 name: "foo", 1194 srcs: ["a", "b"], 1195}`, 1196 expectedCount: 0, 1197 }, 1198 { 1199 description: "explicitly available", 1200 moduleTypeUnderTest: "filegroup", 1201 moduleTypeUnderTestFactory: android.FileGroupFactory, 1202 moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build, 1203 bp: `filegroup { 1204 name: "foo", 1205 srcs: ["a", "b"], 1206 bazel_module: { bp2build_available: true }, 1207}`, 1208 expectedCount: 1, 1209 }, 1210 { 1211 description: "generates more than 1 target if needed", 1212 moduleTypeUnderTest: "custom", 1213 moduleTypeUnderTestFactory: customModuleFactory, 1214 moduleTypeUnderTestBp2BuildMutator: customBp2BuildMutatorFromStarlark, 1215 bp: `custom { 1216 name: "foo", 1217 bazel_module: { bp2build_available: true }, 1218}`, 1219 expectedCount: 3, 1220 }, 1221 } 1222 1223 dir := "." 1224 for _, testCase := range testCases { 1225 config := android.TestConfig(buildDir, nil, testCase.bp, nil) 1226 ctx := android.NewTestContext(config) 1227 ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory) 1228 ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator) 1229 ctx.RegisterForBazelConversion() 1230 1231 _, errs := ctx.ParseFileList(dir, []string{"Android.bp"}) 1232 android.FailIfErrored(t, errs) 1233 _, errs = ctx.ResolveDependencies(config) 1234 android.FailIfErrored(t, errs) 1235 1236 codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build) 1237 bazelTargets := generateBazelTargetsForDir(codegenCtx, dir) 1238 if actualCount := len(bazelTargets); actualCount != testCase.expectedCount { 1239 t.Fatalf("%s: Expected %d bazel target, got %d", testCase.description, testCase.expectedCount, actualCount) 1240 } 1241 } 1242} 1243 1244func TestAllowlistingBp2buildTargetsWithConfig(t *testing.T) { 1245 testCases := []struct { 1246 moduleTypeUnderTest string 1247 moduleTypeUnderTestFactory android.ModuleFactory 1248 moduleTypeUnderTestBp2BuildMutator bp2buildMutator 1249 expectedCount map[string]int 1250 description string 1251 bp2buildConfig android.Bp2BuildConfig 1252 checkDir string 1253 fs map[string]string 1254 }{ 1255 { 1256 description: "test bp2build config package and subpackages config", 1257 moduleTypeUnderTest: "filegroup", 1258 moduleTypeUnderTestFactory: android.FileGroupFactory, 1259 moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build, 1260 expectedCount: map[string]int{ 1261 "migrated": 1, 1262 "migrated/but_not_really": 0, 1263 "migrated/but_not_really/but_really": 1, 1264 "not_migrated": 0, 1265 "also_not_migrated": 0, 1266 }, 1267 bp2buildConfig: android.Bp2BuildConfig{ 1268 "migrated": android.Bp2BuildDefaultTrueRecursively, 1269 "migrated/but_not_really": android.Bp2BuildDefaultFalse, 1270 "not_migrated": android.Bp2BuildDefaultFalse, 1271 }, 1272 fs: map[string]string{ 1273 "migrated/Android.bp": `filegroup { name: "a" }`, 1274 "migrated/but_not_really/Android.bp": `filegroup { name: "b" }`, 1275 "migrated/but_not_really/but_really/Android.bp": `filegroup { name: "c" }`, 1276 "not_migrated/Android.bp": `filegroup { name: "d" }`, 1277 "also_not_migrated/Android.bp": `filegroup { name: "e" }`, 1278 }, 1279 }, 1280 { 1281 description: "test bp2build config opt-in and opt-out", 1282 moduleTypeUnderTest: "filegroup", 1283 moduleTypeUnderTestFactory: android.FileGroupFactory, 1284 moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build, 1285 expectedCount: map[string]int{ 1286 "package-opt-in": 2, 1287 "package-opt-in/subpackage": 0, 1288 "package-opt-out": 1, 1289 "package-opt-out/subpackage": 0, 1290 }, 1291 bp2buildConfig: android.Bp2BuildConfig{ 1292 "package-opt-in": android.Bp2BuildDefaultFalse, 1293 "package-opt-out": android.Bp2BuildDefaultTrueRecursively, 1294 }, 1295 fs: map[string]string{ 1296 "package-opt-in/Android.bp": ` 1297filegroup { name: "opt-in-a" } 1298filegroup { name: "opt-in-b", bazel_module: { bp2build_available: true } } 1299filegroup { name: "opt-in-c", bazel_module: { bp2build_available: true } } 1300`, 1301 1302 "package-opt-in/subpackage/Android.bp": ` 1303filegroup { name: "opt-in-d" } // parent package not configured to DefaultTrueRecursively 1304`, 1305 1306 "package-opt-out/Android.bp": ` 1307filegroup { name: "opt-out-a" } 1308filegroup { name: "opt-out-b", bazel_module: { bp2build_available: false } } 1309filegroup { name: "opt-out-c", bazel_module: { bp2build_available: false } } 1310`, 1311 1312 "package-opt-out/subpackage/Android.bp": ` 1313filegroup { name: "opt-out-g", bazel_module: { bp2build_available: false } } 1314filegroup { name: "opt-out-h", bazel_module: { bp2build_available: false } } 1315`, 1316 }, 1317 }, 1318 } 1319 1320 dir := "." 1321 for _, testCase := range testCases { 1322 fs := make(map[string][]byte) 1323 toParse := []string{ 1324 "Android.bp", 1325 } 1326 for f, content := range testCase.fs { 1327 if strings.HasSuffix(f, "Android.bp") { 1328 toParse = append(toParse, f) 1329 } 1330 fs[f] = []byte(content) 1331 } 1332 config := android.TestConfig(buildDir, nil, "", fs) 1333 ctx := android.NewTestContext(config) 1334 ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory) 1335 ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator) 1336 ctx.RegisterBp2BuildConfig(testCase.bp2buildConfig) 1337 ctx.RegisterForBazelConversion() 1338 1339 _, errs := ctx.ParseFileList(dir, toParse) 1340 android.FailIfErrored(t, errs) 1341 _, errs = ctx.ResolveDependencies(config) 1342 android.FailIfErrored(t, errs) 1343 1344 codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build) 1345 1346 // For each directory, test that the expected number of generated targets is correct. 1347 for dir, expectedCount := range testCase.expectedCount { 1348 bazelTargets := generateBazelTargetsForDir(codegenCtx, dir) 1349 if actualCount := len(bazelTargets); actualCount != expectedCount { 1350 t.Fatalf( 1351 "%s: Expected %d bazel target for %s package, got %d", 1352 testCase.description, 1353 expectedCount, 1354 dir, 1355 actualCount) 1356 } 1357 1358 } 1359 } 1360} 1361 1362func TestCombineBuildFilesBp2buildTargets(t *testing.T) { 1363 testCases := []struct { 1364 description string 1365 moduleTypeUnderTest string 1366 moduleTypeUnderTestFactory android.ModuleFactory 1367 moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext) 1368 preArchMutators []android.RegisterMutatorFunc 1369 depsMutators []android.RegisterMutatorFunc 1370 bp string 1371 expectedBazelTargets []string 1372 fs map[string]string 1373 dir string 1374 }{ 1375 { 1376 description: "filegroup bazel_module.label", 1377 moduleTypeUnderTest: "filegroup", 1378 moduleTypeUnderTestFactory: android.FileGroupFactory, 1379 moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build, 1380 bp: `filegroup { 1381 name: "fg_foo", 1382 bazel_module: { label: "//other:fg_foo" }, 1383}`, 1384 expectedBazelTargets: []string{ 1385 `// BUILD file`, 1386 }, 1387 fs: map[string]string{ 1388 "other/BUILD.bazel": `// BUILD file`, 1389 }, 1390 }, 1391 { 1392 description: "multiple bazel_module.label same BUILD", 1393 moduleTypeUnderTest: "filegroup", 1394 moduleTypeUnderTestFactory: android.FileGroupFactory, 1395 moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build, 1396 bp: `filegroup { 1397 name: "fg_foo", 1398 bazel_module: { label: "//other:fg_foo" }, 1399} 1400 1401filegroup { 1402 name: "foo", 1403 bazel_module: { label: "//other:foo" }, 1404}`, 1405 expectedBazelTargets: []string{ 1406 `// BUILD file`, 1407 }, 1408 fs: map[string]string{ 1409 "other/BUILD.bazel": `// BUILD file`, 1410 }, 1411 }, 1412 { 1413 description: "filegroup bazel_module.label and bp2build", 1414 moduleTypeUnderTest: "filegroup", 1415 moduleTypeUnderTestFactory: android.FileGroupFactory, 1416 moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build, 1417 bp: `filegroup { 1418 name: "fg_foo", 1419 bazel_module: { 1420 label: "//other:fg_foo", 1421 bp2build_available: true, 1422 }, 1423}`, 1424 expectedBazelTargets: []string{ 1425 `filegroup( 1426 name = "fg_foo", 1427)`, 1428 `// BUILD file`, 1429 }, 1430 fs: map[string]string{ 1431 "other/BUILD.bazel": `// BUILD file`, 1432 }, 1433 }, 1434 { 1435 description: "filegroup bazel_module.label and filegroup bp2build", 1436 moduleTypeUnderTest: "filegroup", 1437 moduleTypeUnderTestFactory: android.FileGroupFactory, 1438 moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build, 1439 bp: `filegroup { 1440 name: "fg_foo", 1441 bazel_module: { 1442 label: "//other:fg_foo", 1443 }, 1444} 1445 1446filegroup { 1447 name: "fg_bar", 1448 bazel_module: { 1449 bp2build_available: true, 1450 }, 1451}`, 1452 expectedBazelTargets: []string{ 1453 `filegroup( 1454 name = "fg_bar", 1455)`, 1456 `// BUILD file`, 1457 }, 1458 fs: map[string]string{ 1459 "other/BUILD.bazel": `// BUILD file`, 1460 }, 1461 }, 1462 } 1463 1464 dir := "." 1465 for _, testCase := range testCases { 1466 fs := make(map[string][]byte) 1467 toParse := []string{ 1468 "Android.bp", 1469 } 1470 for f, content := range testCase.fs { 1471 if strings.HasSuffix(f, "Android.bp") { 1472 toParse = append(toParse, f) 1473 } 1474 fs[f] = []byte(content) 1475 } 1476 config := android.TestConfig(buildDir, nil, testCase.bp, fs) 1477 ctx := android.NewTestContext(config) 1478 ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory) 1479 for _, m := range testCase.depsMutators { 1480 ctx.DepsBp2BuildMutators(m) 1481 } 1482 ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator) 1483 ctx.RegisterForBazelConversion() 1484 1485 _, errs := ctx.ParseFileList(dir, toParse) 1486 if Errored(t, testCase.description, errs) { 1487 continue 1488 } 1489 _, errs = ctx.ResolveDependencies(config) 1490 if Errored(t, testCase.description, errs) { 1491 continue 1492 } 1493 1494 checkDir := dir 1495 if testCase.dir != "" { 1496 checkDir = testCase.dir 1497 } 1498 bazelTargets := generateBazelTargetsForDir(NewCodegenContext(config, *ctx.Context, Bp2Build), checkDir) 1499 if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount { 1500 t.Errorf("%s: Expected %d bazel target, got %d\n%s", testCase.description, expectedCount, actualCount, bazelTargets) 1501 } else { 1502 for i, target := range bazelTargets { 1503 if w, g := testCase.expectedBazelTargets[i], target.content; w != g { 1504 t.Errorf( 1505 "%s: Expected generated Bazel target to be '%s', got '%s'", 1506 testCase.description, 1507 w, 1508 g, 1509 ) 1510 } 1511 } 1512 } 1513 } 1514} 1515 1516func TestGlobExcludeSrcs(t *testing.T) { 1517 testCases := []struct { 1518 description string 1519 moduleTypeUnderTest string 1520 moduleTypeUnderTestFactory android.ModuleFactory 1521 moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext) 1522 bp string 1523 expectedBazelTargets []string 1524 fs map[string]string 1525 dir string 1526 }{ 1527 { 1528 description: "filegroup top level exclude_srcs", 1529 moduleTypeUnderTest: "filegroup", 1530 moduleTypeUnderTestFactory: android.FileGroupFactory, 1531 moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build, 1532 bp: `filegroup { 1533 name: "fg_foo", 1534 srcs: ["**/*.txt"], 1535 exclude_srcs: ["c.txt"], 1536 bazel_module: { bp2build_available: true }, 1537}`, 1538 expectedBazelTargets: []string{`filegroup( 1539 name = "fg_foo", 1540 srcs = [ 1541 "//dir:e.txt", 1542 "//dir:f.txt", 1543 "a.txt", 1544 "b.txt", 1545 ], 1546)`, 1547 }, 1548 fs: map[string]string{ 1549 "a.txt": "", 1550 "b.txt": "", 1551 "c.txt": "", 1552 "dir/Android.bp": "", 1553 "dir/e.txt": "", 1554 "dir/f.txt": "", 1555 }, 1556 }, 1557 { 1558 description: "filegroup in subdir exclude_srcs", 1559 moduleTypeUnderTest: "filegroup", 1560 moduleTypeUnderTestFactory: android.FileGroupFactory, 1561 moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build, 1562 bp: "", 1563 dir: "dir", 1564 fs: map[string]string{ 1565 "dir/Android.bp": `filegroup { 1566 name: "fg_foo", 1567 srcs: ["**/*.txt"], 1568 exclude_srcs: ["b.txt"], 1569 bazel_module: { bp2build_available: true }, 1570} 1571`, 1572 "dir/a.txt": "", 1573 "dir/b.txt": "", 1574 "dir/subdir/Android.bp": "", 1575 "dir/subdir/e.txt": "", 1576 "dir/subdir/f.txt": "", 1577 }, 1578 expectedBazelTargets: []string{`filegroup( 1579 name = "fg_foo", 1580 srcs = [ 1581 "//dir/subdir:e.txt", 1582 "//dir/subdir:f.txt", 1583 "a.txt", 1584 ], 1585)`, 1586 }, 1587 }, 1588 } 1589 1590 dir := "." 1591 for _, testCase := range testCases { 1592 fs := make(map[string][]byte) 1593 toParse := []string{ 1594 "Android.bp", 1595 } 1596 for f, content := range testCase.fs { 1597 if strings.HasSuffix(f, "Android.bp") { 1598 toParse = append(toParse, f) 1599 } 1600 fs[f] = []byte(content) 1601 } 1602 config := android.TestConfig(buildDir, nil, testCase.bp, fs) 1603 ctx := android.NewTestContext(config) 1604 ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory) 1605 ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator) 1606 ctx.RegisterForBazelConversion() 1607 1608 _, errs := ctx.ParseFileList(dir, toParse) 1609 if Errored(t, testCase.description, errs) { 1610 continue 1611 } 1612 _, errs = ctx.ResolveDependencies(config) 1613 if Errored(t, testCase.description, errs) { 1614 continue 1615 } 1616 1617 checkDir := dir 1618 if testCase.dir != "" { 1619 checkDir = testCase.dir 1620 } 1621 bazelTargets := generateBazelTargetsForDir(NewCodegenContext(config, *ctx.Context, Bp2Build), checkDir) 1622 if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount { 1623 t.Errorf("%s: Expected %d bazel target, got %d\n%s", testCase.description, expectedCount, actualCount, bazelTargets) 1624 } else { 1625 for i, target := range bazelTargets { 1626 if w, g := testCase.expectedBazelTargets[i], target.content; w != g { 1627 t.Errorf( 1628 "%s: Expected generated Bazel target to be '%s', got '%s'", 1629 testCase.description, 1630 w, 1631 g, 1632 ) 1633 } 1634 } 1635 } 1636 } 1637} 1638