Source file src/testing/fstest/testfs_test.go

     1  // Copyright 2021 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 fstest
     6  
     7  import (
     8  	"errors"
     9  	"internal/testenv"
    10  	"io/fs"
    11  	"os"
    12  	"path/filepath"
    13  	"slices"
    14  	"strings"
    15  	"testing"
    16  )
    17  
    18  func TestSymlink(t *testing.T) {
    19  	testenv.MustHaveSymlink(t)
    20  
    21  	tmp := t.TempDir()
    22  	tmpfs := os.DirFS(tmp)
    23  
    24  	if err := os.WriteFile(filepath.Join(tmp, "hello"), []byte("hello, world\n"), 0644); err != nil {
    25  		t.Fatal(err)
    26  	}
    27  
    28  	if err := os.Symlink(filepath.Join(tmp, "hello"), filepath.Join(tmp, "hello.link")); err != nil {
    29  		t.Fatal(err)
    30  	}
    31  	if err := os.Symlink("hello", filepath.Join(tmp, "hello_rel.link")); err != nil {
    32  		t.Fatal(err)
    33  	}
    34  
    35  	if err := TestFS(tmpfs, "hello", "hello.link"); err != nil {
    36  		t.Fatal(err)
    37  	}
    38  }
    39  
    40  func TestDash(t *testing.T) {
    41  	m := MapFS{
    42  		"a-b/a": {Data: []byte("a-b/a")},
    43  	}
    44  	if err := TestFS(m, "a-b/a"); err != nil {
    45  		t.Error(err)
    46  	}
    47  }
    48  
    49  type shuffledFS MapFS
    50  
    51  func (fsys shuffledFS) Open(name string) (fs.File, error) {
    52  	f, err := MapFS(fsys).Open(name)
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  	return &shuffledFile{File: f}, nil
    57  }
    58  
    59  type shuffledFile struct{ fs.File }
    60  
    61  func (f *shuffledFile) ReadDir(n int) ([]fs.DirEntry, error) {
    62  	dirents, err := f.File.(fs.ReadDirFile).ReadDir(n)
    63  	// Shuffle in a deterministic way, all we care about is making sure that the
    64  	// list of directory entries is not is the lexicographic order.
    65  	//
    66  	// We do this to make sure that the TestFS test suite is not affected by the
    67  	// order of directory entries.
    68  	slices.SortFunc(dirents, func(a, b fs.DirEntry) int {
    69  		return strings.Compare(b.Name(), a.Name())
    70  	})
    71  	return dirents, err
    72  }
    73  
    74  func TestShuffledFS(t *testing.T) {
    75  	fsys := shuffledFS{
    76  		"tmp/one":   {Data: []byte("1")},
    77  		"tmp/two":   {Data: []byte("2")},
    78  		"tmp/three": {Data: []byte("3")},
    79  	}
    80  	if err := TestFS(fsys, "tmp/one", "tmp/two", "tmp/three"); err != nil {
    81  		t.Error(err)
    82  	}
    83  }
    84  
    85  // failPermFS is a filesystem that always fails with fs.ErrPermission.
    86  type failPermFS struct{}
    87  
    88  func (f failPermFS) Open(name string) (fs.File, error) {
    89  	if !fs.ValidPath(name) {
    90  		return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrInvalid}
    91  	}
    92  	return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrPermission}
    93  }
    94  
    95  func TestTestFSWrappedErrors(t *testing.T) {
    96  	err := TestFS(failPermFS{})
    97  	if err == nil {
    98  		t.Fatal("error expected")
    99  	}
   100  	t.Logf("Error (expecting wrapped fs.ErrPermission):\n%v", err)
   101  
   102  	if !errors.Is(err, fs.ErrPermission) {
   103  		t.Errorf("error should be a wrapped ErrPermission: %#v", err)
   104  	}
   105  
   106  	// TestFS is expected to return a list of errors.
   107  	// Enforce that the list can be extracted for browsing.
   108  	var errs interface{ Unwrap() []error }
   109  	if !errors.As(err, &errs) {
   110  		t.Errorf("caller should be able to extract the errors as a list: %#v", err)
   111  	} else {
   112  		for _, err := range errs.Unwrap() {
   113  			// ErrPermission is expected
   114  			// but any other error must be reported.
   115  			if !errors.Is(err, fs.ErrPermission) {
   116  				t.Errorf("unexpected error: %v", err)
   117  			}
   118  		}
   119  	}
   120  }
   121  

View as plain text