package cephfs import ( "testing" "github.com/stretchr/testify/assert" ) func TestOpenCloseDir(t *testing.T) { mount := fsConnect(t) defer fsDisconnect(t, mount) dir1 := "/base" err := mount.MakeDir(dir1, 0755) assert.NoError(t, err) defer func() { assert.NoError(t, mount.RemoveDir(dir1)) }() dir2 := dir1 + "/a" err = mount.MakeDir(dir2, 0755) assert.NoError(t, err) defer func() { assert.NoError(t, mount.RemoveDir(dir2)) }() dir, err := mount.OpenDir(dir1) assert.NoError(t, err) assert.NotNil(t, dir) err = dir.Close() assert.NoError(t, err) dir, err = mount.OpenDir(dir2) assert.NoError(t, err) assert.NotNil(t, dir) err = dir.Close() assert.NoError(t, err) dir, err = mount.OpenDir("/no.such.dir") assert.Error(t, err) assert.Nil(t, dir) } func TestReadDir(t *testing.T) { mount := fsConnect(t) defer fsDisconnect(t, mount) dir1 := "/base" err := mount.MakeDir(dir1, 0755) assert.NoError(t, err) defer func() { assert.NoError(t, mount.RemoveDir(dir1)) }() subdirs := []string{"a", "bb", "ccc", "dddd"} for _, s := range subdirs { spath := dir1 + "/" + s err = mount.MakeDir(spath, 0755) assert.NoError(t, err) defer func(d string) { assert.NoError(t, mount.RemoveDir(d)) }(spath) } t.Run("root", func(t *testing.T) { dir, err := mount.OpenDir("/") assert.NoError(t, err) assert.NotNil(t, dir) defer func() { assert.NoError(t, dir.Close()) }() found := []string{} for { entry, err := dir.ReadDir() assert.NoError(t, err) if entry == nil { break } assert.NotEqual(t, Inode(0), entry.Inode()) assert.NotEqual(t, "", entry.Name()) found = append(found, entry.Name()) } assert.Contains(t, found, "base") }) t.Run("dir1", func(t *testing.T) { dir, err := mount.OpenDir(dir1) assert.NoError(t, err) assert.NotNil(t, dir) defer func() { assert.NoError(t, dir.Close()) }() found := []string{} for { entry, err := dir.ReadDir() assert.NoError(t, err) if entry == nil { break } assert.NotEqual(t, Inode(0), entry.Inode()) assert.NotEqual(t, "", entry.Name()) // we have created all the contents of this dir and they are all // empty dirs. assert.Equal(t, DTypeDir, entry.DType()) found = append(found, entry.Name()) } assert.Subset(t, found, subdirs) }) } func TestDirectoryList(t *testing.T) { mount := fsConnect(t) defer fsDisconnect(t, mount) dir1 := "/base" err := mount.MakeDir(dir1, 0755) assert.NoError(t, err) defer func() { assert.NoError(t, mount.RemoveDir(dir1)) }() subdirs := []string{"a", "bb", "ccc", "dddd"} for _, s := range subdirs { spath := dir1 + "/" + s err = mount.MakeDir(spath, 0755) assert.NoError(t, err) defer func(d string) { assert.NoError(t, mount.RemoveDir(d)) }(spath) } t.Run("root", func(t *testing.T) { dir, err := mount.OpenDir("/") assert.NoError(t, err) assert.NotNil(t, dir) defer func() { assert.NoError(t, dir.Close()) }() entries, err := dir.list() assert.NoError(t, err) assert.Greater(t, len(entries), 1) found := entries.names() assert.Contains(t, found, "base") }) t.Run("dir1", func(t *testing.T) { dir, err := mount.OpenDir(dir1) assert.NoError(t, err) assert.NotNil(t, dir) defer func() { assert.NoError(t, dir.Close()) }() entries, err := dir.list() assert.NoError(t, err) assert.Greater(t, len(entries), 1) found := entries.names() assert.Subset(t, found, subdirs) }) t.Run("dir1Twice", func(t *testing.T) { dir, err := mount.OpenDir(dir1) assert.NoError(t, err) assert.NotNil(t, dir) defer func() { assert.NoError(t, dir.Close()) }() entries, err := dir.list() assert.NoError(t, err) assert.Greater(t, len(entries), 1) found := entries.names() assert.Subset(t, found, subdirs) // verify that calling list gives a complete list // even after being used for the same directory already entries, err = dir.list() assert.NoError(t, err) assert.Greater(t, len(entries), 1) found = entries.names() assert.Subset(t, found, subdirs) }) } func TestReadDirPlus(t *testing.T) { mount := fsConnect(t) defer fsDisconnect(t, mount) dir1 := "/base" err := mount.MakeDir(dir1, 0755) assert.NoError(t, err) defer func() { assert.NoError(t, mount.RemoveDir(dir1)) }() subdirs := []string{"a", "bb", "ccc", "dddd"} for _, s := range subdirs { spath := dir1 + "/" + s err = mount.MakeDir(spath, 0755) assert.NoError(t, err) defer func(d string) { assert.NoError(t, mount.RemoveDir(d)) }(spath) } t.Run("root", func(t *testing.T) { dir, err := mount.OpenDir("/") assert.NoError(t, err) assert.NotNil(t, dir) defer func() { assert.NoError(t, dir.Close()) }() found := []string{} for { entry, err := dir.ReadDirPlus(StatxBasicStats, AtSymlinkNofollow) assert.NoError(t, err) if entry == nil { break } assert.NotEqual(t, Inode(0), entry.Inode()) assert.NotEqual(t, "", entry.Name()) found = append(found, entry.Name()) } assert.Contains(t, found, "base") }) t.Run("dir1", func(t *testing.T) { dir, err := mount.OpenDir(dir1) assert.NoError(t, err) assert.NotNil(t, dir) defer func() { assert.NoError(t, dir.Close()) }() found := []string{} for { entry, err := dir.ReadDirPlus(StatxBasicStats, AtSymlinkNofollow) assert.NoError(t, err) if entry == nil { break } assert.NotEqual(t, Inode(0), entry.Inode()) assert.NotEqual(t, "", entry.Name()) // we have created all the contents of this dir and they are all // empty dirs. assert.Equal(t, DTypeDir, entry.DType()) // get statx data from the entry, and check it st := entry.Statx() assert.Equal(t, StatxBasicStats, st.Mask&StatxBasicStats) assert.Equal(t, uint16(0755), st.Mode&0777) found = append(found, entry.Name()) } assert.Subset(t, found, subdirs) }) } func TestReadDirPlusInvalid(t *testing.T) { mount := fsConnect(t) defer fsDisconnect(t, mount) dir, err := mount.OpenDir("/") assert.NoError(t, err) assert.NotNil(t, dir) defer func() { assert.NoError(t, dir.Close()) }() // Feed it an invalid flag to trigger in EINVAL in libcephfs. This could // break in the future if it ever becomes a valid flag but it works well // enough for now, and the error suddenly changing to no error will be // kinda obvious. _, err = dir.ReadDirPlus(StatxBasicStats, AtFlags(1<<13)) assert.Error(t, err) }