Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix sorting in IOFS.ReadDir #372

Merged
merged 1 commit into from Jul 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 6 additions & 1 deletion iofs.go
Expand Up @@ -76,7 +76,12 @@ func (iofs IOFS) ReadDir(name string) ([]fs.DirEntry, error) {
defer f.Close()

if rdf, ok := f.(fs.ReadDirFile); ok {
return rdf.ReadDir(-1)
items, err := rdf.ReadDir(-1)
if err != nil {
return nil, iofs.wrapError("readdir", name, err)
}
sort.Slice(items, func(i, j int) bool { return items[i].Name() < items[j].Name() })
return items, nil
}

items, err := f.Readdir(-1)
Expand Down
36 changes: 28 additions & 8 deletions iofs_test.go
Expand Up @@ -9,6 +9,7 @@ import (
"fmt"
"io"
"io/fs"
"math/rand"
"os"
"path/filepath"
"runtime"
Expand Down Expand Up @@ -76,7 +77,17 @@ func TestIOFSNativeDirEntryWhenPossible(t *testing.T) {
t.Fatal(err)
}

for i := 1; i <= 2; i++ {
const numFiles = 10

var fileNumbers []int
for i := 0; i < numFiles; i++ {
fileNumbers = append(fileNumbers, i)
}
rand.Shuffle(len(fileNumbers), func(i, j int) {
fileNumbers[i], fileNumbers[j] = fileNumbers[j], fileNumbers[i]
})

for _, i := range fileNumbers {
f, err := osfs.Create(fmt.Sprintf("dir1/dir2/test%d.txt", i))
if err != nil {
t.Fatal(err)
Expand All @@ -89,25 +100,34 @@ func TestIOFSNativeDirEntryWhenPossible(t *testing.T) {
t.Fatal(err)
}

assertDirEntries := func(entries []fs.DirEntry) {
if len(entries) != 2 {
t.Fatalf("expected 2, got %d", len(entries))
assertDirEntries := func(entries []fs.DirEntry, ordered bool) {
if len(entries) != numFiles {
t.Fatalf("expected %d, got %d", numFiles, len(entries))
}
for _, entry := range entries {
for i, entry := range entries {
if _, ok := entry.(dirEntry); ok {
t.Fatal("DirEntry not native")
}
if ordered && entry.Name() != fmt.Sprintf("test%d.txt", i) {
t.Fatalf("expected %s, got %s", fmt.Sprintf("test%d.txt", i), entry.Name())
}
}
}

dirEntries, err := dir2.(fs.ReadDirFile).ReadDir(-1)
if err != nil {
t.Fatal(err)
}
assertDirEntries(dirEntries)
assertDirEntries(dirEntries, false)

iofs := NewIOFS(osfs)

dirEntries, err = iofs.ReadDir("dir1/dir2")
if err != nil {
t.Fatal(err)
}
assertDirEntries(dirEntries, true)

fileCount := 0
err = fs.WalkDir(iofs, "", func(path string, d fs.DirEntry, err error) error {
if err != nil {
Expand All @@ -130,8 +150,8 @@ func TestIOFSNativeDirEntryWhenPossible(t *testing.T) {
t.Fatal(err)
}

if fileCount != 2 {
t.Fatalf("expected 2, got %d", fileCount)
if fileCount != numFiles {
t.Fatalf("expected %d, got %d", numFiles, fileCount)
}

}
Expand Down
10 changes: 5 additions & 5 deletions ioutil.go
Expand Up @@ -141,7 +141,7 @@ func WriteFile(fs Fs, filename string, data []byte, perm os.FileMode) error {
// We generate random temporary file names so that there's a good
// chance the file doesn't exist yet - keeps the number of tries in
// TempFile to a minimum.
var rand uint32
var randNum uint32
var randmu sync.Mutex

func reseed() uint32 {
Expand All @@ -150,12 +150,12 @@ func reseed() uint32 {

func nextRandom() string {
randmu.Lock()
r := rand
r := randNum
if r == 0 {
r = reseed()
}
r = r*1664525 + 1013904223 // constants from Numerical Recipes
rand = r
randNum = r
randmu.Unlock()
return strconv.Itoa(int(1e9 + r%1e9))[1:]
}
Expand Down Expand Up @@ -194,7 +194,7 @@ func TempFile(fs Fs, dir, pattern string) (f File, err error) {
if os.IsExist(err) {
if nconflict++; nconflict > 10 {
randmu.Lock()
rand = reseed()
randNum = reseed()
randmu.Unlock()
}
continue
Expand Down Expand Up @@ -226,7 +226,7 @@ func TempDir(fs Fs, dir, prefix string) (name string, err error) {
if os.IsExist(err) {
if nconflict++; nconflict > 10 {
randmu.Lock()
rand = reseed()
randNum = reseed()
randmu.Unlock()
}
continue
Expand Down