Add pathtools.Filesystem.Stat for soong_zip
Stat is used by soong_zip. Add it to the FileSystem interface and add tests for it. Test: fs_test.go Change-Id: I1baa2b27398846a4e55bcf4fa291c62f507a4e9d
This commit is contained in:
parent
15fbefb87e
commit
3316a5ee54
2 changed files with 120 additions and 13 deletions
|
@ -106,6 +106,9 @@ type FileSystem interface {
|
|||
// Lstat returns info on a file without following symlinks.
|
||||
Lstat(name string) (os.FileInfo, error)
|
||||
|
||||
// Lstat returns info on a file.
|
||||
Stat(name string) (os.FileInfo, error)
|
||||
|
||||
// ListDirsRecursive returns a list of all the directories in a path, following symlinks if requested.
|
||||
ListDirsRecursive(name string, follow ShouldFollowSymlinks) (dirs []string, err error)
|
||||
|
||||
|
@ -159,6 +162,10 @@ func (osFs) Lstat(path string) (stats os.FileInfo, err error) {
|
|||
return os.Lstat(path)
|
||||
}
|
||||
|
||||
func (osFs) Stat(path string) (stats os.FileInfo, err error) {
|
||||
return os.Stat(path)
|
||||
}
|
||||
|
||||
// Returns a list of all directories under dir
|
||||
func (osFs) ListDirsRecursive(name string, follow ShouldFollowSymlinks) (dirs []string, err error) {
|
||||
return listDirsRecursive(OsFs, name, follow)
|
||||
|
@ -349,24 +356,46 @@ func (ms *mockStat) ModTime() time.Time { return time.Time{} }
|
|||
func (ms *mockStat) Sys() interface{} { return nil }
|
||||
|
||||
func (m *mockFs) Lstat(name string) (os.FileInfo, error) {
|
||||
name = filepath.Clean(name)
|
||||
dir, file := saneSplit(name)
|
||||
dir = m.followSymlinks(dir)
|
||||
name = filepath.Join(dir, file)
|
||||
|
||||
ms := mockStat{
|
||||
name: name,
|
||||
name: file,
|
||||
}
|
||||
|
||||
if symlink, isSymlink := m.symlinks[name]; isSymlink {
|
||||
ms.mode = os.ModeSymlink
|
||||
ms.size = int64(len(symlink))
|
||||
} else if _, isDir := m.dirs[name]; isDir {
|
||||
ms.mode = os.ModeDir
|
||||
} else if _, isFile := m.files[name]; isFile {
|
||||
ms.mode = 0
|
||||
ms.size = int64(len(m.files[name]))
|
||||
} else {
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
|
||||
return &ms, nil
|
||||
}
|
||||
|
||||
func (m *mockFs) Stat(name string) (os.FileInfo, error) {
|
||||
name = filepath.Clean(name)
|
||||
origName := name
|
||||
name = m.followSymlinks(name)
|
||||
|
||||
ms := mockStat{
|
||||
name: filepath.Base(origName),
|
||||
size: int64(len(m.files[name])),
|
||||
}
|
||||
|
||||
if isSymlink, err := m.IsSymlink(name); err != nil {
|
||||
// IsSymlink handles ErrNotExist
|
||||
return nil, err
|
||||
} else if isSymlink {
|
||||
ms.mode = os.ModeSymlink
|
||||
} else if isDir, err := m.IsDir(name); err != nil {
|
||||
return nil, err
|
||||
} else if isDir {
|
||||
if _, isDir := m.dirs[name]; isDir {
|
||||
ms.mode = os.ModeDir
|
||||
} else {
|
||||
} else if _, isFile := m.files[name]; isFile {
|
||||
ms.mode = 0
|
||||
ms.size = int64(len(m.files[name]))
|
||||
} else {
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
|
||||
return &ms, nil
|
||||
|
|
|
@ -409,11 +409,89 @@ func TestFs_Lstat(t *testing.T) {
|
|||
return
|
||||
}
|
||||
if got.Mode()&os.ModeType != test.mode {
|
||||
t.Errorf("fs.Readlink(%q).Mode()&os.ModeType want: %x, got %x",
|
||||
t.Errorf("fs.Lstat(%q).Mode()&os.ModeType want: %x, got %x",
|
||||
test.name, test.mode, got.Mode()&os.ModeType)
|
||||
}
|
||||
if test.mode == 0 && got.Size() != test.size {
|
||||
t.Errorf("fs.Readlink(%q).Size() want: %d, got %d", test.name, test.size, got.Size())
|
||||
t.Errorf("fs.Lstat(%q).Size() want: %d, got %d", test.name, test.size, got.Size())
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFs_Stat(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
mode os.FileMode
|
||||
size int64
|
||||
err error
|
||||
}{
|
||||
{".", os.ModeDir, 0, nil},
|
||||
{"/", os.ModeDir, 0, nil},
|
||||
|
||||
{"a", os.ModeDir, 0, nil},
|
||||
{"a/a", os.ModeDir, 0, nil},
|
||||
{"a/a/a", 0, 0, nil},
|
||||
{"a/a/f", 0, 0, nil},
|
||||
|
||||
{"b", os.ModeDir, 0, nil},
|
||||
{"b/a", os.ModeDir, 0, nil},
|
||||
{"b/a/a", 0, 0, nil},
|
||||
{"b/a/f", 0, 0, nil},
|
||||
|
||||
{"c", os.ModeDir, 0, nil},
|
||||
{"c/a", 0, 0, nil},
|
||||
{"c/f", 0, 0, nil},
|
||||
|
||||
{"d/a", 0, 0, nil},
|
||||
{"d/f", 0, 0, nil},
|
||||
|
||||
{"e", 0, 0, nil},
|
||||
|
||||
{"f", 0, 0, nil},
|
||||
|
||||
{"dangling", 0, 0, os.ErrNotExist},
|
||||
|
||||
{"a/missing", 0, 0, os.ErrNotExist},
|
||||
{"b/missing", 0, 0, os.ErrNotExist},
|
||||
{"c/missing", 0, 0, os.ErrNotExist},
|
||||
{"d/missing", 0, 0, os.ErrNotExist},
|
||||
{"e/missing", 0, 0, os.ErrNotExist},
|
||||
{"dangling/missing", 0, 0, os.ErrNotExist},
|
||||
|
||||
{"a/missing/missing", 0, 0, os.ErrNotExist},
|
||||
{"b/missing/missing", 0, 0, os.ErrNotExist},
|
||||
{"c/missing/missing", 0, 0, os.ErrNotExist},
|
||||
{"d/missing/missing", 0, 0, os.ErrNotExist},
|
||||
{"e/missing/missing", 0, 0, os.ErrNotExist},
|
||||
{"dangling/missing/missing", 0, 0, os.ErrNotExist},
|
||||
}
|
||||
|
||||
mock := symlinkMockFs()
|
||||
fsList := []FileSystem{mock, OsFs}
|
||||
names := []string{"mock", "os"}
|
||||
|
||||
os.Chdir("testdata/dangling")
|
||||
defer os.Chdir("../..")
|
||||
|
||||
for i, fs := range fsList {
|
||||
t.Run(names[i], func(t *testing.T) {
|
||||
|
||||
for _, test := range testCases {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
got, err := fs.Stat(test.name)
|
||||
checkErr(t, test.err, err)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if got.Mode()&os.ModeType != test.mode {
|
||||
t.Errorf("fs.Stat(%q).Mode()&os.ModeType want: %x, got %x",
|
||||
test.name, test.mode, got.Mode()&os.ModeType)
|
||||
}
|
||||
if test.mode == 0 && got.Size() != test.size {
|
||||
t.Errorf("fs.Stat(%q).Size() want: %d, got %d", test.name, test.size, got.Size())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue