// Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package fstest import ( "errors" "internal/testenv" "io/fs" "os" "path/filepath" "sort" "testing" ) func TestSymlink(t *testing.T) { testenv.MustHaveSymlink(t) tmp := t.TempDir() tmpfs := os.DirFS(tmp) if err := os.WriteFile(filepath.Join(tmp, "hello"), []byte("hello, world\n"), 0644); err != nil { t.Fatal(err) } if err := os.Symlink(filepath.Join(tmp, "hello"), filepath.Join(tmp, "hello.link")); err != nil { t.Fatal(err) } if err := TestFS(tmpfs, "hello", "hello.link"); err != nil { t.Fatal(err) } } func TestDash(t *testing.T) { m := MapFS{ "a-b/a": {Data: []byte("a-b/a")}, } if err := TestFS(m, "a-b/a"); err != nil { t.Error(err) } } type shuffledFS MapFS func (fsys shuffledFS) Open(name string) (fs.File, error) { f, err := MapFS(fsys).Open(name) if err != nil { return nil, err } return &shuffledFile{File: f}, nil } type shuffledFile struct{ fs.File } func (f *shuffledFile) ReadDir(n int) ([]fs.DirEntry, error) { dirents, err := f.File.(fs.ReadDirFile).ReadDir(n) // Shuffle in a deterministic way, all we care about is making sure that the // list of directory entries is not is the lexicographic order. // // We do this to make sure that the TestFS test suite is not affected by the // order of directory entries. sort.Slice(dirents, func(i, j int) bool { return dirents[i].Name() > dirents[j].Name() }) return dirents, err } func TestShuffledFS(t *testing.T) { fsys := shuffledFS{ "tmp/one": {Data: []byte("1")}, "tmp/two": {Data: []byte("2")}, "tmp/three": {Data: []byte("3")}, } if err := TestFS(fsys, "tmp/one", "tmp/two", "tmp/three"); err != nil { t.Error(err) } } // failPermFS is a filesystem that always fails with fs.ErrPermission. type failPermFS struct{} func (f failPermFS) Open(name string) (fs.File, error) { if !fs.ValidPath(name) { return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrInvalid} } return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrPermission} } func TestTestFSWrappedErrors(t *testing.T) { err := TestFS(failPermFS{}) if err == nil { t.Fatal("error expected") } t.Logf("Error (expecting wrapped fs.ErrPermission):\n%v", err) if !errors.Is(err, fs.ErrPermission) { t.Errorf("error should be a wrapped ErrPermission: %#v", err) } // TestFS is expected to return a list of errors. // Enforce that the list can be extracted for browsing. var errs interface{ Unwrap() []error } if !errors.As(err, &errs) { t.Errorf("caller should be able to extract the errors as a list: %#v", err) } else { for _, err := range errs.Unwrap() { // ErrPermission is expected // but any other error must be reported. if !errors.Is(err, fs.ErrPermission) { t.Errorf("unexpected error: %v", err) } } } }