github.com/jd-ly/tools@v0.5.7/internal/imports/fix_test.go (about) 1 // Copyright 2013 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package imports 6 7 import ( 8 "context" 9 "flag" 10 "fmt" 11 "go/build" 12 "io/ioutil" 13 "log" 14 "path/filepath" 15 "reflect" 16 "runtime" 17 "sort" 18 "strings" 19 "sync" 20 "testing" 21 22 "github.com/jd-ly/tools/go/packages/packagestest" 23 "github.com/jd-ly/tools/internal/gocommand" 24 ) 25 26 var testDebug = flag.Bool("debug", false, "enable debug output") 27 28 var tests = []struct { 29 name string 30 formatOnly bool 31 in, out string 32 }{ 33 // Adding an import to an existing parenthesized import 34 { 35 name: "factored_imports_add", 36 in: `package foo 37 import ( 38 "fmt" 39 ) 40 func bar() { 41 var b bytes.Buffer 42 fmt.Println(b.String()) 43 } 44 `, 45 out: `package foo 46 47 import ( 48 "bytes" 49 "fmt" 50 ) 51 52 func bar() { 53 var b bytes.Buffer 54 fmt.Println(b.String()) 55 } 56 `, 57 }, 58 59 // Adding an import to an existing parenthesized import, 60 // verifying it goes into the first section. 61 { 62 name: "factored_imports_add_first_sec", 63 in: `package foo 64 import ( 65 "fmt" 66 67 "github.com/golang/snappy" 68 ) 69 func bar() { 70 var b bytes.Buffer 71 _ = snappy.ErrCorrupt 72 fmt.Println(b.String()) 73 } 74 `, 75 out: `package foo 76 77 import ( 78 "bytes" 79 "fmt" 80 81 "github.com/golang/snappy" 82 ) 83 84 func bar() { 85 var b bytes.Buffer 86 _ = snappy.ErrCorrupt 87 fmt.Println(b.String()) 88 } 89 `, 90 }, 91 92 // Adding an import to an existing parenthesized import, 93 // verifying it goes into the first section. (test 2) 94 { 95 name: "factored_imports_add_first_sec_2", 96 in: `package foo 97 import ( 98 "fmt" 99 100 "github.com/golang/snappy" 101 ) 102 func bar() { 103 _ = math.NaN 104 _ = fmt.Sprintf 105 _ = snappy.ErrCorrupt 106 } 107 `, 108 out: `package foo 109 110 import ( 111 "fmt" 112 "math" 113 114 "github.com/golang/snappy" 115 ) 116 117 func bar() { 118 _ = math.NaN 119 _ = fmt.Sprintf 120 _ = snappy.ErrCorrupt 121 } 122 `, 123 }, 124 125 // Adding a new import line, without parens 126 { 127 name: "add_import_section", 128 in: `package foo 129 func bar() { 130 var b bytes.Buffer 131 } 132 `, 133 out: `package foo 134 135 import "bytes" 136 137 func bar() { 138 var b bytes.Buffer 139 } 140 `, 141 }, 142 143 // Adding two new imports, which should make a parenthesized import decl. 144 { 145 name: "add_import_paren_section", 146 in: `package foo 147 func bar() { 148 _, _ := bytes.Buffer, zip.NewReader 149 } 150 `, 151 out: `package foo 152 153 import ( 154 "archive/zip" 155 "bytes" 156 ) 157 158 func bar() { 159 _, _ := bytes.Buffer, zip.NewReader 160 } 161 `, 162 }, 163 164 // Make sure we don't add things twice 165 { 166 name: "no_double_add", 167 in: `package foo 168 func bar() { 169 _, _ := bytes.Buffer, bytes.NewReader 170 } 171 `, 172 out: `package foo 173 174 import "bytes" 175 176 func bar() { 177 _, _ := bytes.Buffer, bytes.NewReader 178 } 179 `, 180 }, 181 182 // Make sure we don't add packages that don't have the right exports 183 { 184 name: "no_mismatched_add", 185 in: `package foo 186 187 func bar() { 188 _ := bytes.NonexistentSymbol 189 } 190 `, 191 out: `package foo 192 193 func bar() { 194 _ := bytes.NonexistentSymbol 195 } 196 `, 197 }, 198 199 // Remove unused imports, 1 of a factored block 200 { 201 name: "remove_unused_1_of_2", 202 in: `package foo 203 import ( 204 "bytes" 205 "fmt" 206 ) 207 208 func bar() { 209 _, _ := bytes.Buffer, bytes.NewReader 210 } 211 `, 212 out: `package foo 213 214 import ( 215 "bytes" 216 ) 217 218 func bar() { 219 _, _ := bytes.Buffer, bytes.NewReader 220 } 221 `, 222 }, 223 224 // Remove unused imports, 2 of 2 225 { 226 name: "remove_unused_2_of_2", 227 in: `package foo 228 import ( 229 "bytes" 230 "fmt" 231 ) 232 233 func bar() { 234 } 235 `, 236 out: `package foo 237 238 func bar() { 239 } 240 `, 241 }, 242 243 // Remove unused imports, 1 of 1 244 { 245 name: "remove_unused_1_of_1", 246 in: `package foo 247 248 import "fmt" 249 250 func bar() { 251 } 252 `, 253 out: `package foo 254 255 func bar() { 256 } 257 `, 258 }, 259 260 // Don't remove empty imports. 261 { 262 name: "dont_remove_empty_imports", 263 in: `package foo 264 import ( 265 _ "image/png" 266 _ "image/jpeg" 267 ) 268 `, 269 out: `package foo 270 271 import ( 272 _ "image/jpeg" 273 _ "image/png" 274 ) 275 `, 276 }, 277 278 // Don't remove dot imports. 279 { 280 name: "dont_remove_dot_imports", 281 in: `package foo 282 import ( 283 . "foo" 284 . "bar" 285 ) 286 `, 287 out: `package foo 288 289 import ( 290 . "bar" 291 . "foo" 292 ) 293 `, 294 }, 295 296 // Skip refs the parser can resolve. 297 { 298 name: "skip_resolved_refs", 299 in: `package foo 300 301 func f() { 302 type t struct{ Println func(string) } 303 fmt := t{Println: func(string) {}} 304 fmt.Println("foo") 305 } 306 `, 307 out: `package foo 308 309 func f() { 310 type t struct{ Println func(string) } 311 fmt := t{Println: func(string) {}} 312 fmt.Println("foo") 313 } 314 `, 315 }, 316 317 // Do not add a package we already have a resolution for. 318 { 319 name: "skip_template", 320 in: `package foo 321 322 import "html/template" 323 324 func f() { t = template.New("sometemplate") } 325 `, 326 out: `package foo 327 328 import "html/template" 329 330 func f() { t = template.New("sometemplate") } 331 `, 332 }, 333 334 // Don't touch cgo 335 { 336 name: "cgo", 337 in: `package foo 338 339 /* 340 #include <foo.h> 341 */ 342 import "C" 343 `, 344 out: `package foo 345 346 /* 347 #include <foo.h> 348 */ 349 import "C" 350 `, 351 }, 352 353 // Put some things in their own section 354 { 355 name: "make_sections", 356 in: `package foo 357 358 import ( 359 "os" 360 ) 361 362 func foo () { 363 _, _ = os.Args, fmt.Println 364 _, _ = snappy.ErrCorrupt, p.P 365 } 366 `, 367 out: `package foo 368 369 import ( 370 "fmt" 371 "os" 372 373 "github.com/golang/snappy" 374 "rsc.io/p" 375 ) 376 377 func foo() { 378 _, _ = os.Args, fmt.Println 379 _, _ = snappy.ErrCorrupt, p.P 380 } 381 `, 382 }, 383 // Merge import blocks, even when no additions are required. 384 { 385 name: "merge_import_blocks_no_fix", 386 in: `package foo 387 388 import ( 389 "fmt" 390 ) 391 import "os" 392 393 import ( 394 "rsc.io/p" 395 ) 396 397 var _, _ = os.Args, fmt.Println 398 var _, _ = snappy.ErrCorrupt, p.P 399 `, 400 out: `package foo 401 402 import ( 403 "fmt" 404 "os" 405 406 "github.com/golang/snappy" 407 "rsc.io/p" 408 ) 409 410 var _, _ = os.Args, fmt.Println 411 var _, _ = snappy.ErrCorrupt, p.P 412 `, 413 }, 414 // Delete existing empty import block 415 { 416 name: "delete_empty_import_block", 417 in: `package foo 418 419 import () 420 `, 421 out: `package foo 422 `, 423 }, 424 425 // Use existing empty import block 426 { 427 name: "use_empty_import_block", 428 in: `package foo 429 430 import () 431 432 func f() { 433 _ = fmt.Println 434 } 435 `, 436 out: `package foo 437 438 import "fmt" 439 440 func f() { 441 _ = fmt.Println 442 } 443 `, 444 }, 445 446 // Blank line before adding new section. 447 { 448 name: "blank_line_before_new_group", 449 in: `package foo 450 451 import ( 452 "fmt" 453 "net" 454 ) 455 456 func f() { 457 _ = net.Dial 458 _ = fmt.Printf 459 _ = snappy.ErrCorrupt 460 } 461 `, 462 out: `package foo 463 464 import ( 465 "fmt" 466 "net" 467 468 "github.com/golang/snappy" 469 ) 470 471 func f() { 472 _ = net.Dial 473 _ = fmt.Printf 474 _ = snappy.ErrCorrupt 475 } 476 `, 477 }, 478 479 // Blank line between standard library and third-party stuff. 480 { 481 name: "blank_line_separating_std_and_third_party", 482 in: `package foo 483 484 import ( 485 "github.com/golang/snappy" 486 "fmt" 487 "net" 488 ) 489 490 func f() { 491 _ = net.Dial 492 _ = fmt.Printf 493 _ = snappy.Foo 494 } 495 `, 496 out: `package foo 497 498 import ( 499 "fmt" 500 "net" 501 502 "github.com/golang/snappy" 503 ) 504 505 func f() { 506 _ = net.Dial 507 _ = fmt.Printf 508 _ = snappy.Foo 509 } 510 `, 511 }, 512 513 // golang.org/issue/6884 514 { 515 name: "new_imports_before_comment", 516 in: `package main 517 518 // A comment 519 func main() { 520 fmt.Println("Hello, world") 521 } 522 `, 523 out: `package main 524 525 import "fmt" 526 527 // A comment 528 func main() { 529 fmt.Println("Hello, world") 530 } 531 `, 532 }, 533 534 // golang.org/issue/7132 535 { 536 name: "new_section_for_dotless_import", 537 in: `package main 538 539 import ( 540 "fmt" 541 542 "gu" 543 "manypackages.com/packagea" 544 ) 545 546 var ( 547 a = packagea.A 548 b = gu.A 549 c = fmt.Printf 550 ) 551 `, 552 out: `package main 553 554 import ( 555 "fmt" 556 557 "gu" 558 559 "manypackages.com/packagea" 560 ) 561 562 var ( 563 a = packagea.A 564 b = gu.A 565 c = fmt.Printf 566 ) 567 `, 568 }, 569 570 { 571 name: "fragment_with_main", 572 in: `func main(){fmt.Println("Hello, world")}`, 573 out: `package main 574 575 import "fmt" 576 577 func main() { fmt.Println("Hello, world") } 578 `, 579 }, 580 581 { 582 name: "fragment_without_main", 583 in: `func notmain(){fmt.Println("Hello, world")}`, 584 out: `import "fmt" 585 586 func notmain() { fmt.Println("Hello, world") }`, 587 }, 588 589 // Remove first import within in a 2nd/3rd/4th/etc. section. 590 // golang.org/issue/7679 591 { 592 name: "remove_first_import_in_section", 593 in: `package main 594 595 import ( 596 "fmt" 597 598 "manypackages.com/packagea" 599 "manypackages.com/packageb" 600 ) 601 602 func main() { 603 var _ = fmt.Println 604 //var _ = packagea.A 605 var _ = packageb.B 606 } 607 `, 608 out: `package main 609 610 import ( 611 "fmt" 612 613 "manypackages.com/packageb" 614 ) 615 616 func main() { 617 var _ = fmt.Println 618 //var _ = packagea.A 619 var _ = packageb.B 620 } 621 `, 622 }, 623 624 // Blank line can be added before all types of import declarations. 625 // golang.org/issue/7866 626 { 627 name: "new_section_for_all_kinds_of_imports", 628 in: `package main 629 630 import ( 631 "fmt" 632 renamed_packagea "manypackages.com/packagea" 633 634 . "manypackages.com/packageb" 635 "io" 636 637 _ "manypackages.com/packagec" 638 "strings" 639 ) 640 641 var _, _, _, _, _ = fmt.Errorf, io.Copy, strings.Contains, renamed_packagea.A, B 642 `, 643 out: `package main 644 645 import ( 646 "fmt" 647 648 renamed_packagea "manypackages.com/packagea" 649 650 "io" 651 652 . "manypackages.com/packageb" 653 654 "strings" 655 656 _ "manypackages.com/packagec" 657 ) 658 659 var _, _, _, _, _ = fmt.Errorf, io.Copy, strings.Contains, renamed_packagea.A, B 660 `, 661 }, 662 663 // Non-idempotent comment formatting 664 // golang.org/issue/8035 665 { 666 name: "comments_formatted", 667 in: `package main 668 669 import ( 670 "fmt" // A 671 "go/ast" // B 672 _ "manypackages.com/packagec" // C 673 ) 674 675 func main() { _, _ = fmt.Print, ast.Walk } 676 `, 677 out: `package main 678 679 import ( 680 "fmt" // A 681 "go/ast" // B 682 683 _ "manypackages.com/packagec" // C 684 ) 685 686 func main() { _, _ = fmt.Print, ast.Walk } 687 `, 688 }, 689 690 // Failure to delete all duplicate imports 691 // golang.org/issue/8459 692 { 693 name: "remove_duplicates", 694 in: `package main 695 696 import ( 697 "fmt" 698 "log" 699 "log" 700 "math" 701 ) 702 703 func main() { fmt.Println("pi:", math.Pi) } 704 `, 705 out: `package main 706 707 import ( 708 "fmt" 709 "math" 710 ) 711 712 func main() { fmt.Println("pi:", math.Pi) } 713 `, 714 }, 715 716 // Too aggressive prefix matching 717 // golang.org/issue/9961 718 { 719 name: "no_extra_groups", 720 in: `package p 721 722 import ( 723 "zip" 724 725 "rsc.io/p" 726 ) 727 728 var ( 729 _ = fmt.Print 730 _ = zip.Store 731 _ p.P 732 _ = regexp.Compile 733 ) 734 `, 735 out: `package p 736 737 import ( 738 "fmt" 739 "regexp" 740 "zip" 741 742 "rsc.io/p" 743 ) 744 745 var ( 746 _ = fmt.Print 747 _ = zip.Store 748 _ p.P 749 _ = regexp.Compile 750 ) 751 `, 752 }, 753 754 // Unused named import is mistaken for unnamed import 755 // golang.org/issue/8149 756 { 757 name: "named_import_doesnt_provide_package_name", 758 in: `package main 759 760 import foo "fmt" 761 762 func main() { fmt.Println() } 763 `, 764 out: `package main 765 766 import "fmt" 767 768 func main() { fmt.Println() } 769 `, 770 }, 771 772 // Unused named import is mistaken for unnamed import 773 // golang.org/issue/8149 774 { 775 name: "unused_named_import_removed", 776 in: `package main 777 778 import ( 779 "fmt" 780 x "fmt" 781 ) 782 783 func main() { fmt.Println() } 784 `, 785 out: `package main 786 787 import ( 788 "fmt" 789 ) 790 791 func main() { fmt.Println() } 792 `, 793 }, 794 795 { 796 name: "ignore_unexported_identifier", 797 in: `package main 798 var _ = fmt.unexported`, 799 out: `package main 800 801 var _ = fmt.unexported 802 `, 803 }, 804 805 // FormatOnly 806 { 807 name: "formatonly_works", 808 formatOnly: true, 809 in: `package main 810 811 import ( 812 "fmt" 813 "manypackages.com/packagea" 814 ) 815 816 func main() {} 817 `, 818 out: `package main 819 820 import ( 821 "fmt" 822 823 "manypackages.com/packagea" 824 ) 825 826 func main() {} 827 `, 828 }, 829 830 { 831 name: "preserve_import_group", 832 in: `package p 833 834 import ( 835 "bytes" 836 "fmt" 837 ) 838 839 var _ = fmt.Sprintf 840 `, 841 out: `package p 842 843 import ( 844 "fmt" 845 ) 846 847 var _ = fmt.Sprintf 848 `, 849 }, 850 { 851 name: "import_grouping_not_path_dependent_no_groups", 852 in: `package main 853 854 import ( 855 "time" 856 ) 857 858 func main() { 859 _ = snappy.ErrCorrupt 860 _ = p.P 861 _ = time.Parse 862 } 863 `, 864 out: `package main 865 866 import ( 867 "time" 868 869 "github.com/golang/snappy" 870 "rsc.io/p" 871 ) 872 873 func main() { 874 _ = snappy.ErrCorrupt 875 _ = p.P 876 _ = time.Parse 877 } 878 `, 879 }, 880 881 { 882 name: "import_grouping_not_path_dependent_existing_group", 883 in: `package main 884 885 import ( 886 "time" 887 888 "github.com/golang/snappy" 889 ) 890 891 func main() { 892 _ = snappy.ErrCorrupt 893 _ = p.P 894 _ = time.Parse 895 } 896 `, 897 out: `package main 898 899 import ( 900 "time" 901 902 "github.com/golang/snappy" 903 "rsc.io/p" 904 ) 905 906 func main() { 907 _ = snappy.ErrCorrupt 908 _ = p.P 909 _ = time.Parse 910 } 911 `, 912 }, 913 914 // golang.org/issue/12097 915 { 916 name: "package_statement_insertion_preserves_comments", 917 in: `// a 918 // b 919 // c 920 921 func main() { 922 _ = fmt.Println 923 }`, 924 out: `package main 925 926 import "fmt" 927 928 // a 929 // b 930 // c 931 932 func main() { 933 _ = fmt.Println 934 } 935 `, 936 }, 937 938 { 939 name: "import_comment_stays_on_import", 940 in: `package main 941 942 import ( 943 "math" // fun 944 ) 945 946 func main() { 947 x := math.MaxInt64 948 fmt.Println(strings.Join(",", []string{"hi"}), x) 949 }`, 950 out: `package main 951 952 import ( 953 "fmt" 954 "math" // fun 955 "strings" 956 ) 957 958 func main() { 959 x := math.MaxInt64 960 fmt.Println(strings.Join(",", []string{"hi"}), x) 961 } 962 `, 963 }, 964 965 { 966 name: "no_blank_after_comment", 967 in: `package main 968 969 import ( 970 _ "io" 971 _ "net/http" 972 _ "net/http/pprof" // install the pprof http handlers 973 _ "strings" 974 ) 975 976 func main() { 977 } 978 `, 979 out: `package main 980 981 import ( 982 _ "io" 983 _ "net/http" 984 _ "net/http/pprof" // install the pprof http handlers 985 _ "strings" 986 ) 987 988 func main() { 989 } 990 `, 991 }, 992 993 { 994 name: "no_blank_after_comment_reordered", 995 in: `package main 996 997 import ( 998 _ "io" 999 _ "net/http/pprof" // install the pprof http handlers 1000 _ "net/http" 1001 _ "strings" 1002 ) 1003 1004 func main() { 1005 } 1006 `, 1007 out: `package main 1008 1009 import ( 1010 _ "io" 1011 _ "net/http" 1012 _ "net/http/pprof" // install the pprof http handlers 1013 _ "strings" 1014 ) 1015 1016 func main() { 1017 } 1018 `, 1019 }, 1020 1021 { 1022 name: "no_blank_after_comment_unnamed", 1023 in: `package main 1024 1025 import ( 1026 "encoding/json" 1027 "io" 1028 "net/http" 1029 _ "net/http/pprof" // install the pprof http handlers 1030 "strings" 1031 1032 "manypackages.com/packagea" 1033 ) 1034 1035 func main() { 1036 _ = strings.ToUpper("hello") 1037 _ = io.EOF 1038 var ( 1039 _ json.Number 1040 _ *http.Request 1041 _ packagea.A 1042 ) 1043 } 1044 `, 1045 out: `package main 1046 1047 import ( 1048 "encoding/json" 1049 "io" 1050 "net/http" 1051 _ "net/http/pprof" // install the pprof http handlers 1052 "strings" 1053 1054 "manypackages.com/packagea" 1055 ) 1056 1057 func main() { 1058 _ = strings.ToUpper("hello") 1059 _ = io.EOF 1060 var ( 1061 _ json.Number 1062 _ *http.Request 1063 _ packagea.A 1064 ) 1065 } 1066 `, 1067 }, 1068 1069 { 1070 name: "blank_after_package_statement_with_comment", 1071 in: `package p // comment 1072 1073 import "math" 1074 1075 var _ = fmt.Printf 1076 `, 1077 out: `package p // comment 1078 1079 import "fmt" 1080 1081 var _ = fmt.Printf 1082 `, 1083 }, 1084 1085 { 1086 name: "blank_after_package_statement_no_comment", 1087 in: `package p 1088 1089 import "math" 1090 1091 var _ = fmt.Printf 1092 `, 1093 out: `package p 1094 1095 import "fmt" 1096 1097 var _ = fmt.Printf 1098 `, 1099 }, 1100 1101 { 1102 name: "cryptorand_preferred_easy_possible", 1103 in: `package p 1104 1105 var _ = rand.Read 1106 `, 1107 out: `package p 1108 1109 import "crypto/rand" 1110 1111 var _ = rand.Read 1112 `, 1113 }, 1114 1115 { 1116 name: "cryptorand_preferred_easy_impossible", 1117 in: `package p 1118 1119 var _ = rand.NewZipf 1120 `, 1121 out: `package p 1122 1123 import "math/rand" 1124 1125 var _ = rand.NewZipf 1126 `, 1127 }, 1128 1129 { 1130 name: "cryptorand_preferred_complex_possible", 1131 in: `package p 1132 1133 var _, _ = rand.Read, rand.Prime 1134 `, 1135 out: `package p 1136 1137 import "crypto/rand" 1138 1139 var _, _ = rand.Read, rand.Prime 1140 `, 1141 }, 1142 1143 { 1144 name: "cryptorand_preferred_complex_impossible", 1145 in: `package p 1146 1147 var _, _ = rand.Read, rand.NewZipf 1148 `, 1149 out: `package p 1150 1151 import "math/rand" 1152 1153 var _, _ = rand.Read, rand.NewZipf 1154 `, 1155 }, 1156 } 1157 1158 func TestSimpleCases(t *testing.T) { 1159 const localPrefix = "local.com,github.com/local" 1160 for _, tt := range tests { 1161 t.Run(tt.name, func(t *testing.T) { 1162 testConfig{ 1163 modules: []packagestest.Module{ 1164 { 1165 Name: "golang.org/fake", 1166 Files: fm{"x.go": tt.in}, 1167 }, 1168 // Skeleton non-stdlib packages for use during testing. 1169 // Each includes one arbitrary symbol, e.g. the first declaration in the first file. 1170 // Try not to add more without a good reason. 1171 // DO NOT USE PACKAGES NOT LISTED HERE -- they will be downloaded! 1172 { 1173 Name: "rsc.io", 1174 Files: fm{"p/x.go": "package p\nfunc P(){}\n"}, 1175 }, 1176 { 1177 Name: "github.com/golang/snappy", 1178 Files: fm{"x.go": "package snappy\nvar ErrCorrupt error\n"}, 1179 }, 1180 { 1181 Name: "manypackages.com", 1182 Files: fm{ 1183 "packagea/x.go": "package packagea\nfunc A(){}\n", 1184 "packageb/x.go": "package packageb\nfunc B(){}\n", 1185 "packagec/x.go": "package packagec\nfunc C(){}\n", 1186 "packaged/x.go": "package packaged\nfunc D(){}\n", 1187 }, 1188 }, 1189 { 1190 Name: "local.com", 1191 Files: fm{"foo/x.go": "package foo\nfunc Foo(){}\n"}, 1192 }, 1193 { 1194 Name: "github.com/local", 1195 Files: fm{"bar/x.go": "package bar\nfunc Bar(){}\n"}, 1196 }, 1197 }, 1198 }.test(t, func(t *goimportTest) { 1199 options := &Options{ 1200 LocalPrefix: localPrefix, 1201 TabWidth: 8, 1202 TabIndent: true, 1203 Comments: true, 1204 Fragment: true, 1205 FormatOnly: tt.formatOnly, 1206 } 1207 t.assertProcessEquals("golang.org/fake", "x.go", nil, options, tt.out) 1208 }) 1209 1210 }) 1211 } 1212 } 1213 1214 func TestAppengine(t *testing.T) { 1215 const input = `package p 1216 1217 var _, _, _ = fmt.Printf, appengine.Main, datastore.ErrInvalidEntityType 1218 ` 1219 1220 const want = `package p 1221 1222 import ( 1223 "fmt" 1224 1225 "appengine" 1226 "appengine/datastore" 1227 ) 1228 1229 var _, _, _ = fmt.Printf, appengine.Main, datastore.ErrInvalidEntityType 1230 ` 1231 1232 testConfig{ 1233 gopathOnly: true, // can't create a module named appengine, so no module tests. 1234 modules: []packagestest.Module{ 1235 { 1236 Name: "golang.org/fake", 1237 Files: fm{"x.go": input}, 1238 }, 1239 { 1240 Name: "appengine", 1241 Files: fm{ 1242 "x.go": "package appengine\nfunc Main(){}\n", 1243 "datastore/x.go": "package datastore\nvar ErrInvalidEntityType error\n", 1244 }, 1245 }, 1246 }, 1247 }.processTest(t, "golang.org/fake", "x.go", nil, nil, want) 1248 } 1249 1250 func TestReadFromFilesystem(t *testing.T) { 1251 tests := []struct { 1252 name string 1253 in, out string 1254 }{ 1255 { 1256 name: "works", 1257 in: `package foo 1258 func bar() { 1259 fmt.Println("hi") 1260 } 1261 `, 1262 out: `package foo 1263 1264 import "fmt" 1265 1266 func bar() { 1267 fmt.Println("hi") 1268 } 1269 `, 1270 }, 1271 { 1272 name: "missing_package", 1273 in: ` 1274 func bar() { 1275 fmt.Println("hi") 1276 } 1277 `, 1278 out: ` 1279 import "fmt" 1280 1281 func bar() { 1282 fmt.Println("hi") 1283 } 1284 `, 1285 }, 1286 } 1287 1288 for _, tt := range tests { 1289 t.Run(tt.name, func(t *testing.T) { 1290 options := &Options{ 1291 TabWidth: 8, 1292 TabIndent: true, 1293 Comments: true, 1294 Fragment: true, 1295 } 1296 testConfig{ 1297 module: packagestest.Module{ 1298 Name: "golang.org/fake", 1299 Files: fm{"x.go": tt.in}, 1300 }, 1301 }.processTest(t, "golang.org/fake", "x.go", nil, options, tt.out) 1302 }) 1303 } 1304 1305 } 1306 1307 // Test support for packages in GOPATH that are actually symlinks. 1308 // Also test that a symlink loop does not block the process. 1309 func TestImportSymlinks(t *testing.T) { 1310 switch runtime.GOOS { 1311 case "windows", "plan9": 1312 t.Skipf("skipping test on %q as there are no symlinks", runtime.GOOS) 1313 } 1314 1315 const input = `package p 1316 1317 var ( 1318 _ = fmt.Print 1319 _ = mypkg.Foo 1320 ) 1321 ` 1322 const want = `package p 1323 1324 import ( 1325 "fmt" 1326 1327 "golang.org/fake/x/y/mypkg" 1328 ) 1329 1330 var ( 1331 _ = fmt.Print 1332 _ = mypkg.Foo 1333 ) 1334 ` 1335 1336 testConfig{ 1337 module: packagestest.Module{ 1338 Name: "golang.org/fake", 1339 Files: fm{ 1340 "target/f.go": "package mypkg\nvar Foo = 123\n", 1341 "x/y/mypkg": packagestest.Symlink("../../target"), // valid symlink 1342 "x/y/apkg": packagestest.Symlink(".."), // symlink loop 1343 "myotherpackage/toformat.go": input, 1344 }, 1345 }, 1346 }.processTest(t, "golang.org/fake", "myotherpackage/toformat.go", nil, nil, want) 1347 } 1348 1349 func TestImportSymlinksWithIgnore(t *testing.T) { 1350 switch runtime.GOOS { 1351 case "windows", "plan9": 1352 t.Skipf("skipping test on %q as there are no symlinks", runtime.GOOS) 1353 } 1354 1355 const input = `package p 1356 1357 var ( 1358 _ = fmt.Print 1359 _ = mypkg.Foo 1360 ) 1361 ` 1362 const want = `package p 1363 1364 import "fmt" 1365 1366 var ( 1367 _ = fmt.Print 1368 _ = mypkg.Foo 1369 ) 1370 ` 1371 1372 testConfig{ 1373 gopathOnly: true, 1374 module: packagestest.Module{ 1375 Name: "golang.org/fake", 1376 Files: fm{ 1377 "target/f.go": "package mypkg\nvar Foo = 123\n", 1378 "x/y/mypkg": packagestest.Symlink("../../target"), // valid symlink 1379 "x/y/apkg": packagestest.Symlink(".."), // symlink loop 1380 "myotherpkg/toformat.go": input, 1381 "../../.goimportsignore": "golang.org/fake/x/y/mypkg\n", 1382 }, 1383 }, 1384 }.processTest(t, "golang.org/fake", "myotherpkg/toformat.go", nil, nil, want) 1385 } 1386 1387 // Test for x/y/v2 convention for package y. 1388 func TestModuleVersion(t *testing.T) { 1389 const input = `package p 1390 1391 import ( 1392 "fmt" 1393 1394 "github.com/foo/v2" 1395 ) 1396 1397 var ( 1398 _ = fmt.Print 1399 _ = foo.Foo 1400 ) 1401 ` 1402 1403 testConfig{ 1404 modules: []packagestest.Module{ 1405 { 1406 Name: "mypkg.com/outpkg", 1407 Files: fm{"toformat.go": input}, 1408 }, 1409 { 1410 Name: "github.com/foo/v2", 1411 Files: fm{"x.go": "package foo\n func Foo(){}\n"}, 1412 }, 1413 }, 1414 }.processTest(t, "mypkg.com/outpkg", "toformat.go", nil, nil, input) 1415 } 1416 1417 // Test for correctly identifying the name of a vendored package when it 1418 // differs from its directory name. In this test, the import line 1419 // "mypkg.com/mypkg_v1" would be removed if goimports wasn't able to detect 1420 // that the package name is "mypkg". 1421 func TestVendorPackage(t *testing.T) { 1422 const input = `package p 1423 import ( 1424 "fmt" 1425 "mypkg.com/mypkg_v1" 1426 ) 1427 var _, _ = fmt.Print, mypkg.Foo 1428 ` 1429 1430 const want = `package p 1431 1432 import ( 1433 "fmt" 1434 1435 mypkg "mypkg.com/mypkg_v1" 1436 ) 1437 1438 var _, _ = fmt.Print, mypkg.Foo 1439 ` 1440 1441 testConfig{ 1442 gopathOnly: true, 1443 module: packagestest.Module{ 1444 Name: "mypkg.com/outpkg", 1445 Files: fm{ 1446 "vendor/mypkg.com/mypkg_v1/f.go": "package mypkg\nvar Foo = 123\n", 1447 "toformat.go": input, 1448 }, 1449 }, 1450 }.processTest(t, "mypkg.com/outpkg", "toformat.go", nil, nil, want) 1451 } 1452 1453 func TestInternal(t *testing.T) { 1454 const input = `package bar 1455 1456 var _ = race.Acquire 1457 ` 1458 const importAdded = `package bar 1459 1460 import "foo.com/internal/race" 1461 1462 var _ = race.Acquire 1463 ` 1464 1465 // Packages under the same directory should be able to use internal packages. 1466 testConfig{ 1467 module: packagestest.Module{ 1468 Name: "foo.com", 1469 Files: fm{ 1470 "internal/race/x.go": "package race\n func Acquire(){}\n", 1471 "bar/x.go": input, 1472 }, 1473 }, 1474 }.processTest(t, "foo.com", "bar/x.go", nil, nil, importAdded) 1475 1476 // Packages outside the same directory should not. 1477 testConfig{ 1478 modules: []packagestest.Module{ 1479 { 1480 Name: "foo.com", 1481 Files: fm{"internal/race/x.go": "package race\n func Acquire(){}\n"}, 1482 }, 1483 { 1484 Name: "bar.com", 1485 Files: fm{"x.go": input}, 1486 }, 1487 }, 1488 }.processTest(t, "bar.com", "x.go", nil, nil, input) 1489 } 1490 1491 func TestProcessVendor(t *testing.T) { 1492 const input = `package p 1493 1494 var _ = hpack.HuffmanDecode 1495 ` 1496 const want = `package p 1497 1498 import "golang.org/x/net/http2/hpack" 1499 1500 var _ = hpack.HuffmanDecode 1501 ` 1502 testConfig{ 1503 gopathOnly: true, 1504 module: packagestest.Module{ 1505 Name: "foo.com", 1506 Files: fm{ 1507 "vendor/golang.org/x/net/http2/hpack/huffman.go": "package hpack\nfunc HuffmanDecode() { }\n", 1508 "bar/x.go": input, 1509 }, 1510 }, 1511 }.processTest(t, "foo.com", "bar/x.go", nil, nil, want) 1512 } 1513 1514 func TestFindStdlib(t *testing.T) { 1515 tests := []struct { 1516 pkg string 1517 symbols []string 1518 want string 1519 }{ 1520 {"http", []string{"Get"}, "net/http"}, 1521 {"http", []string{"Get", "Post"}, "net/http"}, 1522 {"http", []string{"Get", "Foo"}, ""}, 1523 {"bytes", []string{"Buffer"}, "bytes"}, 1524 {"ioutil", []string{"Discard"}, "io/ioutil"}, 1525 } 1526 for _, tt := range tests { 1527 input := "package p\n" 1528 for _, sym := range tt.symbols { 1529 input += fmt.Sprintf("var _ = %s.%s\n", tt.pkg, sym) 1530 } 1531 testConfig{ 1532 module: packagestest.Module{ 1533 Name: "foo.com", 1534 Files: fm{"x.go": input}, 1535 }, 1536 }.test(t, func(t *goimportTest) { 1537 buf, err := t.process("foo.com", "x.go", nil, nil) 1538 if err != nil { 1539 t.Fatal(err) 1540 } 1541 if got := string(buf); !strings.Contains(got, tt.want) { 1542 t.Errorf("Process(%q) = %q, wanted it to contain %q", input, buf, tt.want) 1543 } 1544 }) 1545 } 1546 } 1547 1548 // https://golang.org/issue/31814 1549 func TestStdlibNotPrefixed(t *testing.T) { 1550 const input = `package p 1551 var _ = bytes.Buffer 1552 ` 1553 const want = `package p 1554 1555 import "bytes" 1556 1557 var _ = bytes.Buffer 1558 ` 1559 // Force a scan of the stdlib. 1560 savedStdlib := stdlib 1561 defer func() { stdlib = savedStdlib }() 1562 stdlib = map[string][]string{} 1563 1564 testConfig{ 1565 module: packagestest.Module{ 1566 Name: "ignored.com", 1567 Files: fm{"x.go": "package x"}, 1568 }, 1569 }.test(t, func(t *goimportTest) { 1570 // Run in GOROOT/src so that the std module shows up in go list -m all. 1571 t.env.WorkingDir = filepath.Join(t.goroot, "src") 1572 got, err := t.processNonModule(filepath.Join(t.goroot, "src/x.go"), []byte(input), nil) 1573 if err != nil { 1574 t.Fatalf("Process() = %v", err) 1575 } 1576 if string(got) != want { 1577 t.Errorf("Got:\n%s\nWant:\n%s", got, want) 1578 } 1579 }) 1580 } 1581 1582 func TestStdlibSelfImports(t *testing.T) { 1583 const input = `package ecdsa 1584 1585 var _ = ecdsa.GenerateKey 1586 ` 1587 1588 testConfig{ 1589 module: packagestest.Module{ 1590 Name: "ignored.com", 1591 Files: fm{"x.go": "package x"}, 1592 }, 1593 }.test(t, func(t *goimportTest) { 1594 got, err := t.processNonModule(filepath.Join(t.goroot, "src/crypto/ecdsa/foo.go"), []byte(input), nil) 1595 if err != nil { 1596 t.Fatalf("Process() = %v", err) 1597 } 1598 if string(got) != input { 1599 t.Errorf("Got:\n%s\nWant:\n%s", got, input) 1600 } 1601 }) 1602 } 1603 1604 type testConfig struct { 1605 gopathOnly bool 1606 module packagestest.Module 1607 modules []packagestest.Module 1608 } 1609 1610 // fm is the type for a packagestest.Module's Files, abbreviated for shorter lines. 1611 type fm map[string]interface{} 1612 1613 func (c testConfig) test(t *testing.T, fn func(*goimportTest)) { 1614 t.Helper() 1615 1616 if c.module.Name != "" { 1617 c.modules = []packagestest.Module{c.module} 1618 } 1619 1620 for _, exporter := range packagestest.All { 1621 t.Run(exporter.Name(), func(t *testing.T) { 1622 t.Helper() 1623 if c.gopathOnly && exporter.Name() == "Modules" { 1624 t.Skip("test marked GOPATH-only") 1625 } 1626 exported := packagestest.Export(t, exporter, c.modules) 1627 defer exported.Cleanup() 1628 1629 env := map[string]string{} 1630 for _, kv := range exported.Config.Env { 1631 split := strings.SplitN(kv, "=", 2) 1632 env[split[0]] = split[1] 1633 } 1634 it := &goimportTest{ 1635 T: t, 1636 env: &ProcessEnv{ 1637 Env: env, 1638 WorkingDir: exported.Config.Dir, 1639 GocmdRunner: &gocommand.Runner{}, 1640 }, 1641 exported: exported, 1642 } 1643 if *testDebug { 1644 it.env.Logf = log.Printf 1645 } 1646 // packagestest clears out GOROOT to work around golang/go#32849, 1647 // which isn't relevant here. Fill it back in so we can find the standard library. 1648 it.env.Env["GOROOT"] = build.Default.GOROOT 1649 it.goroot = build.Default.GOROOT 1650 1651 fn(it) 1652 }) 1653 } 1654 } 1655 1656 func (c testConfig) processTest(t *testing.T, module, file string, contents []byte, opts *Options, want string) { 1657 t.Helper() 1658 c.test(t, func(t *goimportTest) { 1659 t.Helper() 1660 t.assertProcessEquals(module, file, contents, opts, want) 1661 }) 1662 } 1663 1664 type goimportTest struct { 1665 *testing.T 1666 goroot string 1667 env *ProcessEnv 1668 exported *packagestest.Exported 1669 } 1670 1671 func (t *goimportTest) process(module, file string, contents []byte, opts *Options) ([]byte, error) { 1672 t.Helper() 1673 f := t.exported.File(module, file) 1674 if f == "" { 1675 t.Fatalf("%v not found in exported files (typo in filename?)", file) 1676 } 1677 return t.processNonModule(f, contents, opts) 1678 } 1679 1680 func (t *goimportTest) processNonModule(file string, contents []byte, opts *Options) ([]byte, error) { 1681 if contents == nil { 1682 var err error 1683 contents, err = ioutil.ReadFile(file) 1684 if err != nil { 1685 return nil, err 1686 } 1687 } 1688 if opts == nil { 1689 opts = &Options{Comments: true, TabIndent: true, TabWidth: 8} 1690 } 1691 // ProcessEnv is not safe for concurrent use. Make a copy. 1692 opts.Env = t.env.CopyConfig() 1693 return Process(file, contents, opts) 1694 } 1695 1696 func (t *goimportTest) assertProcessEquals(module, file string, contents []byte, opts *Options, want string) { 1697 buf, err := t.process(module, file, contents, opts) 1698 if err != nil { 1699 t.Fatalf("Process() = %v", err) 1700 } 1701 if string(buf) != want { 1702 t.Errorf("Got:\n%s\nWant:\n%s", buf, want) 1703 } 1704 } 1705 1706 // Tests that added imports are renamed when the import path's base doesn't 1707 // match its package name. 1708 func TestRenameWhenPackageNameMismatch(t *testing.T) { 1709 const input = `package main 1710 const Y = bar.X` 1711 1712 const want = `package main 1713 1714 import bar "foo.com/foo/bar/baz" 1715 1716 const Y = bar.X 1717 ` 1718 testConfig{ 1719 module: packagestest.Module{ 1720 Name: "foo.com", 1721 Files: fm{ 1722 "foo/bar/baz/x.go": "package bar \n const X = 1", 1723 "test/t.go": input, 1724 }, 1725 }, 1726 }.processTest(t, "foo.com", "test/t.go", nil, nil, want) 1727 } 1728 1729 // Tests that an existing import with badly mismatched path/name has its name 1730 // correctly added. See #28645 and #29041. 1731 func TestAddNameToMismatchedImport(t *testing.T) { 1732 const input = `package main 1733 1734 import ( 1735 "foo.com/a.thing" 1736 "foo.com/surprise" 1737 "foo.com/v1" 1738 "foo.com/other/v2" 1739 "foo.com/other/v3" 1740 "foo.com/go-thing" 1741 "foo.com/go-wrong" 1742 ) 1743 1744 var _ = []interface{}{bar.X, v1.Y, a.A, v2.V2, other.V3, thing.Thing, gow.Wrong}` 1745 1746 const want = `package main 1747 1748 import ( 1749 "foo.com/a.thing" 1750 "foo.com/go-thing" 1751 gow "foo.com/go-wrong" 1752 v2 "foo.com/other/v2" 1753 "foo.com/other/v3" 1754 bar "foo.com/surprise" 1755 v1 "foo.com/v1" 1756 ) 1757 1758 var _ = []interface{}{bar.X, v1.Y, a.A, v2.V2, other.V3, thing.Thing, gow.Wrong} 1759 ` 1760 1761 testConfig{ 1762 module: packagestest.Module{ 1763 Name: "foo.com", 1764 Files: fm{ 1765 "a.thing/a.go": "package a \n const A = 1", 1766 "surprise/x.go": "package bar \n const X = 1", 1767 "v1/x.go": "package v1 \n const Y = 1", 1768 "other/v2/y.go": "package v2 \n const V2 = 1", 1769 "other/v3/z.go": "package other \n const V3 = 1", 1770 "go-thing/b.go": "package thing \n const Thing = 1", 1771 "go-wrong/b.go": "package gow \n const Wrong = 1", 1772 "test/t.go": input, 1773 }, 1774 }, 1775 }.processTest(t, "foo.com", "test/t.go", nil, nil, want) 1776 } 1777 1778 // Tests that the LocalPrefix option causes imports 1779 // to be added into a later group (num=3). 1780 func TestLocalPrefix(t *testing.T) { 1781 tests := []struct { 1782 name string 1783 modules []packagestest.Module 1784 localPrefix string 1785 src string 1786 want string 1787 }{ 1788 { 1789 name: "one_local", 1790 modules: []packagestest.Module{ 1791 { 1792 Name: "foo.com", 1793 Files: fm{ 1794 "bar/bar.go": "package bar \n const X = 1", 1795 }, 1796 }, 1797 }, 1798 localPrefix: "foo.com/", 1799 src: "package main \n const Y = bar.X \n const _ = runtime.GOOS", 1800 want: `package main 1801 1802 import ( 1803 "runtime" 1804 1805 "foo.com/bar" 1806 ) 1807 1808 const Y = bar.X 1809 const _ = runtime.GOOS 1810 `, 1811 }, 1812 { 1813 name: "two_local", 1814 modules: []packagestest.Module{ 1815 { 1816 Name: "foo.com", 1817 Files: fm{ 1818 "foo/foo.go": "package foo \n const X = 1", 1819 "foo/bar/bar.go": "package bar \n const X = 1", 1820 }, 1821 }, 1822 }, 1823 localPrefix: "foo.com/foo", 1824 src: "package main \n const Y = bar.X \n const Z = foo.X \n const _ = runtime.GOOS", 1825 want: `package main 1826 1827 import ( 1828 "runtime" 1829 1830 "foo.com/foo" 1831 "foo.com/foo/bar" 1832 ) 1833 1834 const Y = bar.X 1835 const Z = foo.X 1836 const _ = runtime.GOOS 1837 `, 1838 }, 1839 { 1840 name: "three_prefixes", 1841 modules: []packagestest.Module{ 1842 { 1843 Name: "example.org/pkg", 1844 Files: fm{"pkg.go": "package pkg \n const A = 1"}, 1845 }, 1846 { 1847 Name: "foo.com", 1848 Files: fm{"bar/bar.go": "package bar \n const B = 1"}, 1849 }, 1850 { 1851 Name: "code.org/r/p", 1852 Files: fm{"expproj/expproj.go": "package expproj \n const C = 1"}, 1853 }, 1854 }, 1855 localPrefix: "example.org/pkg,foo.com/,code.org", 1856 src: "package main \n const X = pkg.A \n const Y = bar.B \n const Z = expproj.C \n const _ = runtime.GOOS", 1857 want: `package main 1858 1859 import ( 1860 "runtime" 1861 1862 "code.org/r/p/expproj" 1863 "example.org/pkg" 1864 "foo.com/bar" 1865 ) 1866 1867 const X = pkg.A 1868 const Y = bar.B 1869 const Z = expproj.C 1870 const _ = runtime.GOOS 1871 `, 1872 }, 1873 } 1874 1875 for _, tt := range tests { 1876 t.Run(tt.name, func(t *testing.T) { 1877 testConfig{ 1878 // The module being processed has to be first so it's the primary module. 1879 modules: append([]packagestest.Module{{ 1880 Name: "test.com", 1881 Files: fm{"t.go": tt.src}, 1882 }}, tt.modules...), 1883 }.test(t, func(t *goimportTest) { 1884 options := &Options{ 1885 LocalPrefix: tt.localPrefix, 1886 TabWidth: 8, 1887 TabIndent: true, 1888 Comments: true, 1889 Fragment: true, 1890 } 1891 t.assertProcessEquals("test.com", "t.go", nil, options, tt.want) 1892 }) 1893 }) 1894 } 1895 } 1896 1897 // Tests that "package documentation" files are ignored. 1898 func TestIgnoreDocumentationPackage(t *testing.T) { 1899 const input = `package x 1900 1901 const Y = foo.X 1902 ` 1903 const want = `package x 1904 1905 import "foo.com/foo" 1906 1907 const Y = foo.X 1908 ` 1909 1910 testConfig{ 1911 module: packagestest.Module{ 1912 Name: "foo.com", 1913 Files: fm{ 1914 "foo/foo.go": "package foo\nconst X = 1\n", 1915 "foo/doc.go": "package documentation \n // just to confuse things\n", 1916 "x/x.go": input, 1917 }, 1918 }, 1919 }.processTest(t, "foo.com", "x/x.go", nil, nil, want) 1920 } 1921 1922 // Tests importPathToNameGoPathParse and in particular that it stops 1923 // after finding the first non-documentation package name, not 1924 // reporting an error on inconsistent package names (since it should 1925 // never make it that far). 1926 func TestImportPathToNameGoPathParse(t *testing.T) { 1927 testConfig{ 1928 module: packagestest.Module{ 1929 Name: "example.net/pkg", 1930 Files: fm{ 1931 "doc.go": "package documentation\n", // ignored 1932 "gen.go": "package main\n", // also ignored 1933 "pkg.go": "package the_pkg_name_to_find\n and this syntax error is ignored because of parser.PackageClauseOnly", 1934 "z.go": "package inconsistent\n", // inconsistent but ignored 1935 }, 1936 }, 1937 }.test(t, func(t *goimportTest) { 1938 if strings.Contains(t.Name(), "GoPackages") { 1939 t.Skip("go/packages does not ignore package main") 1940 } 1941 r, err := t.env.GetResolver() 1942 if err != nil { 1943 t.Fatal(err) 1944 } 1945 srcDir := filepath.Dir(t.exported.File("example.net/pkg", "z.go")) 1946 names, err := r.loadPackageNames([]string{"example.net/pkg"}, srcDir) 1947 if err != nil { 1948 t.Fatal(err) 1949 } 1950 const want = "the_pkg_name_to_find" 1951 if got := names["example.net/pkg"]; got != want { 1952 t.Errorf("loadPackageNames(..) = %q; want %q", got, want) 1953 } 1954 }) 1955 } 1956 1957 func TestIgnoreConfiguration(t *testing.T) { 1958 const input = `package x 1959 1960 const _ = pkg.X 1961 ` 1962 const want = `package x 1963 1964 import "foo.com/otherwise-longer-so-worse-example/foo/pkg" 1965 1966 const _ = pkg.X 1967 ` 1968 1969 testConfig{ 1970 gopathOnly: true, 1971 module: packagestest.Module{ 1972 Name: "foo.com", 1973 Files: fm{ 1974 "../.goimportsignore": "# comment line\n\n foo.com/example", // tests comment, blank line, whitespace trimming 1975 "example/pkg/pkg.go": "package pkg\nconst X = 1", 1976 "otherwise-longer-so-worse-example/foo/pkg/pkg.go": "package pkg\nconst X = 1", 1977 "x/x.go": input, 1978 }, 1979 }, 1980 }.processTest(t, "foo.com", "x/x.go", nil, nil, want) 1981 } 1982 1983 // Skip "node_modules" directory. 1984 func TestSkipNodeModules(t *testing.T) { 1985 const input = `package x 1986 1987 const _ = pkg.X 1988 ` 1989 const want = `package x 1990 1991 import "foo.com/otherwise-longer/not_modules/pkg" 1992 1993 const _ = pkg.X 1994 ` 1995 1996 testConfig{ 1997 gopathOnly: true, 1998 module: packagestest.Module{ 1999 Name: "foo.com", 2000 Files: fm{ 2001 "example/node_modules/pkg/a.go": "package pkg\nconst X = 1", 2002 "otherwise-longer/not_modules/pkg/a.go": "package pkg\nconst X = 1", 2003 "x/x.go": input, 2004 }, 2005 }, 2006 }.processTest(t, "foo.com", "x/x.go", nil, nil, want) 2007 } 2008 2009 // Tests that package global variables with the same name and function name as 2010 // a function in a separate package do not result in an import which masks 2011 // the global variable 2012 func TestGlobalImports(t *testing.T) { 2013 const usesGlobal = `package pkg 2014 2015 func doSomething() { 2016 t := time.Now() 2017 } 2018 ` 2019 2020 const declaresGlobal = `package pkg 2021 2022 type Time struct{} 2023 2024 func (t Time) Now() Time { 2025 return Time{} 2026 } 2027 2028 var time Time 2029 ` 2030 2031 testConfig{ 2032 module: packagestest.Module{ 2033 Name: "foo.com", 2034 Files: fm{ 2035 "pkg/uses.go": usesGlobal, 2036 "pkg/global.go": declaresGlobal, 2037 }, 2038 }, 2039 }.processTest(t, "foo.com", "pkg/uses.go", nil, nil, usesGlobal) 2040 } 2041 2042 // Some people put multiple packages' files in the same directory. Globals 2043 // declared in other packages should be ignored. 2044 func TestGlobalImports_DifferentPackage(t *testing.T) { 2045 const declaresGlobal = `package main 2046 var fmt int 2047 ` 2048 const input = `package pkg 2049 var _ = fmt.Printf 2050 ` 2051 const want = `package pkg 2052 2053 import "fmt" 2054 2055 var _ = fmt.Printf 2056 ` 2057 2058 testConfig{ 2059 module: packagestest.Module{ 2060 Name: "foo.com", 2061 Files: fm{ 2062 "pkg/main.go": declaresGlobal, 2063 "pkg/uses.go": input, 2064 }, 2065 }, 2066 }.processTest(t, "foo.com", "pkg/uses.go", nil, nil, want) 2067 } 2068 2069 func TestGlobalImports_MultipleMains(t *testing.T) { 2070 const declaresGlobal = `package main 2071 var fmt int 2072 ` 2073 const input = `package main 2074 import "fmt" 2075 var _, _ = fmt.Printf, bytes.Equal 2076 ` 2077 const want = `package main 2078 2079 import ( 2080 "bytes" 2081 "fmt" 2082 ) 2083 2084 var _, _ = fmt.Printf, bytes.Equal 2085 ` 2086 2087 testConfig{ 2088 module: packagestest.Module{ 2089 Name: "foo.com", 2090 Files: fm{ 2091 "pkg/main.go": declaresGlobal, 2092 "pkg/uses.go": input, 2093 }, 2094 }, 2095 }.processTest(t, "foo.com", "pkg/uses.go", nil, nil, want) 2096 } 2097 2098 // Tests that sibling files - other files in the same package - can provide an 2099 // import that may not be the default one otherwise. 2100 func TestSiblingImports(t *testing.T) { 2101 2102 // provide is the sibling file that provides the desired import. 2103 const provide = `package siblingimporttest 2104 2105 import "local/log" 2106 import "my/bytes" 2107 import renamed "fmt" 2108 2109 func LogSomething() { 2110 log.Print("Something") 2111 bytes.SomeFunc() 2112 renamed.Println("Something") 2113 } 2114 ` 2115 2116 // need is the file being tested that needs the import. 2117 const need = `package siblingimporttest 2118 2119 var _ = bytes.Buffer{} 2120 2121 func LogSomethingElse() { 2122 log.Print("Something else") 2123 renamed.Println("Yet another") 2124 } 2125 ` 2126 2127 // want is the expected result file 2128 const want = `package siblingimporttest 2129 2130 import ( 2131 "bytes" 2132 renamed "fmt" 2133 "local/log" 2134 ) 2135 2136 var _ = bytes.Buffer{} 2137 2138 func LogSomethingElse() { 2139 log.Print("Something else") 2140 renamed.Println("Yet another") 2141 } 2142 ` 2143 2144 testConfig{ 2145 module: packagestest.Module{ 2146 Name: "foo.com", 2147 Files: fm{ 2148 "p/needs_import.go": need, 2149 "p/provides_import.go": provide, 2150 }, 2151 }, 2152 }.processTest(t, "foo.com", "p/needs_import.go", nil, nil, want) 2153 } 2154 2155 // Tests #29180: a sibling import of the right package with the wrong name is used. 2156 func TestSiblingImport_Misnamed(t *testing.T) { 2157 const sibling = `package main 2158 import renamed "fmt" 2159 var _ = renamed.Printf 2160 ` 2161 const input = `package pkg 2162 var _ = fmt.Printf 2163 ` 2164 const want = `package pkg 2165 2166 import "fmt" 2167 2168 var _ = fmt.Printf 2169 ` 2170 2171 testConfig{ 2172 module: packagestest.Module{ 2173 Name: "foo.com", 2174 Files: fm{ 2175 "pkg/main.go": sibling, 2176 "pkg/uses.go": input, 2177 }, 2178 }, 2179 }.processTest(t, "foo.com", "pkg/uses.go", nil, nil, want) 2180 2181 } 2182 2183 // Tests that an input file's own package is ignored. 2184 func TestIgnoreOwnPackage(t *testing.T) { 2185 const input = `package pkg 2186 2187 const _ = pkg.X 2188 ` 2189 const want = `package pkg 2190 2191 const _ = pkg.X 2192 ` 2193 2194 testConfig{ 2195 module: packagestest.Module{ 2196 Name: "foo.com", 2197 Files: fm{ 2198 "pkg/a.go": "package pkg\nconst X = 1", 2199 "pkg/b.go": input, 2200 }, 2201 }, 2202 }.processTest(t, "foo.com", "pkg/b.go", nil, nil, want) 2203 } 2204 2205 func TestExternalTestImportsPackageUnderTest(t *testing.T) { 2206 const provide = `package pkg 2207 func DoIt(){} 2208 ` 2209 const input = `package pkg_test 2210 2211 var _ = pkg.DoIt` 2212 2213 const want = `package pkg_test 2214 2215 import "foo.com/pkg" 2216 2217 var _ = pkg.DoIt 2218 ` 2219 2220 testConfig{ 2221 module: packagestest.Module{ 2222 Name: "foo.com", 2223 Files: fm{ 2224 "pkg/provide.go": provide, 2225 "pkg/x_test.go": input, 2226 }, 2227 }, 2228 }.processTest(t, "foo.com", "pkg/x_test.go", nil, nil, want) 2229 } 2230 2231 func TestPkgIsCandidate(t *testing.T) { 2232 tests := []struct { 2233 name string 2234 filename string 2235 pkgIdent string 2236 pkg *pkg 2237 want bool 2238 }{ 2239 { 2240 name: "normal_match", 2241 filename: "/gopath/src/my/pkg/pkg.go", 2242 pkgIdent: "client", 2243 pkg: &pkg{ 2244 dir: "/gopath/src/client", 2245 importPathShort: "client", 2246 }, 2247 want: true, 2248 }, 2249 { 2250 name: "no_match", 2251 filename: "/gopath/src/my/pkg/pkg.go", 2252 pkgIdent: "zzz", 2253 pkg: &pkg{ 2254 dir: "/gopath/src/client", 2255 importPathShort: "client", 2256 }, 2257 want: false, 2258 }, 2259 { 2260 name: "match_too_early", 2261 filename: "/gopath/src/my/pkg/pkg.go", 2262 pkgIdent: "client", 2263 pkg: &pkg{ 2264 dir: "/gopath/src/client/foo/foo/foo", 2265 importPathShort: "client/foo/foo", 2266 }, 2267 want: false, 2268 }, 2269 { 2270 name: "substring_match", 2271 filename: "/gopath/src/my/pkg/pkg.go", 2272 pkgIdent: "client", 2273 pkg: &pkg{ 2274 dir: "/gopath/src/foo/go-client", 2275 importPathShort: "foo/go-client", 2276 }, 2277 want: true, 2278 }, 2279 { 2280 name: "hidden_internal", 2281 filename: "/gopath/src/my/pkg/pkg.go", 2282 pkgIdent: "client", 2283 pkg: &pkg{ 2284 dir: "/gopath/src/foo/internal/client", 2285 importPathShort: "foo/internal/client", 2286 }, 2287 want: false, 2288 }, 2289 { 2290 name: "visible_internal", 2291 filename: "/gopath/src/foo/bar.go", 2292 pkgIdent: "client", 2293 pkg: &pkg{ 2294 dir: "/gopath/src/foo/internal/client", 2295 importPathShort: "foo/internal/client", 2296 }, 2297 want: true, 2298 }, 2299 { 2300 name: "invisible_vendor", 2301 filename: "/gopath/src/foo/bar.go", 2302 pkgIdent: "client", 2303 pkg: &pkg{ 2304 dir: "/gopath/src/other/vendor/client", 2305 importPathShort: "client", 2306 }, 2307 want: false, 2308 }, 2309 { 2310 name: "visible_vendor", 2311 filename: "/gopath/src/foo/bar.go", 2312 pkgIdent: "client", 2313 pkg: &pkg{ 2314 dir: "/gopath/src/foo/vendor/client", 2315 importPathShort: "client", 2316 }, 2317 want: true, 2318 }, 2319 { 2320 name: "match_with_hyphens", 2321 filename: "/gopath/src/foo/bar.go", 2322 pkgIdent: "socketio", 2323 pkg: &pkg{ 2324 dir: "/gopath/src/foo/socket-io", 2325 importPathShort: "foo/socket-io", 2326 }, 2327 want: true, 2328 }, 2329 { 2330 name: "match_with_mixed_case", 2331 filename: "/gopath/src/foo/bar.go", 2332 pkgIdent: "fooprod", 2333 pkg: &pkg{ 2334 dir: "/gopath/src/foo/FooPROD", 2335 importPathShort: "foo/FooPROD", 2336 }, 2337 want: true, 2338 }, 2339 { 2340 name: "matches_with_hyphen_and_caps", 2341 filename: "/gopath/src/foo/bar.go", 2342 pkgIdent: "fooprod", 2343 pkg: &pkg{ 2344 dir: "/gopath/src/foo/Foo-PROD", 2345 importPathShort: "foo/Foo-PROD", 2346 }, 2347 want: true, 2348 }, 2349 } 2350 for i, tt := range tests { 2351 t.Run(tt.name, func(t *testing.T) { 2352 refs := references{tt.pkgIdent: nil} 2353 got := pkgIsCandidate(tt.filename, refs, tt.pkg) 2354 if got != tt.want { 2355 t.Errorf("test %d. pkgIsCandidate(%q, %q, %+v) = %v; want %v", 2356 i, tt.filename, tt.pkgIdent, *tt.pkg, got, tt.want) 2357 } 2358 }) 2359 } 2360 } 2361 2362 // Issue 20941: this used to panic on Windows. 2363 func TestProcessStdin(t *testing.T) { 2364 testConfig{ 2365 module: packagestest.Module{ 2366 Name: "foo.com", 2367 }, 2368 }.test(t, func(t *goimportTest) { 2369 got, err := t.processNonModule("<standard input>", []byte("package main\nfunc main() {\n\tfmt.Println(123)\n}\n"), nil) 2370 if err != nil { 2371 t.Fatal(err) 2372 } 2373 if !strings.Contains(string(got), `"fmt"`) { 2374 t.Errorf("expected fmt import; got: %s", got) 2375 } 2376 }) 2377 } 2378 2379 // Tests LocalPackagePromotion when there is a local package that matches, it 2380 // should be the closest match. 2381 // https://golang.org/issues/17557 2382 func TestLocalPackagePromotion(t *testing.T) { 2383 const input = `package main 2384 var c = &config.SystemConfig{} 2385 ` 2386 const want = `package main 2387 2388 import "mycompany.net/tool/config" 2389 2390 var c = &config.SystemConfig{} 2391 ` 2392 2393 testConfig{ 2394 modules: []packagestest.Module{ 2395 { 2396 Name: "config.net/config", 2397 Files: fm{"config.go": "package config\n type SystemConfig struct {}"}, // Will match but should not be first choice 2398 }, 2399 { 2400 Name: "mycompany.net/config", 2401 Files: fm{"config.go": "package config\n type SystemConfig struct {}"}, // Will match but should not be first choice 2402 }, 2403 { 2404 Name: "mycompany.net/tool", 2405 Files: fm{ 2406 "config/config.go": "package config\n type SystemConfig struct {}", // Local package should be promoted over shorter package 2407 "main.go": input, 2408 }, 2409 }, 2410 }, 2411 }.processTest(t, "mycompany.net/tool", "main.go", nil, nil, want) 2412 } 2413 2414 // Tests FindImportInLocalGoFiles looks at the import lines for other Go files in the 2415 // local directory, since the user is likely to import the same packages in the current 2416 // Go file. If an import is found that satisfies the need, it should be used over the 2417 // standard library. 2418 // https://golang.org/issues/17557 2419 func TestFindImportInLocalGoFiles(t *testing.T) { 2420 const input = `package main 2421 var _ = &bytes.Buffer{}` 2422 2423 const want = `package main 2424 2425 import "bytes.net/bytes" 2426 2427 var _ = &bytes.Buffer{} 2428 ` 2429 testConfig{ 2430 modules: []packagestest.Module{ 2431 { 2432 Name: "mycompany.net/tool", 2433 Files: fm{ 2434 "io.go": "package main\n import \"bytes.net/bytes\"\n var _ = &bytes.Buffer{}", // Contains package import that will cause stdlib to be ignored 2435 "main.go": input, 2436 }, 2437 }, 2438 { 2439 Name: "bytes.net/bytes", 2440 Files: fm{"bytes.go": "package bytes\n type Buffer struct {}"}, // Should be selected over standard library 2441 }, 2442 }, 2443 }.processTest(t, "mycompany.net/tool", "main.go", nil, nil, want) 2444 } 2445 2446 func TestInMemoryFile(t *testing.T) { 2447 const input = `package main 2448 var _ = &bytes.Buffer{}` 2449 2450 const want = `package main 2451 2452 import "bytes" 2453 2454 var _ = &bytes.Buffer{} 2455 ` 2456 testConfig{ 2457 module: packagestest.Module{ 2458 Name: "foo.com", 2459 Files: fm{"x.go": "package x\n"}, 2460 }, 2461 }.processTest(t, "foo.com", "x.go", []byte(input), nil, want) 2462 } 2463 2464 func TestImportNoGoFiles(t *testing.T) { 2465 const input = `package main 2466 var _ = &bytes.Buffer{}` 2467 2468 const want = `package main 2469 2470 import "bytes" 2471 2472 var _ = &bytes.Buffer{} 2473 ` 2474 testConfig{ 2475 module: packagestest.Module{ 2476 Name: "mycompany.net", 2477 }, 2478 }.test(t, func(t *goimportTest) { 2479 buf, err := t.processNonModule("mycompany.net/tool/main.go", []byte(input), nil) 2480 if err != nil { 2481 t.Fatalf("Process() = %v", err) 2482 } 2483 if string(buf) != want { 2484 t.Errorf("Got:\n%s\nWant:\n%s", buf, want) 2485 } 2486 }) 2487 2488 } 2489 2490 // Ensures a token as large as 500000 bytes can be handled 2491 // https://golang.org/issues/18201 2492 func TestProcessLargeToken(t *testing.T) { 2493 largeString := strings.Repeat("x", 500000) 2494 2495 input := `package testimports 2496 2497 import ( 2498 "bytes" 2499 ) 2500 2501 const s = fmt.Sprintf("%s", "` + largeString + `") 2502 var _ = bytes.Buffer{} 2503 2504 // end 2505 ` 2506 2507 want := `package testimports 2508 2509 import ( 2510 "bytes" 2511 "fmt" 2512 ) 2513 2514 const s = fmt.Sprintf("%s", "` + largeString + `") 2515 2516 var _ = bytes.Buffer{} 2517 2518 // end 2519 ` 2520 2521 testConfig{ 2522 module: packagestest.Module{ 2523 Name: "foo.com", 2524 Files: fm{"foo.go": input}, 2525 }, 2526 }.processTest(t, "foo.com", "foo.go", nil, nil, want) 2527 } 2528 2529 // Tests that an external test package will import the package under test if it 2530 // also uses symbols exported only in test files. 2531 // https://golang.org/issues/29979 2532 func TestExternalTest(t *testing.T) { 2533 const input = `package a_test 2534 func TestX() { 2535 a.X() 2536 a.Y() 2537 } 2538 ` 2539 const want = `package a_test 2540 2541 import "foo.com/a" 2542 2543 func TestX() { 2544 a.X() 2545 a.Y() 2546 } 2547 ` 2548 2549 testConfig{ 2550 modules: []packagestest.Module{ 2551 { 2552 Name: "foo.com/a", 2553 Files: fm{ 2554 "a.go": "package a\n func X() {}", 2555 "export_test.go": "package a\n func Y() {}", 2556 "a_test.go": input, 2557 }, 2558 }, 2559 }, 2560 }.processTest(t, "foo.com/a", "a_test.go", nil, nil, want) 2561 } 2562 2563 // TestGetCandidates tests that get packages finds packages 2564 // with correct priorities. 2565 func TestGetCandidates(t *testing.T) { 2566 type res struct { 2567 relevance float64 2568 name, path string 2569 } 2570 want := []res{ 2571 {0, "bytes", "bytes"}, 2572 {0, "http", "net/http"}, 2573 {0, "rand", "crypto/rand"}, 2574 {0, "bar", "bar.com/bar"}, 2575 {0, "foo", "foo.com/foo"}, 2576 } 2577 2578 testConfig{ 2579 modules: []packagestest.Module{ 2580 { 2581 Name: "bar.com", 2582 Files: fm{"bar/bar.go": "package bar\n"}, 2583 }, 2584 { 2585 Name: "foo.com", 2586 Files: fm{"foo/foo.go": "package foo\n"}, 2587 }, 2588 }, 2589 }.test(t, func(t *goimportTest) { 2590 var mu sync.Mutex 2591 var got []res 2592 add := func(c ImportFix) { 2593 mu.Lock() 2594 defer mu.Unlock() 2595 for _, w := range want { 2596 if c.StmtInfo.ImportPath == w.path { 2597 got = append(got, res{c.Relevance, c.IdentName, c.StmtInfo.ImportPath}) 2598 } 2599 } 2600 } 2601 if err := GetAllCandidates(context.Background(), add, "", "x.go", "x", t.env); err != nil { 2602 t.Fatalf("GetAllCandidates() = %v", err) 2603 } 2604 // Sort, then clear out relevance so it doesn't mess up the DeepEqual. 2605 sort.Slice(got, func(i, j int) bool { 2606 ri, rj := got[i], got[j] 2607 if ri.relevance != rj.relevance { 2608 return ri.relevance > rj.relevance // Highest first. 2609 } 2610 return ri.name < rj.name 2611 }) 2612 for i := range got { 2613 got[i].relevance = 0 2614 } 2615 if !reflect.DeepEqual(want, got) { 2616 t.Errorf("wanted results in order %v, got %v", want, got) 2617 } 2618 }) 2619 } 2620 2621 func TestGetImportPaths(t *testing.T) { 2622 type res struct { 2623 relevance float64 2624 name, path string 2625 } 2626 want := []res{ 2627 {0, "http", "net/http"}, 2628 {0, "net", "net"}, 2629 {0, "neta", "neta.com/neta"}, 2630 } 2631 2632 testConfig{ 2633 modules: []packagestest.Module{ 2634 { 2635 Name: "neta.com", 2636 Files: fm{"neta/neta.go": "package neta\n"}, 2637 }, 2638 }, 2639 }.test(t, func(t *goimportTest) { 2640 var mu sync.Mutex 2641 var got []res 2642 add := func(c ImportFix) { 2643 mu.Lock() 2644 defer mu.Unlock() 2645 for _, w := range want { 2646 if c.StmtInfo.ImportPath == w.path { 2647 got = append(got, res{c.Relevance, c.IdentName, c.StmtInfo.ImportPath}) 2648 } 2649 } 2650 } 2651 if err := GetImportPaths(context.Background(), add, "ne", "x.go", "x", t.env); err != nil { 2652 t.Fatalf("GetImportPaths() = %v", err) 2653 } 2654 // Sort, then clear out relevance so it doesn't mess up the DeepEqual. 2655 sort.Slice(got, func(i, j int) bool { 2656 ri, rj := got[i], got[j] 2657 if ri.relevance != rj.relevance { 2658 return ri.relevance > rj.relevance // Highest first. 2659 } 2660 return ri.name < rj.name 2661 }) 2662 for i := range got { 2663 got[i].relevance = 0 2664 } 2665 if !reflect.DeepEqual(want, got) { 2666 t.Errorf("wanted results in order %v, got %v", want, got) 2667 } 2668 }) 2669 } 2670 2671 func TestGetPackageCompletions(t *testing.T) { 2672 type res struct { 2673 relevance float64 2674 name, path, symbol string 2675 } 2676 want := []res{ 2677 {0, "rand", "math/rand", "Seed"}, 2678 {0, "rand", "bar.com/rand", "Bar"}, 2679 } 2680 2681 testConfig{ 2682 modules: []packagestest.Module{ 2683 { 2684 Name: "bar.com", 2685 Files: fm{"rand/bar.go": "package rand\nvar Bar int\n"}, 2686 }, 2687 }, 2688 }.test(t, func(t *goimportTest) { 2689 var mu sync.Mutex 2690 var got []res 2691 add := func(c PackageExport) { 2692 mu.Lock() 2693 defer mu.Unlock() 2694 for _, csym := range c.Exports { 2695 for _, w := range want { 2696 if c.Fix.StmtInfo.ImportPath == w.path && csym == w.symbol { 2697 got = append(got, res{c.Fix.Relevance, c.Fix.IdentName, c.Fix.StmtInfo.ImportPath, csym}) 2698 } 2699 } 2700 } 2701 } 2702 if err := GetPackageExports(context.Background(), add, "rand", "x.go", "x", t.env); err != nil { 2703 t.Fatalf("getPackageCompletions() = %v", err) 2704 } 2705 // Sort, then clear out relevance so it doesn't mess up the DeepEqual. 2706 sort.Slice(got, func(i, j int) bool { 2707 ri, rj := got[i], got[j] 2708 if ri.relevance != rj.relevance { 2709 return ri.relevance > rj.relevance // Highest first. 2710 } 2711 return ri.name < rj.name 2712 }) 2713 for i := range got { 2714 got[i].relevance = 0 2715 } 2716 if !reflect.DeepEqual(want, got) { 2717 t.Errorf("wanted results in order %v, got %v", want, got) 2718 } 2719 }) 2720 } 2721 2722 // Tests #34895: process should not panic on concurrent calls. 2723 func TestConcurrentProcess(t *testing.T) { 2724 testConfig{ 2725 module: packagestest.Module{ 2726 Name: "foo.com", 2727 Files: fm{ 2728 "p/first.go": `package foo 2729 2730 func _() { 2731 fmt.Println() 2732 } 2733 `, 2734 "p/second.go": `package foo 2735 2736 import "fmt" 2737 2738 func _() { 2739 fmt.Println() 2740 imports.Bar() // not imported. 2741 } 2742 `, 2743 }, 2744 }, 2745 }.test(t, func(t *goimportTest) { 2746 var ( 2747 n = 10 2748 wg sync.WaitGroup 2749 ) 2750 wg.Add(n) 2751 for i := 0; i < n; i++ { 2752 go func() { 2753 defer wg.Done() 2754 _, err := t.process("foo.com", "p/first.go", nil, nil) 2755 if err != nil { 2756 t.Error(err) 2757 } 2758 }() 2759 } 2760 wg.Wait() 2761 }) 2762 } 2763 2764 func TestNonlocalDot(t *testing.T) { 2765 const input = `package main 2766 import ( 2767 "fmt" 2768 ) 2769 var _, _ = fmt.Sprintf, dot.Dot 2770 ` 2771 const want = `package main 2772 2773 import ( 2774 "fmt" 2775 "noninternet/dot.v1/dot" 2776 ) 2777 2778 var _, _ = fmt.Sprintf, dot.Dot 2779 ` 2780 testConfig{ 2781 modules: []packagestest.Module{ 2782 { 2783 Name: "golang.org/fake", 2784 Files: fm{"x.go": input}, 2785 }, 2786 { 2787 Name: "noninternet/dot.v1", 2788 Files: fm{ 2789 "dot/dot.go": "package dot\nfunc Dot(){}\n", 2790 }, 2791 }, 2792 }, 2793 gopathOnly: true, // our modules testing setup doesn't allow modules without dots. 2794 }.processTest(t, "golang.org/fake", "x.go", nil, nil, want) 2795 }