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  }