github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/vfs/read_test.go (about)

     1  package vfs
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  	"os"
     7  	"testing"
     8  
     9  	"github.com/rclone/rclone/fstest"
    10  	"github.com/stretchr/testify/assert"
    11  	"github.com/stretchr/testify/require"
    12  )
    13  
    14  // Open a file for write
    15  func readHandleCreate(t *testing.T) (r *fstest.Run, vfs *VFS, fh *ReadFileHandle) {
    16  	r, vfs = newTestVFS(t)
    17  
    18  	file1 := r.WriteObject(context.Background(), "dir/file1", "0123456789abcdef", t1)
    19  	r.CheckRemoteItems(t, file1)
    20  
    21  	h, err := vfs.OpenFile("dir/file1", os.O_RDONLY, 0777)
    22  	require.NoError(t, err)
    23  	fh, ok := h.(*ReadFileHandle)
    24  	require.True(t, ok)
    25  
    26  	return r, vfs, fh
    27  }
    28  
    29  // read data from the string
    30  func readString(t *testing.T, fh *ReadFileHandle, n int) string {
    31  	buf := make([]byte, n)
    32  	n, err := fh.Read(buf)
    33  	if err != io.EOF {
    34  		assert.NoError(t, err)
    35  	}
    36  	return string(buf[:n])
    37  }
    38  
    39  func TestReadFileHandleMethods(t *testing.T) {
    40  	_, _, fh := readHandleCreate(t)
    41  
    42  	// String
    43  	assert.Equal(t, "dir/file1 (r)", fh.String())
    44  	assert.Equal(t, "<nil *ReadFileHandle>", (*ReadFileHandle)(nil).String())
    45  	assert.Equal(t, "<nil *ReadFileHandle.file>", new(ReadFileHandle).String())
    46  
    47  	// Name
    48  	assert.Equal(t, "dir/file1", fh.Name())
    49  
    50  	// Node
    51  	node := fh.Node()
    52  	assert.Equal(t, "file1", node.Name())
    53  
    54  	// Size
    55  	assert.Equal(t, int64(16), fh.Size())
    56  
    57  	// Read 1
    58  	assert.Equal(t, "0", readString(t, fh, 1))
    59  
    60  	// Read remainder
    61  	assert.Equal(t, "123456789abcdef", readString(t, fh, 256))
    62  
    63  	// Read EOF
    64  	buf := make([]byte, 16)
    65  	_, err := fh.Read(buf)
    66  	assert.Equal(t, io.EOF, err)
    67  
    68  	// Stat
    69  	var fi os.FileInfo
    70  	fi, err = fh.Stat()
    71  	assert.NoError(t, err)
    72  	assert.Equal(t, int64(16), fi.Size())
    73  	assert.Equal(t, "file1", fi.Name())
    74  
    75  	// Close
    76  	assert.False(t, fh.closed)
    77  	assert.Equal(t, nil, fh.Close())
    78  	assert.True(t, fh.closed)
    79  
    80  	// Close again
    81  	assert.Equal(t, ECLOSED, fh.Close())
    82  }
    83  
    84  func TestReadFileHandleSeek(t *testing.T) {
    85  	_, _, fh := readHandleCreate(t)
    86  
    87  	assert.Equal(t, "0", readString(t, fh, 1))
    88  
    89  	// 0 means relative to the origin of the file,
    90  	n, err := fh.Seek(5, io.SeekStart)
    91  	assert.NoError(t, err)
    92  	assert.Equal(t, int64(5), n)
    93  	assert.Equal(t, "5", readString(t, fh, 1))
    94  
    95  	// 1 means relative to the current offset
    96  	n, err = fh.Seek(-3, io.SeekCurrent)
    97  	assert.NoError(t, err)
    98  	assert.Equal(t, int64(3), n)
    99  	assert.Equal(t, "3", readString(t, fh, 1))
   100  
   101  	// 2 means relative to the end.
   102  	n, err = fh.Seek(-3, io.SeekEnd)
   103  	assert.NoError(t, err)
   104  	assert.Equal(t, int64(13), n)
   105  	assert.Equal(t, "d", readString(t, fh, 1))
   106  
   107  	// Seek off the end
   108  	_, err = fh.Seek(100, io.SeekStart)
   109  	assert.NoError(t, err)
   110  
   111  	// Get the error on read
   112  	buf := make([]byte, 16)
   113  	l, err := fh.Read(buf)
   114  	assert.Equal(t, io.EOF, err)
   115  	assert.Equal(t, 0, l)
   116  
   117  	// Check if noSeek is set we get an error
   118  	fh.noSeek = true
   119  	_, err = fh.Seek(0, io.SeekStart)
   120  	assert.Equal(t, ESPIPE, err)
   121  
   122  	// Close
   123  	assert.Equal(t, nil, fh.Close())
   124  }
   125  
   126  func TestReadFileHandleReadAt(t *testing.T) {
   127  	_, _, fh := readHandleCreate(t)
   128  
   129  	// read from start
   130  	buf := make([]byte, 1)
   131  	n, err := fh.ReadAt(buf, 0)
   132  	require.NoError(t, err)
   133  	assert.Equal(t, 1, n)
   134  	assert.Equal(t, "0", string(buf[:n]))
   135  
   136  	// seek forwards
   137  	n, err = fh.ReadAt(buf, 5)
   138  	require.NoError(t, err)
   139  	assert.Equal(t, 1, n)
   140  	assert.Equal(t, "5", string(buf[:n]))
   141  
   142  	// seek backwards
   143  	n, err = fh.ReadAt(buf, 1)
   144  	require.NoError(t, err)
   145  	assert.Equal(t, 1, n)
   146  	assert.Equal(t, "1", string(buf[:n]))
   147  
   148  	// read exactly to the end
   149  	buf = make([]byte, 6)
   150  	n, err = fh.ReadAt(buf, 10)
   151  	require.NoError(t, err)
   152  	assert.Equal(t, 6, n)
   153  	assert.Equal(t, "abcdef", string(buf[:n]))
   154  
   155  	// read off the end
   156  	buf = make([]byte, 256)
   157  	n, err = fh.ReadAt(buf, 10)
   158  	assert.Equal(t, io.EOF, err)
   159  	assert.Equal(t, 6, n)
   160  	assert.Equal(t, "abcdef", string(buf[:n]))
   161  
   162  	// read starting off the end
   163  	n, err = fh.ReadAt(buf, 100)
   164  	assert.Equal(t, io.EOF, err)
   165  	assert.Equal(t, 0, n)
   166  
   167  	// check noSeek gives an error
   168  	fh.noSeek = true
   169  	_, err = fh.ReadAt(buf, 100)
   170  	assert.Equal(t, ESPIPE, err)
   171  
   172  	// Properly close the file
   173  	assert.NoError(t, fh.Close())
   174  
   175  	// check reading on closed file
   176  	fh.noSeek = true
   177  	_, err = fh.ReadAt(buf, 100)
   178  	assert.Equal(t, ECLOSED, err)
   179  }
   180  
   181  func TestReadFileHandleFlush(t *testing.T) {
   182  	_, _, fh := readHandleCreate(t)
   183  
   184  	// Check Flush does nothing if read not called
   185  	err := fh.Flush()
   186  	assert.NoError(t, err)
   187  	assert.False(t, fh.closed)
   188  
   189  	// Read data
   190  	buf := make([]byte, 256)
   191  	n, err := fh.Read(buf)
   192  	assert.Equal(t, io.EOF, err)
   193  	assert.Equal(t, 16, n)
   194  
   195  	// Check Flush does nothing if read called
   196  	err = fh.Flush()
   197  	assert.NoError(t, err)
   198  	assert.False(t, fh.closed)
   199  
   200  	// Check flush does nothing if called again
   201  	err = fh.Flush()
   202  	assert.NoError(t, err)
   203  	assert.False(t, fh.closed)
   204  
   205  	// Properly close the file
   206  	assert.NoError(t, fh.Close())
   207  }
   208  
   209  func TestReadFileHandleRelease(t *testing.T) {
   210  	_, _, fh := readHandleCreate(t)
   211  
   212  	// Check Release does nothing if file not read from
   213  	err := fh.Release()
   214  	assert.NoError(t, err)
   215  	assert.False(t, fh.closed)
   216  
   217  	// Read data
   218  	buf := make([]byte, 256)
   219  	n, err := fh.Read(buf)
   220  	assert.Equal(t, io.EOF, err)
   221  	assert.Equal(t, 16, n)
   222  
   223  	// Check Release closes file
   224  	err = fh.Release()
   225  	assert.NoError(t, err)
   226  	assert.True(t, fh.closed)
   227  
   228  	// Check Release does nothing if called again
   229  	err = fh.Release()
   230  	assert.NoError(t, err)
   231  	assert.True(t, fh.closed)
   232  }