The sync report flags (--combined, --missing-on-src, --missing-on-dst, --match, --differ, --error and --dest-after) were only wired up in the CLI commands so there was no way to get these reports over the rc or from librclone. This adds boolean parameters of the same names as operations/check (combined, missingOnSrc, missingOnDst, match, differ, error and destAfter) to sync/sync, sync/copy and sync/move. Each requested report is returned as an array of strings in the output, just as operations/check does. All default to off so existing callers see no change in the output. To share the code between the CLI and the rc the report writer helper from operations/check is exported as operations.RcReportWriter, the lsf defaults for --dest-after are moved into operations.NewSyncLoggerOpt and the listing setup and --no-traverse warnings from operationsflags.ConfigureLoggers into LoggerOpt.Init.
143 lines
4.4 KiB
Go
143 lines
4.4 KiB
Go
package sync
|
|
|
|
import (
|
|
"context"
|
|
"sort"
|
|
"testing"
|
|
|
|
"github.com/rclone/rclone/fs/cache"
|
|
"github.com/rclone/rclone/fs/rc"
|
|
"github.com/rclone/rclone/fstest"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func rcNewRun(t *testing.T, method string) (*fstest.Run, *rc.Call) {
|
|
if *fstest.RemoteName != "" {
|
|
t.Skip("Skipping test on non local remote")
|
|
}
|
|
r := fstest.NewRun(t)
|
|
call := rc.Calls.Get(method)
|
|
assert.NotNil(t, call)
|
|
cache.Put(r.LocalName, r.Flocal)
|
|
cache.Put(r.FremoteName, r.Fremote)
|
|
return r, call
|
|
}
|
|
|
|
// sync/copy: copy a directory from source remote to destination remote
|
|
func TestRcCopy(t *testing.T) {
|
|
r, call := rcNewRun(t, "sync/copy")
|
|
r.Mkdir(context.Background(), r.Fremote)
|
|
|
|
file1 := r.WriteBoth(context.Background(), "file1", "file1 contents", t1)
|
|
file2 := r.WriteFile("subdir/file2", "file2 contents", t2)
|
|
file3 := r.WriteObject(context.Background(), "subdir/subsubdir/file3", "file3 contents", t3)
|
|
|
|
r.CheckLocalItems(t, file1, file2)
|
|
r.CheckRemoteItems(t, file1, file3)
|
|
|
|
in := rc.Params{
|
|
"srcFs": r.LocalName,
|
|
"dstFs": r.FremoteName,
|
|
}
|
|
out, err := call.Fn(context.Background(), in)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, rc.Params{}, out)
|
|
|
|
r.CheckLocalItems(t, file1, file2)
|
|
r.CheckRemoteItems(t, file1, file2, file3)
|
|
}
|
|
|
|
// sync/move: move a directory from source remote to destination remote
|
|
func TestRcMove(t *testing.T) {
|
|
r, call := rcNewRun(t, "sync/move")
|
|
r.Mkdir(context.Background(), r.Fremote)
|
|
|
|
file1 := r.WriteBoth(context.Background(), "file1", "file1 contents", t1)
|
|
file2 := r.WriteFile("subdir/file2", "file2 contents", t2)
|
|
file3 := r.WriteObject(context.Background(), "subdir/subsubdir/file3", "file3 contents", t3)
|
|
|
|
r.CheckLocalItems(t, file1, file2)
|
|
r.CheckRemoteItems(t, file1, file3)
|
|
|
|
in := rc.Params{
|
|
"srcFs": r.LocalName,
|
|
"dstFs": r.FremoteName,
|
|
}
|
|
out, err := call.Fn(context.Background(), in)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, rc.Params{}, out)
|
|
|
|
r.CheckLocalItems(t)
|
|
r.CheckRemoteItems(t, file1, file2, file3)
|
|
}
|
|
|
|
// sync/sync: sync a directory from source remote to destination remote
|
|
func TestRcSync(t *testing.T) {
|
|
r, call := rcNewRun(t, "sync/sync")
|
|
r.Mkdir(context.Background(), r.Fremote)
|
|
|
|
file1 := r.WriteBoth(context.Background(), "file1", "file1 contents", t1)
|
|
file2 := r.WriteFile("subdir/file2", "file2 contents", t2)
|
|
file3 := r.WriteObject(context.Background(), "subdir/subsubdir/file3", "file3 contents", t3)
|
|
|
|
r.CheckLocalItems(t, file1, file2)
|
|
r.CheckRemoteItems(t, file1, file3)
|
|
|
|
in := rc.Params{
|
|
"srcFs": r.LocalName,
|
|
"dstFs": r.FremoteName,
|
|
}
|
|
out, err := call.Fn(context.Background(), in)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, rc.Params{}, out)
|
|
|
|
r.CheckLocalItems(t, file1, file2)
|
|
r.CheckRemoteItems(t, file1, file2)
|
|
}
|
|
|
|
// sync/copy: check the reports are returned when requested
|
|
func TestRcCopyReports(t *testing.T) {
|
|
r, call := rcNewRun(t, "sync/copy")
|
|
r.Mkdir(context.Background(), r.Fremote)
|
|
|
|
file1 := r.WriteBoth(context.Background(), "file1", "file1 contents", t1)
|
|
file2 := r.WriteFile("subdir/file2", "file2 contents", t2)
|
|
file3 := r.WriteObject(context.Background(), "subdir/subsubdir/file3", "file3 contents", t3)
|
|
file4 := r.WriteFile("file4", "file4 contents", t1)
|
|
file4dst := r.WriteObject(context.Background(), "file4", "different contents", t1)
|
|
|
|
r.CheckLocalItems(t, file1, file2, file4)
|
|
r.CheckRemoteItems(t, file1, file3, file4dst)
|
|
|
|
in := rc.Params{
|
|
"srcFs": r.LocalName,
|
|
"dstFs": r.FremoteName,
|
|
"combined": true,
|
|
"missingOnSrc": true,
|
|
"missingOnDst": true,
|
|
"match": true,
|
|
"differ": true,
|
|
"destAfter": true,
|
|
}
|
|
out, err := call.Fn(context.Background(), in)
|
|
require.NoError(t, err)
|
|
|
|
sorted := func(name string) []string {
|
|
result, ok := out[name].(*[]string)
|
|
require.True(t, ok, name)
|
|
sort.Strings(*result)
|
|
return *result
|
|
}
|
|
assert.Equal(t, []string{"* file4", "+ subdir/file2", "- subdir/subsubdir/file3", "= file1"}, sorted("combined"))
|
|
assert.Equal(t, []string{"subdir/subsubdir/file3"}, sorted("missingOnSrc"))
|
|
assert.Equal(t, []string{"subdir/file2"}, sorted("missingOnDst"))
|
|
assert.Equal(t, []string{"file1"}, sorted("match"))
|
|
assert.Equal(t, []string{"file4"}, sorted("differ"))
|
|
assert.Equal(t, []string{"file1", "file4", "subdir/file2", "subdir/subsubdir/file3"}, sorted("destAfter"))
|
|
assert.NotContains(t, out, "error")
|
|
|
|
r.CheckLocalItems(t, file1, file2, file4)
|
|
r.CheckRemoteItems(t, file1, file2, file3, file4)
|
|
}
|