// Copyright 2017 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 vfs import ( "bytes" "errors" "fmt" "os" "path/filepath" "testing" "time" ) type fakeFileInfo struct { dir bool link bool basename string modtime time.Time ents []*fakeFileInfo contents string err error } func (f *fakeFileInfo) Name() string { return f.basename } func (f *fakeFileInfo) Sys() interface{} { return nil } func (f *fakeFileInfo) ModTime() time.Time { return f.modtime } func (f *fakeFileInfo) IsDir() bool { return f.dir } func (f *fakeFileInfo) Size() int64 { return int64(len(f.contents)) } func (f *fakeFileInfo) Mode() os.FileMode { if f.dir { return 0755 | os.ModeDir } if f.link { return 0644 | os.ModeSymlink } return 0644 } func TestOSReadDirFollowsSymLinks(t *testing.T) { // Stat is called on ReadDir output by osFS oldstat := stat stat = func(path string) (os.FileInfo, error) { if filepath.ToSlash(path) != "/tmp/subdir/is_link" { t.Fatalf("stat called on unexpected path %q", path) } return &fakeFileInfo{ link: false, basename: "foo", }, nil } defer func() { stat = oldstat }() oldreaddir := readdir readdir = func(path string) ([]os.FileInfo, error) { return []os.FileInfo{ &fakeFileInfo{ link: true, basename: "is_link", }, &fakeFileInfo{ link: false, basename: "not_link", }, }, nil } defer func() { readdir = oldreaddir }() fs := OS("/tmp") result, err := fs.ReadDir("subdir") if err != nil { t.Fatal(err) } var gotBuf bytes.Buffer for i, fi := range result { fmt.Fprintf(&gotBuf, "result[%d] = %v, %v\n", i, fi.Name(), fi.Mode()) } got := gotBuf.String() want := `result[0] = foo, -rw-r--r-- result[1] = not_link, -rw-r--r-- ` if got != want { t.Errorf("ReadDir got:\n%s\n\nwant:\n%s\n", got, want) } } func TestOSReadDirHandlesReadDirErrors(t *testing.T) { oldreaddir := readdir readdir = func(path string) ([]os.FileInfo, error) { return []os.FileInfo{ &fakeFileInfo{ dir: false, basename: "foo", }, }, errors.New("some arbitrary filesystem failure") } defer func() { readdir = oldreaddir }() fs := OS("/tmp") _, err := fs.ReadDir("subdir") if got, want := fmt.Sprint(err), "some arbitrary filesystem failure"; got != want { t.Errorf("ReadDir = %v; want %q", got, want) } }