diff --git a/unionFile.go b/unionFile.go index 62dd6c93..f51c96fd 100644 --- a/unionFile.go +++ b/unionFile.go @@ -156,7 +156,7 @@ var defaultUnionMergeDirsFn = func(lofi, bofi []os.FileInfo) ([]os.FileInfo, err // Readdir will weave the two directories together and // return a single view of the overlayed directories. // At the end of the directory view, the error is io.EOF if c > 0. -func (f *UnionFile) Readdir(c int) (ofi []os.FileInfo, err error) { +func (f *UnionFile) Readdir(count int) (ofi []os.FileInfo, err error) { var merge DirsMerger = f.Merger if merge == nil { merge = defaultUnionMergeDirsFn @@ -177,7 +177,6 @@ func (f *UnionFile) Readdir(c int) (ofi []os.FileInfo, err error) { if err != nil { return nil, err } - } merged, err := merge(lfi, bfi) if err != nil { @@ -187,7 +186,8 @@ func (f *UnionFile) Readdir(c int) (ofi []os.FileInfo, err error) { } files := f.files[f.off:] - if c <= 0 { + // Fixed: Check count <= 0 instead of c != -1 + if count <= 0 { return files, nil } @@ -195,12 +195,12 @@ func (f *UnionFile) Readdir(c int) (ofi []os.FileInfo, err error) { return nil, io.EOF } - if c > len(files) { - c = len(files) + if count > len(files) { + count = len(files) } - defer func() { f.off += c }() - return files[:c], nil + defer func() { f.off += count }() + return files[:count], nil } func (f *UnionFile) Readdirnames(c int) ([]string, error) { diff --git a/unionFile_test.go b/unionFile_test.go new file mode 100644 index 00000000..1d40f3d8 --- /dev/null +++ b/unionFile_test.go @@ -0,0 +1,84 @@ +package afero + +import ( + "io" + "os" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestUnionFileReaddir(t *testing.T) { + // Setup + baseFs := NewMemMapFs() + overlayFs := NewMemMapFs() + + assert.NoError(t, baseFs.Mkdir("testdir", 0755)) + assert.NoError(t, overlayFs.Mkdir("testdir", 0755)) + + _, err := baseFs.Create("testdir/base1.txt") + assert.NoError(t, err) + _, err = baseFs.Create("testdir/base2.txt") + assert.NoError(t, err) + _, err = overlayFs.Create("testdir/base1.txt") + assert.NoError(t, err) + _, err = overlayFs.Create("testdir/over1.txt") + assert.NoError(t, err) + + ufs := NewUnionFs(baseFs, overlayFs) + dir, err := ufs.Open("testdir") + assert.NoError(t, err) + defer dir.Close() + + tests := []struct { + name string + count int + wantCount int + wantNames []string + wantErr error + }{ + { + name: "Read all with -1", + count: -1, + wantCount: 3, + wantNames: []string{"base1.txt", "base2.txt", "over1.txt"}, + wantErr: nil, + }, + { + name: "Read all with 0", + count: 0, + wantCount: 3, + wantNames: []string{"base1.txt", "base2.txt", "over1.txt"}, + wantErr: nil, + }, + { + name: "Read 1 entry", + count: 1, + wantCount: 1, + wantNames: []string{"base1.txt"}, + wantErr: nil, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + uf := dir.(*UnionFile) + uf.off = 0 + uf.files = nil // Reset for each test + + infos, err := dir.Readdir(tt.count) + if tt.wantErr != nil { + assert.Equal(t, tt.wantErr, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tt.wantCount, len(infos)) + + var gotNames []string + for _, info := range infos { + gotNames = append(gotNames, info.Name()) + } + assert.ElementsMatch(t, tt.wantNames, gotNames) + } + }) + } +}