2017-10-29 22:14:05 +01:00
|
|
|
package vfs
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/ncw/rclone/fstest"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Open a file for write
|
|
|
|
func readHandleCreate(t *testing.T, r *fstest.Run) (*VFS, *ReadFileHandle) {
|
|
|
|
vfs := New(r.Fremote, nil)
|
|
|
|
|
|
|
|
file1 := r.WriteObject("dir/file1", "0123456789abcdef", t1)
|
|
|
|
fstest.CheckItems(t, r.Fremote, file1)
|
|
|
|
|
|
|
|
h, err := vfs.OpenFile("dir/file1", os.O_RDONLY, 0777)
|
|
|
|
require.NoError(t, err)
|
|
|
|
fh, ok := h.(*ReadFileHandle)
|
|
|
|
require.True(t, ok)
|
|
|
|
|
|
|
|
return vfs, fh
|
|
|
|
}
|
|
|
|
|
|
|
|
// read data from the string
|
|
|
|
func readString(t *testing.T, fh *ReadFileHandle, n int) string {
|
|
|
|
buf := make([]byte, n)
|
|
|
|
n, err := fh.Read(buf)
|
|
|
|
if err != io.EOF {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
return string(buf[:n])
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestReadFileHandleMethods(t *testing.T) {
|
|
|
|
r := fstest.NewRun(t)
|
|
|
|
defer r.Finalise()
|
|
|
|
_, fh := readHandleCreate(t, r)
|
|
|
|
|
|
|
|
// String
|
|
|
|
assert.Equal(t, "dir/file1 (r)", fh.String())
|
|
|
|
assert.Equal(t, "<nil *ReadFileHandle>", (*ReadFileHandle)(nil).String())
|
|
|
|
assert.Equal(t, "<nil *ReadFileHandle.file>", new(ReadFileHandle).String())
|
|
|
|
|
|
|
|
// Node
|
|
|
|
node := fh.Node()
|
|
|
|
assert.Equal(t, "file1", node.Name())
|
|
|
|
|
|
|
|
// Size
|
|
|
|
assert.Equal(t, int64(16), fh.Size())
|
|
|
|
|
|
|
|
// Read 1
|
|
|
|
assert.Equal(t, "0", readString(t, fh, 1))
|
|
|
|
|
|
|
|
// Read remainder
|
|
|
|
assert.Equal(t, "123456789abcdef", readString(t, fh, 256))
|
|
|
|
|
|
|
|
// Read EOF
|
|
|
|
buf := make([]byte, 16)
|
|
|
|
_, err := fh.Read(buf)
|
|
|
|
assert.Equal(t, io.EOF, err)
|
|
|
|
|
|
|
|
// Stat
|
|
|
|
var fi os.FileInfo
|
|
|
|
fi, err = fh.Stat()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, int64(16), fi.Size())
|
|
|
|
assert.Equal(t, "file1", fi.Name())
|
|
|
|
|
|
|
|
// Close
|
|
|
|
assert.False(t, fh.closed)
|
|
|
|
assert.Equal(t, nil, fh.Close())
|
|
|
|
assert.True(t, fh.closed)
|
|
|
|
|
|
|
|
// Close again
|
2017-11-03 12:35:36 +01:00
|
|
|
assert.Equal(t, ECLOSED, fh.Close())
|
2017-10-29 22:14:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestReadFileHandleSeek(t *testing.T) {
|
|
|
|
r := fstest.NewRun(t)
|
|
|
|
defer r.Finalise()
|
|
|
|
_, fh := readHandleCreate(t, r)
|
|
|
|
|
|
|
|
assert.Equal(t, "0", readString(t, fh, 1))
|
|
|
|
|
|
|
|
// 0 means relative to the origin of the file,
|
2018-04-06 20:53:06 +02:00
|
|
|
n, err := fh.Seek(5, io.SeekStart)
|
2017-10-29 22:14:05 +01:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, int64(5), n)
|
|
|
|
assert.Equal(t, "5", readString(t, fh, 1))
|
|
|
|
|
|
|
|
// 1 means relative to the current offset
|
2018-04-06 20:53:06 +02:00
|
|
|
n, err = fh.Seek(-3, io.SeekCurrent)
|
2017-10-29 22:14:05 +01:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, int64(3), n)
|
|
|
|
assert.Equal(t, "3", readString(t, fh, 1))
|
|
|
|
|
|
|
|
// 2 means relative to the end.
|
2018-04-06 20:53:06 +02:00
|
|
|
n, err = fh.Seek(-3, io.SeekEnd)
|
2017-10-29 22:14:05 +01:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, int64(13), n)
|
|
|
|
assert.Equal(t, "d", readString(t, fh, 1))
|
|
|
|
|
|
|
|
// Seek off the end
|
2018-04-06 20:53:06 +02:00
|
|
|
n, err = fh.Seek(100, io.SeekStart)
|
2017-10-29 22:14:05 +01:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
// Get the error on read
|
|
|
|
buf := make([]byte, 16)
|
|
|
|
l, err := fh.Read(buf)
|
|
|
|
assert.Equal(t, io.EOF, err)
|
|
|
|
assert.Equal(t, 0, l)
|
|
|
|
|
|
|
|
// Check if noSeek is set we get an error
|
|
|
|
fh.noSeek = true
|
2018-04-06 20:53:06 +02:00
|
|
|
_, err = fh.Seek(0, io.SeekStart)
|
2017-10-29 22:14:05 +01:00
|
|
|
assert.Equal(t, ESPIPE, err)
|
|
|
|
|
|
|
|
// Close
|
|
|
|
assert.Equal(t, nil, fh.Close())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestReadFileHandleReadAt(t *testing.T) {
|
|
|
|
r := fstest.NewRun(t)
|
|
|
|
defer r.Finalise()
|
|
|
|
_, fh := readHandleCreate(t, r)
|
|
|
|
|
|
|
|
// read from start
|
|
|
|
buf := make([]byte, 1)
|
|
|
|
n, err := fh.ReadAt(buf, 0)
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, 1, n)
|
|
|
|
assert.Equal(t, "0", string(buf[:n]))
|
|
|
|
|
|
|
|
// seek forwards
|
|
|
|
n, err = fh.ReadAt(buf, 5)
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, 1, n)
|
|
|
|
assert.Equal(t, "5", string(buf[:n]))
|
|
|
|
|
|
|
|
// seek backwards
|
|
|
|
n, err = fh.ReadAt(buf, 1)
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, 1, n)
|
|
|
|
assert.Equal(t, "1", string(buf[:n]))
|
|
|
|
|
|
|
|
// read exactly to the end
|
|
|
|
buf = make([]byte, 6)
|
|
|
|
n, err = fh.ReadAt(buf, 10)
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, 6, n)
|
|
|
|
assert.Equal(t, "abcdef", string(buf[:n]))
|
|
|
|
|
|
|
|
// read off the end
|
|
|
|
buf = make([]byte, 256)
|
|
|
|
n, err = fh.ReadAt(buf, 10)
|
|
|
|
assert.Equal(t, io.EOF, err)
|
|
|
|
assert.Equal(t, 6, n)
|
|
|
|
assert.Equal(t, "abcdef", string(buf[:n]))
|
|
|
|
|
|
|
|
// read starting off the end
|
|
|
|
n, err = fh.ReadAt(buf, 100)
|
|
|
|
assert.Equal(t, io.EOF, err)
|
|
|
|
assert.Equal(t, 0, n)
|
|
|
|
|
|
|
|
// check noSeek gives an error
|
|
|
|
fh.noSeek = true
|
|
|
|
n, err = fh.ReadAt(buf, 100)
|
|
|
|
assert.Equal(t, ESPIPE, err)
|
|
|
|
|
|
|
|
// Properly close the file
|
|
|
|
assert.NoError(t, fh.Close())
|
|
|
|
|
|
|
|
// check reading on closed file
|
|
|
|
fh.noSeek = true
|
|
|
|
n, err = fh.ReadAt(buf, 100)
|
2017-11-03 12:35:36 +01:00
|
|
|
assert.Equal(t, ECLOSED, err)
|
2017-10-29 22:14:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestReadFileHandleFlush(t *testing.T) {
|
|
|
|
r := fstest.NewRun(t)
|
|
|
|
defer r.Finalise()
|
|
|
|
_, fh := readHandleCreate(t, r)
|
|
|
|
|
|
|
|
// Check Flush does nothing if read not called
|
|
|
|
err := fh.Flush()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.False(t, fh.closed)
|
|
|
|
|
|
|
|
// Read data
|
|
|
|
buf := make([]byte, 256)
|
|
|
|
n, err := fh.Read(buf)
|
|
|
|
assert.Equal(t, io.EOF, err)
|
|
|
|
assert.Equal(t, 16, n)
|
|
|
|
|
|
|
|
// Check Flush does nothing if read called
|
|
|
|
err = fh.Flush()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.False(t, fh.closed)
|
|
|
|
|
|
|
|
// Check flush does nothing if called again
|
|
|
|
err = fh.Flush()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.False(t, fh.closed)
|
|
|
|
|
|
|
|
// Properly close the file
|
|
|
|
assert.NoError(t, fh.Close())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestReadFileHandleRelease(t *testing.T) {
|
|
|
|
r := fstest.NewRun(t)
|
|
|
|
defer r.Finalise()
|
|
|
|
_, fh := readHandleCreate(t, r)
|
|
|
|
|
|
|
|
// Check Release does nothing if file not read from
|
|
|
|
err := fh.Release()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.False(t, fh.closed)
|
|
|
|
|
|
|
|
// Read data
|
|
|
|
buf := make([]byte, 256)
|
|
|
|
n, err := fh.Read(buf)
|
|
|
|
assert.Equal(t, io.EOF, err)
|
|
|
|
assert.Equal(t, 16, n)
|
|
|
|
|
|
|
|
// Check Release closes file
|
|
|
|
err = fh.Release()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.True(t, fh.closed)
|
|
|
|
|
|
|
|
// Check Release does nothing if called again
|
|
|
|
err = fh.Release()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.True(t, fh.closed)
|
|
|
|
}
|