golang.org/x/tools/gopls@v0.15.3/internal/cache/filemap_test.go (about)

     1  // Copyright 2023 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 cache
     6  
     7  import (
     8  	"path/filepath"
     9  	"sort"
    10  	"testing"
    11  
    12  	"github.com/google/go-cmp/cmp"
    13  	"golang.org/x/tools/gopls/internal/file"
    14  	"golang.org/x/tools/gopls/internal/protocol"
    15  )
    16  
    17  func TestFileMap(t *testing.T) {
    18  	const (
    19  		set = iota
    20  		del
    21  	)
    22  	type op struct {
    23  		op      int // set or remove
    24  		path    string
    25  		overlay bool
    26  	}
    27  	tests := []struct {
    28  		label        string
    29  		ops          []op
    30  		wantFiles    []string
    31  		wantOverlays []string
    32  		wantDirs     []string
    33  	}{
    34  		{"empty", nil, nil, nil, nil},
    35  		{"singleton", []op{
    36  			{set, "/a/b", false},
    37  		}, []string{"/a/b"}, nil, []string{"/", "/a"}},
    38  		{"overlay", []op{
    39  			{set, "/a/b", true},
    40  		}, []string{"/a/b"}, []string{"/a/b"}, []string{"/", "/a"}},
    41  		{"replace overlay", []op{
    42  			{set, "/a/b", true},
    43  			{set, "/a/b", false},
    44  		}, []string{"/a/b"}, nil, []string{"/", "/a"}},
    45  		{"multi dir", []op{
    46  			{set, "/a/b", false},
    47  			{set, "/c/d", false},
    48  		}, []string{"/a/b", "/c/d"}, nil, []string{"/", "/a", "/c"}},
    49  		{"empty dir", []op{
    50  			{set, "/a/b", false},
    51  			{set, "/c/d", false},
    52  			{del, "/a/b", false},
    53  		}, []string{"/c/d"}, nil, []string{"/", "/c"}},
    54  	}
    55  
    56  	// Normalize paths for windows compatibility.
    57  	normalize := func(path string) string {
    58  		y := filepath.ToSlash(path)
    59  		// Windows paths may start with a drive letter
    60  		if len(y) > 2 && y[1] == ':' && y[0] >= 'A' && y[0] <= 'Z' {
    61  			y = y[2:]
    62  		}
    63  		return y
    64  	}
    65  
    66  	for _, test := range tests {
    67  		t.Run(test.label, func(t *testing.T) {
    68  			m := newFileMap()
    69  			for _, op := range test.ops {
    70  				uri := protocol.URIFromPath(filepath.FromSlash(op.path))
    71  				switch op.op {
    72  				case set:
    73  					var fh file.Handle
    74  					if op.overlay {
    75  						fh = &overlay{uri: uri}
    76  					} else {
    77  						fh = &diskFile{uri: uri}
    78  					}
    79  					m.set(uri, fh)
    80  				case del:
    81  					m.delete(uri)
    82  				}
    83  			}
    84  
    85  			var gotFiles []string
    86  			m.foreach(func(uri protocol.DocumentURI, _ file.Handle) {
    87  				gotFiles = append(gotFiles, normalize(uri.Path()))
    88  			})
    89  			sort.Strings(gotFiles)
    90  			if diff := cmp.Diff(test.wantFiles, gotFiles); diff != "" {
    91  				t.Errorf("Files mismatch (-want +got):\n%s", diff)
    92  			}
    93  
    94  			var gotOverlays []string
    95  			for _, o := range m.getOverlays() {
    96  				gotOverlays = append(gotOverlays, normalize(o.URI().Path()))
    97  			}
    98  			if diff := cmp.Diff(test.wantOverlays, gotOverlays); diff != "" {
    99  				t.Errorf("Overlays mismatch (-want +got):\n%s", diff)
   100  			}
   101  
   102  			var gotDirs []string
   103  			m.getDirs().Range(func(dir string) {
   104  				gotDirs = append(gotDirs, normalize(dir))
   105  			})
   106  			sort.Strings(gotDirs)
   107  			if diff := cmp.Diff(test.wantDirs, gotDirs); diff != "" {
   108  				t.Errorf("Dirs mismatch (-want +got):\n%s", diff)
   109  			}
   110  		})
   111  	}
   112  }