github.com/v2fly/tools@v0.100.0/internal/lsp/fake/workdir_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 5 package fake 6 7 import ( 8 "context" 9 "io/ioutil" 10 "os" 11 "sort" 12 "testing" 13 "time" 14 15 "github.com/v2fly/tools/internal/lsp/protocol" 16 ) 17 18 const data = ` 19 -- go.mod -- 20 go 1.12 21 -- nested/README.md -- 22 Hello World! 23 ` 24 25 func newWorkdir(t *testing.T) (*Workdir, <-chan []FileEvent, func()) { 26 t.Helper() 27 28 tmpdir, err := ioutil.TempDir("", "goplstest-workdir-") 29 if err != nil { 30 t.Fatal(err) 31 } 32 wd := NewWorkdir(tmpdir) 33 if err := wd.writeInitialFiles(data); err != nil { 34 t.Fatal(err) 35 } 36 cleanup := func() { 37 if err := os.RemoveAll(tmpdir); err != nil { 38 t.Error(err) 39 } 40 } 41 42 fileEvents := make(chan []FileEvent) 43 watch := func(_ context.Context, events []FileEvent) { 44 go func() { 45 fileEvents <- events 46 }() 47 } 48 wd.AddWatcher(watch) 49 return wd, fileEvents, cleanup 50 } 51 52 func TestWorkdir_ReadFile(t *testing.T) { 53 wd, _, cleanup := newWorkdir(t) 54 defer cleanup() 55 56 got, err := wd.ReadFile("nested/README.md") 57 if err != nil { 58 t.Fatal(err) 59 } 60 want := "Hello World!\n" 61 if got != want { 62 t.Errorf("reading workdir file, got %q, want %q", got, want) 63 } 64 } 65 66 func TestWorkdir_WriteFile(t *testing.T) { 67 wd, events, cleanup := newWorkdir(t) 68 defer cleanup() 69 ctx := context.Background() 70 71 tests := []struct { 72 path string 73 wantType protocol.FileChangeType 74 }{ 75 {"data.txt", protocol.Created}, 76 {"nested/README.md", protocol.Changed}, 77 } 78 79 for _, test := range tests { 80 if err := wd.WriteFile(ctx, test.path, "42"); err != nil { 81 t.Fatal(err) 82 } 83 es := <-events 84 if got := len(es); got != 1 { 85 t.Fatalf("len(events) = %d, want 1", got) 86 } 87 if es[0].Path != test.path { 88 t.Errorf("event.Path = %q, want %q", es[0].Path, test.path) 89 } 90 if es[0].ProtocolEvent.Type != test.wantType { 91 t.Errorf("event type = %v, want %v", es[0].ProtocolEvent.Type, test.wantType) 92 } 93 got, err := wd.ReadFile(test.path) 94 if err != nil { 95 t.Fatal(err) 96 } 97 want := "42" 98 if got != want { 99 t.Errorf("ws.ReadFile(%q) = %q, want %q", test.path, got, want) 100 } 101 } 102 } 103 104 func TestWorkdir_ListFiles(t *testing.T) { 105 wd, _, cleanup := newWorkdir(t) 106 defer cleanup() 107 108 checkFiles := func(dir string, want []string) { 109 files, err := wd.listFiles(dir) 110 if err != nil { 111 t.Fatal(err) 112 } 113 sort.Strings(want) 114 var got []string 115 for p := range files { 116 got = append(got, p) 117 } 118 sort.Strings(got) 119 if len(got) != len(want) { 120 t.Fatalf("ListFiles(): len = %d, want %d; got=%v; want=%v", len(got), len(want), got, want) 121 } 122 for i, f := range got { 123 if f != want[i] { 124 t.Errorf("ListFiles()[%d] = %s, want %s", i, f, want[i]) 125 } 126 } 127 } 128 129 checkFiles(".", []string{"go.mod", "nested/README.md"}) 130 checkFiles("nested", []string{"nested/README.md"}) 131 } 132 133 func TestWorkdir_CheckForFileChanges(t *testing.T) { 134 t.Skip("broken on darwin-amd64-10_12") 135 wd, events, cleanup := newWorkdir(t) 136 defer cleanup() 137 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 138 defer cancel() 139 140 checkChange := func(path string, typ protocol.FileChangeType) { 141 if err := wd.CheckForFileChanges(ctx); err != nil { 142 t.Fatal(err) 143 } 144 var gotEvt FileEvent 145 select { 146 case <-ctx.Done(): 147 t.Fatal(ctx.Err()) 148 case ev := <-events: 149 gotEvt = ev[0] 150 } 151 // Only check relative path and Type 152 if gotEvt.Path != path || gotEvt.ProtocolEvent.Type != typ { 153 t.Errorf("file events: got %v, want {Path: %s, Type: %v}", gotEvt, path, typ) 154 } 155 } 156 // Sleep some positive amount of time to ensure a distinct mtime. 157 time.Sleep(100 * time.Millisecond) 158 if err := WriteFileData("go.mod", []byte("module foo.test\n"), wd.RelativeTo); err != nil { 159 t.Fatal(err) 160 } 161 checkChange("go.mod", protocol.Changed) 162 if err := WriteFileData("newFile", []byte("something"), wd.RelativeTo); err != nil { 163 t.Fatal(err) 164 } 165 checkChange("newFile", protocol.Created) 166 fp := wd.AbsPath("newFile") 167 if err := os.Remove(fp); err != nil { 168 t.Fatal(err) 169 } 170 checkChange("newFile", protocol.Deleted) 171 } 172 173 func TestSplitModuleVersionPath(t *testing.T) { 174 tests := []struct { 175 path string 176 wantModule, wantVersion, wantSuffix string 177 }{ 178 {"foo.com@v1.2.3/bar", "foo.com", "v1.2.3", "bar"}, 179 {"foo.com/module@v1.2.3/bar", "foo.com/module", "v1.2.3", "bar"}, 180 {"foo.com@v1.2.3", "foo.com", "v1.2.3", ""}, 181 {"std@v1.14.0", "std", "v1.14.0", ""}, 182 {"another/module/path", "another/module/path", "", ""}, 183 } 184 185 for _, test := range tests { 186 module, version, suffix := splitModuleVersionPath(test.path) 187 if module != test.wantModule || version != test.wantVersion || suffix != test.wantSuffix { 188 t.Errorf("splitModuleVersionPath(%q) =\n\t(%q, %q, %q)\nwant\n\t(%q, %q, %q)", 189 test.path, module, version, suffix, test.wantModule, test.wantVersion, test.wantSuffix) 190 } 191 } 192 }