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