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  }