github.com/ncw/rclone@v1.48.1-0.20190724201158-a35aa1360e3e/backend/cache/cache_upload_test.go (about) 1 // +build !plan9 2 3 package cache_test 4 5 import ( 6 "context" 7 "fmt" 8 "math/rand" 9 "os" 10 "path" 11 "strconv" 12 "testing" 13 "time" 14 15 "github.com/ncw/rclone/backend/cache" 16 _ "github.com/ncw/rclone/backend/drive" 17 "github.com/ncw/rclone/fs" 18 "github.com/stretchr/testify/require" 19 ) 20 21 func TestInternalUploadTempDirCreated(t *testing.T) { 22 id := fmt.Sprintf("tiutdc%v", time.Now().Unix()) 23 rootFs, boltDb := runInstance.newCacheFs(t, remoteName, id, false, true, 24 nil, 25 map[string]string{"tmp_upload_path": path.Join(runInstance.tmpUploadDir, id)}) 26 defer runInstance.cleanupFs(t, rootFs, boltDb) 27 28 _, err := os.Stat(path.Join(runInstance.tmpUploadDir, id)) 29 require.NoError(t, err) 30 } 31 32 func testInternalUploadQueueOneFile(t *testing.T, id string, rootFs fs.Fs, boltDb *cache.Persistent) { 33 // create some rand test data 34 testSize := int64(524288000) 35 testReader := runInstance.randomReader(t, testSize) 36 bu := runInstance.listenForBackgroundUpload(t, rootFs, "one") 37 runInstance.writeRemoteReader(t, rootFs, "one", testReader) 38 // validate that it exists in temp fs 39 ti, err := os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "one"))) 40 require.NoError(t, err) 41 42 if runInstance.rootIsCrypt { 43 require.Equal(t, int64(524416032), ti.Size()) 44 } else { 45 require.Equal(t, testSize, ti.Size()) 46 } 47 de1, err := runInstance.list(t, rootFs, "") 48 require.NoError(t, err) 49 require.Len(t, de1, 1) 50 51 runInstance.completeBackgroundUpload(t, "one", bu) 52 // check if it was removed from temp fs 53 _, err = os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "one"))) 54 require.True(t, os.IsNotExist(err)) 55 56 // check if it can be read 57 data2, err := runInstance.readDataFromRemote(t, rootFs, "one", 0, int64(1024), false) 58 require.NoError(t, err) 59 require.Len(t, data2, 1024) 60 } 61 62 func TestInternalUploadQueueOneFileNoRest(t *testing.T) { 63 id := fmt.Sprintf("tiuqofnr%v", time.Now().Unix()) 64 rootFs, boltDb := runInstance.newCacheFs(t, remoteName, id, true, true, 65 nil, 66 map[string]string{"tmp_upload_path": path.Join(runInstance.tmpUploadDir, id), "tmp_wait_time": "0s"}) 67 defer runInstance.cleanupFs(t, rootFs, boltDb) 68 69 testInternalUploadQueueOneFile(t, id, rootFs, boltDb) 70 } 71 72 func TestInternalUploadQueueOneFileWithRest(t *testing.T) { 73 id := fmt.Sprintf("tiuqofwr%v", time.Now().Unix()) 74 rootFs, boltDb := runInstance.newCacheFs(t, remoteName, id, true, true, 75 nil, 76 map[string]string{"tmp_upload_path": path.Join(runInstance.tmpUploadDir, id), "tmp_wait_time": "1m"}) 77 defer runInstance.cleanupFs(t, rootFs, boltDb) 78 79 testInternalUploadQueueOneFile(t, id, rootFs, boltDb) 80 } 81 82 func TestInternalUploadMoveExistingFile(t *testing.T) { 83 id := fmt.Sprintf("tiumef%v", time.Now().Unix()) 84 rootFs, boltDb := runInstance.newCacheFs(t, remoteName, id, true, true, 85 nil, 86 map[string]string{"tmp_upload_path": path.Join(runInstance.tmpUploadDir, id), "tmp_wait_time": "3s"}) 87 defer runInstance.cleanupFs(t, rootFs, boltDb) 88 89 err := rootFs.Mkdir(context.Background(), "one") 90 require.NoError(t, err) 91 err = rootFs.Mkdir(context.Background(), "one/test") 92 require.NoError(t, err) 93 err = rootFs.Mkdir(context.Background(), "second") 94 require.NoError(t, err) 95 96 // create some rand test data 97 testSize := int64(10485760) 98 testReader := runInstance.randomReader(t, testSize) 99 runInstance.writeObjectReader(t, rootFs, "one/test/data.bin", testReader) 100 runInstance.completeAllBackgroundUploads(t, rootFs, "one/test/data.bin") 101 102 de1, err := runInstance.list(t, rootFs, "one/test") 103 require.NoError(t, err) 104 require.Len(t, de1, 1) 105 106 time.Sleep(time.Second * 5) 107 //_ = os.Remove(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "one/test"))) 108 //require.NoError(t, err) 109 110 err = runInstance.dirMove(t, rootFs, "one/test", "second/test") 111 require.NoError(t, err) 112 113 // check if it can be read 114 de1, err = runInstance.list(t, rootFs, "second/test") 115 require.NoError(t, err) 116 require.Len(t, de1, 1) 117 } 118 119 func TestInternalUploadTempPathCleaned(t *testing.T) { 120 id := fmt.Sprintf("tiutpc%v", time.Now().Unix()) 121 rootFs, boltDb := runInstance.newCacheFs(t, remoteName, id, true, true, 122 nil, 123 map[string]string{"cache-tmp-upload-path": path.Join(runInstance.tmpUploadDir, id), "cache-tmp-wait-time": "5s"}) 124 defer runInstance.cleanupFs(t, rootFs, boltDb) 125 126 err := rootFs.Mkdir(context.Background(), "one") 127 require.NoError(t, err) 128 err = rootFs.Mkdir(context.Background(), "one/test") 129 require.NoError(t, err) 130 err = rootFs.Mkdir(context.Background(), "second") 131 require.NoError(t, err) 132 133 // create some rand test data 134 testSize := int64(1048576) 135 testReader := runInstance.randomReader(t, testSize) 136 testReader2 := runInstance.randomReader(t, testSize) 137 runInstance.writeObjectReader(t, rootFs, "one/test/data.bin", testReader) 138 runInstance.writeObjectReader(t, rootFs, "second/data.bin", testReader2) 139 140 runInstance.completeAllBackgroundUploads(t, rootFs, "one/test/data.bin") 141 _, err = os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "one/test"))) 142 require.True(t, os.IsNotExist(err)) 143 _, err = os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "one"))) 144 require.True(t, os.IsNotExist(err)) 145 _, err = os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "second"))) 146 require.False(t, os.IsNotExist(err)) 147 148 runInstance.completeAllBackgroundUploads(t, rootFs, "second/data.bin") 149 _, err = os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "second/data.bin"))) 150 require.True(t, os.IsNotExist(err)) 151 152 de1, err := runInstance.list(t, rootFs, "one/test") 153 require.NoError(t, err) 154 require.Len(t, de1, 1) 155 156 // check if it can be read 157 de1, err = runInstance.list(t, rootFs, "second") 158 require.NoError(t, err) 159 require.Len(t, de1, 1) 160 } 161 162 func TestInternalUploadQueueMoreFiles(t *testing.T) { 163 id := fmt.Sprintf("tiuqmf%v", time.Now().Unix()) 164 rootFs, boltDb := runInstance.newCacheFs(t, remoteName, id, true, true, 165 nil, 166 map[string]string{"tmp_upload_path": path.Join(runInstance.tmpUploadDir, id), "tmp_wait_time": "1s"}) 167 defer runInstance.cleanupFs(t, rootFs, boltDb) 168 169 err := rootFs.Mkdir(context.Background(), "test") 170 require.NoError(t, err) 171 minSize := 5242880 172 maxSize := 10485760 173 totalFiles := 10 174 rand.Seed(time.Now().Unix()) 175 176 lastFile := "" 177 for i := 0; i < totalFiles; i++ { 178 size := int64(rand.Intn(maxSize-minSize) + minSize) 179 testReader := runInstance.randomReader(t, size) 180 remote := "test/" + strconv.Itoa(i) + ".bin" 181 runInstance.writeRemoteReader(t, rootFs, remote, testReader) 182 183 // validate that it exists in temp fs 184 ti, err := os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, remote))) 185 require.NoError(t, err) 186 require.Equal(t, size, runInstance.cleanSize(t, ti.Size())) 187 188 if runInstance.wrappedIsExternal && i < totalFiles-1 { 189 time.Sleep(time.Second * 3) 190 } 191 lastFile = remote 192 } 193 194 // check if cache lists all files, likely temp upload didn't finish yet 195 de1, err := runInstance.list(t, rootFs, "test") 196 require.NoError(t, err) 197 require.Len(t, de1, totalFiles) 198 199 // wait for background uploader to do its thing 200 runInstance.completeAllBackgroundUploads(t, rootFs, lastFile) 201 202 // retry until we have no more temp files and fail if they don't go down to 0 203 _, err = os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "test"))) 204 require.True(t, os.IsNotExist(err)) 205 206 // check if cache lists all files 207 de1, err = runInstance.list(t, rootFs, "test") 208 require.NoError(t, err) 209 require.Len(t, de1, totalFiles) 210 } 211 212 func TestInternalUploadTempFileOperations(t *testing.T) { 213 id := "tiutfo" 214 rootFs, boltDb := runInstance.newCacheFs(t, remoteName, id, true, true, 215 nil, 216 map[string]string{"tmp_upload_path": path.Join(runInstance.tmpUploadDir, id), "tmp_wait_time": "1h"}) 217 defer runInstance.cleanupFs(t, rootFs, boltDb) 218 219 boltDb.PurgeTempUploads() 220 221 // create some rand test data 222 runInstance.mkdir(t, rootFs, "test") 223 runInstance.writeRemoteString(t, rootFs, "test/one", "one content") 224 225 // check if it can be read 226 data1, err := runInstance.readDataFromRemote(t, rootFs, "test/one", 0, int64(len([]byte("one content"))), false) 227 require.NoError(t, err) 228 require.Equal(t, []byte("one content"), data1) 229 // validate that it exists in temp fs 230 _, err = os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "test/one"))) 231 require.NoError(t, err) 232 233 // test DirMove - allowed 234 err = runInstance.dirMove(t, rootFs, "test", "second") 235 if err != errNotSupported { 236 require.NoError(t, err) 237 _, err = rootFs.NewObject(context.Background(), "test/one") 238 require.Error(t, err) 239 _, err = rootFs.NewObject(context.Background(), "second/one") 240 require.NoError(t, err) 241 // validate that it exists in temp fs 242 _, err = os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "test/one"))) 243 require.Error(t, err) 244 _, err = os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "second/one"))) 245 require.NoError(t, err) 246 _, err = boltDb.SearchPendingUpload(runInstance.encryptRemoteIfNeeded(t, path.Join(id, "test/one"))) 247 require.Error(t, err) 248 var started bool 249 started, err = boltDb.SearchPendingUpload(runInstance.encryptRemoteIfNeeded(t, path.Join(id, "second/one"))) 250 require.NoError(t, err) 251 require.False(t, started) 252 runInstance.mkdir(t, rootFs, "test") 253 runInstance.writeRemoteString(t, rootFs, "test/one", "one content") 254 } 255 256 // test Rmdir - allowed 257 err = runInstance.rm(t, rootFs, "test") 258 require.Error(t, err) 259 require.Contains(t, err.Error(), "directory not empty") 260 _, err = rootFs.NewObject(context.Background(), "test/one") 261 require.NoError(t, err) 262 // validate that it exists in temp fs 263 _, err = os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "test/one"))) 264 require.NoError(t, err) 265 started, err := boltDb.SearchPendingUpload(runInstance.encryptRemoteIfNeeded(t, path.Join(id, "test/one"))) 266 require.False(t, started) 267 require.NoError(t, err) 268 269 // test Move/Rename -- allowed 270 err = runInstance.move(t, rootFs, path.Join("test", "one"), path.Join("test", "second")) 271 if err != errNotSupported { 272 require.NoError(t, err) 273 // try to read from it 274 _, err = rootFs.NewObject(context.Background(), "test/one") 275 require.Error(t, err) 276 _, err = rootFs.NewObject(context.Background(), "test/second") 277 require.NoError(t, err) 278 data2, err := runInstance.readDataFromRemote(t, rootFs, "test/second", 0, int64(len([]byte("one content"))), false) 279 require.NoError(t, err) 280 require.Equal(t, []byte("one content"), data2) 281 // validate that it exists in temp fs 282 _, err = os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "test/one"))) 283 require.Error(t, err) 284 _, err = os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "test/second"))) 285 require.NoError(t, err) 286 runInstance.writeRemoteString(t, rootFs, "test/one", "one content") 287 } 288 289 // test Copy -- allowed 290 err = runInstance.copy(t, rootFs, path.Join("test", "one"), path.Join("test", "third")) 291 if err != errNotSupported { 292 require.NoError(t, err) 293 _, err = rootFs.NewObject(context.Background(), "test/one") 294 require.NoError(t, err) 295 _, err = rootFs.NewObject(context.Background(), "test/third") 296 require.NoError(t, err) 297 data2, err := runInstance.readDataFromRemote(t, rootFs, "test/third", 0, int64(len([]byte("one content"))), false) 298 require.NoError(t, err) 299 require.Equal(t, []byte("one content"), data2) 300 // validate that it exists in temp fs 301 _, err = os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "test/one"))) 302 require.NoError(t, err) 303 _, err = os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "test/third"))) 304 require.NoError(t, err) 305 } 306 307 // test Remove -- allowed 308 err = runInstance.rm(t, rootFs, "test/one") 309 require.NoError(t, err) 310 _, err = rootFs.NewObject(context.Background(), "test/one") 311 require.Error(t, err) 312 // validate that it doesn't exist in temp fs 313 _, err = os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "test/one"))) 314 require.Error(t, err) 315 runInstance.writeRemoteString(t, rootFs, "test/one", "one content") 316 317 // test Update -- allowed 318 firstModTime, err := runInstance.modTime(t, rootFs, "test/one") 319 require.NoError(t, err) 320 err = runInstance.updateData(t, rootFs, "test/one", "one content", " updated") 321 require.NoError(t, err) 322 obj2, err := rootFs.NewObject(context.Background(), "test/one") 323 require.NoError(t, err) 324 data2 := runInstance.readDataFromObj(t, obj2, 0, int64(len("one content updated")), false) 325 require.Equal(t, "one content updated", string(data2)) 326 tmpInfo, err := os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "test/one"))) 327 require.NoError(t, err) 328 if runInstance.rootIsCrypt { 329 require.Equal(t, int64(67), tmpInfo.Size()) 330 } else { 331 require.Equal(t, int64(len(data2)), tmpInfo.Size()) 332 } 333 334 // test SetModTime -- allowed 335 secondModTime, err := runInstance.modTime(t, rootFs, "test/one") 336 require.NoError(t, err) 337 require.NotEqual(t, secondModTime, firstModTime) 338 require.NotEqual(t, time.Time{}, firstModTime) 339 require.NotEqual(t, time.Time{}, secondModTime) 340 } 341 342 func TestInternalUploadUploadingFileOperations(t *testing.T) { 343 id := "tiuufo" 344 rootFs, boltDb := runInstance.newCacheFs(t, remoteName, id, true, true, 345 nil, 346 map[string]string{"tmp_upload_path": path.Join(runInstance.tmpUploadDir, id), "tmp_wait_time": "1h"}) 347 defer runInstance.cleanupFs(t, rootFs, boltDb) 348 349 boltDb.PurgeTempUploads() 350 351 // create some rand test data 352 runInstance.mkdir(t, rootFs, "test") 353 runInstance.writeRemoteString(t, rootFs, "test/one", "one content") 354 355 // check if it can be read 356 data1, err := runInstance.readDataFromRemote(t, rootFs, "test/one", 0, int64(len([]byte("one content"))), false) 357 require.NoError(t, err) 358 require.Equal(t, []byte("one content"), data1) 359 // validate that it exists in temp fs 360 _, err = os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "test/one"))) 361 require.NoError(t, err) 362 363 err = boltDb.SetPendingUploadToStarted(runInstance.encryptRemoteIfNeeded(t, path.Join(rootFs.Root(), "test/one"))) 364 require.NoError(t, err) 365 366 // test DirMove 367 err = runInstance.dirMove(t, rootFs, "test", "second") 368 if err != errNotSupported { 369 require.Error(t, err) 370 _, err = rootFs.NewObject(context.Background(), "test/one") 371 require.NoError(t, err) 372 // validate that it exists in temp fs 373 _, err = os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "test/one"))) 374 require.NoError(t, err) 375 _, err = os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "second/one"))) 376 require.Error(t, err) 377 } 378 379 // test Rmdir 380 err = runInstance.rm(t, rootFs, "test") 381 require.Error(t, err) 382 _, err = rootFs.NewObject(context.Background(), "test/one") 383 require.NoError(t, err) 384 // validate that it doesn't exist in temp fs 385 _, err = os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "test/one"))) 386 require.NoError(t, err) 387 388 // test Move/Rename 389 err = runInstance.move(t, rootFs, path.Join("test", "one"), path.Join("test", "second")) 390 if err != errNotSupported { 391 require.Error(t, err) 392 // try to read from it 393 _, err = rootFs.NewObject(context.Background(), "test/one") 394 require.NoError(t, err) 395 _, err = rootFs.NewObject(context.Background(), "test/second") 396 require.Error(t, err) 397 // validate that it exists in temp fs 398 _, err = os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "test/one"))) 399 require.NoError(t, err) 400 _, err = os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "test/second"))) 401 require.Error(t, err) 402 } 403 404 // test Copy -- allowed 405 err = runInstance.copy(t, rootFs, path.Join("test", "one"), path.Join("test", "third")) 406 if err != errNotSupported { 407 require.NoError(t, err) 408 _, err = rootFs.NewObject(context.Background(), "test/one") 409 require.NoError(t, err) 410 _, err = rootFs.NewObject(context.Background(), "test/third") 411 require.NoError(t, err) 412 data2, err := runInstance.readDataFromRemote(t, rootFs, "test/third", 0, int64(len([]byte("one content"))), false) 413 require.NoError(t, err) 414 require.Equal(t, []byte("one content"), data2) 415 // validate that it exists in temp fs 416 _, err = os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "test/one"))) 417 require.NoError(t, err) 418 _, err = os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "test/third"))) 419 require.NoError(t, err) 420 } 421 422 // test Remove 423 err = runInstance.rm(t, rootFs, "test/one") 424 require.Error(t, err) 425 _, err = rootFs.NewObject(context.Background(), "test/one") 426 require.NoError(t, err) 427 // validate that it doesn't exist in temp fs 428 _, err = os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "test/one"))) 429 require.NoError(t, err) 430 runInstance.writeRemoteString(t, rootFs, "test/one", "one content") 431 432 // test Update - this seems to work. Why? FIXME 433 //firstModTime, err := runInstance.modTime(t, rootFs, "test/one") 434 //require.NoError(t, err) 435 //err = runInstance.updateData(t, rootFs, "test/one", "one content", " updated", func() { 436 // data2 := runInstance.readDataFromRemote(t, rootFs, "test/one", 0, int64(len("one content updated")), true) 437 // require.Equal(t, "one content", string(data2)) 438 // 439 // tmpInfo, err := os.Stat(path.Join(runInstance.tmpUploadDir, id, runInstance.encryptRemoteIfNeeded(t, "test/one"))) 440 // require.NoError(t, err) 441 // if runInstance.rootIsCrypt { 442 // require.Equal(t, int64(67), tmpInfo.Size()) 443 // } else { 444 // require.Equal(t, int64(len(data2)), tmpInfo.Size()) 445 // } 446 //}) 447 //require.Error(t, err) 448 449 // test SetModTime -- seems to work cause of previous 450 //secondModTime, err := runInstance.modTime(t, rootFs, "test/one") 451 //require.NoError(t, err) 452 //require.Equal(t, secondModTime, firstModTime) 453 //require.NotEqual(t, time.Time{}, firstModTime) 454 //require.NotEqual(t, time.Time{}, secondModTime) 455 }