From a23524d34a67486615df96ea6309877a0f7a05c7 Mon Sep 17 00:00:00 2001 From: Felicitas Pojtinger Date: Thu, 20 Jan 2022 21:34:36 +0100 Subject: [PATCH] feat: Add sequential read tests, allow reading directory if length of buffer is 0 --- pkg/fs/file.go | 8 +-- pkg/fs/file_test.go | 161 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+), 4 deletions(-) diff --git a/pkg/fs/file.go b/pkg/fs/file.go index ea3f33f..699c3fd 100644 --- a/pkg/fs/file.go +++ b/pkg/fs/file.go @@ -451,10 +451,6 @@ func (f *File) Read(p []byte) (n int, err error) { "p": len(p), }) - if f.info.IsDir() { - return -1, config.ErrIsDirectory - } - if !f.flags.Read { return -1, os.ErrPermission } @@ -463,6 +459,10 @@ func (f *File) Read(p []byte) (n int, err error) { return 0, nil } + if f.info.IsDir() { + return -1, config.ErrIsDirectory + } + f.ioLock.Lock() defer f.ioLock.Unlock() diff --git a/pkg/fs/file_test.go b/pkg/fs/file_test.go index 4ad16ac..9ff1cf9 100644 --- a/pkg/fs/file_test.go +++ b/pkg/fs/file_test.go @@ -1,6 +1,7 @@ package fs import ( + "bytes" "crypto/sha512" "encoding/base64" "errors" @@ -1140,6 +1141,112 @@ var readTests = []struct { withOsFs bool large bool }{ + { + "Can read / into empty buffer", + "/", + false, + func(f afero.Fs) error { return nil }, + func(f afero.File) error { + wantContent := []byte{} + gotContent := make([]byte, len(wantContent)) + + wantLength := len(wantContent) + gotLength, err := f.Read(gotContent) + if err != io.EOF { + return err + } + + if wantLength != gotLength { + return fmt.Errorf("invalid read length, got %v, want %v", gotLength, wantLength) + } + + if string(wantContent) != string(gotContent) { + return fmt.Errorf("invalid read content, got %v, want %v", gotContent, wantContent) + } + + return nil + }, + true, + true, + false, + }, + { + "Can read /mydir into empty buffer", + "/mydir", + false, + func(f afero.Fs) error { + if err := f.Mkdir("/mydir", os.ModePerm); err != nil { + return err + } + + return nil + }, + func(f afero.File) error { + wantContent := []byte{} + gotContent := make([]byte, len(wantContent)) + + wantLength := len(wantContent) + gotLength, err := f.Read(gotContent) + if err != io.EOF { + return err + } + + if wantLength != gotLength { + return fmt.Errorf("invalid read length, got %v, want %v", gotLength, wantLength) + } + + if string(wantContent) != string(gotContent) { + return fmt.Errorf("invalid read content, got %v, want %v", gotContent, wantContent) + } + + return nil + }, + true, + true, + false, + }, + { + "Can not read / into non-empty buffer", + "/", + true, + func(f afero.Fs) error { return nil }, + func(f afero.File) error { + gotContent := make([]byte, 10) + + if _, err := f.Read(gotContent); err != io.EOF { + return err + } + + return nil + }, + true, + true, + false, + }, + { + "Can not read /mydir into non-empty buffer", + "/mydir", + true, + func(f afero.Fs) error { + if err := f.Mkdir("/mydir", os.ModePerm); err != nil { + return err + } + + return nil + }, + func(f afero.File) error { + gotContent := make([]byte, 10) + + if _, err := f.Read(gotContent); err != io.EOF { + return err + } + + return nil + }, + true, + true, + false, + }, { "Can read /test.txt if it exists and is empty", "/test.txt", @@ -1301,6 +1408,60 @@ var readTests = []struct { true, true, }, + { + "Can read /test.txt sequentially if it exists and contains 30 MB amount of data", + "/test.txt", + false, + func(f afero.Fs) error { + file, err := f.Create("/test.txt") + if err != nil { + return err + } + + r := newDeterministicReader(1000) + + if _, err := io.Copy(file, r); err != nil { + return err + } + + return file.Close() + }, + func(f afero.File) error { + firstChunk := make([]byte, 32800768/2) + secondChunk := make([]byte, 32800768/2) + + if _, err := f.Read(firstChunk); err != nil { + return err + } + + if _, err := f.Read(secondChunk); err != nil { + return err + } + + wantHash := "HTUi7GuNreHASha4hhl1xwuYk03pyTJ0IJbFLv04UdccT9m_NA2oBFTrnMxJhEu3VMGxDYk_04Th9C0zOj5MyA==" + wantLength := int64(32800768) + + hasher := sha512.New() + gotLength, err := io.Copy(hasher, bytes.NewBuffer(append(firstChunk, secondChunk...))) + if err != nil { + return err + } + gotHash := base64.URLEncoding.EncodeToString(hasher.Sum(nil)) + + if gotLength != wantLength { + return fmt.Errorf("invalid read length, got %v, want %v", gotLength, wantLength) + } + + if gotHash != wantHash { + return fmt.Errorf("invalid read hash, got %v, want %v", gotHash, wantHash) + } + + return nil + }, + true, + true, + false, + }, } func TestFile_Read(t *testing.T) {