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