libgocryptfs/internal/syscallcompat/getdents_test.go
Jakob Unterwurzacher 70bcf58a9b syscallcompat: convert Getdents to fd input, add emulation
Now that we have Fstatat we can use it in Getdents to
get rid of the path name.

Also, add an emulated version of getdents for MacOS. This allows
to drop the !HaveGetdents special cases from fusefrontend.

Modify the getdents test to test both native getdents and the emulated
version.
2017-12-03 19:33:26 +01:00

93 lines
2.3 KiB
Go

// +build linux
package syscallcompat
import (
"io/ioutil"
"os"
"strings"
"syscall"
"testing"
"github.com/hanwen/go-fuse/fuse"
)
var getdentsUnderTest = getdents
func TestGetdents(t *testing.T) {
t.Logf("testing native getdents")
testGetdents(t)
t.Logf("testing emulateGetdents")
getdentsUnderTest = emulateGetdents
testGetdents(t)
}
func testGetdents(t *testing.T) {
// Fill a directory with filenames of length 1 ... 255
testDir, err := ioutil.TempDir(tmpDir, "TestGetdents")
if err != nil {
t.Fatal(err)
}
for i := 1; i <= syscall.NAME_MAX; i++ {
n := strings.Repeat("x", i)
err = ioutil.WriteFile(testDir+"/"+n, nil, 0600)
if err != nil {
t.Fatal(err)
}
}
// "/", "/dev" and "/proc/self" are good test cases because they contain
// many different file types (block and char devices, symlinks,
// mountpoints).
dirs := []string{testDir, "/", "/dev", "/proc/self"}
for _, dir := range dirs {
// Read directory using stdlib Readdir()
fd, err := os.Open(dir)
if err != nil {
t.Fatal(err)
}
defer fd.Close()
readdirEntries, err := fd.Readdir(0)
if err != nil {
t.Fatal(err)
}
readdirMap := make(map[string]*syscall.Stat_t)
for _, v := range readdirEntries {
readdirMap[v.Name()] = fuse.ToStatT(v)
}
// Read using our Getdents() implementation
_, err = fd.Seek(0, 0) // Rewind directory
if err != nil {
t.Fatal(err)
}
getdentsEntries, err := getdentsUnderTest(int(fd.Fd()))
if err != nil {
t.Fatal(err)
}
getdentsMap := make(map[string]fuse.DirEntry)
for _, v := range getdentsEntries {
getdentsMap[v.Name] = v
}
// Compare results
if len(getdentsEntries) != len(readdirEntries) {
t.Fatalf("len(getdentsEntries)=%d, len(readdirEntries)=%d",
len(getdentsEntries), len(readdirEntries))
}
for name := range readdirMap {
g := getdentsMap[name]
r := readdirMap[name]
rTyp := r.Mode & syscall.S_IFMT
if g.Mode != rTyp {
t.Errorf("%q: g.Mode=%#o, r.Mode=%#o", name, g.Mode, rTyp)
}
if g.Ino != r.Ino {
// The inode number of a directory that is reported by stat
// and getdents is different when it is a mountpoint. Only
// throw an error when we are NOT looking at a directory.
if g.Mode != syscall.S_IFDIR {
t.Errorf("%s: g.Ino=%d, r.Ino=%d", name, g.Ino, r.Ino)
}
}
}
}
}