github.com/xhghs/rclone@v1.51.1-0.20200430155106-e186a28cced8/fs/sync/sync_test.go (about) 1 // Test sync/copy/move 2 3 package sync 4 5 import ( 6 "context" 7 "fmt" 8 "runtime" 9 "strings" 10 "testing" 11 "time" 12 13 "github.com/pkg/errors" 14 _ "github.com/rclone/rclone/backend/all" // import all backends 15 "github.com/rclone/rclone/fs" 16 "github.com/rclone/rclone/fs/accounting" 17 "github.com/rclone/rclone/fs/filter" 18 "github.com/rclone/rclone/fs/fserrors" 19 "github.com/rclone/rclone/fs/hash" 20 "github.com/rclone/rclone/fs/operations" 21 "github.com/rclone/rclone/fstest" 22 "github.com/stretchr/testify/assert" 23 "github.com/stretchr/testify/require" 24 "golang.org/x/text/unicode/norm" 25 ) 26 27 // Some times used in the tests 28 var ( 29 t1 = fstest.Time("2001-02-03T04:05:06.499999999Z") 30 t2 = fstest.Time("2011-12-25T12:59:59.123456789Z") 31 t3 = fstest.Time("2011-12-30T12:59:59.000000000Z") 32 ) 33 34 // TestMain drives the tests 35 func TestMain(m *testing.M) { 36 fstest.TestMain(m) 37 } 38 39 // Check dry run is working 40 func TestCopyWithDryRun(t *testing.T) { 41 r := fstest.NewRun(t) 42 defer r.Finalise() 43 file1 := r.WriteFile("sub dir/hello world", "hello world", t1) 44 r.Mkdir(context.Background(), r.Fremote) 45 46 fs.Config.DryRun = true 47 err := CopyDir(context.Background(), r.Fremote, r.Flocal, false) 48 fs.Config.DryRun = false 49 require.NoError(t, err) 50 51 fstest.CheckItems(t, r.Flocal, file1) 52 fstest.CheckItems(t, r.Fremote) 53 } 54 55 // Now without dry run 56 func TestCopy(t *testing.T) { 57 r := fstest.NewRun(t) 58 defer r.Finalise() 59 file1 := r.WriteFile("sub dir/hello world", "hello world", t1) 60 r.Mkdir(context.Background(), r.Fremote) 61 62 err := CopyDir(context.Background(), r.Fremote, r.Flocal, false) 63 require.NoError(t, err) 64 65 fstest.CheckItems(t, r.Flocal, file1) 66 fstest.CheckItems(t, r.Fremote, file1) 67 } 68 69 func TestCopyMissingDirectory(t *testing.T) { 70 r := fstest.NewRun(t) 71 defer r.Finalise() 72 r.Mkdir(context.Background(), r.Fremote) 73 74 nonExistingFs, err := fs.NewFs("/non-existing") 75 if err != nil { 76 t.Fatal(err) 77 } 78 79 err = CopyDir(context.Background(), r.Fremote, nonExistingFs, false) 80 require.Error(t, err) 81 } 82 83 // Now with --no-traverse 84 func TestCopyNoTraverse(t *testing.T) { 85 r := fstest.NewRun(t) 86 defer r.Finalise() 87 88 fs.Config.NoTraverse = true 89 defer func() { fs.Config.NoTraverse = false }() 90 91 file1 := r.WriteFile("sub dir/hello world", "hello world", t1) 92 93 err := CopyDir(context.Background(), r.Fremote, r.Flocal, false) 94 require.NoError(t, err) 95 96 fstest.CheckItems(t, r.Flocal, file1) 97 fstest.CheckItems(t, r.Fremote, file1) 98 } 99 100 // Now with --no-traverse 101 func TestSyncNoTraverse(t *testing.T) { 102 r := fstest.NewRun(t) 103 defer r.Finalise() 104 105 fs.Config.NoTraverse = true 106 defer func() { fs.Config.NoTraverse = false }() 107 108 file1 := r.WriteFile("sub dir/hello world", "hello world", t1) 109 110 accounting.GlobalStats().ResetCounters() 111 err := Sync(context.Background(), r.Fremote, r.Flocal, false) 112 require.NoError(t, err) 113 114 fstest.CheckItems(t, r.Flocal, file1) 115 fstest.CheckItems(t, r.Fremote, file1) 116 } 117 118 // Test copy with depth 119 func TestCopyWithDepth(t *testing.T) { 120 r := fstest.NewRun(t) 121 defer r.Finalise() 122 file1 := r.WriteFile("sub dir/hello world", "hello world", t1) 123 file2 := r.WriteFile("hello world2", "hello world2", t2) 124 125 // Check the MaxDepth too 126 fs.Config.MaxDepth = 1 127 defer func() { fs.Config.MaxDepth = -1 }() 128 129 err := CopyDir(context.Background(), r.Fremote, r.Flocal, false) 130 require.NoError(t, err) 131 132 fstest.CheckItems(t, r.Flocal, file1, file2) 133 fstest.CheckItems(t, r.Fremote, file2) 134 } 135 136 // Test copy with files from 137 func testCopyWithFilesFrom(t *testing.T, noTraverse bool) { 138 r := fstest.NewRun(t) 139 defer r.Finalise() 140 file1 := r.WriteFile("potato2", "hello world", t1) 141 file2 := r.WriteFile("hello world2", "hello world2", t2) 142 143 // Set the --files-from equivalent 144 f, err := filter.NewFilter(nil) 145 require.NoError(t, err) 146 require.NoError(t, f.AddFile("potato2")) 147 require.NoError(t, f.AddFile("notfound")) 148 149 // Monkey patch the active filter 150 oldFilter := filter.Active 151 oldNoTraverse := fs.Config.NoTraverse 152 filter.Active = f 153 fs.Config.NoTraverse = noTraverse 154 unpatch := func() { 155 filter.Active = oldFilter 156 fs.Config.NoTraverse = oldNoTraverse 157 } 158 defer unpatch() 159 160 err = CopyDir(context.Background(), r.Fremote, r.Flocal, false) 161 require.NoError(t, err) 162 unpatch() 163 164 fstest.CheckItems(t, r.Flocal, file1, file2) 165 fstest.CheckItems(t, r.Fremote, file1) 166 } 167 func TestCopyWithFilesFrom(t *testing.T) { testCopyWithFilesFrom(t, false) } 168 func TestCopyWithFilesFromAndNoTraverse(t *testing.T) { testCopyWithFilesFrom(t, true) } 169 170 // Test copy empty directories 171 func TestCopyEmptyDirectories(t *testing.T) { 172 r := fstest.NewRun(t) 173 defer r.Finalise() 174 file1 := r.WriteFile("sub dir/hello world", "hello world", t1) 175 err := operations.Mkdir(context.Background(), r.Flocal, "sub dir2") 176 require.NoError(t, err) 177 r.Mkdir(context.Background(), r.Fremote) 178 179 err = CopyDir(context.Background(), r.Fremote, r.Flocal, true) 180 require.NoError(t, err) 181 182 fstest.CheckListingWithPrecision( 183 t, 184 r.Fremote, 185 []fstest.Item{ 186 file1, 187 }, 188 []string{ 189 "sub dir", 190 "sub dir2", 191 }, 192 fs.GetModifyWindow(r.Fremote), 193 ) 194 } 195 196 // Test move empty directories 197 func TestMoveEmptyDirectories(t *testing.T) { 198 r := fstest.NewRun(t) 199 defer r.Finalise() 200 file1 := r.WriteFile("sub dir/hello world", "hello world", t1) 201 err := operations.Mkdir(context.Background(), r.Flocal, "sub dir2") 202 require.NoError(t, err) 203 r.Mkdir(context.Background(), r.Fremote) 204 205 err = MoveDir(context.Background(), r.Fremote, r.Flocal, false, true) 206 require.NoError(t, err) 207 208 fstest.CheckListingWithPrecision( 209 t, 210 r.Fremote, 211 []fstest.Item{ 212 file1, 213 }, 214 []string{ 215 "sub dir", 216 "sub dir2", 217 }, 218 fs.GetModifyWindow(r.Fremote), 219 ) 220 } 221 222 // Test sync empty directories 223 func TestSyncEmptyDirectories(t *testing.T) { 224 r := fstest.NewRun(t) 225 defer r.Finalise() 226 file1 := r.WriteFile("sub dir/hello world", "hello world", t1) 227 err := operations.Mkdir(context.Background(), r.Flocal, "sub dir2") 228 require.NoError(t, err) 229 r.Mkdir(context.Background(), r.Fremote) 230 231 err = Sync(context.Background(), r.Fremote, r.Flocal, true) 232 require.NoError(t, err) 233 234 fstest.CheckListingWithPrecision( 235 t, 236 r.Fremote, 237 []fstest.Item{ 238 file1, 239 }, 240 []string{ 241 "sub dir", 242 "sub dir2", 243 }, 244 fs.GetModifyWindow(r.Fremote), 245 ) 246 } 247 248 // Test a server side copy if possible, or the backup path if not 249 func TestServerSideCopy(t *testing.T) { 250 r := fstest.NewRun(t) 251 defer r.Finalise() 252 file1 := r.WriteObject(context.Background(), "sub dir/hello world", "hello world", t1) 253 fstest.CheckItems(t, r.Fremote, file1) 254 255 FremoteCopy, _, finaliseCopy, err := fstest.RandomRemote() 256 require.NoError(t, err) 257 defer finaliseCopy() 258 t.Logf("Server side copy (if possible) %v -> %v", r.Fremote, FremoteCopy) 259 260 err = CopyDir(context.Background(), FremoteCopy, r.Fremote, false) 261 require.NoError(t, err) 262 263 fstest.CheckItems(t, FremoteCopy, file1) 264 } 265 266 // Check that if the local file doesn't exist when we copy it up, 267 // nothing happens to the remote file 268 func TestCopyAfterDelete(t *testing.T) { 269 r := fstest.NewRun(t) 270 defer r.Finalise() 271 file1 := r.WriteObject(context.Background(), "sub dir/hello world", "hello world", t1) 272 fstest.CheckItems(t, r.Flocal) 273 fstest.CheckItems(t, r.Fremote, file1) 274 275 err := operations.Mkdir(context.Background(), r.Flocal, "") 276 require.NoError(t, err) 277 278 err = CopyDir(context.Background(), r.Fremote, r.Flocal, false) 279 require.NoError(t, err) 280 281 fstest.CheckItems(t, r.Flocal) 282 fstest.CheckItems(t, r.Fremote, file1) 283 } 284 285 // Check the copy downloading a file 286 func TestCopyRedownload(t *testing.T) { 287 r := fstest.NewRun(t) 288 defer r.Finalise() 289 file1 := r.WriteObject(context.Background(), "sub dir/hello world", "hello world", t1) 290 fstest.CheckItems(t, r.Fremote, file1) 291 292 err := CopyDir(context.Background(), r.Flocal, r.Fremote, false) 293 require.NoError(t, err) 294 295 // Test with combined precision of local and remote as we copied it there and back 296 fstest.CheckListingWithPrecision(t, r.Flocal, []fstest.Item{file1}, nil, fs.GetModifyWindow(r.Flocal, r.Fremote)) 297 } 298 299 // Create a file and sync it. Change the last modified date and resync. 300 // If we're only doing sync by size and checksum, we expect nothing to 301 // to be transferred on the second sync. 302 func TestSyncBasedOnCheckSum(t *testing.T) { 303 r := fstest.NewRun(t) 304 defer r.Finalise() 305 fs.Config.CheckSum = true 306 defer func() { fs.Config.CheckSum = false }() 307 308 file1 := r.WriteFile("check sum", "-", t1) 309 fstest.CheckItems(t, r.Flocal, file1) 310 311 accounting.GlobalStats().ResetCounters() 312 err := Sync(context.Background(), r.Fremote, r.Flocal, false) 313 require.NoError(t, err) 314 315 // We should have transferred exactly one file. 316 assert.Equal(t, toyFileTransfers(r), accounting.GlobalStats().GetTransfers()) 317 fstest.CheckItems(t, r.Fremote, file1) 318 319 // Change last modified date only 320 file2 := r.WriteFile("check sum", "-", t2) 321 fstest.CheckItems(t, r.Flocal, file2) 322 323 accounting.GlobalStats().ResetCounters() 324 err = Sync(context.Background(), r.Fremote, r.Flocal, false) 325 require.NoError(t, err) 326 327 // We should have transferred no files 328 assert.Equal(t, int64(0), accounting.GlobalStats().GetTransfers()) 329 fstest.CheckItems(t, r.Flocal, file2) 330 fstest.CheckItems(t, r.Fremote, file1) 331 } 332 333 // Create a file and sync it. Change the last modified date and the 334 // file contents but not the size. If we're only doing sync by size 335 // only, we expect nothing to to be transferred on the second sync. 336 func TestSyncSizeOnly(t *testing.T) { 337 r := fstest.NewRun(t) 338 defer r.Finalise() 339 fs.Config.SizeOnly = true 340 defer func() { fs.Config.SizeOnly = false }() 341 342 file1 := r.WriteFile("sizeonly", "potato", t1) 343 fstest.CheckItems(t, r.Flocal, file1) 344 345 accounting.GlobalStats().ResetCounters() 346 err := Sync(context.Background(), r.Fremote, r.Flocal, false) 347 require.NoError(t, err) 348 349 // We should have transferred exactly one file. 350 assert.Equal(t, toyFileTransfers(r), accounting.GlobalStats().GetTransfers()) 351 fstest.CheckItems(t, r.Fremote, file1) 352 353 // Update mtime, md5sum but not length of file 354 file2 := r.WriteFile("sizeonly", "POTATO", t2) 355 fstest.CheckItems(t, r.Flocal, file2) 356 357 accounting.GlobalStats().ResetCounters() 358 err = Sync(context.Background(), r.Fremote, r.Flocal, false) 359 require.NoError(t, err) 360 361 // We should have transferred no files 362 assert.Equal(t, int64(0), accounting.GlobalStats().GetTransfers()) 363 fstest.CheckItems(t, r.Flocal, file2) 364 fstest.CheckItems(t, r.Fremote, file1) 365 } 366 367 // Create a file and sync it. Keep the last modified date but change 368 // the size. With --ignore-size we expect nothing to to be 369 // transferred on the second sync. 370 func TestSyncIgnoreSize(t *testing.T) { 371 r := fstest.NewRun(t) 372 defer r.Finalise() 373 fs.Config.IgnoreSize = true 374 defer func() { fs.Config.IgnoreSize = false }() 375 376 file1 := r.WriteFile("ignore-size", "contents", t1) 377 fstest.CheckItems(t, r.Flocal, file1) 378 379 accounting.GlobalStats().ResetCounters() 380 err := Sync(context.Background(), r.Fremote, r.Flocal, false) 381 require.NoError(t, err) 382 383 // We should have transferred exactly one file. 384 assert.Equal(t, toyFileTransfers(r), accounting.GlobalStats().GetTransfers()) 385 fstest.CheckItems(t, r.Fremote, file1) 386 387 // Update size but not date of file 388 file2 := r.WriteFile("ignore-size", "longer contents but same date", t1) 389 fstest.CheckItems(t, r.Flocal, file2) 390 391 accounting.GlobalStats().ResetCounters() 392 err = Sync(context.Background(), r.Fremote, r.Flocal, false) 393 require.NoError(t, err) 394 395 // We should have transferred no files 396 assert.Equal(t, int64(0), accounting.GlobalStats().GetTransfers()) 397 fstest.CheckItems(t, r.Flocal, file2) 398 fstest.CheckItems(t, r.Fremote, file1) 399 } 400 401 func TestSyncIgnoreTimes(t *testing.T) { 402 r := fstest.NewRun(t) 403 defer r.Finalise() 404 file1 := r.WriteBoth(context.Background(), "existing", "potato", t1) 405 fstest.CheckItems(t, r.Fremote, file1) 406 407 accounting.GlobalStats().ResetCounters() 408 err := Sync(context.Background(), r.Fremote, r.Flocal, false) 409 require.NoError(t, err) 410 411 // We should have transferred exactly 0 files because the 412 // files were identical. 413 assert.Equal(t, int64(0), accounting.GlobalStats().GetTransfers()) 414 415 fs.Config.IgnoreTimes = true 416 defer func() { fs.Config.IgnoreTimes = false }() 417 418 accounting.GlobalStats().ResetCounters() 419 err = Sync(context.Background(), r.Fremote, r.Flocal, false) 420 require.NoError(t, err) 421 422 // We should have transferred exactly one file even though the 423 // files were identical. 424 assert.Equal(t, toyFileTransfers(r), accounting.GlobalStats().GetTransfers()) 425 426 fstest.CheckItems(t, r.Flocal, file1) 427 fstest.CheckItems(t, r.Fremote, file1) 428 } 429 430 func TestSyncIgnoreExisting(t *testing.T) { 431 r := fstest.NewRun(t) 432 defer r.Finalise() 433 file1 := r.WriteFile("existing", "potato", t1) 434 435 fs.Config.IgnoreExisting = true 436 defer func() { fs.Config.IgnoreExisting = false }() 437 438 accounting.GlobalStats().ResetCounters() 439 err := Sync(context.Background(), r.Fremote, r.Flocal, false) 440 require.NoError(t, err) 441 fstest.CheckItems(t, r.Flocal, file1) 442 fstest.CheckItems(t, r.Fremote, file1) 443 444 // Change everything 445 r.WriteFile("existing", "newpotatoes", t2) 446 accounting.GlobalStats().ResetCounters() 447 err = Sync(context.Background(), r.Fremote, r.Flocal, false) 448 require.NoError(t, err) 449 // Items should not change 450 fstest.CheckItems(t, r.Fremote, file1) 451 } 452 453 func TestSyncIgnoreErrors(t *testing.T) { 454 r := fstest.NewRun(t) 455 fs.Config.IgnoreErrors = true 456 defer func() { 457 fs.Config.IgnoreErrors = false 458 r.Finalise() 459 }() 460 file1 := r.WriteFile("a/potato2", "------------------------------------------------------------", t1) 461 file2 := r.WriteObject(context.Background(), "b/potato", "SMALLER BUT SAME DATE", t2) 462 file3 := r.WriteBoth(context.Background(), "c/non empty space", "AhHa!", t2) 463 require.NoError(t, operations.Mkdir(context.Background(), r.Fremote, "d")) 464 465 fstest.CheckListingWithPrecision( 466 t, 467 r.Flocal, 468 []fstest.Item{ 469 file1, 470 file3, 471 }, 472 []string{ 473 "a", 474 "c", 475 }, 476 fs.GetModifyWindow(r.Fremote), 477 ) 478 fstest.CheckListingWithPrecision( 479 t, 480 r.Fremote, 481 []fstest.Item{ 482 file2, 483 file3, 484 }, 485 []string{ 486 "b", 487 "c", 488 "d", 489 }, 490 fs.GetModifyWindow(r.Fremote), 491 ) 492 493 accounting.GlobalStats().ResetCounters() 494 _ = fs.CountError(errors.New("boom")) 495 assert.NoError(t, Sync(context.Background(), r.Fremote, r.Flocal, false)) 496 497 fstest.CheckListingWithPrecision( 498 t, 499 r.Flocal, 500 []fstest.Item{ 501 file1, 502 file3, 503 }, 504 []string{ 505 "a", 506 "c", 507 }, 508 fs.GetModifyWindow(r.Fremote), 509 ) 510 fstest.CheckListingWithPrecision( 511 t, 512 r.Fremote, 513 []fstest.Item{ 514 file1, 515 file3, 516 }, 517 []string{ 518 "a", 519 "c", 520 }, 521 fs.GetModifyWindow(r.Fremote), 522 ) 523 } 524 525 func TestSyncAfterChangingModtimeOnly(t *testing.T) { 526 r := fstest.NewRun(t) 527 defer r.Finalise() 528 file1 := r.WriteFile("empty space", "-", t2) 529 file2 := r.WriteObject(context.Background(), "empty space", "-", t1) 530 531 fstest.CheckItems(t, r.Flocal, file1) 532 fstest.CheckItems(t, r.Fremote, file2) 533 534 fs.Config.DryRun = true 535 defer func() { fs.Config.DryRun = false }() 536 537 accounting.GlobalStats().ResetCounters() 538 err := Sync(context.Background(), r.Fremote, r.Flocal, false) 539 require.NoError(t, err) 540 541 fstest.CheckItems(t, r.Flocal, file1) 542 fstest.CheckItems(t, r.Fremote, file2) 543 544 fs.Config.DryRun = false 545 546 accounting.GlobalStats().ResetCounters() 547 err = Sync(context.Background(), r.Fremote, r.Flocal, false) 548 require.NoError(t, err) 549 550 fstest.CheckItems(t, r.Flocal, file1) 551 fstest.CheckItems(t, r.Fremote, file1) 552 } 553 554 func TestSyncAfterChangingModtimeOnlyWithNoUpdateModTime(t *testing.T) { 555 r := fstest.NewRun(t) 556 defer r.Finalise() 557 558 if r.Fremote.Hashes().Count() == 0 { 559 t.Logf("Can't check this if no hashes supported") 560 return 561 } 562 563 fs.Config.NoUpdateModTime = true 564 defer func() { 565 fs.Config.NoUpdateModTime = false 566 }() 567 568 file1 := r.WriteFile("empty space", "-", t2) 569 file2 := r.WriteObject(context.Background(), "empty space", "-", t1) 570 571 fstest.CheckItems(t, r.Flocal, file1) 572 fstest.CheckItems(t, r.Fremote, file2) 573 574 accounting.GlobalStats().ResetCounters() 575 err := Sync(context.Background(), r.Fremote, r.Flocal, false) 576 require.NoError(t, err) 577 578 fstest.CheckItems(t, r.Flocal, file1) 579 fstest.CheckItems(t, r.Fremote, file2) 580 } 581 582 func TestSyncDoesntUpdateModtime(t *testing.T) { 583 r := fstest.NewRun(t) 584 defer r.Finalise() 585 if fs.GetModifyWindow(r.Fremote) == fs.ModTimeNotSupported { 586 t.Skip("Can't run this test on fs which doesn't support mod time") 587 } 588 589 file1 := r.WriteFile("foo", "foo", t2) 590 file2 := r.WriteObject(context.Background(), "foo", "bar", t1) 591 592 fstest.CheckItems(t, r.Flocal, file1) 593 fstest.CheckItems(t, r.Fremote, file2) 594 595 accounting.GlobalStats().ResetCounters() 596 err := Sync(context.Background(), r.Fremote, r.Flocal, false) 597 require.NoError(t, err) 598 599 fstest.CheckItems(t, r.Flocal, file1) 600 fstest.CheckItems(t, r.Fremote, file1) 601 602 // We should have transferred exactly one file, not set the mod time 603 assert.Equal(t, toyFileTransfers(r), accounting.GlobalStats().GetTransfers()) 604 } 605 606 func TestSyncAfterAddingAFile(t *testing.T) { 607 r := fstest.NewRun(t) 608 defer r.Finalise() 609 file1 := r.WriteBoth(context.Background(), "empty space", "-", t2) 610 file2 := r.WriteFile("potato", "------------------------------------------------------------", t3) 611 612 fstest.CheckItems(t, r.Flocal, file1, file2) 613 fstest.CheckItems(t, r.Fremote, file1) 614 615 accounting.GlobalStats().ResetCounters() 616 err := Sync(context.Background(), r.Fremote, r.Flocal, false) 617 require.NoError(t, err) 618 fstest.CheckItems(t, r.Flocal, file1, file2) 619 fstest.CheckItems(t, r.Fremote, file1, file2) 620 } 621 622 func TestSyncAfterChangingFilesSizeOnly(t *testing.T) { 623 r := fstest.NewRun(t) 624 defer r.Finalise() 625 file1 := r.WriteObject(context.Background(), "potato", "------------------------------------------------------------", t3) 626 file2 := r.WriteFile("potato", "smaller but same date", t3) 627 fstest.CheckItems(t, r.Fremote, file1) 628 fstest.CheckItems(t, r.Flocal, file2) 629 630 accounting.GlobalStats().ResetCounters() 631 err := Sync(context.Background(), r.Fremote, r.Flocal, false) 632 require.NoError(t, err) 633 fstest.CheckItems(t, r.Flocal, file2) 634 fstest.CheckItems(t, r.Fremote, file2) 635 } 636 637 // Sync after changing a file's contents, changing modtime but length 638 // remaining the same 639 func TestSyncAfterChangingContentsOnly(t *testing.T) { 640 r := fstest.NewRun(t) 641 defer r.Finalise() 642 var file1 fstest.Item 643 if r.Fremote.Precision() == fs.ModTimeNotSupported { 644 t.Logf("ModTimeNotSupported so forcing file to be a different size") 645 file1 = r.WriteObject(context.Background(), "potato", "different size to make sure it syncs", t3) 646 } else { 647 file1 = r.WriteObject(context.Background(), "potato", "smaller but same date", t3) 648 } 649 file2 := r.WriteFile("potato", "SMALLER BUT SAME DATE", t2) 650 fstest.CheckItems(t, r.Fremote, file1) 651 fstest.CheckItems(t, r.Flocal, file2) 652 653 accounting.GlobalStats().ResetCounters() 654 err := Sync(context.Background(), r.Fremote, r.Flocal, false) 655 require.NoError(t, err) 656 fstest.CheckItems(t, r.Flocal, file2) 657 fstest.CheckItems(t, r.Fremote, file2) 658 } 659 660 // Sync after removing a file and adding a file --dry-run 661 func TestSyncAfterRemovingAFileAndAddingAFileDryRun(t *testing.T) { 662 r := fstest.NewRun(t) 663 defer r.Finalise() 664 file1 := r.WriteFile("potato2", "------------------------------------------------------------", t1) 665 file2 := r.WriteObject(context.Background(), "potato", "SMALLER BUT SAME DATE", t2) 666 file3 := r.WriteBoth(context.Background(), "empty space", "-", t2) 667 668 fs.Config.DryRun = true 669 accounting.GlobalStats().ResetCounters() 670 err := Sync(context.Background(), r.Fremote, r.Flocal, false) 671 fs.Config.DryRun = false 672 require.NoError(t, err) 673 674 fstest.CheckItems(t, r.Flocal, file3, file1) 675 fstest.CheckItems(t, r.Fremote, file3, file2) 676 } 677 678 // Sync after removing a file and adding a file 679 func TestSyncAfterRemovingAFileAndAddingAFile(t *testing.T) { 680 r := fstest.NewRun(t) 681 defer r.Finalise() 682 file1 := r.WriteFile("potato2", "------------------------------------------------------------", t1) 683 file2 := r.WriteObject(context.Background(), "potato", "SMALLER BUT SAME DATE", t2) 684 file3 := r.WriteBoth(context.Background(), "empty space", "-", t2) 685 fstest.CheckItems(t, r.Fremote, file2, file3) 686 fstest.CheckItems(t, r.Flocal, file1, file3) 687 688 accounting.GlobalStats().ResetCounters() 689 err := Sync(context.Background(), r.Fremote, r.Flocal, false) 690 require.NoError(t, err) 691 fstest.CheckItems(t, r.Flocal, file1, file3) 692 fstest.CheckItems(t, r.Fremote, file1, file3) 693 } 694 695 // Sync after removing a file and adding a file 696 func TestSyncAfterRemovingAFileAndAddingAFileSubDir(t *testing.T) { 697 r := fstest.NewRun(t) 698 defer r.Finalise() 699 file1 := r.WriteFile("a/potato2", "------------------------------------------------------------", t1) 700 file2 := r.WriteObject(context.Background(), "b/potato", "SMALLER BUT SAME DATE", t2) 701 file3 := r.WriteBoth(context.Background(), "c/non empty space", "AhHa!", t2) 702 require.NoError(t, operations.Mkdir(context.Background(), r.Fremote, "d")) 703 require.NoError(t, operations.Mkdir(context.Background(), r.Fremote, "d/e")) 704 705 fstest.CheckListingWithPrecision( 706 t, 707 r.Flocal, 708 []fstest.Item{ 709 file1, 710 file3, 711 }, 712 []string{ 713 "a", 714 "c", 715 }, 716 fs.GetModifyWindow(r.Fremote), 717 ) 718 fstest.CheckListingWithPrecision( 719 t, 720 r.Fremote, 721 []fstest.Item{ 722 file2, 723 file3, 724 }, 725 []string{ 726 "b", 727 "c", 728 "d", 729 "d/e", 730 }, 731 fs.GetModifyWindow(r.Fremote), 732 ) 733 734 accounting.GlobalStats().ResetCounters() 735 err := Sync(context.Background(), r.Fremote, r.Flocal, false) 736 require.NoError(t, err) 737 738 fstest.CheckListingWithPrecision( 739 t, 740 r.Flocal, 741 []fstest.Item{ 742 file1, 743 file3, 744 }, 745 []string{ 746 "a", 747 "c", 748 }, 749 fs.GetModifyWindow(r.Fremote), 750 ) 751 fstest.CheckListingWithPrecision( 752 t, 753 r.Fremote, 754 []fstest.Item{ 755 file1, 756 file3, 757 }, 758 []string{ 759 "a", 760 "c", 761 }, 762 fs.GetModifyWindow(r.Fremote), 763 ) 764 } 765 766 // Sync after removing a file and adding a file with IO Errors 767 func TestSyncAfterRemovingAFileAndAddingAFileSubDirWithErrors(t *testing.T) { 768 r := fstest.NewRun(t) 769 defer r.Finalise() 770 file1 := r.WriteFile("a/potato2", "------------------------------------------------------------", t1) 771 file2 := r.WriteObject(context.Background(), "b/potato", "SMALLER BUT SAME DATE", t2) 772 file3 := r.WriteBoth(context.Background(), "c/non empty space", "AhHa!", t2) 773 require.NoError(t, operations.Mkdir(context.Background(), r.Fremote, "d")) 774 775 fstest.CheckListingWithPrecision( 776 t, 777 r.Flocal, 778 []fstest.Item{ 779 file1, 780 file3, 781 }, 782 []string{ 783 "a", 784 "c", 785 }, 786 fs.GetModifyWindow(r.Fremote), 787 ) 788 fstest.CheckListingWithPrecision( 789 t, 790 r.Fremote, 791 []fstest.Item{ 792 file2, 793 file3, 794 }, 795 []string{ 796 "b", 797 "c", 798 "d", 799 }, 800 fs.GetModifyWindow(r.Fremote), 801 ) 802 803 accounting.GlobalStats().ResetCounters() 804 _ = fs.CountError(errors.New("boom")) 805 err := Sync(context.Background(), r.Fremote, r.Flocal, false) 806 assert.Equal(t, fs.ErrorNotDeleting, err) 807 808 fstest.CheckListingWithPrecision( 809 t, 810 r.Flocal, 811 []fstest.Item{ 812 file1, 813 file3, 814 }, 815 []string{ 816 "a", 817 "c", 818 }, 819 fs.GetModifyWindow(r.Fremote), 820 ) 821 fstest.CheckListingWithPrecision( 822 t, 823 r.Fremote, 824 []fstest.Item{ 825 file1, 826 file2, 827 file3, 828 }, 829 []string{ 830 "a", 831 "b", 832 "c", 833 "d", 834 }, 835 fs.GetModifyWindow(r.Fremote), 836 ) 837 } 838 839 // Sync test delete after 840 func TestSyncDeleteAfter(t *testing.T) { 841 // This is the default so we've checked this already 842 // check it is the default 843 require.Equal(t, fs.Config.DeleteMode, fs.DeleteModeAfter, "Didn't default to --delete-after") 844 } 845 846 // Sync test delete during 847 func TestSyncDeleteDuring(t *testing.T) { 848 fs.Config.DeleteMode = fs.DeleteModeDuring 849 defer func() { 850 fs.Config.DeleteMode = fs.DeleteModeDefault 851 }() 852 853 TestSyncAfterRemovingAFileAndAddingAFile(t) 854 } 855 856 // Sync test delete before 857 func TestSyncDeleteBefore(t *testing.T) { 858 fs.Config.DeleteMode = fs.DeleteModeBefore 859 defer func() { 860 fs.Config.DeleteMode = fs.DeleteModeDefault 861 }() 862 863 TestSyncAfterRemovingAFileAndAddingAFile(t) 864 } 865 866 // Copy test delete before - shouldn't delete anything 867 func TestCopyDeleteBefore(t *testing.T) { 868 r := fstest.NewRun(t) 869 defer r.Finalise() 870 871 fs.Config.DeleteMode = fs.DeleteModeBefore 872 defer func() { 873 fs.Config.DeleteMode = fs.DeleteModeDefault 874 }() 875 876 file1 := r.WriteObject(context.Background(), "potato", "hopefully not deleted", t1) 877 file2 := r.WriteFile("potato2", "hopefully copied in", t1) 878 fstest.CheckItems(t, r.Fremote, file1) 879 fstest.CheckItems(t, r.Flocal, file2) 880 881 accounting.GlobalStats().ResetCounters() 882 err := CopyDir(context.Background(), r.Fremote, r.Flocal, false) 883 require.NoError(t, err) 884 885 fstest.CheckItems(t, r.Fremote, file1, file2) 886 fstest.CheckItems(t, r.Flocal, file2) 887 } 888 889 // Test with exclude 890 func TestSyncWithExclude(t *testing.T) { 891 r := fstest.NewRun(t) 892 defer r.Finalise() 893 file1 := r.WriteBoth(context.Background(), "potato2", "------------------------------------------------------------", t1) 894 file2 := r.WriteBoth(context.Background(), "empty space", "-", t2) 895 file3 := r.WriteFile("enormous", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", t1) // 100 bytes 896 fstest.CheckItems(t, r.Fremote, file1, file2) 897 fstest.CheckItems(t, r.Flocal, file1, file2, file3) 898 899 filter.Active.Opt.MaxSize = 40 900 defer func() { 901 filter.Active.Opt.MaxSize = -1 902 }() 903 904 accounting.GlobalStats().ResetCounters() 905 err := Sync(context.Background(), r.Fremote, r.Flocal, false) 906 require.NoError(t, err) 907 fstest.CheckItems(t, r.Fremote, file2, file1) 908 909 // Now sync the other way round and check enormous doesn't get 910 // deleted as it is excluded from the sync 911 accounting.GlobalStats().ResetCounters() 912 err = Sync(context.Background(), r.Flocal, r.Fremote, false) 913 require.NoError(t, err) 914 fstest.CheckItems(t, r.Flocal, file2, file1, file3) 915 } 916 917 // Test with exclude and delete excluded 918 func TestSyncWithExcludeAndDeleteExcluded(t *testing.T) { 919 r := fstest.NewRun(t) 920 defer r.Finalise() 921 file1 := r.WriteBoth(context.Background(), "potato2", "------------------------------------------------------------", t1) // 60 bytes 922 file2 := r.WriteBoth(context.Background(), "empty space", "-", t2) 923 file3 := r.WriteBoth(context.Background(), "enormous", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", t1) // 100 bytes 924 fstest.CheckItems(t, r.Fremote, file1, file2, file3) 925 fstest.CheckItems(t, r.Flocal, file1, file2, file3) 926 927 filter.Active.Opt.MaxSize = 40 928 filter.Active.Opt.DeleteExcluded = true 929 defer func() { 930 filter.Active.Opt.MaxSize = -1 931 filter.Active.Opt.DeleteExcluded = false 932 }() 933 934 accounting.GlobalStats().ResetCounters() 935 err := Sync(context.Background(), r.Fremote, r.Flocal, false) 936 require.NoError(t, err) 937 fstest.CheckItems(t, r.Fremote, file2) 938 939 // Check sync the other way round to make sure enormous gets 940 // deleted even though it is excluded 941 accounting.GlobalStats().ResetCounters() 942 err = Sync(context.Background(), r.Flocal, r.Fremote, false) 943 require.NoError(t, err) 944 fstest.CheckItems(t, r.Flocal, file2) 945 } 946 947 // Test with UpdateOlder set 948 func TestSyncWithUpdateOlder(t *testing.T) { 949 r := fstest.NewRun(t) 950 defer r.Finalise() 951 if fs.GetModifyWindow(r.Fremote) == fs.ModTimeNotSupported { 952 t.Skip("Can't run this test on fs which doesn't support mod time") 953 } 954 t2plus := t2.Add(time.Second / 2) 955 t2minus := t2.Add(time.Second / 2) 956 oneF := r.WriteFile("one", "one", t1) 957 twoF := r.WriteFile("two", "two", t3) 958 threeF := r.WriteFile("three", "three", t2) 959 fourF := r.WriteFile("four", "four", t2) 960 fiveF := r.WriteFile("five", "five", t2) 961 fstest.CheckItems(t, r.Flocal, oneF, twoF, threeF, fourF, fiveF) 962 oneO := r.WriteObject(context.Background(), "one", "ONE", t2) 963 twoO := r.WriteObject(context.Background(), "two", "TWO", t2) 964 threeO := r.WriteObject(context.Background(), "three", "THREE", t2plus) 965 fourO := r.WriteObject(context.Background(), "four", "FOURFOUR", t2minus) 966 fstest.CheckItems(t, r.Fremote, oneO, twoO, threeO, fourO) 967 968 fs.Config.UpdateOlder = true 969 oldModifyWindow := fs.Config.ModifyWindow 970 fs.Config.ModifyWindow = fs.ModTimeNotSupported 971 defer func() { 972 fs.Config.UpdateOlder = false 973 fs.Config.ModifyWindow = oldModifyWindow 974 }() 975 976 err := Sync(context.Background(), r.Fremote, r.Flocal, false) 977 require.NoError(t, err) 978 fstest.CheckItems(t, r.Fremote, oneO, twoF, threeO, fourF, fiveF) 979 980 if r.Fremote.Hashes().Count() == 0 { 981 t.Logf("Skip test with --checksum as no hashes supported") 982 return 983 } 984 985 // now enable checksum 986 fs.Config.CheckSum = true 987 defer func() { fs.Config.CheckSum = false }() 988 989 err = Sync(context.Background(), r.Fremote, r.Flocal, false) 990 require.NoError(t, err) 991 fstest.CheckItems(t, r.Fremote, oneO, twoF, threeF, fourF, fiveF) 992 } 993 994 // Test with a max transfer duration 995 func TestSyncWithMaxDuration(t *testing.T) { 996 if *fstest.RemoteName != "" { 997 t.Skip("Skipping test on non local remote") 998 } 999 r := fstest.NewRun(t) 1000 defer r.Finalise() 1001 1002 maxDuration := 250 * time.Millisecond 1003 fs.Config.MaxDuration = maxDuration 1004 bytesPerSecond := 300 1005 accounting.SetBwLimit(fs.SizeSuffix(bytesPerSecond)) 1006 oldTransfers := fs.Config.Transfers 1007 fs.Config.Transfers = 1 1008 defer func() { 1009 fs.Config.MaxDuration = 0 // reset back to default 1010 fs.Config.Transfers = oldTransfers 1011 accounting.SetBwLimit(fs.SizeSuffix(0)) 1012 }() 1013 1014 // 5 files of 60 bytes at 60 bytes/s 5 seconds 1015 testFiles := make([]fstest.Item, 5) 1016 for i := 0; i < len(testFiles); i++ { 1017 testFiles[i] = r.WriteFile(fmt.Sprintf("file%d", i), "------------------------------------------------------------", t1) 1018 } 1019 1020 fstest.CheckListing(t, r.Flocal, testFiles) 1021 1022 accounting.GlobalStats().ResetCounters() 1023 startTime := time.Now() 1024 err := Sync(context.Background(), r.Fremote, r.Flocal, false) 1025 require.Equal(t, context.DeadlineExceeded, errors.Cause(err)) 1026 err = accounting.GlobalStats().GetLastError() 1027 require.NoError(t, err) 1028 1029 elapsed := time.Since(startTime) 1030 maxTransferTime := (time.Duration(len(testFiles)) * 60 * time.Second) / time.Duration(bytesPerSecond) 1031 1032 what := fmt.Sprintf("expecting elapsed time %v between %v and %v", elapsed, maxDuration, maxTransferTime) 1033 require.True(t, elapsed >= maxDuration, what) 1034 require.True(t, elapsed < 5*time.Second, what) 1035 // we must not have transferred all files during the session 1036 require.True(t, accounting.GlobalStats().GetTransfers() < int64(len(testFiles))) 1037 } 1038 1039 // Test with TrackRenames set 1040 func TestSyncWithTrackRenames(t *testing.T) { 1041 r := fstest.NewRun(t) 1042 defer r.Finalise() 1043 1044 fs.Config.TrackRenames = true 1045 defer func() { 1046 fs.Config.TrackRenames = false 1047 }() 1048 1049 haveHash := r.Fremote.Hashes().Overlap(r.Flocal.Hashes()).GetOne() != hash.None 1050 canTrackRenames := haveHash && operations.CanServerSideMove(r.Fremote) 1051 t.Logf("Can track renames: %v", canTrackRenames) 1052 1053 f1 := r.WriteFile("potato", "Potato Content", t1) 1054 f2 := r.WriteFile("yam", "Yam Content", t2) 1055 1056 accounting.GlobalStats().ResetCounters() 1057 require.NoError(t, Sync(context.Background(), r.Fremote, r.Flocal, false)) 1058 1059 fstest.CheckItems(t, r.Fremote, f1, f2) 1060 fstest.CheckItems(t, r.Flocal, f1, f2) 1061 1062 // Now rename locally. 1063 f2 = r.RenameFile(f2, "yaml") 1064 1065 accounting.GlobalStats().ResetCounters() 1066 require.NoError(t, Sync(context.Background(), r.Fremote, r.Flocal, false)) 1067 1068 fstest.CheckItems(t, r.Fremote, f1, f2) 1069 1070 // As currently there is no Fs interface providing number of chunks 1071 // in a file, this test depends on the well-known names of test remotes. 1072 remote := r.Fremote.Name() 1073 1074 // Union remote can Move but returns CantMove error. 1075 moveAsCopyDelete := r.Fremote.Features().Move == nil || remote == "TestUnion" 1076 1077 chunker := strings.HasPrefix(remote, "TestChunker") 1078 wrappedMoveAsCopyDelete := chunker && strings.HasSuffix(remote, "S3") 1079 1080 chunk3b := chunker && strings.Contains(remote, "Chunk3b") // chunker with 3 byte chunks 1081 chunk50b := chunker && strings.Contains(remote, "Chunk50b") // chunker with 50 byte chunks 1082 chunkDefault := chunker && !strings.Contains(remote, "ChunkerChunk") // default big chunk size 1083 chunkBig := chunk50b || chunkDefault // file is smaller than chunk size 1084 1085 // Verify number of checks for a toy 14 byte file. 1086 // The order of cases matters! 1087 var checks int 1088 switch { 1089 case canTrackRenames && chunk3b: 1090 checks = 8 // chunker makes extra checks for each small chunk 1091 case canTrackRenames && chunkBig: 1092 checks = 4 // chunker makes 1 extra check for a single big chunk 1093 case canTrackRenames && moveAsCopyDelete: 1094 checks = 4 // 2 file checks + 1 move + 1 delete 1095 case canTrackRenames: 1096 checks = 3 // 2 file checks + 1 move 1097 case !chunker: 1098 checks = 2 // 2 file checks on a generic non-chunking remote 1099 case chunk3b: 1100 checks = 6 // chunker makes extra checks for each small chunk 1101 case chunkBig && wrappedMoveAsCopyDelete: 1102 checks = 4 // one more extra check because S3 emulates Move as Copy+Delete 1103 case chunkBig: 1104 checks = 3 // chunker makes 1 extra check for a single big chunk 1105 default: 1106 checks = -1 // skip verification for chunker with unknown chunk size 1107 } 1108 if checks != -1 { // "-1" allows remotes to bypass this check 1109 assert.Equal(t, int64(checks), accounting.GlobalStats().GetChecks()) 1110 } 1111 1112 // Verify number of copy operations for a toy 14 byte file. 1113 // The order of cases matters! 1114 var copies int64 1115 switch { 1116 case canTrackRenames && moveAsCopyDelete: 1117 copies = 1 // 1 copy 1118 case canTrackRenames: 1119 copies = 0 // 0 copy 1120 case chunkBig && wrappedMoveAsCopyDelete: 1121 copies = 2 // extra Copy because S3 emulates Move as Copy+Delete. 1122 default: 1123 copies = 1 1124 } 1125 if copies != -1 { // "-1" allows remotes to bypass this check 1126 assert.Equal(t, copies, accounting.GlobalStats().GetTransfers()) 1127 } 1128 } 1129 1130 func toyFileTransfers(r *fstest.Run) int64 { 1131 remote := r.Fremote.Name() 1132 transfers := 1 1133 if strings.HasPrefix(remote, "TestChunker") && strings.HasSuffix(remote, "S3") { 1134 transfers++ // Extra Copy because S3 emulates Move as Copy+Delete. 1135 } 1136 return int64(transfers) 1137 } 1138 1139 // Test a server side move if possible, or the backup path if not 1140 func testServerSideMove(t *testing.T, r *fstest.Run, withFilter, testDeleteEmptyDirs bool) { 1141 FremoteMove, _, finaliseMove, err := fstest.RandomRemote() 1142 require.NoError(t, err) 1143 defer finaliseMove() 1144 1145 file1 := r.WriteBoth(context.Background(), "potato2", "------------------------------------------------------------", t1) 1146 file2 := r.WriteBoth(context.Background(), "empty space", "-", t2) 1147 file3u := r.WriteBoth(context.Background(), "potato3", "------------------------------------------------------------ UPDATED", t2) 1148 1149 if testDeleteEmptyDirs { 1150 err := operations.Mkdir(context.Background(), r.Fremote, "tomatoDir") 1151 require.NoError(t, err) 1152 } 1153 1154 fstest.CheckItems(t, r.Fremote, file2, file1, file3u) 1155 1156 t.Logf("Server side move (if possible) %v -> %v", r.Fremote, FremoteMove) 1157 1158 // Write just one file in the new remote 1159 r.WriteObjectTo(context.Background(), FremoteMove, "empty space", "-", t2, false) 1160 file3 := r.WriteObjectTo(context.Background(), FremoteMove, "potato3", "------------------------------------------------------------", t1, false) 1161 fstest.CheckItems(t, FremoteMove, file2, file3) 1162 1163 // Do server side move 1164 accounting.GlobalStats().ResetCounters() 1165 err = MoveDir(context.Background(), FremoteMove, r.Fremote, testDeleteEmptyDirs, false) 1166 require.NoError(t, err) 1167 1168 if withFilter { 1169 fstest.CheckItems(t, r.Fremote, file2) 1170 } else { 1171 fstest.CheckItems(t, r.Fremote) 1172 } 1173 1174 if testDeleteEmptyDirs { 1175 fstest.CheckListingWithPrecision(t, r.Fremote, nil, []string{}, fs.GetModifyWindow(r.Fremote)) 1176 } 1177 1178 fstest.CheckItems(t, FremoteMove, file2, file1, file3u) 1179 1180 // Create a new empty remote for stuff to be moved into 1181 FremoteMove2, _, finaliseMove2, err := fstest.RandomRemote() 1182 require.NoError(t, err) 1183 defer finaliseMove2() 1184 1185 if testDeleteEmptyDirs { 1186 err := operations.Mkdir(context.Background(), FremoteMove, "tomatoDir") 1187 require.NoError(t, err) 1188 } 1189 1190 // Move it back to a new empty remote, dst does not exist this time 1191 accounting.GlobalStats().ResetCounters() 1192 err = MoveDir(context.Background(), FremoteMove2, FremoteMove, testDeleteEmptyDirs, false) 1193 require.NoError(t, err) 1194 1195 if withFilter { 1196 fstest.CheckItems(t, FremoteMove2, file1, file3u) 1197 fstest.CheckItems(t, FremoteMove, file2) 1198 } else { 1199 fstest.CheckItems(t, FremoteMove2, file2, file1, file3u) 1200 fstest.CheckItems(t, FremoteMove) 1201 } 1202 1203 if testDeleteEmptyDirs { 1204 fstest.CheckListingWithPrecision(t, FremoteMove, nil, []string{}, fs.GetModifyWindow(r.Fremote)) 1205 } 1206 } 1207 1208 // Test move 1209 func TestMoveWithDeleteEmptySrcDirs(t *testing.T) { 1210 r := fstest.NewRun(t) 1211 defer r.Finalise() 1212 file1 := r.WriteFile("sub dir/hello world", "hello world", t1) 1213 file2 := r.WriteFile("nested/sub dir/file", "nested", t1) 1214 r.Mkdir(context.Background(), r.Fremote) 1215 1216 // run move with --delete-empty-src-dirs 1217 err := MoveDir(context.Background(), r.Fremote, r.Flocal, true, false) 1218 require.NoError(t, err) 1219 1220 fstest.CheckListingWithPrecision( 1221 t, 1222 r.Flocal, 1223 nil, 1224 []string{}, 1225 fs.GetModifyWindow(r.Flocal), 1226 ) 1227 fstest.CheckItems(t, r.Fremote, file1, file2) 1228 } 1229 1230 func TestMoveWithoutDeleteEmptySrcDirs(t *testing.T) { 1231 r := fstest.NewRun(t) 1232 defer r.Finalise() 1233 file1 := r.WriteFile("sub dir/hello world", "hello world", t1) 1234 file2 := r.WriteFile("nested/sub dir/file", "nested", t1) 1235 r.Mkdir(context.Background(), r.Fremote) 1236 1237 err := MoveDir(context.Background(), r.Fremote, r.Flocal, false, false) 1238 require.NoError(t, err) 1239 1240 fstest.CheckListingWithPrecision( 1241 t, 1242 r.Flocal, 1243 nil, 1244 []string{ 1245 "sub dir", 1246 "nested", 1247 "nested/sub dir", 1248 }, 1249 fs.GetModifyWindow(r.Flocal), 1250 ) 1251 fstest.CheckItems(t, r.Fremote, file1, file2) 1252 } 1253 1254 // Test a server side move if possible, or the backup path if not 1255 func TestServerSideMove(t *testing.T) { 1256 r := fstest.NewRun(t) 1257 defer r.Finalise() 1258 testServerSideMove(t, r, false, false) 1259 } 1260 1261 // Test a server side move if possible, or the backup path if not 1262 func TestServerSideMoveWithFilter(t *testing.T) { 1263 r := fstest.NewRun(t) 1264 defer r.Finalise() 1265 1266 filter.Active.Opt.MinSize = 40 1267 defer func() { 1268 filter.Active.Opt.MinSize = -1 1269 }() 1270 1271 testServerSideMove(t, r, true, false) 1272 } 1273 1274 // Test a server side move if possible 1275 func TestServerSideMoveDeleteEmptySourceDirs(t *testing.T) { 1276 r := fstest.NewRun(t) 1277 defer r.Finalise() 1278 testServerSideMove(t, r, false, true) 1279 } 1280 1281 // Test a server side move with overlap 1282 func TestServerSideMoveOverlap(t *testing.T) { 1283 r := fstest.NewRun(t) 1284 defer r.Finalise() 1285 1286 if r.Fremote.Features().DirMove != nil { 1287 t.Skip("Skipping test as remote supports DirMove") 1288 } 1289 1290 subRemoteName := r.FremoteName + "/rclone-move-test" 1291 FremoteMove, err := fs.NewFs(subRemoteName) 1292 require.NoError(t, err) 1293 1294 file1 := r.WriteObject(context.Background(), "potato2", "------------------------------------------------------------", t1) 1295 fstest.CheckItems(t, r.Fremote, file1) 1296 1297 // Subdir move with no filters should return ErrorCantMoveOverlapping 1298 err = MoveDir(context.Background(), FremoteMove, r.Fremote, false, false) 1299 assert.EqualError(t, err, fs.ErrorOverlapping.Error()) 1300 1301 // Now try with a filter which should also fail with ErrorCantMoveOverlapping 1302 filter.Active.Opt.MinSize = 40 1303 defer func() { 1304 filter.Active.Opt.MinSize = -1 1305 }() 1306 err = MoveDir(context.Background(), FremoteMove, r.Fremote, false, false) 1307 assert.EqualError(t, err, fs.ErrorOverlapping.Error()) 1308 } 1309 1310 // Test a sync with overlap 1311 func TestSyncOverlap(t *testing.T) { 1312 r := fstest.NewRun(t) 1313 defer r.Finalise() 1314 1315 subRemoteName := r.FremoteName + "/rclone-sync-test" 1316 FremoteSync, err := fs.NewFs(subRemoteName) 1317 require.NoError(t, err) 1318 1319 checkErr := func(err error) { 1320 require.Error(t, err) 1321 assert.True(t, fserrors.IsFatalError(err)) 1322 assert.Equal(t, fs.ErrorOverlapping.Error(), err.Error()) 1323 } 1324 1325 checkErr(Sync(context.Background(), FremoteSync, r.Fremote, false)) 1326 checkErr(Sync(context.Background(), r.Fremote, FremoteSync, false)) 1327 checkErr(Sync(context.Background(), r.Fremote, r.Fremote, false)) 1328 checkErr(Sync(context.Background(), FremoteSync, FremoteSync, false)) 1329 } 1330 1331 // Test with CompareDest set 1332 func TestSyncCompareDest(t *testing.T) { 1333 r := fstest.NewRun(t) 1334 defer r.Finalise() 1335 1336 fs.Config.CompareDest = r.FremoteName + "/CompareDest" 1337 defer func() { 1338 fs.Config.CompareDest = "" 1339 }() 1340 1341 fdst, err := fs.NewFs(r.FremoteName + "/dst") 1342 require.NoError(t, err) 1343 1344 // check empty dest, empty compare 1345 file1 := r.WriteFile("one", "one", t1) 1346 fstest.CheckItems(t, r.Flocal, file1) 1347 1348 accounting.GlobalStats().ResetCounters() 1349 err = Sync(context.Background(), fdst, r.Flocal, false) 1350 require.NoError(t, err) 1351 1352 file1dst := file1 1353 file1dst.Path = "dst/one" 1354 1355 fstest.CheckItems(t, r.Fremote, file1dst) 1356 1357 // check old dest, empty compare 1358 file1b := r.WriteFile("one", "onet2", t2) 1359 fstest.CheckItems(t, r.Fremote, file1dst) 1360 fstest.CheckItems(t, r.Flocal, file1b) 1361 1362 accounting.GlobalStats().ResetCounters() 1363 err = Sync(context.Background(), fdst, r.Flocal, false) 1364 require.NoError(t, err) 1365 1366 file1bdst := file1b 1367 file1bdst.Path = "dst/one" 1368 1369 fstest.CheckItems(t, r.Fremote, file1bdst) 1370 1371 // check old dest, new compare 1372 file3 := r.WriteObject(context.Background(), "dst/one", "one", t1) 1373 file2 := r.WriteObject(context.Background(), "CompareDest/one", "onet2", t2) 1374 file1c := r.WriteFile("one", "onet2", t2) 1375 fstest.CheckItems(t, r.Fremote, file2, file3) 1376 fstest.CheckItems(t, r.Flocal, file1c) 1377 1378 accounting.GlobalStats().ResetCounters() 1379 err = Sync(context.Background(), fdst, r.Flocal, false) 1380 require.NoError(t, err) 1381 1382 fstest.CheckItems(t, r.Fremote, file2, file3) 1383 1384 // check empty dest, new compare 1385 file4 := r.WriteObject(context.Background(), "CompareDest/two", "two", t2) 1386 file5 := r.WriteFile("two", "two", t2) 1387 fstest.CheckItems(t, r.Fremote, file2, file3, file4) 1388 fstest.CheckItems(t, r.Flocal, file1c, file5) 1389 1390 accounting.GlobalStats().ResetCounters() 1391 err = Sync(context.Background(), fdst, r.Flocal, false) 1392 require.NoError(t, err) 1393 1394 fstest.CheckItems(t, r.Fremote, file2, file3, file4) 1395 1396 // check new dest, new compare 1397 accounting.GlobalStats().ResetCounters() 1398 err = Sync(context.Background(), fdst, r.Flocal, false) 1399 require.NoError(t, err) 1400 1401 fstest.CheckItems(t, r.Fremote, file2, file3, file4) 1402 1403 // check empty dest, old compare 1404 file5b := r.WriteFile("two", "twot3", t3) 1405 fstest.CheckItems(t, r.Fremote, file2, file3, file4) 1406 fstest.CheckItems(t, r.Flocal, file1c, file5b) 1407 1408 accounting.GlobalStats().ResetCounters() 1409 err = Sync(context.Background(), fdst, r.Flocal, false) 1410 require.NoError(t, err) 1411 1412 file5bdst := file5b 1413 file5bdst.Path = "dst/two" 1414 1415 fstest.CheckItems(t, r.Fremote, file2, file3, file4, file5bdst) 1416 } 1417 1418 // Test with CopyDest set 1419 func TestSyncCopyDest(t *testing.T) { 1420 r := fstest.NewRun(t) 1421 defer r.Finalise() 1422 1423 if r.Fremote.Features().Copy == nil { 1424 t.Skip("Skipping test as remote does not support server side copy") 1425 } 1426 1427 fs.Config.CopyDest = r.FremoteName + "/CopyDest" 1428 defer func() { 1429 fs.Config.CopyDest = "" 1430 }() 1431 1432 fdst, err := fs.NewFs(r.FremoteName + "/dst") 1433 require.NoError(t, err) 1434 1435 // check empty dest, empty copy 1436 file1 := r.WriteFile("one", "one", t1) 1437 fstest.CheckItems(t, r.Flocal, file1) 1438 1439 accounting.GlobalStats().ResetCounters() 1440 err = Sync(context.Background(), fdst, r.Flocal, false) 1441 require.NoError(t, err) 1442 1443 file1dst := file1 1444 file1dst.Path = "dst/one" 1445 1446 fstest.CheckItems(t, r.Fremote, file1dst) 1447 1448 // check old dest, empty copy 1449 file1b := r.WriteFile("one", "onet2", t2) 1450 fstest.CheckItems(t, r.Fremote, file1dst) 1451 fstest.CheckItems(t, r.Flocal, file1b) 1452 1453 accounting.GlobalStats().ResetCounters() 1454 err = Sync(context.Background(), fdst, r.Flocal, false) 1455 require.NoError(t, err) 1456 1457 file1bdst := file1b 1458 file1bdst.Path = "dst/one" 1459 1460 fstest.CheckItems(t, r.Fremote, file1bdst) 1461 1462 // check old dest, new copy, backup-dir 1463 1464 fs.Config.BackupDir = r.FremoteName + "/BackupDir" 1465 1466 file3 := r.WriteObject(context.Background(), "dst/one", "one", t1) 1467 file2 := r.WriteObject(context.Background(), "CopyDest/one", "onet2", t2) 1468 file1c := r.WriteFile("one", "onet2", t2) 1469 fstest.CheckItems(t, r.Fremote, file2, file3) 1470 fstest.CheckItems(t, r.Flocal, file1c) 1471 1472 accounting.GlobalStats().ResetCounters() 1473 err = Sync(context.Background(), fdst, r.Flocal, false) 1474 require.NoError(t, err) 1475 1476 file2dst := file2 1477 file2dst.Path = "dst/one" 1478 file3.Path = "BackupDir/one" 1479 1480 fstest.CheckItems(t, r.Fremote, file2, file2dst, file3) 1481 fs.Config.BackupDir = "" 1482 1483 // check empty dest, new copy 1484 file4 := r.WriteObject(context.Background(), "CopyDest/two", "two", t2) 1485 file5 := r.WriteFile("two", "two", t2) 1486 fstest.CheckItems(t, r.Fremote, file2, file2dst, file3, file4) 1487 fstest.CheckItems(t, r.Flocal, file1c, file5) 1488 1489 accounting.GlobalStats().ResetCounters() 1490 err = Sync(context.Background(), fdst, r.Flocal, false) 1491 require.NoError(t, err) 1492 1493 file4dst := file4 1494 file4dst.Path = "dst/two" 1495 1496 fstest.CheckItems(t, r.Fremote, file2, file2dst, file3, file4, file4dst) 1497 1498 // check new dest, new copy 1499 accounting.GlobalStats().ResetCounters() 1500 err = Sync(context.Background(), fdst, r.Flocal, false) 1501 require.NoError(t, err) 1502 1503 fstest.CheckItems(t, r.Fremote, file2, file2dst, file3, file4, file4dst) 1504 1505 // check empty dest, old copy 1506 file6 := r.WriteObject(context.Background(), "CopyDest/three", "three", t2) 1507 file7 := r.WriteFile("three", "threet3", t3) 1508 fstest.CheckItems(t, r.Fremote, file2, file2dst, file3, file4, file4dst, file6) 1509 fstest.CheckItems(t, r.Flocal, file1c, file5, file7) 1510 1511 accounting.GlobalStats().ResetCounters() 1512 err = Sync(context.Background(), fdst, r.Flocal, false) 1513 require.NoError(t, err) 1514 1515 file7dst := file7 1516 file7dst.Path = "dst/three" 1517 1518 fstest.CheckItems(t, r.Fremote, file2, file2dst, file3, file4, file4dst, file6, file7dst) 1519 } 1520 1521 // Test with BackupDir set 1522 func testSyncBackupDir(t *testing.T, suffix string, suffixKeepExtension bool) { 1523 r := fstest.NewRun(t) 1524 defer r.Finalise() 1525 1526 if !operations.CanServerSideMove(r.Fremote) { 1527 t.Skip("Skipping test as remote does not support server side move") 1528 } 1529 r.Mkdir(context.Background(), r.Fremote) 1530 1531 fs.Config.BackupDir = r.FremoteName + "/backup" 1532 fs.Config.Suffix = suffix 1533 fs.Config.SuffixKeepExtension = suffixKeepExtension 1534 defer func() { 1535 fs.Config.BackupDir = "" 1536 fs.Config.Suffix = "" 1537 fs.Config.SuffixKeepExtension = false 1538 }() 1539 1540 // Make the setup so we have one, two, three in the dest 1541 // and one (different), two (same) in the source 1542 file1 := r.WriteObject(context.Background(), "dst/one", "one", t1) 1543 file2 := r.WriteObject(context.Background(), "dst/two", "two", t1) 1544 file3 := r.WriteObject(context.Background(), "dst/three.txt", "three", t1) 1545 file2a := r.WriteFile("two", "two", t1) 1546 file1a := r.WriteFile("one", "oneA", t2) 1547 1548 fstest.CheckItems(t, r.Fremote, file1, file2, file3) 1549 fstest.CheckItems(t, r.Flocal, file1a, file2a) 1550 1551 fdst, err := fs.NewFs(r.FremoteName + "/dst") 1552 require.NoError(t, err) 1553 1554 accounting.GlobalStats().ResetCounters() 1555 err = Sync(context.Background(), fdst, r.Flocal, false) 1556 require.NoError(t, err) 1557 1558 // one should be moved to the backup dir and the new one installed 1559 file1.Path = "backup/one" + suffix 1560 file1a.Path = "dst/one" 1561 // two should be unchanged 1562 // three should be moved to the backup dir 1563 if suffixKeepExtension { 1564 file3.Path = "backup/three" + suffix + ".txt" 1565 } else { 1566 file3.Path = "backup/three.txt" + suffix 1567 } 1568 1569 fstest.CheckItems(t, r.Fremote, file1, file2, file3, file1a) 1570 1571 // Now check what happens if we do it again 1572 // Restore a different three and update one in the source 1573 file3a := r.WriteObject(context.Background(), "dst/three.txt", "threeA", t2) 1574 file1b := r.WriteFile("one", "oneBB", t3) 1575 fstest.CheckItems(t, r.Fremote, file1, file2, file3, file1a, file3a) 1576 1577 // This should delete three and overwrite one again, checking 1578 // the files got overwritten correctly in backup-dir 1579 accounting.GlobalStats().ResetCounters() 1580 err = Sync(context.Background(), fdst, r.Flocal, false) 1581 require.NoError(t, err) 1582 1583 // one should be moved to the backup dir and the new one installed 1584 file1a.Path = "backup/one" + suffix 1585 file1b.Path = "dst/one" 1586 // two should be unchanged 1587 // three should be moved to the backup dir 1588 if suffixKeepExtension { 1589 file3a.Path = "backup/three" + suffix + ".txt" 1590 } else { 1591 file3a.Path = "backup/three.txt" + suffix 1592 } 1593 1594 fstest.CheckItems(t, r.Fremote, file1b, file2, file3a, file1a) 1595 } 1596 func TestSyncBackupDir(t *testing.T) { testSyncBackupDir(t, "", false) } 1597 func TestSyncBackupDirWithSuffix(t *testing.T) { testSyncBackupDir(t, ".bak", false) } 1598 func TestSyncBackupDirWithSuffixKeepExtension(t *testing.T) { testSyncBackupDir(t, "-2019-01-01", true) } 1599 1600 // Test with Suffix set 1601 func testSyncSuffix(t *testing.T, suffix string, suffixKeepExtension bool) { 1602 r := fstest.NewRun(t) 1603 defer r.Finalise() 1604 1605 if !operations.CanServerSideMove(r.Fremote) { 1606 t.Skip("Skipping test as remote does not support server side move") 1607 } 1608 r.Mkdir(context.Background(), r.Fremote) 1609 1610 fs.Config.Suffix = suffix 1611 fs.Config.SuffixKeepExtension = suffixKeepExtension 1612 defer func() { 1613 fs.Config.BackupDir = "" 1614 fs.Config.Suffix = "" 1615 fs.Config.SuffixKeepExtension = false 1616 }() 1617 1618 // Make the setup so we have one, two, three in the dest 1619 // and one (different), two (same) in the source 1620 file1 := r.WriteObject(context.Background(), "dst/one", "one", t1) 1621 file2 := r.WriteObject(context.Background(), "dst/two", "two", t1) 1622 file3 := r.WriteObject(context.Background(), "dst/three.txt", "three", t1) 1623 file2a := r.WriteFile("two", "two", t1) 1624 file1a := r.WriteFile("one", "oneA", t2) 1625 file3a := r.WriteFile("three.txt", "threeA", t1) 1626 1627 fstest.CheckItems(t, r.Fremote, file1, file2, file3) 1628 fstest.CheckItems(t, r.Flocal, file1a, file2a, file3a) 1629 1630 fdst, err := fs.NewFs(r.FremoteName + "/dst") 1631 require.NoError(t, err) 1632 1633 accounting.GlobalStats().ResetCounters() 1634 err = operations.CopyFile(context.Background(), fdst, r.Flocal, "one", "one") 1635 require.NoError(t, err) 1636 err = operations.CopyFile(context.Background(), fdst, r.Flocal, "two", "two") 1637 require.NoError(t, err) 1638 err = operations.CopyFile(context.Background(), fdst, r.Flocal, "three.txt", "three.txt") 1639 require.NoError(t, err) 1640 1641 // one should be moved to the backup dir and the new one installed 1642 file1.Path = "dst/one" + suffix 1643 file1a.Path = "dst/one" 1644 // two should be unchanged 1645 // three should be moved to the backup dir 1646 if suffixKeepExtension { 1647 file3.Path = "dst/three" + suffix + ".txt" 1648 } else { 1649 file3.Path = "dst/three.txt" + suffix 1650 } 1651 file3a.Path = "dst/three.txt" 1652 1653 fstest.CheckItems(t, r.Fremote, file1, file2, file3, file1a, file3a) 1654 1655 // Now check what happens if we do it again 1656 // Restore a different three and update one in the source 1657 file3b := r.WriteFile("three.txt", "threeBDifferentSize", t3) 1658 file1b := r.WriteFile("one", "oneBB", t3) 1659 fstest.CheckItems(t, r.Fremote, file1, file2, file3, file1a, file3a) 1660 1661 // This should delete three and overwrite one again, checking 1662 // the files got overwritten correctly in backup-dir 1663 accounting.GlobalStats().ResetCounters() 1664 err = operations.CopyFile(context.Background(), fdst, r.Flocal, "one", "one") 1665 require.NoError(t, err) 1666 err = operations.CopyFile(context.Background(), fdst, r.Flocal, "two", "two") 1667 require.NoError(t, err) 1668 err = operations.CopyFile(context.Background(), fdst, r.Flocal, "three.txt", "three.txt") 1669 require.NoError(t, err) 1670 1671 // one should be moved to the backup dir and the new one installed 1672 file1a.Path = "dst/one" + suffix 1673 file1b.Path = "dst/one" 1674 // two should be unchanged 1675 // three should be moved to the backup dir 1676 if suffixKeepExtension { 1677 file3a.Path = "dst/three" + suffix + ".txt" 1678 } else { 1679 file3a.Path = "dst/three.txt" + suffix 1680 } 1681 file3b.Path = "dst/three.txt" 1682 1683 fstest.CheckItems(t, r.Fremote, file1b, file3b, file2, file3a, file1a) 1684 } 1685 func TestSyncSuffix(t *testing.T) { testSyncSuffix(t, ".bak", false) } 1686 func TestSyncSuffixKeepExtension(t *testing.T) { testSyncSuffix(t, "-2019-01-01", true) } 1687 1688 // Check we can sync two files with differing UTF-8 representations 1689 func TestSyncUTFNorm(t *testing.T) { 1690 if runtime.GOOS == "darwin" { 1691 t.Skip("Can't test UTF normalization on OS X") 1692 } 1693 1694 r := fstest.NewRun(t) 1695 defer r.Finalise() 1696 1697 // Two strings with different unicode normalization (from OS X) 1698 Encoding1 := "Testêé" 1699 Encoding2 := "Testêé" 1700 assert.NotEqual(t, Encoding1, Encoding2) 1701 assert.Equal(t, norm.NFC.String(Encoding1), norm.NFC.String(Encoding2)) 1702 1703 file1 := r.WriteFile(Encoding1, "This is a test", t1) 1704 fstest.CheckItems(t, r.Flocal, file1) 1705 1706 file2 := r.WriteObject(context.Background(), Encoding2, "This is a old test", t2) 1707 fstest.CheckItems(t, r.Fremote, file2) 1708 1709 accounting.GlobalStats().ResetCounters() 1710 err := Sync(context.Background(), r.Fremote, r.Flocal, false) 1711 require.NoError(t, err) 1712 1713 // We should have transferred exactly one file, but kept the 1714 // normalized state of the file. 1715 assert.Equal(t, toyFileTransfers(r), accounting.GlobalStats().GetTransfers()) 1716 fstest.CheckItems(t, r.Flocal, file1) 1717 file1.Path = file2.Path 1718 fstest.CheckItems(t, r.Fremote, file1) 1719 } 1720 1721 // Test --immutable 1722 func TestSyncImmutable(t *testing.T) { 1723 r := fstest.NewRun(t) 1724 defer r.Finalise() 1725 1726 fs.Config.Immutable = true 1727 defer func() { fs.Config.Immutable = false }() 1728 1729 // Create file on source 1730 file1 := r.WriteFile("existing", "potato", t1) 1731 fstest.CheckItems(t, r.Flocal, file1) 1732 fstest.CheckItems(t, r.Fremote) 1733 1734 // Should succeed 1735 accounting.GlobalStats().ResetCounters() 1736 err := Sync(context.Background(), r.Fremote, r.Flocal, false) 1737 require.NoError(t, err) 1738 fstest.CheckItems(t, r.Flocal, file1) 1739 fstest.CheckItems(t, r.Fremote, file1) 1740 1741 // Modify file data and timestamp on source 1742 file2 := r.WriteFile("existing", "tomatoes", t2) 1743 fstest.CheckItems(t, r.Flocal, file2) 1744 fstest.CheckItems(t, r.Fremote, file1) 1745 1746 // Should fail with ErrorImmutableModified and not modify local or remote files 1747 accounting.GlobalStats().ResetCounters() 1748 err = Sync(context.Background(), r.Fremote, r.Flocal, false) 1749 assert.EqualError(t, err, fs.ErrorImmutableModified.Error()) 1750 fstest.CheckItems(t, r.Flocal, file2) 1751 fstest.CheckItems(t, r.Fremote, file1) 1752 } 1753 1754 // Test --ignore-case-sync 1755 func TestSyncIgnoreCase(t *testing.T) { 1756 r := fstest.NewRun(t) 1757 defer r.Finalise() 1758 1759 // Only test if filesystems are case sensitive 1760 if r.Fremote.Features().CaseInsensitive || r.Flocal.Features().CaseInsensitive { 1761 t.Skip("Skipping test as local or remote are case-insensitive") 1762 } 1763 1764 fs.Config.IgnoreCaseSync = true 1765 defer func() { fs.Config.IgnoreCaseSync = false }() 1766 1767 // Create files with different filename casing 1768 file1 := r.WriteFile("existing", "potato", t1) 1769 fstest.CheckItems(t, r.Flocal, file1) 1770 file2 := r.WriteObject(context.Background(), "EXISTING", "potato", t1) 1771 fstest.CheckItems(t, r.Fremote, file2) 1772 1773 // Should not copy files that are differently-cased but otherwise identical 1774 accounting.GlobalStats().ResetCounters() 1775 err := Sync(context.Background(), r.Fremote, r.Flocal, false) 1776 require.NoError(t, err) 1777 fstest.CheckItems(t, r.Flocal, file1) 1778 fstest.CheckItems(t, r.Fremote, file2) 1779 } 1780 1781 // Test that aborting on max upload works 1782 func TestAbort(t *testing.T) { 1783 r := fstest.NewRun(t) 1784 defer r.Finalise() 1785 1786 if r.Fremote.Name() != "local" { 1787 t.Skip("This test only runs on local") 1788 } 1789 1790 oldMaxTransfer := fs.Config.MaxTransfer 1791 oldTransfers := fs.Config.Transfers 1792 oldCheckers := fs.Config.Checkers 1793 fs.Config.MaxTransfer = 3 * 1024 1794 fs.Config.Transfers = 1 1795 fs.Config.Checkers = 1 1796 defer func() { 1797 fs.Config.MaxTransfer = oldMaxTransfer 1798 fs.Config.Transfers = oldTransfers 1799 fs.Config.Checkers = oldCheckers 1800 }() 1801 1802 // Create file on source 1803 file1 := r.WriteFile("file1", string(make([]byte, 5*1024)), t1) 1804 file2 := r.WriteFile("file2", string(make([]byte, 2*1024)), t1) 1805 file3 := r.WriteFile("file3", string(make([]byte, 3*1024)), t1) 1806 fstest.CheckItems(t, r.Flocal, file1, file2, file3) 1807 fstest.CheckItems(t, r.Fremote) 1808 1809 accounting.GlobalStats().ResetCounters() 1810 1811 err := Sync(context.Background(), r.Fremote, r.Flocal, false) 1812 expectedErr := fserrors.FsError(accounting.ErrorMaxTransferLimitReached) 1813 fserrors.Count(expectedErr) 1814 assert.Equal(t, expectedErr, err) 1815 }