1// Copyright 2017 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 15// This file implements the logic of bpfix and also provides a programmatic interface 16 17package bpfix 18 19import ( 20 "bytes" 21 "fmt" 22 "reflect" 23 "strings" 24 "testing" 25 26 "github.com/google/blueprint/parser" 27 "github.com/google/blueprint/pathtools" 28) 29 30// TODO(jeffrygaston) remove this when position is removed from ParseNode (in b/38325146) and we can directly do reflect.DeepEqual 31func printListOfStrings(items []string) (text string) { 32 if len(items) == 0 { 33 return "[]" 34 } 35 return fmt.Sprintf("[\"%s\"]", strings.Join(items, "\", \"")) 36 37} 38 39func buildTree(local_include_dirs []string, export_include_dirs []string) (file *parser.File, errs []error) { 40 // TODO(jeffrygaston) use the builder class when b/38325146 is done 41 input := fmt.Sprintf(`cc_library_shared { 42 name: "iAmAModule", 43 local_include_dirs: %s, 44 export_include_dirs: %s, 45 } 46 `, 47 printListOfStrings(local_include_dirs), printListOfStrings(export_include_dirs)) 48 tree, errs := parser.Parse("", strings.NewReader(input), parser.NewScope(nil)) 49 if len(errs) > 0 { 50 errs = append([]error{fmt.Errorf("failed to parse:\n%s", input)}, errs...) 51 } 52 return tree, errs 53} 54 55func implFilterListTest(t *testing.T, local_include_dirs []string, export_include_dirs []string, expectedResult []string) { 56 // build tree 57 tree, errs := buildTree(local_include_dirs, export_include_dirs) 58 if len(errs) > 0 { 59 t.Error("failed to build tree") 60 for _, err := range errs { 61 t.Error(err) 62 } 63 t.Fatalf("%d parse errors", len(errs)) 64 } 65 66 fixer := NewFixer(tree) 67 68 // apply simplifications 69 err := runPatchListMod(simplifyKnownPropertiesDuplicatingEachOther)(fixer) 70 if len(errs) > 0 { 71 t.Fatal(err) 72 } 73 74 // lookup legacy property 75 mod := fixer.tree.Defs[0].(*parser.Module) 76 77 expectedResultString := fmt.Sprintf("%q", expectedResult) 78 if expectedResult == nil { 79 expectedResultString = "unset" 80 } 81 82 // check that the value for the legacy property was updated to the correct value 83 errorHeader := fmt.Sprintf("\nFailed to correctly simplify key 'local_include_dirs' in the presence of 'export_include_dirs.'\n"+ 84 "original local_include_dirs: %q\n"+ 85 "original export_include_dirs: %q\n"+ 86 "expected result: %s\n"+ 87 "actual result: ", 88 local_include_dirs, export_include_dirs, expectedResultString) 89 result, found := mod.GetProperty("local_include_dirs") 90 if !found { 91 if expectedResult == nil { 92 return 93 } 94 t.Fatal(errorHeader + "property not found") 95 } 96 97 listResult, ok := result.Value.(*parser.List) 98 if !ok { 99 t.Fatalf("%sproperty is not a list: %v", errorHeader, listResult) 100 } 101 102 if expectedResult == nil { 103 t.Fatalf("%sproperty exists: %v", errorHeader, listResult) 104 } 105 106 actualExpressions := listResult.Values 107 actualValues := make([]string, 0) 108 for _, expr := range actualExpressions { 109 str := expr.(*parser.String) 110 actualValues = append(actualValues, str.Value) 111 } 112 113 if !reflect.DeepEqual(actualValues, expectedResult) { 114 t.Fatalf("%s%q\nlists are different", errorHeader, actualValues) 115 } 116} 117 118func TestSimplifyKnownVariablesDuplicatingEachOther(t *testing.T) { 119 // TODO use []Expression{} once buildTree above can support it (which is after b/38325146 is done) 120 implFilterListTest(t, []string{"include"}, []string{"include"}, nil) 121 implFilterListTest(t, []string{"include1"}, []string{"include2"}, []string{"include1"}) 122 implFilterListTest(t, []string{"include1", "include2", "include3", "include4"}, []string{"include2"}, 123 []string{"include1", "include3", "include4"}) 124 implFilterListTest(t, []string{}, []string{"include"}, []string{}) 125 implFilterListTest(t, []string{}, []string{}, []string{}) 126} 127 128func checkError(t *testing.T, in, expectedErr string, innerTest func(*Fixer) error) { 129 expected := preProcessOutErr(expectedErr) 130 runTestOnce(t, in, expected, innerTest) 131} 132 133func runTestOnce(t *testing.T, in, expected string, innerTest func(*Fixer) error) { 134 fixer, err := preProcessIn(in) 135 if err != nil { 136 t.Fatal(err) 137 } 138 139 out, err := runFixerOnce(fixer, innerTest) 140 if err != nil { 141 out = err.Error() 142 } 143 144 compareResult := compareOutExpected(in, out, expected) 145 if len(compareResult) > 0 { 146 t.Errorf(compareResult) 147 } 148} 149 150func preProcessOutErr(expectedErr string) string { 151 expected := strings.TrimSpace(expectedErr) 152 return expected 153} 154 155func preProcessOut(out string) (expected string, err error) { 156 expected, err = Reformat(out) 157 if err != nil { 158 return expected, err 159 } 160 return expected, nil 161} 162 163func preProcessIn(in string) (fixer *Fixer, err error) { 164 in, err = Reformat(in) 165 if err != nil { 166 return fixer, err 167 } 168 169 tree, errs := parser.Parse("<testcase>", bytes.NewBufferString(in), parser.NewScope(nil)) 170 if errs != nil { 171 return fixer, err 172 } 173 174 fixer = NewFixer(tree) 175 176 return fixer, nil 177} 178 179func runFixerOnce(fixer *Fixer, innerTest func(*Fixer) error) (string, error) { 180 err := innerTest(fixer) 181 if err != nil { 182 return "", err 183 } 184 185 out, err := parser.Print(fixer.tree) 186 if err != nil { 187 return "", err 188 } 189 return string(out), nil 190} 191 192func compareOutExpected(in, out, expected string) string { 193 if out != expected { 194 return fmt.Sprintf("output didn't match:\ninput:\n%s\n\nexpected:\n%s\ngot:\n%s\n", 195 in, expected, out) 196 } 197 return "" 198} 199 200func runPassOnce(t *testing.T, in, out string, innerTest func(*Fixer) error) { 201 expected, err := preProcessOut(out) 202 if err != nil { 203 t.Fatal(err) 204 } 205 206 runTestOnce(t, in, expected, innerTest) 207} 208 209func runPass(t *testing.T, in, out string, innerTest func(*Fixer) error) { 210 expected, err := preProcessOut(out) 211 if err != nil { 212 t.Fatal(err) 213 } 214 215 fixer, err := preProcessIn(in) 216 if err != nil { 217 t.Fatal(err) 218 } 219 220 got := "" 221 prev := "foo" 222 passes := 0 223 for got != prev && passes < 10 { 224 out, err = runFixerOnce(fixer, innerTest) 225 if err != nil { 226 t.Fatal(err) 227 } 228 229 prev = got 230 got = string(out) 231 passes++ 232 } 233 234 compareResult := compareOutExpected(in, out, expected) 235 if len(compareResult) > 0 { 236 t.Errorf(compareResult) 237 } 238} 239 240func TestMergeMatchingProperties(t *testing.T) { 241 tests := []struct { 242 name string 243 in string 244 out string 245 }{ 246 { 247 name: "empty", 248 in: ` 249 java_library { 250 name: "foo", 251 static_libs: [], 252 static_libs: [], 253 } 254 `, 255 out: ` 256 java_library { 257 name: "foo", 258 static_libs: [], 259 } 260 `, 261 }, 262 { 263 name: "single line into multiline", 264 in: ` 265 java_library { 266 name: "foo", 267 static_libs: [ 268 "a", 269 "b", 270 ], 271 //c1 272 static_libs: ["c" /*c2*/], 273 } 274 `, 275 out: ` 276 java_library { 277 name: "foo", 278 static_libs: [ 279 "a", 280 "b", 281 "c", /*c2*/ 282 ], 283 //c1 284 } 285 `, 286 }, 287 { 288 name: "multiline into multiline", 289 in: ` 290 java_library { 291 name: "foo", 292 static_libs: [ 293 "a", 294 "b", 295 ], 296 //c1 297 static_libs: [ 298 //c2 299 "c", //c3 300 "d", 301 ], 302 } 303 `, 304 out: ` 305 java_library { 306 name: "foo", 307 static_libs: [ 308 "a", 309 "b", 310 //c2 311 "c", //c3 312 "d", 313 ], 314 //c1 315 } 316 `, 317 }, 318 } 319 320 for _, test := range tests { 321 t.Run(test.name, func(t *testing.T) { 322 runPass(t, test.in, test.out, func(fixer *Fixer) error { 323 return runPatchListMod(mergeMatchingModuleProperties)(fixer) 324 }) 325 }) 326 } 327} 328 329func TestReorderCommonProperties(t *testing.T) { 330 var tests = []struct { 331 name string 332 in string 333 out string 334 }{ 335 { 336 name: "empty", 337 in: `cc_library {}`, 338 out: `cc_library {}`, 339 }, 340 { 341 name: "only priority", 342 in: ` 343 cc_library { 344 name: "foo", 345 } 346 `, 347 out: ` 348 cc_library { 349 name: "foo", 350 } 351 `, 352 }, 353 { 354 name: "already in order", 355 in: ` 356 cc_library { 357 name: "foo", 358 defaults: ["bar"], 359 } 360 `, 361 out: ` 362 cc_library { 363 name: "foo", 364 defaults: ["bar"], 365 } 366 `, 367 }, 368 { 369 name: "reorder only priority", 370 in: ` 371 cc_library { 372 defaults: ["bar"], 373 name: "foo", 374 } 375 `, 376 out: ` 377 cc_library { 378 name: "foo", 379 defaults: ["bar"], 380 } 381 `, 382 }, 383 { 384 name: "reorder", 385 in: ` 386 cc_library { 387 name: "foo", 388 srcs: ["a.c"], 389 host_supported: true, 390 defaults: ["bar"], 391 shared_libs: ["baz"], 392 } 393 `, 394 out: ` 395 cc_library { 396 name: "foo", 397 defaults: ["bar"], 398 host_supported: true, 399 srcs: ["a.c"], 400 shared_libs: ["baz"], 401 } 402 `, 403 }, 404 } 405 406 for _, test := range tests { 407 t.Run(test.name, func(t *testing.T) { 408 runPass(t, test.in, test.out, func(fixer *Fixer) error { 409 return runPatchListMod(reorderCommonProperties)(fixer) 410 }) 411 }) 412 } 413} 414 415func TestRemoveMatchingModuleListProperties(t *testing.T) { 416 var tests = []struct { 417 name string 418 in string 419 out string 420 }{ 421 { 422 name: "simple", 423 in: ` 424 cc_library { 425 name: "foo", 426 foo: ["a"], 427 bar: ["a"], 428 } 429 `, 430 out: ` 431 cc_library { 432 name: "foo", 433 bar: ["a"], 434 } 435 `, 436 }, 437 { 438 name: "long", 439 in: ` 440 cc_library { 441 name: "foo", 442 foo: [ 443 "a", 444 "b", 445 ], 446 bar: ["a"], 447 } 448 `, 449 out: ` 450 cc_library { 451 name: "foo", 452 foo: [ 453 "b", 454 ], 455 bar: ["a"], 456 } 457 `, 458 }, 459 { 460 name: "long fully removed", 461 in: ` 462 cc_library { 463 name: "foo", 464 foo: [ 465 "a", 466 ], 467 bar: ["a"], 468 } 469 `, 470 out: ` 471 cc_library { 472 name: "foo", 473 bar: ["a"], 474 } 475 `, 476 }, 477 { 478 name: "comment", 479 in: ` 480 cc_library { 481 name: "foo", 482 483 // comment 484 foo: ["a"], 485 486 bar: ["a"], 487 } 488 `, 489 out: ` 490 cc_library { 491 name: "foo", 492 493 // comment 494 495 bar: ["a"], 496 } 497 `, 498 }, 499 { 500 name: "inner comment", 501 in: ` 502 cc_library { 503 name: "foo", 504 foo: [ 505 // comment 506 "a", 507 ], 508 bar: ["a"], 509 } 510 `, 511 out: ` 512 cc_library { 513 name: "foo", 514 bar: ["a"], 515 } 516 `, 517 }, 518 { 519 name: "eol comment", 520 in: ` 521 cc_library { 522 name: "foo", 523 foo: ["a"], // comment 524 bar: ["a"], 525 } 526 `, 527 out: ` 528 cc_library { 529 name: "foo", 530 // comment 531 bar: ["a"], 532 } 533 `, 534 }, 535 { 536 name: "eol comment with blank lines", 537 in: ` 538 cc_library { 539 name: "foo", 540 541 foo: ["a"], // comment 542 543 // bar 544 bar: ["a"], 545 } 546 `, 547 out: ` 548 cc_library { 549 name: "foo", 550 551 // comment 552 553 // bar 554 bar: ["a"], 555 } 556 `, 557 }, 558 } 559 for _, test := range tests { 560 t.Run(test.name, func(t *testing.T) { 561 runPass(t, test.in, test.out, func(fixer *Fixer) error { 562 return runPatchListMod(func(mod *parser.Module, buf []byte, patchList *parser.PatchList) error { 563 return removeMatchingModuleListProperties(mod, patchList, "bar", "foo") 564 })(fixer) 565 }) 566 }) 567 } 568} 569 570func TestReplaceJavaStaticLibs(t *testing.T) { 571 tests := []struct { 572 name string 573 in string 574 out string 575 }{ 576 { 577 name: "static lib", 578 in: ` 579 java_library_static { 580 name: "foo", 581 } 582 `, 583 out: ` 584 java_library { 585 name: "foo", 586 } 587 `, 588 }, 589 { 590 name: "java lib", 591 in: ` 592 java_library { 593 name: "foo", 594 } 595 `, 596 out: ` 597 java_library { 598 name: "foo", 599 } 600 `, 601 }, 602 { 603 name: "java installable lib", 604 in: ` 605 java_library { 606 name: "foo", 607 installable: true, 608 } 609 `, 610 out: ` 611 java_library { 612 name: "foo", 613 installable: true, 614 } 615 `, 616 }, 617 } 618 619 for _, test := range tests { 620 t.Run(test.name, func(t *testing.T) { 621 runPass(t, test.in, test.out, func(fixer *Fixer) error { 622 return rewriteJavaStaticLibs(fixer) 623 }) 624 }) 625 } 626} 627 628func TestRewritePrebuilts(t *testing.T) { 629 tests := []struct { 630 name string 631 in string 632 out string 633 }{ 634 { 635 name: "jar srcs", 636 in: ` 637 java_import { 638 name: "foo", 639 srcs: ["foo.jar"], 640 } 641 `, 642 out: ` 643 java_import { 644 name: "foo", 645 jars: ["foo.jar"], 646 } 647 `, 648 }, 649 { 650 name: "aar srcs", 651 in: ` 652 java_import { 653 name: "foo", 654 srcs: ["foo.aar"], 655 installable: true, 656 } 657 `, 658 out: ` 659 android_library_import { 660 name: "foo", 661 aars: ["foo.aar"], 662 663 } 664 `, 665 }, 666 { 667 name: "host prebuilt", 668 in: ` 669 java_import { 670 name: "foo", 671 srcs: ["foo.jar"], 672 host: true, 673 } 674 `, 675 out: ` 676 java_import_host { 677 name: "foo", 678 jars: ["foo.jar"], 679 680 } 681 `, 682 }, 683 } 684 685 for _, test := range tests { 686 t.Run(test.name, func(t *testing.T) { 687 runPass(t, test.in, test.out, func(fixer *Fixer) error { 688 return rewriteIncorrectAndroidmkPrebuilts(fixer) 689 }) 690 }) 691 } 692} 693 694func TestRewriteCtsModuleTypes(t *testing.T) { 695 tests := []struct { 696 name string 697 in string 698 out string 699 }{ 700 { 701 name: "cts_support_package", 702 in: ` 703 cts_support_package { 704 name: "foo", 705 } 706 `, 707 out: ` 708 android_test_helper_app { 709 name: "foo", 710 defaults: ["cts_support_defaults"], 711 } 712 `, 713 }, 714 { 715 name: "cts_package", 716 in: ` 717 cts_package { 718 name: "foo", 719 } 720 `, 721 out: ` 722 android_test { 723 name: "foo", 724 defaults: ["cts_defaults"], 725 } 726 `, 727 }, 728 { 729 name: "cts_target_java_library", 730 in: ` 731 cts_target_java_library { 732 name: "foo", 733 } 734 `, 735 out: ` 736 java_library { 737 name: "foo", 738 defaults: ["cts_defaults"], 739 } 740 `, 741 }, 742 { 743 name: "cts_host_java_library", 744 in: ` 745 cts_host_java_library { 746 name: "foo", 747 } 748 `, 749 out: ` 750 java_library_host { 751 name: "foo", 752 defaults: ["cts_defaults"], 753 } 754 `, 755 }, 756 } 757 758 for _, test := range tests { 759 t.Run(test.name, func(t *testing.T) { 760 runPass(t, test.in, test.out, rewriteCtsModuleTypes) 761 }) 762 } 763} 764 765func TestRewritePrebuiltEtc(t *testing.T) { 766 tests := []struct { 767 name string 768 in string 769 out string 770 }{ 771 { 772 name: "prebuilt_etc src", 773 in: ` 774 prebuilt_etc { 775 name: "foo", 776 srcs: ["bar"], 777 } 778 `, 779 out: `prebuilt_etc { 780 name: "foo", 781 src: "bar", 782 } 783 `, 784 }, 785 { 786 name: "prebuilt_etc src", 787 in: ` 788 prebuilt_etc { 789 name: "foo", 790 srcs: FOO, 791 } 792 `, 793 out: `prebuilt_etc { 794 name: "foo", 795 src: FOO, 796 } 797 `, 798 }, 799 { 800 name: "prebuilt_etc src", 801 in: ` 802 prebuilt_etc { 803 name: "foo", 804 srcs: ["bar", "baz"], 805 } 806 `, 807 out: `prebuilt_etc { 808 name: "foo", 809 src: "ERROR: LOCAL_SRC_FILES should contain at most one item", 810 811 } 812 `, 813 }, 814 { 815 name: "prebuilt_etc sub_dir", 816 in: ` 817 prebuilt_etc { 818 name: "foo", 819 src: "bar", 820 sub_dir: "baz", 821 } 822 `, 823 out: `prebuilt_etc { 824 name: "foo", 825 src: "bar", 826 relative_install_path: "baz", 827 } 828 `, 829 }, 830 { 831 name: "prebuilt_etc sub_dir", 832 in: ` 833 prebuilt_etc_host { 834 name: "foo", 835 src: "bar", 836 local_module_path: { 837 var: "HOST_OUT", 838 fixed: "/etc/baz", 839 }, 840 } 841 `, 842 out: `prebuilt_etc_host { 843 name: "foo", 844 src: "bar", 845 relative_install_path: "baz", 846 847 } 848 `, 849 }, 850 { 851 name: "prebuilt_etc sub_dir", 852 in: ` 853 prebuilt_etc_host { 854 name: "foo", 855 src: "bar", 856 local_module_path: { 857 var: "HOST_OUT", 858 fixed: "/baz/sub", 859 }, 860 } 861 `, 862 out: `prebuilt_root_host { 863 name: "foo", 864 src: "bar", 865 relative_install_path: "baz/sub", 866 867 } 868 `, 869 }, 870 } 871 for _, test := range tests { 872 t.Run(test.name, func(t *testing.T) { 873 runPass(t, test.in, test.out, func(fixer *Fixer) error { 874 return rewriteAndroidmkPrebuiltEtc(fixer) 875 }) 876 }) 877 } 878} 879 880func TestRewriteAndroidTest(t *testing.T) { 881 tests := []struct { 882 name string 883 in string 884 out string 885 }{ 886 { 887 name: "android_test valid module path", 888 in: ` 889 android_test { 890 name: "foo", 891 local_module_path: { 892 var: "TARGET_OUT_DATA_APPS", 893 }, 894 } 895 `, 896 out: ` 897 android_test { 898 name: "foo", 899 900 } 901 `, 902 }, 903 } 904 for _, test := range tests { 905 t.Run(test.name, func(t *testing.T) { 906 runPass(t, test.in, test.out, func(fixer *Fixer) error { 907 return rewriteAndroidTest(fixer) 908 }) 909 }) 910 } 911} 912 913func TestRewriteAndroidAppImport(t *testing.T) { 914 tests := []struct { 915 name string 916 in string 917 out string 918 }{ 919 { 920 name: "android_app_import apk", 921 in: ` 922 android_app_import { 923 name: "foo", 924 srcs: ["package.apk"], 925 } 926 `, 927 out: ` 928 android_app_import { 929 name: "foo", 930 apk: "package.apk", 931 } 932 `, 933 }, 934 { 935 name: "android_app_import presigned", 936 in: ` 937 android_app_import { 938 name: "foo", 939 apk: "package.apk", 940 certificate: "PRESIGNED", 941 } 942 `, 943 out: ` 944 android_app_import { 945 name: "foo", 946 apk: "package.apk", 947 presigned: true, 948 949 } 950 `, 951 }, 952 } 953 for _, test := range tests { 954 t.Run(test.name, func(t *testing.T) { 955 runPass(t, test.in, test.out, func(fixer *Fixer) error { 956 return rewriteAndroidAppImport(fixer) 957 }) 958 }) 959 } 960} 961 962func TestRemoveEmptyLibDependencies(t *testing.T) { 963 tests := []struct { 964 name string 965 in string 966 out string 967 }{ 968 { 969 name: "remove sole shared lib", 970 in: ` 971 cc_library { 972 name: "foo", 973 shared_libs: ["libhwbinder"], 974 } 975 `, 976 out: ` 977 cc_library { 978 name: "foo", 979 980 } 981 `, 982 }, 983 { 984 name: "remove a shared lib", 985 in: ` 986 cc_library { 987 name: "foo", 988 shared_libs: [ 989 "libhwbinder", 990 "libfoo", 991 "libhidltransport", 992 ], 993 } 994 `, 995 out: ` 996 cc_library { 997 name: "foo", 998 shared_libs: [ 999 1000 "libfoo", 1001 1002 ], 1003 } 1004 `, 1005 }, 1006 } 1007 for _, test := range tests { 1008 t.Run(test.name, func(t *testing.T) { 1009 runPass(t, test.in, test.out, func(fixer *Fixer) error { 1010 return removeEmptyLibDependencies(fixer) 1011 }) 1012 }) 1013 } 1014} 1015 1016func TestRemoveHidlInterfaceTypes(t *testing.T) { 1017 tests := []struct { 1018 name string 1019 in string 1020 out string 1021 }{ 1022 { 1023 name: "remove types", 1024 in: ` 1025 hidl_interface { 1026 name: "foo@1.0", 1027 types: ["ParcelFooBar"], 1028 } 1029 `, 1030 out: ` 1031 hidl_interface { 1032 name: "foo@1.0", 1033 1034 } 1035 `, 1036 }, 1037 } 1038 for _, test := range tests { 1039 t.Run(test.name, func(t *testing.T) { 1040 runPass(t, test.in, test.out, func(fixer *Fixer) error { 1041 return removeHidlInterfaceTypes(fixer) 1042 }) 1043 }) 1044 } 1045} 1046 1047func TestRemoveSoongConfigBoolVariable(t *testing.T) { 1048 tests := []struct { 1049 name string 1050 in string 1051 out string 1052 }{ 1053 { 1054 name: "remove bool", 1055 in: ` 1056 soong_config_module_type { 1057 name: "foo", 1058 variables: ["bar", "baz"], 1059 } 1060 1061 soong_config_bool_variable { 1062 name: "bar", 1063 } 1064 1065 soong_config_string_variable { 1066 name: "baz", 1067 } 1068 `, 1069 out: ` 1070 soong_config_module_type { 1071 name: "foo", 1072 variables: [ 1073 "baz" 1074 ], 1075 bool_variables: ["bar"], 1076 } 1077 1078 soong_config_string_variable { 1079 name: "baz", 1080 } 1081 `, 1082 }, 1083 { 1084 name: "existing bool_variables", 1085 in: ` 1086 soong_config_module_type { 1087 name: "foo", 1088 variables: ["baz"], 1089 bool_variables: ["bar"], 1090 } 1091 1092 soong_config_bool_variable { 1093 name: "baz", 1094 } 1095 `, 1096 out: ` 1097 soong_config_module_type { 1098 name: "foo", 1099 bool_variables: ["bar", "baz"], 1100 } 1101 `, 1102 }, 1103 } 1104 for _, test := range tests { 1105 t.Run(test.name, func(t *testing.T) { 1106 runPass(t, test.in, test.out, removeSoongConfigBoolVariable) 1107 }) 1108 } 1109} 1110 1111func TestRemoveNestedProperty(t *testing.T) { 1112 tests := []struct { 1113 name string 1114 in string 1115 out string 1116 propertyName string 1117 }{ 1118 { 1119 name: "remove no nesting", 1120 in: ` 1121cc_library { 1122 name: "foo", 1123 foo: true, 1124}`, 1125 out: ` 1126cc_library { 1127 name: "foo", 1128} 1129`, 1130 propertyName: "foo", 1131 }, 1132 { 1133 name: "remove one nest", 1134 in: ` 1135cc_library { 1136 name: "foo", 1137 foo: { 1138 bar: true, 1139 }, 1140}`, 1141 out: ` 1142cc_library { 1143 name: "foo", 1144} 1145`, 1146 propertyName: "foo.bar", 1147 }, 1148 { 1149 name: "remove one nest, multiple props", 1150 in: ` 1151cc_library { 1152 name: "foo", 1153 foo: { 1154 bar: true, 1155 baz: false, 1156 }, 1157}`, 1158 out: ` 1159cc_library { 1160 name: "foo", 1161 foo: { 1162 baz: false, 1163 }, 1164} 1165`, 1166 propertyName: "foo.bar", 1167 }, 1168 { 1169 name: "remove multiple nest", 1170 in: ` 1171cc_library { 1172 name: "foo", 1173 foo: { 1174 bar: { 1175 baz: { 1176 a: true, 1177 } 1178 }, 1179 }, 1180}`, 1181 out: ` 1182cc_library { 1183 name: "foo", 1184} 1185`, 1186 propertyName: "foo.bar.baz.a", 1187 }, 1188 { 1189 name: "remove multiple nest, outer non-empty", 1190 in: ` 1191cc_library { 1192 name: "foo", 1193 foo: { 1194 bar: { 1195 baz: { 1196 a: true, 1197 } 1198 }, 1199 other: true, 1200 }, 1201}`, 1202 out: ` 1203cc_library { 1204 name: "foo", 1205 foo: { 1206 other: true, 1207 }, 1208} 1209`, 1210 propertyName: "foo.bar.baz.a", 1211 }, 1212 { 1213 name: "remove multiple nest, inner non-empty", 1214 in: ` 1215cc_library { 1216 name: "foo", 1217 foo: { 1218 bar: { 1219 baz: { 1220 a: true, 1221 }, 1222 other: true, 1223 }, 1224 }, 1225}`, 1226 out: ` 1227cc_library { 1228 name: "foo", 1229 foo: { 1230 bar: { 1231 other: true, 1232 }, 1233 }, 1234} 1235`, 1236 propertyName: "foo.bar.baz.a", 1237 }, 1238 { 1239 name: "remove multiple nest, inner-most non-empty", 1240 in: ` 1241cc_library { 1242 name: "foo", 1243 foo: { 1244 bar: { 1245 baz: { 1246 a: true, 1247 other: true, 1248 }, 1249 }, 1250 }, 1251}`, 1252 out: ` 1253cc_library { 1254 name: "foo", 1255 foo: { 1256 bar: { 1257 baz: { 1258 other: true, 1259 }, 1260 }, 1261 }, 1262} 1263`, 1264 propertyName: "foo.bar.baz.a", 1265 }, 1266 } 1267 1268 for _, test := range tests { 1269 t.Run(test.name, func(t *testing.T) { 1270 runPass(t, test.in, test.out, runPatchListMod(removeObsoleteProperty(test.propertyName))) 1271 }) 1272 } 1273} 1274 1275func TestRemoveObsoleteProperties(t *testing.T) { 1276 tests := []struct { 1277 name string 1278 in string 1279 out string 1280 }{ 1281 { 1282 name: "remove property", 1283 in: ` 1284 cc_library_shared { 1285 name: "foo", 1286 product_variables: { 1287 other: { 1288 bar: true, 1289 }, 1290 pdk: { 1291 enabled: false, 1292 }, 1293 }, 1294 } 1295 `, 1296 out: ` 1297 cc_library_shared { 1298 name: "foo", 1299 product_variables: { 1300 other: { 1301 bar: true, 1302 }, 1303 }, 1304 } 1305 `, 1306 }, 1307 { 1308 name: "remove property and empty product_variables", 1309 in: ` 1310 cc_library_shared { 1311 name: "foo", 1312 product_variables: { 1313 pdk: { 1314 enabled: false, 1315 }, 1316 }, 1317 } 1318 `, 1319 out: ` 1320 cc_library_shared { 1321 name: "foo", 1322 } 1323 `, 1324 }, 1325 } 1326 for _, test := range tests { 1327 t.Run(test.name, func(t *testing.T) { 1328 runPass(t, test.in, test.out, runPatchListMod(removeObsoleteProperty("product_variables.pdk"))) 1329 }) 1330 } 1331} 1332 1333func TestRewriteRuntimeResourceOverlay(t *testing.T) { 1334 tests := []struct { 1335 name string 1336 in string 1337 out string 1338 }{ 1339 { 1340 name: "product_specific runtime_resource_overlay", 1341 in: ` 1342 runtime_resource_overlay { 1343 name: "foo", 1344 resource_dirs: ["res"], 1345 product_specific: true, 1346 } 1347 `, 1348 out: ` 1349 runtime_resource_overlay { 1350 name: "foo", 1351 resource_dirs: ["res"], 1352 product_specific: true, 1353 } 1354 `, 1355 }, 1356 { 1357 // It's probably wrong for runtime_resource_overlay not to be product specific, but let's not 1358 // debate it here. 1359 name: "non-product_specific runtime_resource_overlay", 1360 in: ` 1361 runtime_resource_overlay { 1362 name: "foo", 1363 resource_dirs: ["res"], 1364 product_specific: false, 1365 } 1366 `, 1367 out: ` 1368 runtime_resource_overlay { 1369 name: "foo", 1370 resource_dirs: ["res"], 1371 product_specific: false, 1372 } 1373 `, 1374 }, 1375 { 1376 name: "runtime_resource_overlay without product_specific value", 1377 in: ` 1378 runtime_resource_overlay { 1379 name: "foo", 1380 resource_dirs: ["res"], 1381 } 1382 `, 1383 out: ` 1384 runtime_resource_overlay { 1385 name: "foo", 1386 resource_dirs: ["res"], 1387 product_specific: true, 1388 } 1389 `, 1390 }, 1391 } 1392 for _, test := range tests { 1393 t.Run(test.name, func(t *testing.T) { 1394 runPass(t, test.in, test.out, func(fixer *Fixer) error { 1395 return RewriteRuntimeResourceOverlay(fixer) 1396 }) 1397 }) 1398 } 1399} 1400 1401func TestRewriteTestModuleTypes(t *testing.T) { 1402 tests := []struct { 1403 name string 1404 in string 1405 out string 1406 }{ 1407 { 1408 name: "cc_binary with test_suites", 1409 in: ` 1410 cc_binary { 1411 name: "foo", 1412 srcs: ["srcs"], 1413 test_suites: ["test_suite1"], 1414 } 1415 `, 1416 out: ` 1417 cc_test { 1418 name: "foo", 1419 srcs: ["srcs"], 1420 test_suites: ["test_suite1"], 1421 } 1422 `, 1423 }, 1424 { 1425 name: "cc_binary without test_suites", 1426 in: ` 1427 cc_binary { 1428 name: "foo", 1429 srcs: ["srcs"], 1430 } 1431 `, 1432 out: ` 1433 cc_binary { 1434 name: "foo", 1435 srcs: ["srcs"], 1436 } 1437 `, 1438 }, 1439 { 1440 name: "android_app with android_test", 1441 in: ` 1442 android_app { 1443 name: "foo", 1444 srcs: ["srcs"], 1445 test_suites: ["test_suite1"], 1446 } 1447 `, 1448 out: ` 1449 android_test { 1450 name: "foo", 1451 srcs: ["srcs"], 1452 test_suites: ["test_suite1"], 1453 } 1454 `, 1455 }, 1456 { 1457 name: "android_app without test_suites", 1458 in: ` 1459 android_app { 1460 name: "foo", 1461 srcs: ["srcs"], 1462 } 1463 `, 1464 out: ` 1465 android_app { 1466 name: "foo", 1467 srcs: ["srcs"], 1468 } 1469 `, 1470 }, 1471 } 1472 for _, test := range tests { 1473 t.Run(test.name, func(t *testing.T) { 1474 runPass(t, test.in, test.out, func(fixer *Fixer) error { 1475 return rewriteTestModuleTypes(fixer) 1476 }) 1477 }) 1478 } 1479} 1480 1481func TestFormatFlagProperty(t *testing.T) { 1482 tests := []struct { 1483 name string 1484 in string 1485 out string 1486 }{ 1487 { 1488 name: "group options and values for apptflags, dxflags, javacflags, and kotlincflags", 1489 in: ` 1490 android_test { 1491 name: "foo", 1492 aaptflags: [ 1493 // comment1_1 1494 "--flag1", 1495 // comment1_2 1496 "1", 1497 // comment2_1 1498 // comment2_2 1499 "--flag2", 1500 // comment3_1 1501 // comment3_2 1502 // comment3_3 1503 "--flag3", 1504 // comment3_4 1505 // comment3_5 1506 // comment3_6 1507 "3", 1508 // other comment1_1 1509 // other comment1_2 1510 ], 1511 dxflags: [ 1512 "--flag1", 1513 // comment1_1 1514 "1", 1515 // comment2_1 1516 "--flag2", 1517 // comment3_1 1518 "--flag3", 1519 // comment3_2 1520 "3", 1521 ], 1522 javacflags: [ 1523 "--flag1", 1524 1525 "1", 1526 "--flag2", 1527 "--flag3", 1528 "3", 1529 ], 1530 kotlincflags: [ 1531 1532 "--flag1", 1533 "1", 1534 1535 "--flag2", 1536 "--flag3", 1537 "3", 1538 1539 ], 1540 } 1541 `, 1542 out: ` 1543 android_test { 1544 name: "foo", 1545 aaptflags: [ 1546 // comment1_1 1547 // comment1_2 1548 "--flag1 1", 1549 // comment2_1 1550 // comment2_2 1551 "--flag2", 1552 // comment3_1 1553 // comment3_2 1554 // comment3_3 1555 // comment3_4 1556 // comment3_5 1557 // comment3_6 1558 "--flag3 3", 1559 // other comment1_1 1560 // other comment1_2 1561 ], 1562 dxflags: [ 1563 // comment1_1 1564 "--flag1 1", 1565 // comment2_1 1566 "--flag2", 1567 // comment3_1 1568 // comment3_2 1569 "--flag3 3", 1570 ], 1571 javacflags: [ 1572 1573 "--flag1 1", 1574 "--flag2", 1575 "--flag3 3", 1576 ], 1577 kotlincflags: [ 1578 1579 "--flag1 1", 1580 1581 "--flag2", 1582 "--flag3 3", 1583 1584 ], 1585 } 1586 `, 1587 }, 1588 { 1589 name: "group options and values for asflags, cflags, clang_asflags, clang_cflags, conlyflags, cppflags, ldflags, and tidy_flags", 1590 in: ` 1591 cc_test { 1592 name: "foo", 1593 asflags: [ 1594 // comment1_1 1595 "--flag1", 1596 "1", 1597 // comment2_1 1598 // comment2_2 1599 "--flag2", 1600 // comment2_3 1601 "2", 1602 // comment3_1 1603 // comment3_2 1604 "--flag3", 1605 // comment3_3 1606 // comment3_4 1607 // comment3_4 1608 "3", 1609 // comment4_1 1610 // comment4_2 1611 // comment4_3 1612 "--flag4", 1613 ], 1614 cflags: [ 1615 "--flag1", 1616 "1", 1617 "--flag2", 1618 "2", 1619 "--flag3", 1620 "3", 1621 "--flag4", 1622 ], 1623 clang_asflags: [ 1624 "--flag1", 1625 "1", 1626 "--flag2", 1627 "2", 1628 "--flag3", 1629 "3", 1630 "--flag4", 1631 ], 1632 clang_cflags: [ 1633 "--flag1", 1634 "1", 1635 "--flag2", 1636 "2", 1637 "--flag3", 1638 "3", 1639 "--flag4", 1640 ], 1641 conlyflags: [ 1642 "--flag1", 1643 "1", 1644 "--flag2", 1645 "2", 1646 "--flag3", 1647 "3", 1648 "--flag4", 1649 ], 1650 cppflags: [ 1651 "--flag1", 1652 "1", 1653 "--flag2", 1654 "2", 1655 "--flag3", 1656 "3", 1657 "--flag4", 1658 ], 1659 ldflags: [ 1660 "--flag1", 1661 "1", 1662 "--flag2", 1663 "2", 1664 "--flag3", 1665 "3", 1666 "--flag4", 1667 ], 1668 tidy_flags: [ 1669 "--flag1", 1670 "1", 1671 "--flag2", 1672 "2", 1673 "--flag3", 1674 "3", 1675 "--flag4", 1676 ], 1677 } 1678 `, 1679 out: ` 1680 cc_test { 1681 name: "foo", 1682 asflags: [ 1683 // comment1_1 1684 "--flag1 1", 1685 // comment2_1 1686 // comment2_2 1687 // comment2_3 1688 "--flag2 2", 1689 // comment3_1 1690 // comment3_2 1691 // comment3_3 1692 // comment3_4 1693 // comment3_4 1694 "--flag3 3", 1695 // comment4_1 1696 // comment4_2 1697 // comment4_3 1698 "--flag4", 1699 ], 1700 cflags: [ 1701 "--flag1 1", 1702 "--flag2 2", 1703 "--flag3 3", 1704 "--flag4", 1705 ], 1706 clang_asflags: [ 1707 "--flag1 1", 1708 "--flag2 2", 1709 "--flag3 3", 1710 "--flag4", 1711 ], 1712 clang_cflags: [ 1713 "--flag1 1", 1714 "--flag2 2", 1715 "--flag3 3", 1716 "--flag4", 1717 ], 1718 conlyflags: [ 1719 "--flag1 1", 1720 "--flag2 2", 1721 "--flag3 3", 1722 "--flag4", 1723 ], 1724 cppflags: [ 1725 "--flag1 1", 1726 "--flag2 2", 1727 "--flag3 3", 1728 "--flag4", 1729 ], 1730 ldflags: [ 1731 "--flag1 1", 1732 "--flag2 2", 1733 "--flag3 3", 1734 "--flag4", 1735 ], 1736 tidy_flags: [ 1737 "--flag1 1", 1738 "--flag2 2", 1739 "--flag3 3", 1740 "--flag4", 1741 ], 1742 } 1743 `, 1744 }, 1745 } 1746 for _, test := range tests { 1747 t.Run(test.name, func(t *testing.T) { 1748 runPass(t, test.in, test.out, runPatchListMod(formatFlagProperties)) 1749 }) 1750 } 1751} 1752 1753func TestRewriteLicenseProperty(t *testing.T) { 1754 mockFs := pathtools.MockFs(map[string][]byte{ 1755 "a/b/c/d/Android.mk": []byte("this is not important."), 1756 "a/b/LicenseFile1": []byte("LicenseFile1"), 1757 "a/b/LicenseFile2": []byte("LicenseFile2"), 1758 "a/b/Android.bp": []byte("license {\n\tname: \"reuse_a_b_license\",\n}\n"), 1759 }) 1760 relativePath := "a/b/c/d" 1761 relativePathErr := "a/b/c" 1762 tests := []struct { 1763 name string 1764 in string 1765 fs pathtools.FileSystem 1766 path string 1767 out string 1768 }{ 1769 { 1770 name: "license rewriting with one module", 1771 in: ` 1772 android_test { 1773 name: "foo", 1774 android_license_kinds: ["license_kind"], 1775 android_license_conditions: ["license_notice"], 1776 } 1777 `, 1778 out: ` 1779 package { 1780 // See: http://go/android-license-faq 1781 default_applicable_licenses: [ 1782 "Android-Apache-2.0", 1783 ], 1784 } 1785 1786 android_test { 1787 name: "foo", 1788 android_license_kinds: ["license_kind"], 1789 android_license_conditions: ["license_notice"], 1790 } 1791 `, 1792 }, 1793 { 1794 name: "license rewriting with two modules", 1795 in: ` 1796 android_test { 1797 name: "foo1", 1798 android_license_kinds: ["license_kind1"], 1799 android_license_conditions: ["license_notice1"], 1800 } 1801 1802 android_test { 1803 name: "foo2", 1804 android_license_kinds: ["license_kind2"], 1805 android_license_conditions: ["license_notice2"], 1806 } 1807 `, 1808 out: ` 1809 package { 1810 // See: http://go/android-license-faq 1811 default_applicable_licenses: [ 1812 "Android-Apache-2.0", 1813 ], 1814 } 1815 1816 android_test { 1817 name: "foo1", 1818 android_license_kinds: ["license_kind1"], 1819 android_license_conditions: ["license_notice1"], 1820 } 1821 1822 android_test { 1823 name: "foo2", 1824 android_license_kinds: ["license_kind2"], 1825 android_license_conditions: ["license_notice2"], 1826 } 1827 `, 1828 }, 1829 { 1830 name: "license rewriting with license files in the current directory", 1831 in: ` 1832 android_test { 1833 name: "foo", 1834 android_license_kinds: ["license_kind"], 1835 android_license_conditions: ["license_notice"], 1836 android_license_files: ["LicenseFile1", "LicenseFile2",], 1837 } 1838 `, 1839 fs: mockFs, 1840 path: relativePath, 1841 out: ` 1842 package { 1843 // See: http://go/android-license-faq 1844 default_applicable_licenses: [ 1845 "a_b_c_d_license", 1846 ], 1847 } 1848 1849 license { 1850 name: "a_b_c_d_license", 1851 visibility: [":__subpackages__"], 1852 license_kinds: [ 1853 "license_kind", 1854 ], 1855 license_text: [ 1856 "LicenseFile1", 1857 "LicenseFile2", 1858 ], 1859 } 1860 1861 android_test { 1862 name: "foo", 1863 android_license_kinds: ["license_kind"], 1864 android_license_conditions: ["license_notice"], 1865 android_license_files: [ 1866 "LicenseFile1", 1867 "LicenseFile2", 1868 ], 1869 } 1870 `, 1871 }, 1872 { 1873 name: "license rewriting with license files outside the current directory", 1874 in: ` 1875 android_test { 1876 name: "foo", 1877 android_license_kinds: ["license_kind"], 1878 android_license_conditions: ["license_notice"], 1879 android_license_files: ["../../LicenseFile1", "../../LicenseFile2",], 1880 } 1881 `, 1882 fs: mockFs, 1883 path: relativePath, 1884 out: ` 1885 package { 1886 // See: http://go/android-license-faq 1887 default_applicable_licenses: [ 1888 "reuse_a_b_license", 1889 ], 1890 } 1891 1892 android_test { 1893 name: "foo", 1894 android_license_kinds: ["license_kind"], 1895 android_license_conditions: ["license_notice"], 1896 android_license_files: [ 1897 "../../LicenseFile1", 1898 "../../LicenseFile2", 1899 ], 1900 } 1901 `, 1902 }, 1903 { 1904 name: "license rewriting with no Android.bp file in the expected location", 1905 in: ` 1906 android_test { 1907 name: "foo", 1908 android_license_kinds: ["license_kind"], 1909 android_license_conditions: ["license_notice"], 1910 android_license_files: ["../../LicenseFile1", "../../LicenseFile2",], 1911 } 1912 `, 1913 fs: pathtools.MockFs(map[string][]byte{ 1914 "a/b/c/d/Android.mk": []byte("this is not important."), 1915 "a/b/LicenseFile1": []byte("LicenseFile1"), 1916 "a/b/LicenseFile2": []byte("LicenseFile2"), 1917 "a/Android.bp": []byte("license {\n\tname: \"reuse_a_b_license\",\n}\n"), 1918 }), 1919 path: relativePath, 1920 out: ` 1921 // Error: No Android.bp file is found at path 1922 // a/b 1923 // Please add one there with the needed license module first. 1924 // Then reset the default_applicable_licenses property below with the license module name. 1925 package { 1926 // See: http://go/android-license-faq 1927 default_applicable_licenses: [ 1928 "", 1929 ], 1930 } 1931 1932 android_test { 1933 name: "foo", 1934 android_license_kinds: ["license_kind"], 1935 android_license_conditions: ["license_notice"], 1936 android_license_files: [ 1937 "../../LicenseFile1", 1938 "../../LicenseFile2", 1939 ], 1940 } 1941 `, 1942 }, 1943 { 1944 name: "license rewriting with an Android.bp file without a license module", 1945 in: ` 1946 android_test { 1947 name: "foo", 1948 android_license_kinds: ["license_kind"], 1949 android_license_conditions: ["license_notice"], 1950 android_license_files: ["../../LicenseFile1", "../../LicenseFile2",], 1951 } 1952 `, 1953 fs: pathtools.MockFs(map[string][]byte{ 1954 "a/b/c/d/Android.mk": []byte("this is not important."), 1955 "a/b/LicenseFile1": []byte("LicenseFile1"), 1956 "a/b/LicenseFile2": []byte("LicenseFile2"), 1957 "a/b/Android.bp": []byte("non_license {\n\tname: \"reuse_a_b_license\",\n}\n"), 1958 }), 1959 path: relativePath, 1960 out: ` 1961 // Error: Cannot get the name of the license module in the 1962 // a/b/Android.bp file. 1963 // If no such license module exists, please add one there first. 1964 // Then reset the default_applicable_licenses property below with the license module name. 1965 package { 1966 // See: http://go/android-license-faq 1967 default_applicable_licenses: [ 1968 "", 1969 ], 1970 } 1971 1972 android_test { 1973 name: "foo", 1974 android_license_kinds: ["license_kind"], 1975 android_license_conditions: ["license_notice"], 1976 android_license_files: [ 1977 "../../LicenseFile1", 1978 "../../LicenseFile2", 1979 ], 1980 } 1981 `, 1982 }, 1983 } 1984 for _, test := range tests { 1985 t.Run(test.name, func(t *testing.T) { 1986 runPassOnce(t, test.in, test.out, runPatchListMod(rewriteLicenseProperty(test.fs, test.path))) 1987 }) 1988 } 1989 1990 testErrs := []struct { 1991 name string 1992 in string 1993 fs pathtools.FileSystem 1994 path string 1995 expectedErr string 1996 }{ 1997 { 1998 name: "license rewriting with a wrong path", 1999 in: ` 2000 android_test { 2001 name: "foo", 2002 android_license_kinds: ["license_kind"], 2003 android_license_conditions: ["license_notice"], 2004 android_license_files: ["../../LicenseFile1", "../../LicenseFile2",], 2005 } 2006 `, 2007 fs: mockFs, 2008 path: relativePathErr, 2009 expectedErr: ` 2010 Cannot find an Android.mk file at path "a/b/c" 2011 `, 2012 }, 2013 } 2014 for _, test := range testErrs { 2015 t.Run(test.name, func(t *testing.T) { 2016 checkError(t, test.in, test.expectedErr, runPatchListMod(rewriteLicenseProperty(test.fs, test.path))) 2017 }) 2018 } 2019} 2020 2021func TestHaveSameLicense(t *testing.T) { 2022 tests := []struct { 2023 name string 2024 in string 2025 out string 2026 }{ 2027 { 2028 name: "two modules with the same license", 2029 in: ` 2030 android_test { 2031 name: "foo1", 2032 android_license_kinds: ["license_kind"], 2033 android_license_conditions: ["license_notice"], 2034 } 2035 2036 android_test { 2037 name: "foo2", 2038 android_license_kinds: ["license_kind"], 2039 android_license_conditions: ["license_notice"], 2040 } 2041 `, 2042 out: ` 2043 android_test { 2044 name: "foo1", 2045 android_license_kinds: ["license_kind"], 2046 android_license_conditions: ["license_notice"], 2047 } 2048 2049 android_test { 2050 name: "foo2", 2051 android_license_kinds: ["license_kind"], 2052 android_license_conditions: ["license_notice"], 2053 } 2054 `, 2055 }, 2056 } 2057 for _, test := range tests { 2058 t.Run(test.name, func(t *testing.T) { 2059 runPassOnce(t, test.in, test.out, func(fixer *Fixer) error { 2060 return haveSameLicense(fixer) 2061 }) 2062 }) 2063 } 2064 testErrs := []struct { 2065 name string 2066 in string 2067 expectedErr string 2068 }{ 2069 { 2070 name: "two modules will different licenses", 2071 in: ` 2072 android_test { 2073 name: "foo1", 2074 android_license_kinds: ["license_kind1"], 2075 android_license_conditions: ["license_notice1"], 2076 } 2077 2078 android_test { 2079 name: "foo2", 2080 android_license_kinds: ["license_kind2"], 2081 android_license_conditions: ["license_notice2"], 2082 } 2083 `, 2084 expectedErr: ` 2085 Modules foo1 and foo2 are expected to have the same android_license_kinds property. 2086 `, 2087 }, 2088 } 2089 for _, test := range testErrs { 2090 t.Run(test.name, func(t *testing.T) { 2091 checkError(t, test.in, test.expectedErr, func(fixer *Fixer) error { 2092 return haveSameLicense(fixer) 2093 }) 2094 }) 2095 } 2096} 2097 2098func TestRemoveResourceAndAssetsIfDefault(t *testing.T) { 2099 tests := []struct { 2100 name string 2101 in string 2102 out string 2103 }{ 2104 { 2105 name: "resource_dirs default", 2106 in: ` 2107 android_app { 2108 name: "foo", 2109 resource_dirs: ["res"], 2110 } 2111 `, 2112 out: ` 2113 android_app { 2114 name: "foo", 2115 2116 } 2117 `, 2118 }, 2119 { 2120 name: "resource_dirs not default", 2121 in: ` 2122 android_app { 2123 name: "foo", 2124 resource_dirs: ["reso"], 2125 } 2126 `, 2127 out: ` 2128 android_app { 2129 name: "foo", 2130 resource_dirs: ["reso"], 2131 } 2132 `, 2133 }, 2134 { 2135 name: "resource_dirs includes not default", 2136 in: ` 2137 android_app { 2138 name: "foo", 2139 resource_dirs: ["res", "reso"], 2140 } 2141 `, 2142 out: ` 2143 android_app { 2144 name: "foo", 2145 resource_dirs: ["res", "reso"], 2146 } 2147 `, 2148 }, { 2149 name: "asset_dirs default", 2150 in: ` 2151 android_app { 2152 name: "foo", 2153 asset_dirs: ["assets"], 2154 } 2155 `, 2156 out: ` 2157 android_app { 2158 name: "foo", 2159 2160 } 2161 `, 2162 }, 2163 { 2164 name: "asset_dirs not default", 2165 in: ` 2166 android_app { 2167 name: "foo", 2168 asset_dirs: ["assety"], 2169 } 2170 `, 2171 out: ` 2172 android_app { 2173 name: "foo", 2174 asset_dirs: ["assety"], 2175 } 2176 `, 2177 }, 2178 { 2179 name: "asset_dirs includes not default", 2180 in: ` 2181 android_app { 2182 name: "foo", 2183 asset_dirs: ["assets", "assety"], 2184 } 2185 `, 2186 out: ` 2187 android_app { 2188 name: "foo", 2189 asset_dirs: ["assets", "assety"], 2190 } 2191 `, 2192 }, 2193 { 2194 name: "resource_dirs and asset_dirs both default", 2195 in: ` 2196 android_app { 2197 name: "foo", 2198 asset_dirs: ["assets"], 2199 resource_dirs: ["res"], 2200 } 2201 `, 2202 out: ` 2203 android_app { 2204 name: "foo", 2205 2206 } 2207 `, 2208 }, 2209 } 2210 for _, test := range tests { 2211 t.Run(test.name, func(t *testing.T) { 2212 runPassOnce(t, test.in, test.out, func(fixer *Fixer) error { 2213 return removeResourceAndAssetsIfDefault(fixer) 2214 }) 2215 }) 2216 } 2217} 2218