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