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