Skip to content

Commit

Permalink
Add BoundedReadWriteSeekCloser
Browse files Browse the repository at this point in the history
  • Loading branch information
dsoprea committed Jun 30, 2019
1 parent 45902a0 commit e7b8fc1
Show file tree
Hide file tree
Showing 2 changed files with 227 additions and 0 deletions.
95 changes: 95 additions & 0 deletions filesystem/boundedreadwriteseekcloser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package rifs

import (
"io"

"github.com/dsoprea/go-logging"
)

// BoundedReadWriteSeekCloser wraps a RWS that is also a closer with boundaries.
// This proxies the RWS methods to the inner BRWS inside.
type BoundedReadWriteSeekCloser struct {
io.Closer
*BoundedReadWriteSeeker
}

// NewBoundedReadWriteSeekCloser returns a new BoundedReadWriteSeekCloser.
func NewBoundedReadWriteSeekCloser(rwsc ReadWriteSeekCloser, minimumOffset int64, staticFileSize int) (brwsc *BoundedReadWriteSeekCloser, err error) {
defer func() {
if state := recover(); state != nil {
err = log.Wrap(state.(error))
}
}()

bs, err := NewBoundedReadWriteSeeker(rwsc, minimumOffset, staticFileSize)
log.PanicIf(err)

brwsc = &BoundedReadWriteSeekCloser{
Closer: rwsc,
BoundedReadWriteSeeker: bs,
}

return brwsc, nil
}

// Seek forwards calls to the inner RWS.
func (rwsc *BoundedReadWriteSeekCloser) Seek(offset int64, whence int) (newOffset int64, err error) {
defer func() {
if state := recover(); state != nil {
err = log.Wrap(state.(error))
}
}()

newOffset, err = rwsc.BoundedReadWriteSeeker.Seek(offset, whence)
log.PanicIf(err)

return newOffset, nil
}

// Read forwards calls to the inner RWS.
func (rwsc *BoundedReadWriteSeekCloser) Read(buffer []byte) (readCount int, err error) {
defer func() {
if state := recover(); state != nil {
err = log.Wrap(state.(error))
}
}()

readCount, err = rwsc.BoundedReadWriteSeeker.Read(buffer)
if err != nil {
if err == io.EOF {
return 0, err
}

log.Panic(err)
}

return readCount, nil
}

// Write forwards calls to the inner RWS.
func (rwsc *BoundedReadWriteSeekCloser) Write(buffer []byte) (writtenCount int, err error) {
defer func() {
if state := recover(); state != nil {
err = log.Wrap(state.(error))
}
}()

writtenCount, err = rwsc.BoundedReadWriteSeeker.Write(buffer)
log.PanicIf(err)

return writtenCount, nil
}

// Close forwards calls to the inner RWS.
func (rwsc *BoundedReadWriteSeekCloser) Close() (err error) {
defer func() {
if state := recover(); state != nil {
err = log.Wrap(state.(error))
}
}()

err = rwsc.Closer.Close()
log.PanicIf(err)

return nil
}
132 changes: 132 additions & 0 deletions filesystem/boundedreadwriteseekcloser_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package rifs

import (
"bytes"
"fmt"
"os"
"testing"

"io/ioutil"

"github.com/dsoprea/go-logging"
)

func TestNewBoundedReadWriteSeekerCloser(t *testing.T) {
sb := NewSeekableBuffer()
rwsc := ReadWriteSeekNoopCloser(sb)

brwsc, err := NewBoundedReadWriteSeekCloser(rwsc, 10, 0)
log.PanicIf(err)

err = brwsc.Close()
log.PanicIf(err)
}

func TestNewBoundedReadWriteSeekerCloser_Read(t *testing.T) {
data := []byte("this is a test; this is a test2")
sb := NewSeekableBufferWithBytes(data)
rwsc := ReadWriteSeekNoopCloser(sb)

brwsc, err := NewBoundedReadWriteSeekCloser(rwsc, 10, 0)
log.PanicIf(err)

defer func() {
err = brwsc.Close()
log.PanicIf(err)
}()

recovered, err := ioutil.ReadAll(brwsc)
log.PanicIf(err)

if bytes.Equal(recovered, data[10:]) != true {
t.Fatalf("Read bytes not correct.")
}
}

func TestNewBoundedReadWriteSeekerCloser_Write(t *testing.T) {
sb := NewSeekableBuffer()
rwsc := ReadWriteSeekNoopCloser(sb)

brwsc, err := NewBoundedReadWriteSeekCloser(rwsc, 10, 0)
log.PanicIf(err)

defer func() {
err = brwsc.Close()
log.PanicIf(err)
}()

data := []byte("this is a test; this is a test2")

n, err := brwsc.Write(data)
log.PanicIf(err)

if n != len(data) {
t.Fatalf("Written count not correct: (%d)", n)
}

_, err = sb.Seek(0, os.SEEK_SET)
log.PanicIf(err)

recovered, err := ioutil.ReadAll(sb)
log.PanicIf(err)

expectedRecovered := make([]byte, 10+len(data))
copy(expectedRecovered[10:], data)

if bytes.Equal(recovered, expectedRecovered) != true {
fmt.Printf("ACTUAL (%d):\n%v\n\nEXPECTED (%d):\n%v\n", len(recovered), recovered, len(expectedRecovered), expectedRecovered)

t.Fatalf("Read bytes not correct.")
}
}

func TestNewBoundedReadWriteSeekerCloser_Seek(t *testing.T) {
sb := NewSeekableBuffer()
rwsc := ReadWriteSeekNoopCloser(sb)

brwsc, err := NewBoundedReadWriteSeekCloser(rwsc, 10, 0)
log.PanicIf(err)

defer func() {
err = brwsc.Close()
log.PanicIf(err)
}()

_, err = brwsc.Seek(10, os.SEEK_SET)
log.PanicIf(err)

data := []byte("this is a test; this is a test2")

n, err := brwsc.Write(data)
log.PanicIf(err)

if n != len(data) {
t.Fatalf("Written count not correct: (%d)", n)
}

_, err = sb.Seek(0, os.SEEK_SET)
log.PanicIf(err)

recovered, err := ioutil.ReadAll(sb)
log.PanicIf(err)

expectedRecovered := make([]byte, 20+len(data))
copy(expectedRecovered[20:], data)

if bytes.Equal(recovered, expectedRecovered) != true {
fmt.Printf("ACTUAL (%d):\n%v\n\nEXPECTED (%d):\n%v\n", len(recovered), recovered, len(expectedRecovered), expectedRecovered)

t.Fatalf("Read bytes not correct.")
}
}

func TestNewBoundedReadWriteSeekerCloser_Close(t *testing.T) {
sb := NewSeekableBuffer()
rwsc := ReadWriteSeekNoopCloser(sb)

brwsc, err := NewBoundedReadWriteSeekCloser(rwsc, 10, 0)
log.PanicIf(err)

err = brwsc.Close()
log.PanicIf(err)
}

0 comments on commit e7b8fc1

Please sign in to comment.