1// Copyright 2020 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. 4package cache 5 6import ( 7 "context" 8 "io/ioutil" 9 "os" 10 "path/filepath" 11 "testing" 12 13 "golang.org/x/tools/internal/lsp/fake" 14 "golang.org/x/tools/internal/lsp/source" 15 "golang.org/x/tools/internal/span" 16) 17 18func TestCaseInsensitiveFilesystem(t *testing.T) { 19 base, err := ioutil.TempDir("", t.Name()) 20 if err != nil { 21 t.Fatal(err) 22 } 23 24 inner := filepath.Join(base, "a/B/c/DEFgh") 25 if err := os.MkdirAll(inner, 0777); err != nil { 26 t.Fatal(err) 27 } 28 file := filepath.Join(inner, "f.go") 29 if err := ioutil.WriteFile(file, []byte("hi"), 0777); err != nil { 30 t.Fatal(err) 31 } 32 if _, err := os.Stat(filepath.Join(inner, "F.go")); err != nil { 33 t.Skip("filesystem is case-sensitive") 34 } 35 36 tests := []struct { 37 path string 38 err bool 39 }{ 40 {file, false}, 41 {filepath.Join(inner, "F.go"), true}, 42 {filepath.Join(base, "a/b/c/defgh/f.go"), true}, 43 } 44 for _, tt := range tests { 45 err := checkPathCase(tt.path) 46 if err != nil != tt.err { 47 t.Errorf("checkPathCase(%q) = %v, wanted error: %v", tt.path, err, tt.err) 48 } 49 } 50} 51 52func TestFindWorkspaceRoot(t *testing.T) { 53 workspace := ` 54-- a/go.mod -- 55module a 56-- a/x/x.go 57package x 58-- b/go.mod -- 59module b 60-- b/c/go.mod -- 61module bc 62-- d/gopls.mod -- 63module d-goplsworkspace 64-- d/e/go.mod -- 65module de 66-- f/g/go.mod -- 67module fg 68` 69 dir, err := fake.Tempdir(fake.UnpackTxt(workspace)) 70 if err != nil { 71 t.Fatal(err) 72 } 73 defer os.RemoveAll(dir) 74 75 tests := []struct { 76 folder, want string 77 experimental bool 78 }{ 79 {"", "", false}, // no module at root, and more than one nested module 80 {"a", "a", false}, 81 {"a/x", "a", false}, 82 {"b/c", "b/c", false}, 83 {"d", "d/e", false}, 84 {"d", "d", true}, 85 {"d/e", "d/e", false}, 86 {"d/e", "d", true}, 87 {"f", "f/g", false}, 88 {"f", "f", true}, 89 } 90 91 for _, test := range tests { 92 ctx := context.Background() 93 rel := fake.RelativeTo(dir) 94 folderURI := span.URIFromPath(rel.AbsPath(test.folder)) 95 excludeNothing := func(string) bool { return false } 96 got, err := findWorkspaceRoot(ctx, folderURI, &osFileSource{}, excludeNothing, test.experimental) 97 if err != nil { 98 t.Fatal(err) 99 } 100 if gotf, wantf := filepath.Clean(got.Filename()), rel.AbsPath(test.want); gotf != wantf { 101 t.Errorf("findWorkspaceRoot(%q, %t) = %q, want %q", test.folder, test.experimental, gotf, wantf) 102 } 103 } 104} 105 106func TestInVendor(t *testing.T) { 107 for _, tt := range []struct { 108 path string 109 inVendor bool 110 }{ 111 { 112 path: "foo/vendor/x.go", 113 inVendor: false, 114 }, 115 { 116 path: "foo/vendor/x/x.go", 117 inVendor: true, 118 }, 119 { 120 path: "foo/x.go", 121 inVendor: false, 122 }, 123 } { 124 if got := inVendor(span.URIFromPath(tt.path)); got != tt.inVendor { 125 t.Errorf("expected %s inVendor %v, got %v", tt.path, tt.inVendor, got) 126 } 127 } 128} 129 130func TestFilters(t *testing.T) { 131 tests := []struct { 132 filters []string 133 included []string 134 excluded []string 135 }{ 136 { 137 included: []string{"x"}, 138 }, 139 { 140 filters: []string{"-"}, 141 excluded: []string{"x", "x/a"}, 142 }, 143 { 144 filters: []string{"-x", "+y"}, 145 included: []string{"y", "y/a", "z"}, 146 excluded: []string{"x", "x/a"}, 147 }, 148 { 149 filters: []string{"-x", "+x/y", "-x/y/z"}, 150 included: []string{"x/y", "x/y/a", "a"}, 151 excluded: []string{"x", "x/a", "x/y/z/a"}, 152 }, 153 { 154 filters: []string{"+foobar", "-foo"}, 155 included: []string{"foobar", "foobar/a"}, 156 excluded: []string{"foo", "foo/a"}, 157 }, 158 } 159 160 for _, tt := range tests { 161 opts := &source.Options{} 162 opts.DirectoryFilters = tt.filters 163 for _, inc := range tt.included { 164 if pathExcludedByFilter(inc, opts) { 165 t.Errorf("filters %q excluded %v, wanted included", tt.filters, inc) 166 } 167 } 168 for _, exc := range tt.excluded { 169 if !pathExcludedByFilter(exc, opts) { 170 t.Errorf("filters %q included %v, wanted excluded", tt.filters, exc) 171 } 172 } 173 } 174} 175