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