Removed unused methods from fs package

The fs package tests are going to be a lot of work to get working without the internal test package used by golang/dep, so I removed all of the unused ones by this project to make the work easier.

Signed-off-by: Brice Rising <brice.rising@slalom.com>
pull/6738/head
Brice Rising 7 years ago committed by Yagnesh Mistry
parent 94d87ef95d
commit 51dbd7c1a6

@ -10,149 +10,11 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings"
"syscall" "syscall"
"unicode"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
// HasFilepathPrefix will determine if "path" starts with "prefix" from
// the point of view of a filesystem.
//
// Unlike filepath.HasPrefix, this function is path-aware, meaning that
// it knows that two directories /foo and /foobar are not the same
// thing, and therefore HasFilepathPrefix("/foobar", "/foo") will return
// false.
//
// This function also handles the case where the involved filesystems
// are case-insensitive, meaning /foo/bar and /Foo/Bar correspond to the
// same file. In that situation HasFilepathPrefix("/Foo/Bar", "/foo")
// will return true. The implementation is *not* OS-specific, so a FAT32
// filesystem mounted on Linux will be handled correctly.
func HasFilepathPrefix(path, prefix string) (bool, error) {
// this function is more convoluted then ideal due to need for special
// handling of volume name/drive letter on Windows. vnPath and vnPrefix
// are first compared, and then used to initialize initial values of p and
// d which will be appended to for incremental checks using
// IsCaseSensitiveFilesystem and then equality.
// no need to check IsCaseSensitiveFilesystem because VolumeName return
// empty string on all non-Windows machines
vnPath := strings.ToLower(filepath.VolumeName(path))
vnPrefix := strings.ToLower(filepath.VolumeName(prefix))
if vnPath != vnPrefix {
return false, nil
}
// Because filepath.Join("c:","dir") returns "c:dir", we have to manually
// add path separator to drive letters. Also, we need to set the path root
// on *nix systems, since filepath.Join("", "dir") returns a relative path.
vnPath += string(os.PathSeparator)
vnPrefix += string(os.PathSeparator)
var dn string
if isDir, err := IsDir(path); err != nil {
return false, errors.Wrap(err, "failed to check filepath prefix")
} else if isDir {
dn = path
} else {
dn = filepath.Dir(path)
}
dn = filepath.Clean(dn)
prefix = filepath.Clean(prefix)
// [1:] in the lines below eliminates empty string on *nix and volume name on Windows
dirs := strings.Split(dn, string(os.PathSeparator))[1:]
prefixes := strings.Split(prefix, string(os.PathSeparator))[1:]
if len(prefixes) > len(dirs) {
return false, nil
}
// d,p are initialized with "/" on *nix and volume name on Windows
d := vnPath
p := vnPrefix
for i := range prefixes {
// need to test each component of the path for
// case-sensitiveness because on Unix we could have
// something like ext4 filesystem mounted on FAT
// mountpoint, mounted on ext4 filesystem, i.e. the
// problematic filesystem is not the last one.
caseSensitive, err := IsCaseSensitiveFilesystem(filepath.Join(d, dirs[i]))
if err != nil {
return false, errors.Wrap(err, "failed to check filepath prefix")
}
if caseSensitive {
d = filepath.Join(d, dirs[i])
p = filepath.Join(p, prefixes[i])
} else {
d = filepath.Join(d, strings.ToLower(dirs[i]))
p = filepath.Join(p, strings.ToLower(prefixes[i]))
}
if p != d {
return false, nil
}
}
return true, nil
}
// EquivalentPaths compares the paths passed to check if they are equivalent.
// It respects the case-sensitivity of the underlying filesysyems.
func EquivalentPaths(p1, p2 string) (bool, error) {
p1 = filepath.Clean(p1)
p2 = filepath.Clean(p2)
fi1, err := os.Stat(p1)
if err != nil {
return false, errors.Wrapf(err, "could not check for path equivalence")
}
fi2, err := os.Stat(p2)
if err != nil {
return false, errors.Wrapf(err, "could not check for path equivalence")
}
p1Filename, p2Filename := "", ""
if !fi1.IsDir() {
p1, p1Filename = filepath.Split(p1)
}
if !fi2.IsDir() {
p2, p2Filename = filepath.Split(p2)
}
if isPrefix1, err := HasFilepathPrefix(p1, p2); err != nil {
return false, errors.Wrap(err, "failed to check for path equivalence")
} else if isPrefix2, err := HasFilepathPrefix(p2, p1); err != nil {
return false, errors.Wrap(err, "failed to check for path equivalence")
} else if !isPrefix1 || !isPrefix2 {
return false, nil
}
if p1Filename != "" || p2Filename != "" {
caseSensitive, err := IsCaseSensitiveFilesystem(filepath.Join(p1, p1Filename))
if err != nil {
return false, errors.Wrap(err, "could not check for filesystem case-sensitivity")
}
if caseSensitive {
if p1Filename != p2Filename {
return false, nil
}
} else {
if strings.ToLower(p1Filename) != strings.ToLower(p2Filename) {
return false, nil
}
}
}
return true, nil
}
// RenameWithFallback attempts to rename a file or directory, but falls back to // RenameWithFallback attempts to rename a file or directory, but falls back to
// copying in the event of a cross-device link error. If the fallback copy // copying in the event of a cross-device link error. If the fallback copy
// succeeds, src is still removed, emulating normal rename behavior. // succeeds, src is still removed, emulating normal rename behavior.
@ -193,159 +55,8 @@ func renameByCopy(src, dst string) error {
return errors.Wrapf(os.RemoveAll(src), "cannot delete %s", src) return errors.Wrapf(os.RemoveAll(src), "cannot delete %s", src)
} }
// IsCaseSensitiveFilesystem determines if the filesystem where dir
// exists is case sensitive or not.
//
// CAVEAT: this function works by taking the last component of the given
// path and flipping the case of the first letter for which case
// flipping is a reversible operation (/foo/Bar → /foo/bar), then
// testing for the existence of the new filename. There are two
// possibilities:
//
// 1. The alternate filename does not exist. We can conclude that the
// filesystem is case sensitive.
//
// 2. The filename happens to exist. We have to test if the two files
// are the same file (case insensitive file system) or different ones
// (case sensitive filesystem).
//
// If the input directory is such that the last component is composed
// exclusively of case-less codepoints (e.g. numbers), this function will
// return false.
func IsCaseSensitiveFilesystem(dir string) (bool, error) {
alt := filepath.Join(filepath.Dir(dir), genTestFilename(filepath.Base(dir)))
dInfo, err := os.Stat(dir)
if err != nil {
return false, errors.Wrap(err, "could not determine the case-sensitivity of the filesystem")
}
aInfo, err := os.Stat(alt)
if err != nil {
// If the file doesn't exists, assume we are on a case-sensitive filesystem.
if os.IsNotExist(err) {
return true, nil
}
return false, errors.Wrap(err, "could not determine the case-sensitivity of the filesystem")
}
return !os.SameFile(dInfo, aInfo), nil
}
// genTestFilename returns a string with at most one rune case-flipped.
//
// The transformation is applied only to the first rune that can be
// reversibly case-flipped, meaning:
//
// * A lowercase rune for which it's true that lower(upper(r)) == r
// * An uppercase rune for which it's true that upper(lower(r)) == r
//
// All the other runes are left intact.
func genTestFilename(str string) string {
flip := true
return strings.Map(func(r rune) rune {
if flip {
if unicode.IsLower(r) {
u := unicode.ToUpper(r)
if unicode.ToLower(u) == r {
r = u
flip = false
}
} else if unicode.IsUpper(r) {
l := unicode.ToLower(r)
if unicode.ToUpper(l) == r {
r = l
flip = false
}
}
}
return r
}, str)
}
var errPathNotDir = errors.New("given path is not a directory") var errPathNotDir = errors.New("given path is not a directory")
// ReadActualFilenames is used to determine the actual file names in given directory.
//
// On case sensitive file systems like ext4, it will check if those files exist using
// `os.Stat` and return a map with key and value as filenames which exist in the folder.
//
// Otherwise, it reads the contents of the directory and returns a map which has the
// given file name as the key and actual filename as the value(if it was found).
func ReadActualFilenames(dirPath string, names []string) (map[string]string, error) {
actualFilenames := make(map[string]string, len(names))
if len(names) == 0 {
// This isn't expected to happen for current usage. Adding edge case handling,
// as it may be useful in future.
return actualFilenames, nil
}
// First, check that the given path is valid and it is a directory
dirStat, err := os.Stat(dirPath)
if err != nil {
return nil, errors.Wrap(err, "failed to read actual filenames")
}
if !dirStat.IsDir() {
return nil, errPathNotDir
}
// Ideally, we would use `os.Stat` for getting the actual file names but that returns
// the name we passed in as an argument and not the actual filename. So we are forced
// to list the directory contents and check against that. Since this check is costly,
// we do it only if absolutely necessary.
caseSensitive, err := IsCaseSensitiveFilesystem(dirPath)
if err != nil {
return nil, errors.Wrap(err, "failed to read actual filenames")
}
if caseSensitive {
// There will be no difference between actual filename and given filename. So
// just check if those files exist.
for _, name := range names {
_, err := os.Stat(filepath.Join(dirPath, name))
if err == nil {
actualFilenames[name] = name
} else if !os.IsNotExist(err) {
// Some unexpected err, wrap and return it.
return nil, errors.Wrap(err, "failed to read actual filenames")
}
}
return actualFilenames, nil
}
dir, err := os.Open(dirPath)
if err != nil {
return nil, errors.Wrap(err, "failed to read actual filenames")
}
defer dir.Close()
// Pass -1 to read all filenames in directory
filenames, err := dir.Readdirnames(-1)
if err != nil {
return nil, errors.Wrap(err, "failed to read actual filenames")
}
// namesMap holds the mapping from lowercase name to search name. Using this, we can
// avoid repeatedly looping through names.
namesMap := make(map[string]string, len(names))
for _, name := range names {
namesMap[strings.ToLower(name)] = name
}
for _, filename := range filenames {
searchName, ok := namesMap[strings.ToLower(filename)]
if ok {
// We are interested in this file, case insensitive match successful.
actualFilenames[searchName] = filename
if len(actualFilenames) == len(names) {
// We found all that we were looking for.
return actualFilenames, nil
}
}
}
return actualFilenames, nil
}
var ( var (
errSrcNotDir = errors.New("source is not a directory") errSrcNotDir = errors.New("source is not a directory")
errDstExist = errors.New("destination already exists") errDstExist = errors.New("destination already exists")
@ -480,23 +191,6 @@ func cloneSymlink(sl, dst string) error {
return os.Symlink(resolved, dst) return os.Symlink(resolved, dst)
} }
// EnsureDir tries to ensure that a directory is present at the given path. It first
// checks if the directory already exists at the given path. If there isn't one, it tries
// to create it with the given permissions. However, it does not try to create the
// directory recursively.
func EnsureDir(path string, perm os.FileMode) error {
_, err := IsDir(path)
if os.IsNotExist(err) {
err = os.Mkdir(path, perm)
if err != nil {
return errors.Wrapf(err, "failed to ensure directory at %q", path)
}
}
return err
}
// IsDir determines is the path given is a directory or not. // IsDir determines is the path given is a directory or not.
func IsDir(name string) (bool, error) { func IsDir(name string) (bool, error) {
fi, err := os.Stat(name) fi, err := os.Stat(name)
@ -509,50 +203,6 @@ func IsDir(name string) (bool, error) {
return true, nil return true, nil
} }
// IsNonEmptyDir determines if the path given is a non-empty directory or not.
func IsNonEmptyDir(name string) (bool, error) {
isDir, err := IsDir(name)
if err != nil && !os.IsNotExist(err) {
return false, err
} else if !isDir {
return false, nil
}
// Get file descriptor
f, err := os.Open(name)
if err != nil {
return false, err
}
defer f.Close()
// Query only 1 child. EOF if no children.
_, err = f.Readdirnames(1)
switch err {
case io.EOF:
return false, nil
case nil:
return true, nil
default:
return false, err
}
}
// IsRegular determines if the path given is a regular file or not.
func IsRegular(name string) (bool, error) {
fi, err := os.Stat(name)
if os.IsNotExist(err) {
return false, nil
}
if err != nil {
return false, err
}
mode := fi.Mode()
if mode&os.ModeType != 0 {
return false, errors.Errorf("%q is a %v, expected a file", name, mode)
}
return true, nil
}
// IsSymlink determines if the given path is a symbolic link. // IsSymlink determines if the given path is a symbolic link.
func IsSymlink(path string) (bool, error) { func IsSymlink(path string) (bool, error) {
l, err := os.Lstat(path) l, err := os.Lstat(path)

@ -8,198 +8,10 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"reflect"
"runtime" "runtime"
"strings"
"testing" "testing"
"github.com/golang/dep/internal/test"
"github.com/pkg/errors"
) )
// This function tests HadFilepathPrefix. It should test it on both case
// sensitive and insensitive situations. However, the only reliable way to test
// case-insensitive behaviour is if using case-insensitive filesystem. This
// cannot be guaranteed in an automated test. Therefore, the behaviour of the
// tests is not to test case sensitivity on *nix and to assume that Windows is
// case-insensitive. Please see link below for some background.
//
// https://superuser.com/questions/266110/how-do-you-make-windows-7-fully-case-sensitive-with-respect-to-the-filesystem
//
// NOTE: NTFS can be made case-sensitive. However many Windows programs,
// including Windows Explorer do not handle gracefully multiple files that
// differ only in capitalization. It is possible that this can cause these tests
// to fail on some setups.
func TestHasFilepathPrefix(t *testing.T) {
dir, err := ioutil.TempDir("", "dep")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dir)
// dir2 is the same as dir but with different capitalization on Windows to
// test case insensitivity
var dir2 string
if runtime.GOOS == "windows" {
dir = strings.ToLower(dir)
dir2 = strings.ToUpper(dir)
} else {
dir2 = dir
}
// For testing trailing and repeated separators
sep := string(os.PathSeparator)
cases := []struct {
path string
prefix string
want bool
}{
{filepath.Join(dir, "a", "b"), filepath.Join(dir2), true},
{filepath.Join(dir, "a", "b"), dir2 + sep + sep + "a", true},
{filepath.Join(dir, "a", "b"), filepath.Join(dir2, "a") + sep, true},
{filepath.Join(dir, "a", "b") + sep, filepath.Join(dir2), true},
{dir + sep + sep + filepath.Join("a", "b"), filepath.Join(dir2, "a"), true},
{filepath.Join(dir, "a", "b"), filepath.Join(dir2, "a"), true},
{filepath.Join(dir, "a", "b"), filepath.Join(dir2, "a", "b"), true},
{filepath.Join(dir, "a", "b"), filepath.Join(dir2, "c"), false},
{filepath.Join(dir, "a", "b"), filepath.Join(dir2, "a", "d", "b"), false},
{filepath.Join(dir, "a", "b"), filepath.Join(dir2, "a", "b2"), false},
{filepath.Join(dir), filepath.Join(dir2, "a", "b"), false},
{filepath.Join(dir, "ab"), filepath.Join(dir2, "a", "b"), false},
{filepath.Join(dir, "ab"), filepath.Join(dir2, "a"), false},
{filepath.Join(dir, "123"), filepath.Join(dir2, "123"), true},
{filepath.Join(dir, "123"), filepath.Join(dir2, "1"), false},
{filepath.Join(dir, "⌘"), filepath.Join(dir2, "⌘"), true},
{filepath.Join(dir, "a"), filepath.Join(dir2, "⌘"), false},
{filepath.Join(dir, "⌘"), filepath.Join(dir2, "a"), false},
}
for _, c := range cases {
if err := os.MkdirAll(c.path, 0755); err != nil {
t.Fatal(err)
}
if err = os.MkdirAll(c.prefix, 0755); err != nil {
t.Fatal(err)
}
got, err := HasFilepathPrefix(c.path, c.prefix)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if c.want != got {
t.Fatalf("dir: %q, prefix: %q, expected: %v, got: %v", c.path, c.prefix, c.want, got)
}
}
}
// This function tests HadFilepathPrefix. It should test it on both case
// sensitive and insensitive situations. However, the only reliable way to test
// case-insensitive behaviour is if using case-insensitive filesystem. This
// cannot be guaranteed in an automated test. Therefore, the behaviour of the
// tests is not to test case sensitivity on *nix and to assume that Windows is
// case-insensitive. Please see link below for some background.
//
// https://superuser.com/questions/266110/how-do-you-make-windows-7-fully-case-sensitive-with-respect-to-the-filesystem
//
// NOTE: NTFS can be made case-sensitive. However many Windows programs,
// including Windows Explorer do not handle gracefully multiple files that
// differ only in capitalization. It is possible that this can cause these tests
// to fail on some setups.
func TestHasFilepathPrefix_Files(t *testing.T) {
dir, err := ioutil.TempDir("", "dep")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dir)
// dir2 is the same as dir but with different capitalization on Windows to
// test case insensitivity
var dir2 string
if runtime.GOOS == "windows" {
dir = strings.ToLower(dir)
dir2 = strings.ToUpper(dir)
} else {
dir2 = dir
}
existingFile := filepath.Join(dir, "exists")
if err = os.MkdirAll(existingFile, 0755); err != nil {
t.Fatal(err)
}
nonExistingFile := filepath.Join(dir, "does_not_exists")
cases := []struct {
path string
prefix string
want bool
err bool
}{
{existingFile, filepath.Join(dir2), true, false},
{nonExistingFile, filepath.Join(dir2), false, true},
}
for _, c := range cases {
got, err := HasFilepathPrefix(c.path, c.prefix)
if err != nil && !c.err {
t.Fatalf("unexpected error: %s", err)
}
if c.want != got {
t.Fatalf("dir: %q, prefix: %q, expected: %v, got: %v", c.path, c.prefix, c.want, got)
}
}
}
func TestEquivalentPaths(t *testing.T) {
h := test.NewHelper(t)
h.TempDir("dir")
h.TempDir("dir2")
h.TempFile("file", "")
h.TempFile("file2", "")
h.TempDir("DIR")
h.TempFile("FILE", "")
testcases := []struct {
p1, p2 string
caseSensitiveEquivalent bool
caseInensitiveEquivalent bool
err bool
}{
{h.Path("dir"), h.Path("dir"), true, true, false},
{h.Path("file"), h.Path("file"), true, true, false},
{h.Path("dir"), h.Path("dir2"), false, false, false},
{h.Path("file"), h.Path("file2"), false, false, false},
{h.Path("dir"), h.Path("file"), false, false, false},
{h.Path("dir"), h.Path("DIR"), false, true, false},
{strings.ToLower(h.Path("dir")), strings.ToUpper(h.Path("dir")), false, true, true},
}
caseSensitive, err := IsCaseSensitiveFilesystem(h.Path("dir"))
if err != nil {
t.Fatal("unexpcted error:", err)
}
for _, tc := range testcases {
got, err := EquivalentPaths(tc.p1, tc.p2)
if err != nil && !tc.err {
t.Error("unexpected error:", err)
}
if caseSensitive {
if tc.caseSensitiveEquivalent != got {
t.Errorf("expected EquivalentPaths(%q, %q) to be %t on case-sensitive filesystem, got %t", tc.p1, tc.p2, tc.caseSensitiveEquivalent, got)
}
} else {
if tc.caseInensitiveEquivalent != got {
t.Errorf("expected EquivalentPaths(%q, %q) to be %t on case-insensitive filesystem, got %t", tc.p1, tc.p2, tc.caseInensitiveEquivalent, got)
}
}
}
}
func TestRenameWithFallback(t *testing.T) { func TestRenameWithFallback(t *testing.T) {
dir, err := ioutil.TempDir("", "dep") dir, err := ioutil.TempDir("", "dep")
if err != nil { if err != nil {
@ -238,158 +50,6 @@ func TestRenameWithFallback(t *testing.T) {
} }
} }
func TestIsCaseSensitiveFilesystem(t *testing.T) {
isLinux := runtime.GOOS == "linux"
isWindows := runtime.GOOS == "windows"
isMacOS := runtime.GOOS == "darwin"
if !isLinux && !isWindows && !isMacOS {
t.Skip("Run this test on Windows, Linux and macOS only")
}
dir, err := ioutil.TempDir("", "TestCaseSensitivity")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dir)
var want bool
if isLinux {
want = true
} else {
want = false
}
got, err := IsCaseSensitiveFilesystem(dir)
if err != nil {
t.Fatalf("unexpected error message: \n\t(GOT) %+v", err)
}
if want != got {
t.Fatalf("unexpected value returned: \n\t(GOT) %t\n\t(WNT) %t", got, want)
}
}
func TestReadActualFilenames(t *testing.T) {
// We are trying to skip this test on file systems which are case-sensiive. We could
// have used `fs.IsCaseSensitiveFilesystem` for this check. However, the code we are
// testing also relies on `fs.IsCaseSensitiveFilesystem`. So a bug in
// `fs.IsCaseSensitiveFilesystem` could prevent this test from being run. This is the
// only scenario where we prefer the OS heuristic over doing the actual work of
// validating filesystem case sensitivity via `fs.IsCaseSensitiveFilesystem`.
if runtime.GOOS != "windows" && runtime.GOOS != "darwin" {
t.Skip("skip this test on non-Windows, non-macOS")
}
h := test.NewHelper(t)
defer h.Cleanup()
h.TempDir("")
tmpPath := h.Path(".")
// First, check the scenarios for which we expect an error.
_, err := ReadActualFilenames(filepath.Join(tmpPath, "does_not_exists"), []string{""})
switch {
case err == nil:
t.Fatal("expected err for non-existing folder")
// use `errors.Cause` because the error is wrapped and returned
case !os.IsNotExist(errors.Cause(err)):
t.Fatalf("unexpected error: %+v", err)
}
h.TempFile("tmpFile", "")
_, err = ReadActualFilenames(h.Path("tmpFile"), []string{""})
switch {
case err == nil:
t.Fatal("expected err for passing file instead of directory")
case err != errPathNotDir:
t.Fatalf("unexpected error: %+v", err)
}
cases := []struct {
createFiles []string
names []string
want map[string]string
}{
// If we supply no filenames to the function, it should return an empty map.
{nil, nil, map[string]string{}},
// If the directory contains the given file with different case, it should return
// a map which has the given filename as the key and actual filename as the value.
{
[]string{"test1.txt"},
[]string{"Test1.txt"},
map[string]string{"Test1.txt": "test1.txt"},
},
// 1. If the given filename is same as the actual filename, map should have the
// same key and value for the file.
// 2. If the given filename is present with different case for file extension,
// it should return a map which has the given filename as the key and actual
// filename as the value.
// 3. If the given filename is not present even with a different case, the map
// returned should not have an entry for that filename.
{
[]string{"test2.txt", "test3.TXT"},
[]string{"test2.txt", "Test3.txt", "Test4.txt"},
map[string]string{
"test2.txt": "test2.txt",
"Test3.txt": "test3.TXT",
},
},
}
for _, c := range cases {
for _, file := range c.createFiles {
h.TempFile(file, "")
}
got, err := ReadActualFilenames(tmpPath, c.names)
if err != nil {
t.Fatalf("unexpected error: %+v", err)
}
if !reflect.DeepEqual(c.want, got) {
t.Fatalf("returned value does not match expected: \n\t(GOT) %v\n\t(WNT) %v",
got, c.want)
}
}
}
func TestGenTestFilename(t *testing.T) {
cases := []struct {
str string
want string
}{
{"abc", "Abc"},
{"ABC", "aBC"},
{"AbC", "abC"},
{"αβγ", "Αβγ"},
{"123", "123"},
{"1a2", "1A2"},
{"12a", "12A"},
{"⌘", "⌘"},
}
for _, c := range cases {
got := genTestFilename(c.str)
if c.want != got {
t.Fatalf("str: %q, expected: %q, got: %q", c.str, c.want, got)
}
}
}
func BenchmarkGenTestFilename(b *testing.B) {
cases := []string{
strings.Repeat("a", 128),
strings.Repeat("A", 128),
strings.Repeat("α", 128),
strings.Repeat("1", 128),
strings.Repeat("⌘", 128),
}
for i := 0; i < b.N; i++ {
for _, str := range cases {
genTestFilename(str)
}
}
}
func TestCopyDir(t *testing.T) { func TestCopyDir(t *testing.T) {
dir, err := ioutil.TempDir("", "dep") dir, err := ioutil.TempDir("", "dep")
if err != nil { if err != nil {
@ -843,117 +503,6 @@ func setupInaccessibleDir(t *testing.T, op func(dir string) error) func() {
return cleanup return cleanup
} }
func TestEnsureDir(t *testing.T) {
h := test.NewHelper(t)
defer h.Cleanup()
h.TempDir(".")
h.TempFile("file", "")
tmpPath := h.Path(".")
var dn string
cleanup := setupInaccessibleDir(t, func(dir string) error {
dn = filepath.Join(dir, "dir")
return os.Mkdir(dn, 0777)
})
defer cleanup()
tests := map[string]bool{
// [success] A dir already exists for the given path.
tmpPath: true,
// [success] Dir does not exist but parent dir exists, so should get created.
filepath.Join(tmpPath, "testdir"): true,
// [failure] Dir and parent dir do not exist, should return an error.
filepath.Join(tmpPath, "notexist", "testdir"): false,
// [failure] Regular file present at given path.
h.Path("file"): false,
// [failure] Path inaccessible.
dn: false,
}
if runtime.GOOS == "windows" {
// This test doesn't work on Microsoft Windows because
// of the differences in how file permissions are
// implemented. For this to work, the directory where
// the directory exists should be inaccessible.
delete(tests, dn)
}
for path, shouldEnsure := range tests {
err := EnsureDir(path, 0777)
if shouldEnsure {
if err != nil {
t.Fatalf("unexpected error %q for %q", err, path)
} else if ok, err := IsDir(path); !ok {
t.Fatalf("expected directory to be preset at %q", path)
t.Fatal(err)
}
} else if err == nil {
t.Fatalf("expected error for path %q, got none", path)
}
}
}
func TestIsRegular(t *testing.T) {
wd, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
var fn string
cleanup := setupInaccessibleDir(t, func(dir string) error {
fn = filepath.Join(dir, "file")
fh, err := os.Create(fn)
if err != nil {
return err
}
return fh.Close()
})
defer cleanup()
tests := map[string]struct {
exists bool
err bool
}{
wd: {false, true},
filepath.Join(wd, "testdata"): {false, true},
filepath.Join(wd, "testdata", "test.file"): {true, false},
filepath.Join(wd, "this_file_does_not_exist.thing"): {false, false},
fn: {false, true},
}
if runtime.GOOS == "windows" {
// This test doesn't work on Microsoft Windows because
// of the differences in how file permissions are
// implemented. For this to work, the directory where
// the file exists should be inaccessible.
delete(tests, fn)
}
for f, want := range tests {
got, err := IsRegular(f)
if err != nil {
if want.exists != got {
t.Fatalf("expected %t for %s, got %t", want.exists, f, got)
}
if !want.err {
t.Fatalf("expected no error, got %v", err)
}
} else {
if want.err {
t.Fatalf("expected error for %s, got none", f)
}
}
if got != want.exists {
t.Fatalf("expected %t for %s, got %t", want, f, got)
}
}
}
func TestIsDir(t *testing.T) { func TestIsDir(t *testing.T) {
wd, err := os.Getwd() wd, err := os.Getwd()
if err != nil { if err != nil {
@ -999,61 +548,6 @@ func TestIsDir(t *testing.T) {
} }
} }
func TestIsNonEmptyDir(t *testing.T) {
wd, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
h := test.NewHelper(t)
defer h.Cleanup()
h.TempDir("empty")
testCases := []struct {
path string
empty bool
err bool
}{
{wd, true, false},
{"testdata", true, false},
{filepath.Join(wd, "fs.go"), false, true},
{filepath.Join(wd, "this_file_does_not_exist.thing"), false, false},
{h.Path("empty"), false, false},
}
// This test case doesn't work on Microsoft Windows because of the
// differences in how file permissions are implemented.
if runtime.GOOS != "windows" {
var inaccessibleDir string
cleanup := setupInaccessibleDir(t, func(dir string) error {
inaccessibleDir = filepath.Join(dir, "empty")
return os.Mkdir(inaccessibleDir, 0777)
})
defer cleanup()
testCases = append(testCases, struct {
path string
empty bool
err bool
}{inaccessibleDir, false, true})
}
for _, want := range testCases {
got, err := IsNonEmptyDir(want.path)
if want.err && err == nil {
if got {
t.Fatalf("wanted false with error for %v, but got true", want.path)
}
t.Fatalf("wanted an error for %v, but it was nil", want.path)
}
if got != want.empty {
t.Fatalf("wanted %t for %v, but got %t", want.empty, want.path, got)
}
}
}
func TestIsSymlink(t *testing.T) { func TestIsSymlink(t *testing.T) {
dir, err := ioutil.TempDir("", "dep") dir, err := ioutil.TempDir("", "dep")
if err != nil { if err != nil {

Loading…
Cancel
Save