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 }