diff --git a/mem/file.go b/mem/file.go index 7af2fb5..f99590e 100644 --- a/mem/file.go +++ b/mem/file.go @@ -193,8 +193,11 @@ func (f *File) Read(b []byte) (n int, err error) { } func (f *File) ReadAt(b []byte, off int64) (n int, err error) { + prev := atomic.LoadInt64(&f.at) atomic.StoreInt64(&f.at, off) - return f.Read(b) + n, err = f.Read(b) + atomic.StoreInt64(&f.at, prev) + return } func (f *File) Truncate(size int64) error { diff --git a/mem/file_test.go b/mem/file_test.go index 5769067..bb54db6 100644 --- a/mem/file_test.go +++ b/mem/file_test.go @@ -1,6 +1,7 @@ package mem import ( + "io" "testing" "time" ) @@ -152,3 +153,55 @@ func TestFileDataSizeRace(t *testing.T) { t.Errorf("Failed to read correct value for dir, was %v", s.Size()) } } + +func TestFileReadAtSeekOffset(t *testing.T) { + t.Parallel() + + fd := CreateFile("foo") + f := NewFileHandle(fd) + + _, err := f.WriteString("TEST") + if err != nil { + t.Fatal(err) + } + offset, err := f.Seek(0, io.SeekStart) + if err != nil { + t.Fatal(err) + } + if offset != 0 { + t.Fail() + } + + offsetBeforeReadAt, err := f.Seek(0, io.SeekCurrent) + if err != nil { + t.Fatal(err) + } + if offsetBeforeReadAt != 0 { + t.Fatal("expected 0") + } + + b := make([]byte, 4) + n, err := f.ReadAt(b, 0) + if err != nil { + t.Fatal(err) + } + if n != 4 { + t.Fail() + } + if string(b) != "TEST" { + t.Fail() + } + + offsetAfterReadAt, err := f.Seek(0, io.SeekCurrent) + if err != nil { + t.Fatal(err) + } + if offsetAfterReadAt != offsetBeforeReadAt { + t.Fatal("ReadAt should not affect offset") + } + + err = f.Close() + if err != nil { + t.Fatal(err) + } +}