github.com/jhump/golang-x-tools@v0.0.0-20220218190644-4958d6d39439/internal/lsp/cache/view_test.go (about)

     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.
     4  package cache
     5  
     6  import (
     7  	"context"
     8  	"io/ioutil"
     9  	"os"
    10  	"path/filepath"
    11  	"testing"
    12  
    13  	"github.com/jhump/golang-x-tools/internal/lsp/fake"
    14  	"github.com/jhump/golang-x-tools/internal/lsp/source"
    15  	"github.com/jhump/golang-x-tools/internal/span"
    16  )
    17  
    18  func 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  
    52  func TestFindWorkspaceRoot(t *testing.T) {
    53  	workspace := `
    54  -- a/go.mod --
    55  module a
    56  -- a/x/x.go
    57  package x
    58  -- b/go.mod --
    59  module b
    60  -- b/c/go.mod --
    61  module bc
    62  -- d/gopls.mod --
    63  module d-goplsworkspace
    64  -- d/e/go.mod --
    65  module de
    66  -- f/g/go.mod --
    67  module 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  
   106  func 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  
   130  func 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, "root", "root/gopath/pkg/mod", 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, "root", "root/gopath/pkg/mod", opts) {
   170  				t.Errorf("filters %q included %v, wanted excluded", tt.filters, exc)
   171  			}
   172  		}
   173  	}
   174  }
   175  
   176  func TestSuffixes(t *testing.T) {
   177  	type file struct {
   178  		path string
   179  		want bool
   180  	}
   181  	type cases struct {
   182  		option []string
   183  		files  []file
   184  	}
   185  	tests := []cases{
   186  		{[]string{"tmpl", "gotmpl"}, []file{ // default
   187  			{"foo", false},
   188  			{"foo.tmpl", true},
   189  			{"foo.gotmpl", true},
   190  			{"tmpl", false},
   191  			{"tmpl.go", false}},
   192  		},
   193  		{[]string{"tmpl", "gotmpl", "html", "gohtml"}, []file{
   194  			{"foo.gotmpl", true},
   195  			{"foo.html", true},
   196  			{"foo.gohtml", true},
   197  			{"html", false}},
   198  		},
   199  		{[]string{"tmpl", "gotmpl", ""}, []file{ // possible user mistake
   200  			{"foo.gotmpl", true},
   201  			{"foo.go", false},
   202  			{"foo", false}},
   203  		},
   204  	}
   205  	for _, a := range tests {
   206  		suffixes := a.option
   207  		for _, b := range a.files {
   208  			got := fileHasExtension(b.path, suffixes)
   209  			if got != b.want {
   210  				t.Errorf("got %v, want %v, option %q, file %q (%+v)",
   211  					got, b.want, a.option, b.path, b)
   212  			}
   213  		}
   214  	}
   215  }