2016-07-04 14:12:33 +02:00
// Test sync/copy/move
2018-01-12 17:30:54 +01:00
package sync
2016-07-04 14:12:33 +02:00
import (
2023-10-01 11:02:56 +02:00
"bytes"
2019-06-17 10:34:30 +02:00
"context"
2021-11-04 11:12:57 +01:00
"errors"
2019-07-25 12:28:27 +02:00
"fmt"
2024-02-06 17:00:34 +01:00
"io"
2023-10-01 11:02:56 +02:00
"os"
"os/exec"
2017-09-17 15:05:33 +02:00
"runtime"
2023-10-01 11:02:56 +02:00
"sort"
2019-09-05 22:29:35 +02:00
"strings"
2016-07-04 14:12:33 +02:00
"testing"
"time"
2023-10-01 11:02:56 +02:00
mutex "sync" // renamed as "sync" already in use
2019-07-28 19:47:38 +02:00
_ "github.com/rclone/rclone/backend/all" // import all backends
2024-02-29 01:29:38 +01:00
"github.com/rclone/rclone/cmd/bisync/bilib"
2019-07-28 19:47:38 +02:00
"github.com/rclone/rclone/fs"
"github.com/rclone/rclone/fs/accounting"
"github.com/rclone/rclone/fs/filter"
"github.com/rclone/rclone/fs/fserrors"
"github.com/rclone/rclone/fs/hash"
"github.com/rclone/rclone/fs/operations"
"github.com/rclone/rclone/fstest"
2016-07-04 14:12:33 +02:00
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
2017-09-08 17:19:41 +02:00
"golang.org/x/text/unicode/norm"
2016-07-04 14:12:33 +02:00
)
2018-01-12 17:30:54 +01:00
// Some times used in the tests
var (
t1 = fstest . Time ( "2001-02-03T04:05:06.499999999Z" )
t2 = fstest . Time ( "2011-12-25T12:59:59.123456789Z" )
t3 = fstest . Time ( "2011-12-30T12:59:59.000000000Z" )
)
// TestMain drives the tests
func TestMain ( m * testing . M ) {
fstest . TestMain ( m )
}
2016-07-04 14:12:33 +02:00
// Check dry run is working
func TestCopyWithDryRun ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2016-07-04 14:12:33 +02:00
file1 := r . WriteFile ( "sub dir/hello world" , "hello world" , t1 )
2020-11-05 17:27:01 +01:00
r . Mkdir ( ctx , r . Fremote )
2016-07-04 14:12:33 +02:00
2020-11-05 12:33:32 +01:00
ci . DryRun = true
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := CopyDir ( ctx , r . Fremote , r . Flocal , false )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t ) // error expected here because dry-run
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
r . CheckRemoteItems ( t )
2016-07-04 14:12:33 +02:00
}
// Now without dry run
func TestCopy ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2016-07-04 14:12:33 +02:00
file1 := r . WriteFile ( "sub dir/hello world" , "hello world" , t1 )
2024-02-06 17:00:34 +01:00
_ , err := operations . SetDirModTime ( ctx , r . Flocal , nil , "sub dir" , t2 )
if err != nil && ! errors . Is ( err , fs . ErrorNotImplemented ) {
require . NoError ( t , err )
}
2020-11-05 17:27:01 +01:00
r . Mkdir ( ctx , r . Fremote )
2016-07-04 14:12:33 +02:00
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2024-02-06 17:00:34 +01:00
err = CopyDir ( ctx , r . Fremote , r . Flocal , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2016-07-04 14:12:33 +02:00
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
r . CheckRemoteItems ( t , file1 )
2024-02-06 17:00:34 +01:00
// Check that the modtimes of the directories are as expected
r . CheckDirectoryModTimes ( t , "sub dir" )
}
2024-04-04 19:03:20 +02:00
func testCopyMetadata ( t * testing . T , createEmptySrcDirs bool ) {
2024-02-06 17:00:34 +01:00
ctx := context . Background ( )
ctx , ci := fs . AddConfig ( ctx )
ci . Metadata = true
r := fstest . NewRun ( t )
features := r . Fremote . Features ( )
if ! features . ReadMetadata && ! features . WriteMetadata && ! features . UserMetadata &&
! features . ReadDirMetadata && ! features . WriteDirMetadata && ! features . UserDirMetadata {
t . Skip ( "Skipping as metadata not supported" )
}
2024-06-08 11:40:42 +02:00
if createEmptySrcDirs && ! features . CanHaveEmptyDirectories {
t . Skip ( "Skipping as can't have empty directories" )
}
2024-02-06 17:00:34 +01:00
const content = "hello metadata world!"
const dirPath = "metadata sub dir"
2024-04-04 19:03:20 +02:00
const emptyDirPath = "empty metadata sub dir"
2024-02-06 17:00:34 +01:00
const filePath = dirPath + "/hello metadata world"
fileMetadata := fs . Metadata {
// System metadata supported by all backends
"mtime" : t1 . Format ( time . RFC3339Nano ) ,
// User metadata
"potato" : "jersey" ,
}
dirMetadata := fs . Metadata {
// System metadata supported by all backends
"mtime" : t2 . Format ( time . RFC3339Nano ) ,
// User metadata
"potato" : "king edward" ,
}
// Make the directory with metadata - may fall back to Mkdir
_ , err := operations . MkdirMetadata ( ctx , r . Flocal , dirPath , dirMetadata )
require . NoError ( t , err )
2024-04-04 19:03:20 +02:00
// Make the empty directory with metadata - may fall back to Mkdir
_ , err = operations . MkdirMetadata ( ctx , r . Flocal , emptyDirPath , dirMetadata )
require . NoError ( t , err )
2024-02-06 17:00:34 +01:00
// Upload the file with metadata
in := io . NopCloser ( bytes . NewBufferString ( content ) )
_ , err = operations . Rcat ( ctx , r . Flocal , filePath , in , t1 , fileMetadata )
require . NoError ( t , err )
file1 := fstest . NewItem ( filePath , content , t1 )
// Reset the time of the directory
_ , err = operations . SetDirModTime ( ctx , r . Flocal , nil , dirPath , t2 )
if err != nil && ! errors . Is ( err , fs . ErrorNotImplemented ) {
require . NoError ( t , err )
}
ctx = predictDstFromLogger ( ctx )
2024-04-04 19:03:20 +02:00
err = CopyDir ( ctx , r . Fremote , r . Flocal , createEmptySrcDirs )
2024-02-06 17:00:34 +01:00
require . NoError ( t , err )
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
r . CheckLocalItems ( t , file1 )
r . CheckRemoteItems ( t , file1 )
// Check that the modtimes of the directories are as expected
r . CheckDirectoryModTimes ( t , dirPath )
// Check that the metadata on the directory and file is correct
2024-06-11 12:30:32 +02:00
if features . WriteMetadata && features . ReadMetadata {
2024-02-06 17:00:34 +01:00
fstest . CheckEntryMetadata ( ctx , t , r . Fremote , fstest . NewObject ( ctx , t , r . Fremote , filePath ) , fileMetadata )
}
2024-06-11 12:30:32 +02:00
if features . WriteDirMetadata && features . ReadDirMetadata {
2024-02-06 17:00:34 +01:00
fstest . CheckEntryMetadata ( ctx , t , r . Fremote , fstest . NewDirectory ( ctx , t , r . Fremote , dirPath ) , dirMetadata )
}
2024-04-04 19:03:20 +02:00
if ! createEmptySrcDirs {
// dir must not exist
_ , err := fstest . NewDirectoryRetries ( ctx , t , r . Fremote , emptyDirPath , 1 )
assert . Error ( t , err , "Not expecting to find empty directory" )
assert . True ( t , errors . Is ( err , fs . ErrorDirNotFound ) , fmt . Sprintf ( "expecting wrapped %#v not: %#v" , fs . ErrorDirNotFound , err ) )
} else {
// dir must exist
dir := fstest . NewDirectory ( ctx , t , r . Fremote , emptyDirPath )
if features . ReadDirMetadata {
fstest . CheckEntryMetadata ( ctx , t , r . Fremote , dir , dirMetadata )
}
}
}
func TestCopyMetadata ( t * testing . T ) {
testCopyMetadata ( t , true )
}
func TestCopyMetadataNoEmptyDirs ( t * testing . T ) {
testCopyMetadata ( t , false )
2016-07-04 14:12:33 +02:00
}
2019-06-20 13:50:25 +02:00
func TestCopyMissingDirectory ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2019-06-20 13:50:25 +02:00
r := fstest . NewRun ( t )
2020-11-05 17:27:01 +01:00
r . Mkdir ( ctx , r . Fremote )
2019-06-20 13:50:25 +02:00
2020-11-05 17:27:01 +01:00
nonExistingFs , err := fs . NewFs ( ctx , "/non-existing" )
2019-06-20 13:50:25 +02:00
if err != nil {
t . Fatal ( err )
}
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err = CopyDir ( ctx , r . Fremote , nonExistingFs , false )
2019-06-20 13:50:25 +02:00
require . Error ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2019-06-20 13:50:25 +02:00
}
2018-11-25 17:49:38 +01:00
// Now with --no-traverse
func TestCopyNoTraverse ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2018-11-25 17:49:38 +01:00
r := fstest . NewRun ( t )
2020-11-05 12:33:32 +01:00
ci . NoTraverse = true
2018-11-25 17:49:38 +01:00
file1 := r . WriteFile ( "sub dir/hello world" , "hello world" , t1 )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := CopyDir ( ctx , r . Fremote , r . Flocal , false )
2018-11-25 17:49:38 +01:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2018-11-25 17:49:38 +01:00
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
r . CheckRemoteItems ( t , file1 )
2018-11-25 17:49:38 +01:00
}
2020-05-15 12:39:07 +02:00
// Now with --check-first
func TestCopyCheckFirst ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2020-05-15 12:39:07 +02:00
r := fstest . NewRun ( t )
2020-11-05 12:33:32 +01:00
ci . CheckFirst = true
2020-05-15 12:39:07 +02:00
file1 := r . WriteFile ( "sub dir/hello world" , "hello world" , t1 )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := CopyDir ( ctx , r . Fremote , r . Flocal , false )
2020-05-15 12:39:07 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2020-05-15 12:39:07 +02:00
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
r . CheckRemoteItems ( t , file1 )
2020-05-15 12:39:07 +02:00
}
2018-11-25 17:49:38 +01:00
// Now with --no-traverse
func TestSyncNoTraverse ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2018-11-25 17:49:38 +01:00
r := fstest . NewRun ( t )
2020-11-05 12:33:32 +01:00
ci . NoTraverse = true
2018-11-25 17:49:38 +01:00
file1 := r . WriteFile ( "sub dir/hello world" , "hello world" , t1 )
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := Sync ( ctx , r . Fremote , r . Flocal , false )
2018-11-25 17:49:38 +01:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2018-11-25 17:49:38 +01:00
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
r . CheckRemoteItems ( t , file1 )
2018-11-25 17:49:38 +01:00
}
2016-07-04 14:12:33 +02:00
// Test copy with depth
func TestCopyWithDepth ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2016-07-04 14:12:33 +02:00
file1 := r . WriteFile ( "sub dir/hello world" , "hello world" , t1 )
file2 := r . WriteFile ( "hello world2" , "hello world2" , t2 )
// Check the MaxDepth too
2020-11-05 12:33:32 +01:00
ci . MaxDepth = 1
2016-07-04 14:12:33 +02:00
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := CopyDir ( ctx , r . Fremote , r . Flocal , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2016-07-04 14:12:33 +02:00
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 , file2 )
r . CheckRemoteItems ( t , file2 )
2016-07-04 14:12:33 +02:00
}
2018-10-19 18:41:14 +02:00
// Test copy with files from
2019-02-13 18:14:51 +01:00
func testCopyWithFilesFrom ( t * testing . T , noTraverse bool ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2018-10-19 18:41:14 +02:00
r := fstest . NewRun ( t )
file1 := r . WriteFile ( "potato2" , "hello world" , t1 )
file2 := r . WriteFile ( "hello world2" , "hello world2" , t2 )
// Set the --files-from equivalent
f , err := filter . NewFilter ( nil )
require . NoError ( t , err )
require . NoError ( t , f . AddFile ( "potato2" ) )
require . NoError ( t , f . AddFile ( "notfound" ) )
2020-11-26 18:10:41 +01:00
// Change the active filter
ctx = filter . ReplaceConfig ( ctx , f )
2020-11-05 12:33:32 +01:00
ci . NoTraverse = noTraverse
2018-10-19 18:41:14 +02:00
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err = CopyDir ( ctx , r . Fremote , r . Flocal , false )
2018-10-19 18:41:14 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2018-10-19 18:41:14 +02:00
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 , file2 )
r . CheckRemoteItems ( t , file1 )
2018-10-19 18:41:14 +02:00
}
2019-02-13 18:14:51 +01:00
func TestCopyWithFilesFrom ( t * testing . T ) { testCopyWithFilesFrom ( t , false ) }
func TestCopyWithFilesFromAndNoTraverse ( t * testing . T ) { testCopyWithFilesFrom ( t , true ) }
2018-10-19 18:41:14 +02:00
2018-06-03 10:21:25 +02:00
// Test copy empty directories
func TestCopyEmptyDirectories ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2018-06-03 10:21:25 +02:00
r := fstest . NewRun ( t )
file1 := r . WriteFile ( "sub dir/hello world" , "hello world" , t1 )
2024-04-17 17:55:17 +02:00
_ , err := operations . MkdirModTime ( ctx , r . Flocal , "sub dir2/sub sub dir2" , t2 )
require . NoError ( t , err )
_ , err = operations . SetDirModTime ( ctx , r . Flocal , nil , "sub dir2" , t2 )
2018-06-03 10:21:25 +02:00
require . NoError ( t , err )
2020-11-05 17:27:01 +01:00
r . Mkdir ( ctx , r . Fremote )
2018-06-03 10:21:25 +02:00
2024-02-06 17:00:34 +01:00
// Set the modtime on "sub dir" to something specific
// Without this it fails on the CI and in VirtualBox with variances of up to 10mS
_ , err = operations . SetDirModTime ( ctx , r . Flocal , nil , "sub dir" , t1 )
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err = CopyDir ( ctx , r . Fremote , r . Flocal , true )
2019-03-06 09:43:46 +01:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2019-03-06 09:43:46 +01:00
2021-11-09 12:43:36 +01:00
r . CheckRemoteListing (
2019-03-06 09:43:46 +01:00
t ,
[ ] fstest . Item {
file1 ,
} ,
[ ] string {
"sub dir" ,
"sub dir2" ,
2024-04-17 17:55:17 +02:00
"sub dir2/sub sub dir2" ,
2019-03-06 09:43:46 +01:00
} ,
)
2024-02-06 17:00:34 +01:00
// Check that the modtimes of the directories are as expected
2024-04-17 17:55:17 +02:00
r . CheckDirectoryModTimes ( t , "sub dir" , "sub dir2" , "sub dir2/sub sub dir2" )
2019-03-06 09:43:46 +01:00
}
2024-04-04 19:03:20 +02:00
// Test copy empty directories when we are configured not to create them
func TestCopyNoEmptyDirectories ( t * testing . T ) {
ctx := context . Background ( )
r := fstest . NewRun ( t )
file1 := r . WriteFile ( "sub dir/hello world" , "hello world" , t1 )
err := operations . Mkdir ( ctx , r . Flocal , "sub dir2" )
require . NoError ( t , err )
2024-04-17 17:55:17 +02:00
_ , err = operations . MkdirModTime ( ctx , r . Flocal , "sub dir2/sub sub dir2" , t2 )
require . NoError ( t , err )
2024-04-04 19:03:20 +02:00
r . Mkdir ( ctx , r . Fremote )
err = CopyDir ( ctx , r . Fremote , r . Flocal , false )
require . NoError ( t , err )
r . CheckRemoteListing (
t ,
[ ] fstest . Item {
file1 ,
} ,
[ ] string {
"sub dir" ,
} ,
)
}
2019-03-06 09:43:46 +01:00
// Test move empty directories
func TestMoveEmptyDirectories ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2019-03-06 09:43:46 +01:00
r := fstest . NewRun ( t )
file1 := r . WriteFile ( "sub dir/hello world" , "hello world" , t1 )
2024-02-06 17:00:34 +01:00
_ , err := operations . MkdirModTime ( ctx , r . Flocal , "sub dir2" , t2 )
2019-03-06 09:43:46 +01:00
require . NoError ( t , err )
2024-02-06 17:00:34 +01:00
subDir := fstest . NewDirectory ( ctx , t , r . Flocal , "sub dir" )
subDirT := subDir . ModTime ( ctx )
2020-11-05 17:27:01 +01:00
r . Mkdir ( ctx , r . Fremote )
2019-03-06 09:43:46 +01:00
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err = MoveDir ( ctx , r . Fremote , r . Flocal , false , true )
2019-03-06 09:43:46 +01:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2019-03-06 09:43:46 +01:00
2021-11-09 12:43:36 +01:00
r . CheckRemoteListing (
2019-03-06 09:43:46 +01:00
t ,
[ ] fstest . Item {
file1 ,
} ,
[ ] string {
"sub dir" ,
"sub dir2" ,
} ,
)
2024-02-06 17:00:34 +01:00
// Check that the modtimes of the directories are as expected
r . CheckDirectoryModTimes ( t , "sub dir2" )
// Note that "sub dir" mod time is updated when file1 is deleted from it
// So check it more manually
got := fstest . NewDirectory ( ctx , t , r . Fremote , "sub dir" )
2024-03-01 11:56:48 +01:00
fstest . CheckDirModTime ( ctx , t , r . Fremote , got , subDirT )
2019-03-06 09:43:46 +01:00
}
2024-03-07 17:13:36 +01:00
// Test that --no-update-dir-modtime is working
func TestSyncNoUpdateDirModtime ( t * testing . T ) {
r := fstest . NewRun ( t )
if r . Fremote . Features ( ) . DirSetModTime == nil {
t . Skip ( "Skipping test as backend does not support DirSetModTime" )
}
ctx , ci := fs . AddConfig ( context . Background ( ) )
ci . NoUpdateDirModTime = true
const name = "sub dir no update dir modtime"
// Set the modtime on name to something specific
_ , err := operations . MkdirModTime ( ctx , r . Flocal , name , t1 )
require . NoError ( t , err )
// Create the remote directory with the current time
require . NoError ( t , r . Fremote . Mkdir ( ctx , name ) )
// Read its modification time
wantT := fstest . NewDirectory ( ctx , t , r . Fremote , name ) . ModTime ( ctx )
ctx = predictDstFromLogger ( ctx )
err = Sync ( ctx , r . Fremote , r . Flocal , true )
require . NoError ( t , err )
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
r . CheckRemoteListing (
t ,
[ ] fstest . Item { } ,
[ ] string {
name ,
} ,
)
// Read the new directory modification time - it should not have changed
gotT := fstest . NewDirectory ( ctx , t , r . Fremote , name ) . ModTime ( ctx )
fstest . AssertTimeEqualWithPrecision ( t , name , wantT , gotT , r . Fremote . Precision ( ) )
}
2024-04-04 19:03:20 +02:00
// Test move empty directories when we are not configured to create them
func TestMoveNoEmptyDirectories ( t * testing . T ) {
ctx := context . Background ( )
r := fstest . NewRun ( t )
file1 := r . WriteFile ( "sub dir/hello world" , "hello world" , t1 )
err := operations . Mkdir ( ctx , r . Flocal , "sub dir2" )
require . NoError ( t , err )
r . Mkdir ( ctx , r . Fremote )
err = MoveDir ( ctx , r . Fremote , r . Flocal , false , false )
require . NoError ( t , err )
r . CheckRemoteListing (
t ,
[ ] fstest . Item {
file1 ,
} ,
[ ] string {
"sub dir" ,
} ,
)
}
2019-03-06 09:43:46 +01:00
// Test sync empty directories
func TestSyncEmptyDirectories ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2019-03-06 09:43:46 +01:00
r := fstest . NewRun ( t )
file1 := r . WriteFile ( "sub dir/hello world" , "hello world" , t1 )
2024-02-06 17:00:34 +01:00
_ , err := operations . MkdirModTime ( ctx , r . Flocal , "sub dir2" , t2 )
2019-03-06 09:43:46 +01:00
require . NoError ( t , err )
2024-02-06 17:00:34 +01:00
// Set the modtime on "sub dir" to something specific
// Without this it fails on the CI and in VirtualBox with variances of up to 10mS
_ , err = operations . SetDirModTime ( ctx , r . Flocal , nil , "sub dir" , t1 )
require . NoError ( t , err )
2020-11-05 17:27:01 +01:00
r . Mkdir ( ctx , r . Fremote )
2019-03-06 09:43:46 +01:00
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , r . Fremote , r . Flocal , true )
2018-06-03 10:21:25 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2018-06-03 10:21:25 +02:00
2021-11-09 12:43:36 +01:00
r . CheckRemoteListing (
2018-06-03 10:21:25 +02:00
t ,
[ ] fstest . Item {
file1 ,
} ,
[ ] string {
"sub dir" ,
"sub dir2" ,
} ,
)
2024-02-06 17:00:34 +01:00
// Check that the modtimes of the directories are as expected
r . CheckDirectoryModTimes ( t , "sub dir" , "sub dir2" )
}
// Test delayed mod time setting
func TestSyncSetDelayedModTimes ( t * testing . T ) {
ctx := context . Background ( )
r := fstest . NewRun ( t )
if ! r . Fremote . Features ( ) . DirModTimeUpdatesOnWrite {
t . Skip ( "Backend doesn't have DirModTimeUpdatesOnWrite set" )
}
// Create directories without timestamps
require . NoError ( t , r . Flocal . Mkdir ( ctx , "a1/b1/c1/d1/e1/f1" ) )
require . NoError ( t , r . Flocal . Mkdir ( ctx , "a1/b2/c1/d1/e1/f1" ) )
require . NoError ( t , r . Flocal . Mkdir ( ctx , "a1/b1/c1/d2/e1/f1" ) )
require . NoError ( t , r . Flocal . Mkdir ( ctx , "a1/b1/c1/d2/e1/f2" ) )
dirs := [ ] string {
"a1" ,
"a1/b1" ,
"a1/b1/c1" ,
"a1/b1/c1/d1" ,
"a1/b1/c1/d1/e1" ,
"a1/b1/c1/d1/e1/f1" ,
"a1/b1/c1/d2" ,
"a1/b1/c1/d2/e1" ,
"a1/b1/c1/d2/e1/f1" ,
"a1/b1/c1/d2/e1/f2" ,
"a1/b2" ,
"a1/b2/c1" ,
"a1/b2/c1/d1" ,
"a1/b2/c1/d1/e1" ,
"a1/b2/c1/d1/e1/f1" ,
}
r . CheckLocalListing ( t , [ ] fstest . Item { } , dirs )
// Timestamp the directories in reverse order
ts := t1
for i := len ( dirs ) - 1 ; i >= 0 ; i -- {
dir := dirs [ i ]
_ , err := operations . SetDirModTime ( ctx , r . Flocal , nil , dir , ts )
require . NoError ( t , err )
ts = ts . Add ( time . Minute )
}
r . Mkdir ( ctx , r . Fremote )
ctx = predictDstFromLogger ( ctx )
err := Sync ( ctx , r . Fremote , r . Flocal , true )
require . NoError ( t , err )
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
r . CheckRemoteListing ( t , [ ] fstest . Item { } , dirs )
// Check that the modtimes of the directories are as expected
r . CheckDirectoryModTimes ( t , dirs ... )
2018-06-03 10:21:25 +02:00
}
2024-04-04 19:03:20 +02:00
// Test sync empty directories when we are not configured to create them
func TestSyncNoEmptyDirectories ( t * testing . T ) {
ctx := context . Background ( )
r := fstest . NewRun ( t )
file1 := r . WriteFile ( "sub dir/hello world" , "hello world" , t1 )
err := operations . Mkdir ( ctx , r . Flocal , "sub dir2" )
require . NoError ( t , err )
r . Mkdir ( ctx , r . Fremote )
err = Sync ( ctx , r . Fremote , r . Flocal , false )
require . NoError ( t , err )
r . CheckRemoteListing (
t ,
[ ] fstest . Item {
file1 ,
} ,
[ ] string {
"sub dir" ,
} ,
)
}
2020-10-13 23:43:40 +02:00
// Test a server-side copy if possible, or the backup path if not
2016-07-04 14:12:33 +02:00
func TestServerSideCopy ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2020-11-05 17:27:01 +01:00
file1 := r . WriteObject ( ctx , "sub dir/hello world" , "hello world" , t1 )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1 )
2016-07-04 14:12:33 +02:00
2019-08-08 20:58:02 +02:00
FremoteCopy , _ , finaliseCopy , err := fstest . RandomRemote ( )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
defer finaliseCopy ( )
2017-10-29 13:23:10 +01:00
t . Logf ( "Server side copy (if possible) %v -> %v" , r . Fremote , FremoteCopy )
2016-07-04 14:12:33 +02:00
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err = CopyDir ( ctx , FremoteCopy , r . Fremote , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2016-07-04 14:12:33 +02:00
2017-10-29 13:23:10 +01:00
fstest . CheckItems ( t , FremoteCopy , file1 )
2016-07-04 14:12:33 +02:00
}
// Check that if the local file doesn't exist when we copy it up,
// nothing happens to the remote file
func TestCopyAfterDelete ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2020-11-05 17:27:01 +01:00
file1 := r . WriteObject ( ctx , "sub dir/hello world" , "hello world" , t1 )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t )
r . CheckRemoteItems ( t , file1 )
2016-07-04 14:12:33 +02:00
2020-11-05 17:27:01 +01:00
err := operations . Mkdir ( ctx , r . Flocal , "" )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err = CopyDir ( ctx , r . Fremote , r . Flocal , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2016-07-04 14:12:33 +02:00
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t )
r . CheckRemoteItems ( t , file1 )
2016-07-04 14:12:33 +02:00
}
// Check the copy downloading a file
func TestCopyRedownload ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2020-11-05 17:27:01 +01:00
file1 := r . WriteObject ( ctx , "sub dir/hello world" , "hello world" , t1 )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1 )
2016-07-04 14:12:33 +02:00
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := CopyDir ( ctx , r . Flocal , r . Fremote , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2016-07-04 14:12:33 +02:00
2018-06-10 18:33:17 +02:00
// Test with combined precision of local and remote as we copied it there and back
2021-11-09 12:43:36 +01:00
r . CheckLocalListing ( t , [ ] fstest . Item { file1 } , nil )
2016-07-04 14:12:33 +02:00
}
// Create a file and sync it. Change the last modified date and resync.
// If we're only doing sync by size and checksum, we expect nothing to
// to be transferred on the second sync.
func TestSyncBasedOnCheckSum ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2020-11-05 12:33:32 +01:00
ci . CheckSum = true
2016-07-04 14:12:33 +02:00
2019-06-29 03:17:18 +02:00
file1 := r . WriteFile ( "check sum" , "-" , t1 )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
2016-07-04 14:12:33 +02:00
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := Sync ( ctx , r . Fremote , r . Flocal , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2016-07-04 14:12:33 +02:00
// We should have transferred exactly one file.
2019-09-05 22:29:35 +02:00
assert . Equal ( t , toyFileTransfers ( r ) , accounting . GlobalStats ( ) . GetTransfers ( ) )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1 )
2016-07-04 14:12:33 +02:00
// Change last modified date only
2019-06-29 03:17:18 +02:00
file2 := r . WriteFile ( "check sum" , "-" , t2 )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file2 )
2016-07-04 14:12:33 +02:00
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , r . Fremote , r . Flocal , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2016-07-04 14:12:33 +02:00
// We should have transferred no files
2019-07-18 12:13:54 +02:00
assert . Equal ( t , int64 ( 0 ) , accounting . GlobalStats ( ) . GetTransfers ( ) )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file2 )
r . CheckRemoteItems ( t , file1 )
2016-07-04 14:12:33 +02:00
}
// Create a file and sync it. Change the last modified date and the
// file contents but not the size. If we're only doing sync by size
// only, we expect nothing to to be transferred on the second sync.
func TestSyncSizeOnly ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2020-11-05 12:33:32 +01:00
ci . SizeOnly = true
2016-07-04 14:12:33 +02:00
file1 := r . WriteFile ( "sizeonly" , "potato" , t1 )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
2016-07-04 14:12:33 +02:00
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := Sync ( ctx , r . Fremote , r . Flocal , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2016-07-04 14:12:33 +02:00
// We should have transferred exactly one file.
2019-09-05 22:29:35 +02:00
assert . Equal ( t , toyFileTransfers ( r ) , accounting . GlobalStats ( ) . GetTransfers ( ) )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1 )
2016-07-04 14:12:33 +02:00
// Update mtime, md5sum but not length of file
file2 := r . WriteFile ( "sizeonly" , "POTATO" , t2 )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file2 )
2016-07-04 14:12:33 +02:00
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , r . Fremote , r . Flocal , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2016-07-04 14:12:33 +02:00
// We should have transferred no files
2019-07-18 12:13:54 +02:00
assert . Equal ( t , int64 ( 0 ) , accounting . GlobalStats ( ) . GetTransfers ( ) )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file2 )
r . CheckRemoteItems ( t , file1 )
2016-07-04 14:12:33 +02:00
}
// Create a file and sync it. Keep the last modified date but change
// the size. With --ignore-size we expect nothing to to be
// transferred on the second sync.
func TestSyncIgnoreSize ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2020-11-05 12:33:32 +01:00
ci . IgnoreSize = true
2016-07-04 14:12:33 +02:00
file1 := r . WriteFile ( "ignore-size" , "contents" , t1 )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
2016-07-04 14:12:33 +02:00
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := Sync ( ctx , r . Fremote , r . Flocal , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2016-07-04 14:12:33 +02:00
// We should have transferred exactly one file.
2019-09-05 22:29:35 +02:00
assert . Equal ( t , toyFileTransfers ( r ) , accounting . GlobalStats ( ) . GetTransfers ( ) )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1 )
2016-07-04 14:12:33 +02:00
// Update size but not date of file
file2 := r . WriteFile ( "ignore-size" , "longer contents but same date" , t1 )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file2 )
2016-07-04 14:12:33 +02:00
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , r . Fremote , r . Flocal , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2016-07-04 14:12:33 +02:00
// We should have transferred no files
2019-07-18 12:13:54 +02:00
assert . Equal ( t , int64 ( 0 ) , accounting . GlobalStats ( ) . GetTransfers ( ) )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file2 )
r . CheckRemoteItems ( t , file1 )
2016-07-04 14:12:33 +02:00
}
func TestSyncIgnoreTimes ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2020-11-05 17:27:01 +01:00
file1 := r . WriteBoth ( ctx , "existing" , "potato" , t1 )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1 )
2016-07-04 14:12:33 +02:00
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := Sync ( ctx , r . Fremote , r . Flocal , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2016-07-04 14:12:33 +02:00
// We should have transferred exactly 0 files because the
// files were identical.
2019-07-18 12:13:54 +02:00
assert . Equal ( t , int64 ( 0 ) , accounting . GlobalStats ( ) . GetTransfers ( ) )
2016-07-04 14:12:33 +02:00
2020-11-05 12:33:32 +01:00
ci . IgnoreTimes = true
2016-07-04 14:12:33 +02:00
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , r . Fremote , r . Flocal , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2016-07-04 14:12:33 +02:00
// We should have transferred exactly one file even though the
// files were identical.
2019-09-05 22:29:35 +02:00
assert . Equal ( t , toyFileTransfers ( r ) , accounting . GlobalStats ( ) . GetTransfers ( ) )
2016-07-04 14:12:33 +02:00
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
r . CheckRemoteItems ( t , file1 )
2016-07-04 14:12:33 +02:00
}
func TestSyncIgnoreExisting ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2016-07-04 14:12:33 +02:00
file1 := r . WriteFile ( "existing" , "potato" , t1 )
2020-11-05 12:33:32 +01:00
ci . IgnoreExisting = true
2016-07-04 14:12:33 +02:00
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := Sync ( ctx , r . Fremote , r . Flocal , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
r . CheckRemoteItems ( t , file1 )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2016-07-04 14:12:33 +02:00
// Change everything
r . WriteFile ( "existing" , "newpotatoes" , t2 )
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , r . Fremote , r . Flocal , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
// Items should not change
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1 )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2016-07-04 14:12:33 +02:00
}
2018-03-13 00:40:19 +01:00
func TestSyncIgnoreErrors ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2018-03-13 00:40:19 +01:00
r := fstest . NewRun ( t )
2020-11-05 12:33:32 +01:00
ci . IgnoreErrors = true
2018-03-13 00:40:19 +01:00
file1 := r . WriteFile ( "a/potato2" , "------------------------------------------------------------" , t1 )
2020-11-05 17:27:01 +01:00
file2 := r . WriteObject ( ctx , "b/potato" , "SMALLER BUT SAME DATE" , t2 )
file3 := r . WriteBoth ( ctx , "c/non empty space" , "AhHa!" , t2 )
require . NoError ( t , operations . Mkdir ( ctx , r . Fremote , "d" ) )
2018-03-13 00:40:19 +01:00
2021-11-09 12:43:36 +01:00
r . CheckLocalListing (
2018-03-13 00:40:19 +01:00
t ,
[ ] fstest . Item {
file1 ,
file3 ,
} ,
[ ] string {
"a" ,
"c" ,
} ,
)
2021-11-09 12:43:36 +01:00
r . CheckRemoteListing (
2018-03-13 00:40:19 +01:00
t ,
[ ] fstest . Item {
file2 ,
file3 ,
} ,
[ ] string {
"b" ,
"c" ,
"d" ,
} ,
)
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2019-11-18 15:13:02 +01:00
_ = fs . CountError ( errors . New ( "boom" ) )
2020-11-05 17:27:01 +01:00
assert . NoError ( t , Sync ( ctx , r . Fremote , r . Flocal , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2018-03-13 00:40:19 +01:00
2021-11-09 12:43:36 +01:00
r . CheckLocalListing (
2018-03-13 00:40:19 +01:00
t ,
[ ] fstest . Item {
file1 ,
file3 ,
} ,
[ ] string {
"a" ,
"c" ,
} ,
)
2021-11-09 12:43:36 +01:00
r . CheckRemoteListing (
2018-03-13 00:40:19 +01:00
t ,
[ ] fstest . Item {
file1 ,
file3 ,
} ,
[ ] string {
"a" ,
"c" ,
} ,
)
}
2016-07-04 14:12:33 +02:00
func TestSyncAfterChangingModtimeOnly ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2019-06-29 03:17:18 +02:00
file1 := r . WriteFile ( "empty space" , "-" , t2 )
2020-11-05 17:27:01 +01:00
file2 := r . WriteObject ( ctx , "empty space" , "-" , t1 )
2016-07-12 20:40:41 +02:00
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
r . CheckRemoteItems ( t , file2 )
2016-07-04 14:12:33 +02:00
2020-11-05 12:33:32 +01:00
ci . DryRun = true
2017-02-16 00:09:44 +01:00
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := Sync ( ctx , r . Fremote , r . Flocal , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2016-07-04 14:12:33 +02:00
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
r . CheckRemoteItems ( t , file2 )
2017-02-16 00:09:44 +01:00
2020-11-05 12:33:32 +01:00
ci . DryRun = false
2017-02-16 00:09:44 +01:00
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , r . Fremote , r . Flocal , false )
2017-02-16 00:09:44 +01:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2017-02-16 00:09:44 +01:00
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
r . CheckRemoteItems ( t , file1 )
2016-07-04 14:12:33 +02:00
}
2016-07-12 11:46:45 +02:00
func TestSyncAfterChangingModtimeOnlyWithNoUpdateModTime ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2016-12-31 16:19:26 +01:00
2017-10-29 13:23:10 +01:00
if r . Fremote . Hashes ( ) . Count ( ) == 0 {
2017-02-09 12:01:20 +01:00
t . Logf ( "Can't check this if no hashes supported" )
2016-12-31 16:19:26 +01:00
return
}
2020-11-05 12:33:32 +01:00
ci . NoUpdateModTime = true
2016-07-12 11:46:45 +02:00
2019-06-29 03:17:18 +02:00
file1 := r . WriteFile ( "empty space" , "-" , t2 )
2020-11-05 17:27:01 +01:00
file2 := r . WriteObject ( ctx , "empty space" , "-" , t1 )
2016-07-12 11:46:45 +02:00
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
r . CheckRemoteItems ( t , file2 )
2016-07-12 20:40:41 +02:00
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := Sync ( ctx , r . Fremote , r . Flocal , false )
2016-07-12 11:46:45 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2016-07-12 11:46:45 +02:00
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
r . CheckRemoteItems ( t , file2 )
2016-07-12 11:46:45 +02:00
}
2016-11-28 18:08:15 +01:00
func TestSyncDoesntUpdateModtime ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2020-11-05 17:27:01 +01:00
if fs . GetModifyWindow ( ctx , r . Fremote ) == fs . ModTimeNotSupported {
2018-06-03 20:45:34 +02:00
t . Skip ( "Can't run this test on fs which doesn't support mod time" )
}
2016-11-28 18:08:15 +01:00
file1 := r . WriteFile ( "foo" , "foo" , t2 )
2020-11-05 17:27:01 +01:00
file2 := r . WriteObject ( ctx , "foo" , "bar" , t1 )
2016-11-28 18:08:15 +01:00
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
r . CheckRemoteItems ( t , file2 )
2016-11-28 18:08:15 +01:00
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := Sync ( ctx , r . Fremote , r . Flocal , false )
2016-11-28 18:08:15 +01:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2016-11-28 18:08:15 +01:00
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
r . CheckRemoteItems ( t , file1 )
2016-11-28 18:08:15 +01:00
// We should have transferred exactly one file, not set the mod time
2019-09-05 22:29:35 +02:00
assert . Equal ( t , toyFileTransfers ( r ) , accounting . GlobalStats ( ) . GetTransfers ( ) )
2016-11-28 18:08:15 +01:00
}
2016-07-04 14:12:33 +02:00
func TestSyncAfterAddingAFile ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2020-11-05 17:27:01 +01:00
file1 := r . WriteBoth ( ctx , "empty space" , "-" , t2 )
2016-07-04 14:12:33 +02:00
file2 := r . WriteFile ( "potato" , "------------------------------------------------------------" , t3 )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 , file2 )
r . CheckRemoteItems ( t , file1 )
2016-07-12 20:40:41 +02:00
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := Sync ( ctx , r . Fremote , r . Flocal , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 , file2 )
r . CheckRemoteItems ( t , file1 , file2 )
2016-07-04 14:12:33 +02:00
}
func TestSyncAfterChangingFilesSizeOnly ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2020-11-05 17:27:01 +01:00
file1 := r . WriteObject ( ctx , "potato" , "------------------------------------------------------------" , t3 )
2016-07-04 14:12:33 +02:00
file2 := r . WriteFile ( "potato" , "smaller but same date" , t3 )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1 )
r . CheckLocalItems ( t , file2 )
2016-07-04 14:12:33 +02:00
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := Sync ( ctx , r . Fremote , r . Flocal , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file2 )
r . CheckRemoteItems ( t , file2 )
2016-07-04 14:12:33 +02:00
}
// Sync after changing a file's contents, changing modtime but length
// remaining the same
func TestSyncAfterChangingContentsOnly ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2016-07-04 14:12:33 +02:00
var file1 fstest . Item
2017-10-29 13:23:10 +01:00
if r . Fremote . Precision ( ) == fs . ModTimeNotSupported {
2016-07-04 14:12:33 +02:00
t . Logf ( "ModTimeNotSupported so forcing file to be a different size" )
2020-11-05 17:27:01 +01:00
file1 = r . WriteObject ( ctx , "potato" , "different size to make sure it syncs" , t3 )
2016-07-04 14:12:33 +02:00
} else {
2020-11-05 17:27:01 +01:00
file1 = r . WriteObject ( ctx , "potato" , "smaller but same date" , t3 )
2016-07-04 14:12:33 +02:00
}
file2 := r . WriteFile ( "potato" , "SMALLER BUT SAME DATE" , t2 )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1 )
r . CheckLocalItems ( t , file2 )
2016-07-04 14:12:33 +02:00
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := Sync ( ctx , r . Fremote , r . Flocal , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file2 )
r . CheckRemoteItems ( t , file2 )
2016-07-04 14:12:33 +02:00
}
// Sync after removing a file and adding a file --dry-run
func TestSyncAfterRemovingAFileAndAddingAFileDryRun ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2016-07-04 14:12:33 +02:00
file1 := r . WriteFile ( "potato2" , "------------------------------------------------------------" , t1 )
2020-11-05 17:27:01 +01:00
file2 := r . WriteObject ( ctx , "potato" , "SMALLER BUT SAME DATE" , t2 )
file3 := r . WriteBoth ( ctx , "empty space" , "-" , t2 )
2016-07-04 14:12:33 +02:00
2020-11-05 12:33:32 +01:00
ci . DryRun = true
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := Sync ( ctx , r . Fremote , r . Flocal , false )
2020-11-05 12:33:32 +01:00
ci . DryRun = false
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2016-07-04 14:12:33 +02:00
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file3 , file1 )
r . CheckRemoteItems ( t , file3 , file2 )
2016-07-04 14:12:33 +02:00
}
// Sync after removing a file and adding a file
2021-02-17 21:21:09 +01:00
func testSyncAfterRemovingAFileAndAddingAFile ( ctx context . Context , t * testing . T ) {
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2016-07-04 14:12:33 +02:00
file1 := r . WriteFile ( "potato2" , "------------------------------------------------------------" , t1 )
2020-11-05 17:27:01 +01:00
file2 := r . WriteObject ( ctx , "potato" , "SMALLER BUT SAME DATE" , t2 )
file3 := r . WriteBoth ( ctx , "empty space" , "-" , t2 )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file2 , file3 )
r . CheckLocalItems ( t , file1 , file3 )
2016-07-04 14:12:33 +02:00
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := Sync ( ctx , r . Fremote , r . Flocal , false )
2017-01-25 20:59:53 +01:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 , file3 )
r . CheckRemoteItems ( t , file1 , file3 )
2017-01-25 20:59:53 +01:00
}
2021-02-17 21:21:09 +01:00
func TestSyncAfterRemovingAFileAndAddingAFile ( t * testing . T ) {
testSyncAfterRemovingAFileAndAddingAFile ( context . Background ( ) , t )
}
2017-01-25 20:59:53 +01:00
// Sync after removing a file and adding a file
2021-02-17 21:21:09 +01:00
func testSyncAfterRemovingAFileAndAddingAFileSubDir ( ctx context . Context , t * testing . T ) {
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2017-01-25 20:59:53 +01:00
file1 := r . WriteFile ( "a/potato2" , "------------------------------------------------------------" , t1 )
2020-11-05 17:27:01 +01:00
file2 := r . WriteObject ( ctx , "b/potato" , "SMALLER BUT SAME DATE" , t2 )
file3 := r . WriteBoth ( ctx , "c/non empty space" , "AhHa!" , t2 )
require . NoError ( t , operations . Mkdir ( ctx , r . Fremote , "d" ) )
require . NoError ( t , operations . Mkdir ( ctx , r . Fremote , "d/e" ) )
2017-08-09 22:06:39 +02:00
2021-11-09 12:43:36 +01:00
r . CheckLocalListing (
2017-08-09 22:06:39 +02:00
t ,
[ ] fstest . Item {
file1 ,
file3 ,
} ,
[ ] string {
"a" ,
"c" ,
} ,
)
2021-11-09 12:43:36 +01:00
r . CheckRemoteListing (
2017-08-09 22:06:39 +02:00
t ,
[ ] fstest . Item {
file2 ,
file3 ,
} ,
[ ] string {
"b" ,
"c" ,
"d" ,
"d/e" ,
} ,
)
2017-01-25 20:59:53 +01:00
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := Sync ( ctx , r . Fremote , r . Flocal , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2017-08-09 22:06:39 +02:00
2021-11-09 12:43:36 +01:00
r . CheckLocalListing (
2017-08-09 22:06:39 +02:00
t ,
[ ] fstest . Item {
file1 ,
file3 ,
} ,
[ ] string {
"a" ,
"c" ,
} ,
)
2021-11-09 12:43:36 +01:00
r . CheckRemoteListing (
2017-08-09 22:06:39 +02:00
t ,
[ ] fstest . Item {
file1 ,
file3 ,
} ,
[ ] string {
"a" ,
"c" ,
} ,
)
2016-07-04 14:12:33 +02:00
}
2021-02-17 21:21:09 +01:00
func TestSyncAfterRemovingAFileAndAddingAFileSubDir ( t * testing . T ) {
testSyncAfterRemovingAFileAndAddingAFileSubDir ( context . Background ( ) , t )
}
2016-07-04 14:12:33 +02:00
// Sync after removing a file and adding a file with IO Errors
2017-08-09 22:06:39 +02:00
func TestSyncAfterRemovingAFileAndAddingAFileSubDirWithErrors ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2017-08-09 22:06:39 +02:00
file1 := r . WriteFile ( "a/potato2" , "------------------------------------------------------------" , t1 )
2020-11-05 17:27:01 +01:00
file2 := r . WriteObject ( ctx , "b/potato" , "SMALLER BUT SAME DATE" , t2 )
file3 := r . WriteBoth ( ctx , "c/non empty space" , "AhHa!" , t2 )
require . NoError ( t , operations . Mkdir ( ctx , r . Fremote , "d" ) )
2017-08-09 22:06:39 +02:00
2021-11-09 12:43:36 +01:00
r . CheckLocalListing (
2017-08-09 22:06:39 +02:00
t ,
[ ] fstest . Item {
file1 ,
file3 ,
} ,
[ ] string {
"a" ,
"c" ,
} ,
)
2021-11-09 12:43:36 +01:00
r . CheckRemoteListing (
2017-08-09 22:06:39 +02:00
t ,
[ ] fstest . Item {
file2 ,
file3 ,
} ,
[ ] string {
"b" ,
"c" ,
"d" ,
} ,
)
2016-07-04 14:12:33 +02:00
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2019-11-18 15:13:02 +01:00
_ = fs . CountError ( errors . New ( "boom" ) )
2020-11-05 17:27:01 +01:00
err := Sync ( ctx , r . Fremote , r . Flocal , false )
2016-07-04 14:12:33 +02:00
assert . Equal ( t , fs . ErrorNotDeleting , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2017-08-09 22:06:39 +02:00
2021-11-09 12:43:36 +01:00
r . CheckLocalListing (
2017-08-09 22:06:39 +02:00
t ,
[ ] fstest . Item {
file1 ,
file3 ,
} ,
[ ] string {
"a" ,
"c" ,
} ,
)
2021-11-09 12:43:36 +01:00
r . CheckRemoteListing (
2017-08-09 22:06:39 +02:00
t ,
[ ] fstest . Item {
file1 ,
file2 ,
file3 ,
} ,
[ ] string {
"a" ,
"b" ,
"c" ,
"d" ,
} ,
)
2016-07-04 14:12:33 +02:00
}
2017-01-25 20:35:14 +01:00
// Sync test delete after
func TestSyncDeleteAfter ( t * testing . T ) {
2020-11-05 12:33:32 +01:00
ctx := context . Background ( )
ci := fs . GetConfig ( ctx )
2016-07-04 14:12:33 +02:00
// This is the default so we've checked this already
// check it is the default
2020-11-05 12:33:32 +01:00
require . Equal ( t , ci . DeleteMode , fs . DeleteModeAfter , "Didn't default to --delete-after" )
2016-07-04 14:12:33 +02:00
}
2017-01-25 20:35:14 +01:00
// Sync test delete during
func TestSyncDeleteDuring ( t * testing . T ) {
2020-11-05 12:33:32 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2020-11-05 12:33:32 +01:00
ci . DeleteMode = fs . DeleteModeDuring
2016-07-04 14:12:33 +02:00
2021-02-17 21:21:09 +01:00
testSyncAfterRemovingAFileAndAddingAFile ( ctx , t )
2016-07-04 14:12:33 +02:00
}
2017-01-25 20:35:14 +01:00
// Sync test delete before
func TestSyncDeleteBefore ( t * testing . T ) {
2020-11-05 12:33:32 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2020-11-05 12:33:32 +01:00
ci . DeleteMode = fs . DeleteModeBefore
2016-07-04 14:12:33 +02:00
2021-02-17 21:21:09 +01:00
testSyncAfterRemovingAFileAndAddingAFile ( ctx , t )
2016-07-04 14:12:33 +02:00
}
2017-02-22 14:17:38 +01:00
// Copy test delete before - shouldn't delete anything
func TestCopyDeleteBefore ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2017-02-22 14:17:38 +01:00
2020-11-05 12:33:32 +01:00
ci . DeleteMode = fs . DeleteModeBefore
2017-02-22 14:17:38 +01:00
2020-11-05 17:27:01 +01:00
file1 := r . WriteObject ( ctx , "potato" , "hopefully not deleted" , t1 )
2017-02-22 14:17:38 +01:00
file2 := r . WriteFile ( "potato2" , "hopefully copied in" , t1 )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1 )
r . CheckLocalItems ( t , file2 )
2017-02-22 14:17:38 +01:00
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := CopyDir ( ctx , r . Fremote , r . Flocal , false )
2017-02-22 14:17:38 +01:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2017-02-22 14:17:38 +01:00
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1 , file2 )
r . CheckLocalItems ( t , file2 )
2017-02-22 14:17:38 +01:00
}
2016-07-04 14:12:33 +02:00
// Test with exclude
func TestSyncWithExclude ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2020-11-05 17:27:01 +01:00
file1 := r . WriteBoth ( ctx , "potato2" , "------------------------------------------------------------" , t1 )
file2 := r . WriteBoth ( ctx , "empty space" , "-" , t2 )
2016-07-04 14:12:33 +02:00
file3 := r . WriteFile ( "enormous" , "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" , t1 ) // 100 bytes
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1 , file2 )
r . CheckLocalItems ( t , file1 , file2 , file3 )
2016-07-04 14:12:33 +02:00
2021-02-17 21:21:09 +01:00
fi , err := filter . NewFilter ( nil )
require . NoError ( t , err )
2020-11-26 18:10:41 +01:00
fi . Opt . MaxSize = 40
2021-02-17 21:21:09 +01:00
ctx = filter . ReplaceConfig ( ctx , fi )
2016-07-04 14:12:33 +02:00
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2021-02-17 21:21:09 +01:00
err = Sync ( ctx , r . Fremote , r . Flocal , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file2 , file1 )
2016-07-04 14:12:33 +02:00
// Now sync the other way round and check enormous doesn't get
// deleted as it is excluded from the sync
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , r . Flocal , r . Fremote , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file2 , file1 , file3 )
2016-07-04 14:12:33 +02:00
}
// Test with exclude and delete excluded
func TestSyncWithExcludeAndDeleteExcluded ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2020-11-05 17:27:01 +01:00
file1 := r . WriteBoth ( ctx , "potato2" , "------------------------------------------------------------" , t1 ) // 60 bytes
file2 := r . WriteBoth ( ctx , "empty space" , "-" , t2 )
file3 := r . WriteBoth ( ctx , "enormous" , "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" , t1 ) // 100 bytes
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1 , file2 , file3 )
r . CheckLocalItems ( t , file1 , file2 , file3 )
2016-07-04 14:12:33 +02:00
2021-02-17 21:21:09 +01:00
fi , err := filter . NewFilter ( nil )
require . NoError ( t , err )
2020-11-26 18:10:41 +01:00
fi . Opt . MaxSize = 40
fi . Opt . DeleteExcluded = true
2021-02-17 21:21:09 +01:00
ctx = filter . ReplaceConfig ( ctx , fi )
2016-07-04 14:12:33 +02:00
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2021-02-17 21:21:09 +01:00
err = Sync ( ctx , r . Fremote , r . Flocal , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file2 )
2016-07-04 14:12:33 +02:00
// Check sync the other way round to make sure enormous gets
// deleted even though it is excluded
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , r . Flocal , r . Fremote , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file2 )
2016-07-04 14:12:33 +02:00
}
// Test with UpdateOlder set
func TestSyncWithUpdateOlder ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2020-11-05 17:27:01 +01:00
if fs . GetModifyWindow ( ctx , r . Fremote ) == fs . ModTimeNotSupported {
2018-06-03 20:45:34 +02:00
t . Skip ( "Can't run this test on fs which doesn't support mod time" )
}
2016-07-04 14:12:33 +02:00
t2plus := t2 . Add ( time . Second / 2 )
t2minus := t2 . Add ( time . Second / 2 )
oneF := r . WriteFile ( "one" , "one" , t1 )
twoF := r . WriteFile ( "two" , "two" , t3 )
threeF := r . WriteFile ( "three" , "three" , t2 )
fourF := r . WriteFile ( "four" , "four" , t2 )
fiveF := r . WriteFile ( "five" , "five" , t2 )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , oneF , twoF , threeF , fourF , fiveF )
2020-11-05 17:27:01 +01:00
oneO := r . WriteObject ( ctx , "one" , "ONE" , t2 )
twoO := r . WriteObject ( ctx , "two" , "TWO" , t2 )
threeO := r . WriteObject ( ctx , "three" , "THREE" , t2plus )
fourO := r . WriteObject ( ctx , "four" , "FOURFOUR" , t2minus )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , oneO , twoO , threeO , fourO )
2016-07-04 14:12:33 +02:00
2020-11-05 12:33:32 +01:00
ci . UpdateOlder = true
ci . ModifyWindow = fs . ModTimeNotSupported
2016-07-04 14:12:33 +02:00
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := Sync ( ctx , r . Fremote , r . Flocal , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , oneO , twoF , threeO , fourF , fiveF )
2023-10-01 11:02:56 +02:00
// testLoggerVsLsf(ctx, r.Fremote, operations.GetLoggerOpt(ctx).JSON, t) // no modtime
2019-06-08 15:08:23 +02:00
if r . Fremote . Hashes ( ) . Count ( ) == 0 {
t . Logf ( "Skip test with --checksum as no hashes supported" )
return
}
// now enable checksum
2020-11-05 12:33:32 +01:00
ci . CheckSum = true
2019-06-08 15:08:23 +02:00
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , r . Fremote , r . Flocal , false )
2019-06-08 15:08:23 +02:00
require . NoError ( t , err )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , oneO , twoF , threeF , fourF , fiveF )
2016-07-04 14:12:33 +02:00
}
2019-07-25 12:28:27 +02:00
// Test with a max transfer duration
2021-11-29 17:19:00 +01:00
func testSyncWithMaxDuration ( t * testing . T , cutoffMode fs . CutoffMode ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2020-01-26 10:20:03 +01:00
if * fstest . RemoteName != "" {
t . Skip ( "Skipping test on non local remote" )
}
2019-07-25 12:28:27 +02:00
r := fstest . NewRun ( t )
maxDuration := 250 * time . Millisecond
2020-11-05 12:33:32 +01:00
ci . MaxDuration = maxDuration
2021-11-29 17:19:00 +01:00
ci . CutoffMode = cutoffMode
ci . CheckFirst = true
ci . OrderBy = "size"
2020-11-05 12:33:32 +01:00
ci . Transfers = 1
2021-11-29 17:19:00 +01:00
ci . Checkers = 1
bytesPerSecond := 10 * 1024
accounting . TokenBucket . SetBwLimit ( fs . BwPair { Tx : fs . SizeSuffix ( bytesPerSecond ) , Rx : fs . SizeSuffix ( bytesPerSecond ) } )
2021-02-17 21:21:09 +01:00
defer accounting . TokenBucket . SetBwLimit ( fs . BwPair { Tx : - 1 , Rx : - 1 } )
2019-07-25 12:28:27 +02:00
2021-11-29 17:19:00 +01:00
// write one small file which we expect to transfer and one big one which we don't
file1 := r . WriteFile ( "file1" , string ( make ( [ ] byte , 16 ) ) , t1 )
file2 := r . WriteFile ( "file2" , string ( make ( [ ] byte , 50 * 1024 ) ) , t1 )
r . CheckLocalItems ( t , file1 , file2 )
r . CheckRemoteItems ( t )
2019-07-25 12:28:27 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
// ctx = predictDstFromLogger(ctx) // not currently supported (but tests do pass for CutoffModeSoft)
2019-07-25 12:28:27 +02:00
startTime := time . Now ( )
2020-11-05 17:27:01 +01:00
err := Sync ( ctx , r . Fremote , r . Flocal , false )
2023-10-01 11:02:56 +02:00
// testLoggerVsLsf(ctx, r.Fremote, operations.GetLoggerOpt(ctx).JSON, t)
2023-07-15 18:41:13 +02:00
require . True ( t , errors . Is ( err , ErrorMaxDurationReached ) )
2019-07-25 12:28:27 +02:00
2021-11-29 17:19:00 +01:00
if cutoffMode == fs . CutoffModeHard {
r . CheckRemoteItems ( t , file1 )
assert . Equal ( t , int64 ( 1 ) , accounting . GlobalStats ( ) . GetTransfers ( ) )
} else {
r . CheckRemoteItems ( t , file1 , file2 )
assert . Equal ( t , int64 ( 2 ) , accounting . GlobalStats ( ) . GetTransfers ( ) )
}
2019-07-25 12:28:27 +02:00
elapsed := time . Since ( startTime )
2021-11-29 17:19:00 +01:00
const maxTransferTime = 20 * time . Second
2019-07-25 12:28:27 +02:00
what := fmt . Sprintf ( "expecting elapsed time %v between %v and %v" , elapsed , maxDuration , maxTransferTime )
2021-11-29 17:19:00 +01:00
assert . True ( t , elapsed >= maxDuration , what )
assert . True ( t , elapsed < maxTransferTime , what )
}
func TestSyncWithMaxDuration ( t * testing . T ) {
t . Run ( "Hard" , func ( t * testing . T ) {
testSyncWithMaxDuration ( t , fs . CutoffModeHard )
} )
t . Run ( "Soft" , func ( t * testing . T ) {
testSyncWithMaxDuration ( t , fs . CutoffModeSoft )
} )
2019-07-25 12:28:27 +02:00
}
2016-12-18 11:03:56 +01:00
// Test with TrackRenames set
func TestSyncWithTrackRenames ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2016-12-18 11:03:56 +01:00
2020-11-05 12:33:32 +01:00
ci . TrackRenames = true
2016-12-18 11:03:56 +01:00
defer func ( ) {
2020-11-05 12:33:32 +01:00
ci . TrackRenames = false
2016-12-18 11:03:56 +01:00
} ( )
2018-01-18 21:27:52 +01:00
haveHash := r . Fremote . Hashes ( ) . Overlap ( r . Flocal . Hashes ( ) ) . GetOne ( ) != hash . None
2018-01-12 17:30:54 +01:00
canTrackRenames := haveHash && operations . CanServerSideMove ( r . Fremote )
2017-01-03 18:35:12 +01:00
t . Logf ( "Can track renames: %v" , canTrackRenames )
2016-12-18 11:03:56 +01:00
f1 := r . WriteFile ( "potato" , "Potato Content" , t1 )
f2 := r . WriteFile ( "yam" , "Yam Content" , t2 )
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
require . NoError ( t , Sync ( ctx , r . Fremote , r . Flocal , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2016-12-18 11:03:56 +01:00
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , f1 , f2 )
r . CheckLocalItems ( t , f1 , f2 )
2016-12-18 11:03:56 +01:00
// Now rename locally.
f2 = r . RenameFile ( f2 , "yaml" )
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
require . NoError ( t , Sync ( ctx , r . Fremote , r . Flocal , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2016-12-18 11:03:56 +01:00
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , f1 , f2 )
2016-12-18 11:03:56 +01:00
2020-03-31 11:58:49 +02:00
// Check we renamed something if we should have
if canTrackRenames {
renames := accounting . GlobalStats ( ) . Renames ( 0 )
assert . Equal ( t , canTrackRenames , renames != 0 , fmt . Sprintf ( "canTrackRenames=%v, renames=%d" , canTrackRenames , renames ) )
}
2020-03-20 14:04:56 +01:00
}
2020-03-21 18:35:34 +01:00
func TestParseRenamesStrategyModtime ( t * testing . T ) {
for _ , test := range [ ] struct {
in string
want trackRenamesStrategy
wantErr bool
} {
{ "" , 0 , false } ,
{ "modtime" , trackRenamesStrategyModtime , false } ,
{ "hash" , trackRenamesStrategyHash , false } ,
{ "size" , 0 , false } ,
{ "modtime,hash" , trackRenamesStrategyModtime | trackRenamesStrategyHash , false } ,
{ "hash,modtime,size" , trackRenamesStrategyModtime | trackRenamesStrategyHash , false } ,
{ "size,boom" , 0 , true } ,
} {
got , err := parseTrackRenamesStrategy ( test . in )
assert . Equal ( t , test . want , got , test . in )
assert . Equal ( t , test . wantErr , err != nil , test . in )
}
}
func TestRenamesStrategyModtime ( t * testing . T ) {
both := trackRenamesStrategyHash | trackRenamesStrategyModtime
hash := trackRenamesStrategyHash
modTime := trackRenamesStrategyModtime
assert . True ( t , both . hash ( ) )
assert . True ( t , both . modTime ( ) )
assert . True ( t , hash . hash ( ) )
assert . False ( t , hash . modTime ( ) )
assert . False ( t , modTime . hash ( ) )
assert . True ( t , modTime . modTime ( ) )
}
2020-03-20 14:04:56 +01:00
func TestSyncWithTrackRenamesStrategyModtime ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2020-03-20 14:04:56 +01:00
r := fstest . NewRun ( t )
2020-11-05 12:33:32 +01:00
ci . TrackRenames = true
ci . TrackRenamesStrategy = "modtime"
2020-03-20 14:04:56 +01:00
2020-03-22 12:52:40 +01:00
canTrackRenames := operations . CanServerSideMove ( r . Fremote ) && r . Fremote . Precision ( ) != fs . ModTimeNotSupported
2020-03-20 14:04:56 +01:00
t . Logf ( "Can track renames: %v" , canTrackRenames )
f1 := r . WriteFile ( "potato" , "Potato Content" , t1 )
f2 := r . WriteFile ( "yam" , "Yam Content" , t2 )
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
require . NoError ( t , Sync ( ctx , r . Fremote , r . Flocal , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2020-03-20 14:04:56 +01:00
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , f1 , f2 )
r . CheckLocalItems ( t , f1 , f2 )
2020-03-20 14:04:56 +01:00
// Now rename locally.
f2 = r . RenameFile ( f2 , "yaml" )
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
require . NoError ( t , Sync ( ctx , r . Fremote , r . Flocal , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2020-03-20 14:04:56 +01:00
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , f1 , f2 )
2020-06-09 21:40:03 +02:00
// Check we renamed something if we should have
if canTrackRenames {
renames := accounting . GlobalStats ( ) . Renames ( 0 )
assert . Equal ( t , canTrackRenames , renames != 0 , fmt . Sprintf ( "canTrackRenames=%v, renames=%d" , canTrackRenames , renames ) )
}
}
func TestSyncWithTrackRenamesStrategyLeaf ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2020-06-09 21:40:03 +02:00
r := fstest . NewRun ( t )
2020-11-05 12:33:32 +01:00
ci . TrackRenames = true
ci . TrackRenamesStrategy = "leaf"
2020-06-09 21:40:03 +02:00
canTrackRenames := operations . CanServerSideMove ( r . Fremote ) && r . Fremote . Precision ( ) != fs . ModTimeNotSupported
t . Logf ( "Can track renames: %v" , canTrackRenames )
f1 := r . WriteFile ( "potato" , "Potato Content" , t1 )
f2 := r . WriteFile ( "sub/yam" , "Yam Content" , t2 )
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
require . NoError ( t , Sync ( ctx , r . Fremote , r . Flocal , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2020-06-09 21:40:03 +02:00
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , f1 , f2 )
r . CheckLocalItems ( t , f1 , f2 )
2020-06-09 21:40:03 +02:00
// Now rename locally.
f2 = r . RenameFile ( f2 , "yam" )
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
require . NoError ( t , Sync ( ctx , r . Fremote , r . Flocal , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2020-06-09 21:40:03 +02:00
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , f1 , f2 )
2020-03-20 14:04:56 +01:00
2020-03-31 11:58:49 +02:00
// Check we renamed something if we should have
if canTrackRenames {
renames := accounting . GlobalStats ( ) . Renames ( 0 )
assert . Equal ( t , canTrackRenames , renames != 0 , fmt . Sprintf ( "canTrackRenames=%v, renames=%d" , canTrackRenames , renames ) )
}
2019-09-05 22:29:35 +02:00
}
func toyFileTransfers ( r * fstest . Run ) int64 {
remote := r . Fremote . Name ( )
transfers := 1
if strings . HasPrefix ( remote , "TestChunker" ) && strings . HasSuffix ( remote , "S3" ) {
transfers ++ // Extra Copy because S3 emulates Move as Copy+Delete.
2017-01-03 18:35:12 +01:00
}
2019-09-05 22:29:35 +02:00
return int64 ( transfers )
2016-12-18 11:03:56 +01:00
}
2020-10-13 23:43:40 +02:00
// Test a server-side move if possible, or the backup path if not
2021-02-17 21:21:09 +01:00
func testServerSideMove ( ctx context . Context , t * testing . T , r * fstest . Run , withFilter , testDeleteEmptyDirs bool ) {
2019-08-08 20:58:02 +02:00
FremoteMove , _ , finaliseMove , err := fstest . RandomRemote ( )
2017-08-04 18:08:16 +02:00
require . NoError ( t , err )
defer finaliseMove ( )
2020-11-05 17:27:01 +01:00
file1 := r . WriteBoth ( ctx , "potato2" , "------------------------------------------------------------" , t1 )
file2 := r . WriteBoth ( ctx , "empty space" , "-" , t2 )
file3u := r . WriteBoth ( ctx , "potato3" , "------------------------------------------------------------ UPDATED" , t2 )
2016-07-04 14:12:33 +02:00
2017-11-27 12:42:02 +01:00
if testDeleteEmptyDirs {
2020-11-05 17:27:01 +01:00
err := operations . Mkdir ( ctx , r . Fremote , "tomatoDir" )
2017-11-27 12:42:02 +01:00
require . NoError ( t , err )
}
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file2 , file1 , file3u )
2016-07-04 14:12:33 +02:00
2017-10-29 13:23:10 +01:00
t . Logf ( "Server side move (if possible) %v -> %v" , r . Fremote , FremoteMove )
2016-07-04 14:12:33 +02:00
// Write just one file in the new remote
2020-11-05 17:27:01 +01:00
r . WriteObjectTo ( ctx , FremoteMove , "empty space" , "-" , t2 , false )
file3 := r . WriteObjectTo ( ctx , FremoteMove , "potato3" , "------------------------------------------------------------" , t1 , false )
2017-10-29 13:23:10 +01:00
fstest . CheckItems ( t , FremoteMove , file2 , file3 )
2016-07-04 14:12:33 +02:00
2020-10-13 23:43:40 +02:00
// Do server-side move
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
// ctx = predictDstFromLogger(ctx) // not currently supported -- doesn't list all contents of dir.
2020-11-05 17:27:01 +01:00
err = MoveDir ( ctx , FremoteMove , r . Fremote , testDeleteEmptyDirs , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
// testLoggerVsLsf(ctx, r.Fremote, operations.GetLoggerOpt(ctx).JSON, t)
2016-07-04 14:12:33 +02:00
2016-10-03 20:58:44 +02:00
if withFilter {
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file2 )
2016-10-03 20:58:44 +02:00
} else {
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t )
2016-10-03 20:58:44 +02:00
}
2017-11-27 12:42:02 +01:00
if testDeleteEmptyDirs {
2021-11-09 12:43:36 +01:00
r . CheckRemoteListing ( t , nil , [ ] string { } )
2017-11-27 12:42:02 +01:00
}
2017-10-29 13:23:10 +01:00
fstest . CheckItems ( t , FremoteMove , file2 , file1 , file3u )
2016-07-04 14:12:33 +02:00
2017-08-04 18:08:16 +02:00
// Create a new empty remote for stuff to be moved into
2019-08-08 20:58:02 +02:00
FremoteMove2 , _ , finaliseMove2 , err := fstest . RandomRemote ( )
2017-08-04 18:08:16 +02:00
require . NoError ( t , err )
defer finaliseMove2 ( )
2016-07-11 12:36:46 +02:00
2017-11-27 12:42:02 +01:00
if testDeleteEmptyDirs {
2020-11-05 17:27:01 +01:00
err := operations . Mkdir ( ctx , FremoteMove , "tomatoDir" )
2017-11-27 12:42:02 +01:00
require . NoError ( t , err )
}
2017-08-04 18:08:16 +02:00
// Move it back to a new empty remote, dst does not exist this time
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
// ctx = predictDstFromLogger(ctx)
2020-11-05 17:27:01 +01:00
err = MoveDir ( ctx , FremoteMove2 , FremoteMove , testDeleteEmptyDirs , false )
2016-07-04 14:12:33 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
// testLoggerVsLsf(ctx, r.Fremote, operations.GetLoggerOpt(ctx).JSON, t)
2016-07-04 14:12:33 +02:00
2016-07-11 12:36:46 +02:00
if withFilter {
2017-10-29 13:23:10 +01:00
fstest . CheckItems ( t , FremoteMove2 , file1 , file3u )
fstest . CheckItems ( t , FremoteMove , file2 )
2016-07-11 12:36:46 +02:00
} else {
2017-10-29 13:23:10 +01:00
fstest . CheckItems ( t , FremoteMove2 , file2 , file1 , file3u )
2017-11-23 06:22:01 +01:00
fstest . CheckItems ( t , FremoteMove )
2016-07-11 12:36:46 +02:00
}
2017-11-27 12:42:02 +01:00
if testDeleteEmptyDirs {
2020-11-05 17:27:01 +01:00
fstest . CheckListingWithPrecision ( t , FremoteMove , nil , [ ] string { } , fs . GetModifyWindow ( ctx , r . Fremote ) )
2017-11-27 12:42:02 +01:00
}
2016-07-11 12:36:46 +02:00
}
2023-11-15 21:12:45 +01:00
// Test MoveDir on Local
func TestServerSideMoveLocal ( t * testing . T ) {
ctx := context . Background ( )
r := fstest . NewRun ( t )
f1 := r . WriteFile ( "dir1/file1.txt" , "hello" , t1 )
f2 := r . WriteFile ( "dir2/file2.txt" , "hello again" , t2 )
r . CheckLocalItems ( t , f1 , f2 )
dir1 , err := fs . NewFs ( ctx , r . Flocal . Root ( ) + "/dir1" )
require . NoError ( t , err )
dir2 , err := fs . NewFs ( ctx , r . Flocal . Root ( ) + "/dir2" )
require . NoError ( t , err )
err = MoveDir ( ctx , dir2 , dir1 , false , false )
require . NoError ( t , err )
}
2018-07-17 07:43:58 +02:00
// Test move
func TestMoveWithDeleteEmptySrcDirs ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2018-07-17 07:43:58 +02:00
r := fstest . NewRun ( t )
file1 := r . WriteFile ( "sub dir/hello world" , "hello world" , t1 )
file2 := r . WriteFile ( "nested/sub dir/file" , "nested" , t1 )
2020-11-05 17:27:01 +01:00
r . Mkdir ( ctx , r . Fremote )
2018-07-17 07:43:58 +02:00
// run move with --delete-empty-src-dirs
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := MoveDir ( ctx , r . Fremote , r . Flocal , true , false )
2018-07-17 07:43:58 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2018-07-17 07:43:58 +02:00
2021-11-09 12:43:36 +01:00
r . CheckLocalListing (
2018-07-17 07:43:58 +02:00
t ,
nil ,
[ ] string { } ,
)
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1 , file2 )
2018-07-17 07:43:58 +02:00
}
func TestMoveWithoutDeleteEmptySrcDirs ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2018-07-17 07:43:58 +02:00
r := fstest . NewRun ( t )
file1 := r . WriteFile ( "sub dir/hello world" , "hello world" , t1 )
file2 := r . WriteFile ( "nested/sub dir/file" , "nested" , t1 )
2020-11-05 17:27:01 +01:00
r . Mkdir ( ctx , r . Fremote )
2018-07-17 07:43:58 +02:00
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := MoveDir ( ctx , r . Fremote , r . Flocal , false , false )
2018-07-17 07:43:58 +02:00
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2018-07-17 07:43:58 +02:00
2021-11-09 12:43:36 +01:00
r . CheckLocalListing (
2018-07-17 07:43:58 +02:00
t ,
nil ,
[ ] string {
"sub dir" ,
"nested" ,
"nested/sub dir" ,
} ,
)
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1 , file2 )
2018-07-17 07:43:58 +02:00
}
2021-07-29 18:42:55 +02:00
func TestMoveWithIgnoreExisting ( t * testing . T ) {
ctx := context . Background ( )
ctx , ci := fs . AddConfig ( ctx )
r := fstest . NewRun ( t )
file1 := r . WriteFile ( "existing" , "potato" , t1 )
file2 := r . WriteFile ( "existing-b" , "tomato" , t1 )
ci . IgnoreExisting = true
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
// ctx = predictDstFromLogger(ctx)
2021-07-29 18:42:55 +02:00
err := MoveDir ( ctx , r . Fremote , r . Flocal , false , false )
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
// testLoggerVsLsf(ctx, r.Fremote, operations.GetLoggerOpt(ctx).JSON, t)
2021-11-09 12:43:36 +01:00
r . CheckLocalListing (
2021-07-29 18:42:55 +02:00
t ,
[ ] fstest . Item { } ,
[ ] string { } ,
)
2021-11-09 12:43:36 +01:00
r . CheckRemoteListing (
2021-07-29 18:42:55 +02:00
t ,
[ ] fstest . Item {
file1 ,
file2 ,
} ,
[ ] string { } ,
)
// Recreate first file with modified content
file1b := r . WriteFile ( "existing" , "newpotatoes" , t2 )
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2021-07-29 18:42:55 +02:00
err = MoveDir ( ctx , r . Fremote , r . Flocal , false , false )
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2021-07-29 18:42:55 +02:00
// Source items should still exist in modified state
2021-11-09 12:43:36 +01:00
r . CheckLocalListing (
2021-07-29 18:42:55 +02:00
t ,
[ ] fstest . Item {
file1b ,
} ,
[ ] string { } ,
)
// Dest items should not have changed
2021-11-09 12:43:36 +01:00
r . CheckRemoteListing (
2021-07-29 18:42:55 +02:00
t ,
[ ] fstest . Item {
file1 ,
file2 ,
} ,
[ ] string { } ,
)
}
2020-10-13 23:43:40 +02:00
// Test a server-side move if possible, or the backup path if not
2016-07-11 12:36:46 +02:00
func TestServerSideMove ( t * testing . T ) {
2021-02-17 21:21:09 +01:00
ctx := context . Background ( )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2021-02-17 21:21:09 +01:00
testServerSideMove ( ctx , t , r , false , false )
2016-07-11 12:36:46 +02:00
}
2020-10-13 23:43:40 +02:00
// Test a server-side move if possible, or the backup path if not
2016-07-11 12:36:46 +02:00
func TestServerSideMoveWithFilter ( t * testing . T ) {
2020-11-26 18:10:41 +01:00
ctx := context . Background ( )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2016-07-11 12:36:46 +02:00
2021-02-17 21:21:09 +01:00
fi , err := filter . NewFilter ( nil )
require . NoError ( t , err )
2020-11-26 18:10:41 +01:00
fi . Opt . MinSize = 40
2021-02-17 21:21:09 +01:00
ctx = filter . ReplaceConfig ( ctx , fi )
2016-07-11 12:36:46 +02:00
2021-02-17 21:21:09 +01:00
testServerSideMove ( ctx , t , r , true , false )
2017-11-27 12:42:02 +01:00
}
2020-10-13 23:43:40 +02:00
// Test a server-side move if possible
2017-11-27 12:42:02 +01:00
func TestServerSideMoveDeleteEmptySourceDirs ( t * testing . T ) {
2021-02-17 21:21:09 +01:00
ctx := context . Background ( )
2017-11-27 12:42:02 +01:00
r := fstest . NewRun ( t )
2021-02-17 21:21:09 +01:00
testServerSideMove ( ctx , t , r , false , true )
2016-07-11 12:36:46 +02:00
}
2020-10-13 23:43:40 +02:00
// Test a server-side move with overlap
2016-07-11 12:36:46 +02:00
func TestServerSideMoveOverlap ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2016-10-22 18:53:52 +02:00
2017-10-29 13:23:10 +01:00
if r . Fremote . Features ( ) . DirMove != nil {
2016-10-22 18:53:52 +02:00
t . Skip ( "Skipping test as remote supports DirMove" )
}
2017-10-29 13:23:10 +01:00
subRemoteName := r . FremoteName + "/rclone-move-test"
2020-11-05 17:27:01 +01:00
FremoteMove , err := fs . NewFs ( ctx , subRemoteName )
2016-07-11 12:36:46 +02:00
require . NoError ( t , err )
2020-11-05 17:27:01 +01:00
file1 := r . WriteObject ( ctx , "potato2" , "------------------------------------------------------------" , t1 )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1 )
2016-07-11 12:36:46 +02:00
// Subdir move with no filters should return ErrorCantMoveOverlapping
2023-11-06 08:45:51 +01:00
// ctx = predictDstFromLogger(ctx)
2020-11-05 17:27:01 +01:00
err = MoveDir ( ctx , FremoteMove , r . Fremote , false , false )
2019-02-14 13:06:26 +01:00
assert . EqualError ( t , err , fs . ErrorOverlapping . Error ( ) )
2023-11-06 08:45:51 +01:00
// testLoggerVsLsf(ctx, r.Fremote, operations.GetLoggerOpt(ctx).JSON, t)
2016-07-11 12:36:46 +02:00
// Now try with a filter which should also fail with ErrorCantMoveOverlapping
2021-02-17 21:21:09 +01:00
fi , err := filter . NewFilter ( nil )
require . NoError ( t , err )
2020-11-26 18:10:41 +01:00
fi . Opt . MinSize = 40
2021-02-17 21:21:09 +01:00
ctx = filter . ReplaceConfig ( ctx , fi )
2023-11-06 08:45:51 +01:00
// ctx = predictDstFromLogger(ctx)
2020-11-05 17:27:01 +01:00
err = MoveDir ( ctx , FremoteMove , r . Fremote , false , false )
2019-02-27 18:13:13 +01:00
assert . EqualError ( t , err , fs . ErrorOverlapping . Error ( ) )
2023-11-06 08:45:51 +01:00
// testLoggerVsLsf(ctx, r.Fremote, operations.GetLoggerOpt(ctx).JSON, t)
2019-02-14 13:06:26 +01:00
}
// Test a sync with overlap
func TestSyncOverlap ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2019-02-14 13:06:26 +01:00
r := fstest . NewRun ( t )
subRemoteName := r . FremoteName + "/rclone-sync-test"
2020-11-05 17:27:01 +01:00
FremoteSync , err := fs . NewFs ( ctx , subRemoteName )
2019-02-14 13:06:26 +01:00
require . NoError ( t , err )
checkErr := func ( err error ) {
2019-02-28 12:39:32 +01:00
require . Error ( t , err )
2019-02-14 13:06:26 +01:00
assert . True ( t , fserrors . IsFatalError ( err ) )
2019-02-28 12:39:32 +01:00
assert . Equal ( t , fs . ErrorOverlapping . Error ( ) , err . Error ( ) )
2019-02-14 13:06:26 +01:00
}
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
checkErr ( Sync ( ctx , FremoteSync , r . Fremote , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
checkErr ( Sync ( ctx , r . Fremote , FremoteSync , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
checkErr ( Sync ( ctx , r . Fremote , r . Fremote , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
checkErr ( Sync ( ctx , FremoteSync , FremoteSync , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2016-07-04 14:12:33 +02:00
}
2017-01-10 22:47:03 +01:00
2022-06-01 19:24:54 +02:00
// Test a sync with filtered overlap
func TestSyncOverlapWithFilter ( t * testing . T ) {
ctx := context . Background ( )
r := fstest . NewRun ( t )
fi , err := filter . NewFilter ( nil )
require . NoError ( t , err )
require . NoError ( t , fi . Add ( false , "/rclone-sync-test/" ) )
require . NoError ( t , fi . Add ( false , "*/layer2/" ) )
2022-06-08 09:29:01 +02:00
fi . Opt . ExcludeFile = [ ] string { ".ignore" }
2023-07-15 10:10:26 +02:00
filterCtx := filter . ReplaceConfig ( ctx , fi )
2022-06-01 19:24:54 +02:00
subRemoteName := r . FremoteName + "/rclone-sync-test"
FremoteSync , err := fs . NewFs ( ctx , subRemoteName )
require . NoError ( t , FremoteSync . Mkdir ( ctx , "" ) )
require . NoError ( t , err )
subRemoteName2 := r . FremoteName + "/rclone-sync-test-include/layer2"
FremoteSync2 , err := fs . NewFs ( ctx , subRemoteName2 )
require . NoError ( t , FremoteSync2 . Mkdir ( ctx , "" ) )
require . NoError ( t , err )
subRemoteName3 := r . FremoteName + "/rclone-sync-test-ignore-file"
FremoteSync3 , err := fs . NewFs ( ctx , subRemoteName3 )
require . NoError ( t , FremoteSync3 . Mkdir ( ctx , "" ) )
require . NoError ( t , err )
2022-06-09 14:19:11 +02:00
r . WriteObject ( context . Background ( ) , "rclone-sync-test-ignore-file/.ignore" , "-" , t1 )
2022-06-01 19:24:54 +02:00
checkErr := func ( err error ) {
require . Error ( t , err )
assert . True ( t , fserrors . IsFatalError ( err ) )
assert . Equal ( t , fs . ErrorOverlapping . Error ( ) , err . Error ( ) )
2022-06-09 14:19:11 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2022-06-01 19:24:54 +02:00
}
checkNoErr := func ( err error ) {
require . NoError ( t , err )
}
2022-06-09 14:19:11 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
filterCtx = predictDstFromLogger ( filterCtx )
2023-07-15 10:10:26 +02:00
checkNoErr ( Sync ( filterCtx , FremoteSync , r . Fremote , false ) )
checkErr ( Sync ( ctx , FremoteSync , r . Fremote , false ) )
checkNoErr ( Sync ( filterCtx , r . Fremote , FremoteSync , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( filterCtx , r . Fremote , operations . GetLoggerOpt ( filterCtx ) . JSON , t )
filterCtx = predictDstFromLogger ( filterCtx )
2022-06-01 19:24:54 +02:00
checkErr ( Sync ( ctx , r . Fremote , FremoteSync , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( filterCtx , r . Fremote , operations . GetLoggerOpt ( filterCtx ) . JSON , t )
filterCtx = predictDstFromLogger ( filterCtx )
2023-07-15 10:10:26 +02:00
checkErr ( Sync ( filterCtx , r . Fremote , r . Fremote , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( filterCtx , r . Fremote , operations . GetLoggerOpt ( filterCtx ) . JSON , t )
filterCtx = predictDstFromLogger ( filterCtx )
2022-06-01 19:24:54 +02:00
checkErr ( Sync ( ctx , r . Fremote , r . Fremote , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( filterCtx , r . Fremote , operations . GetLoggerOpt ( filterCtx ) . JSON , t )
filterCtx = predictDstFromLogger ( filterCtx )
2023-07-15 10:10:26 +02:00
checkErr ( Sync ( filterCtx , FremoteSync , FremoteSync , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( filterCtx , r . Fremote , operations . GetLoggerOpt ( filterCtx ) . JSON , t )
filterCtx = predictDstFromLogger ( filterCtx )
2022-06-01 19:24:54 +02:00
checkErr ( Sync ( ctx , FremoteSync , FremoteSync , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( filterCtx , r . Fremote , operations . GetLoggerOpt ( filterCtx ) . JSON , t )
filterCtx = predictDstFromLogger ( filterCtx )
2022-06-01 19:24:54 +02:00
2023-07-15 10:10:26 +02:00
checkNoErr ( Sync ( filterCtx , FremoteSync2 , r . Fremote , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( filterCtx , r . Fremote , operations . GetLoggerOpt ( filterCtx ) . JSON , t )
filterCtx = predictDstFromLogger ( filterCtx )
2023-07-15 10:10:26 +02:00
checkErr ( Sync ( ctx , FremoteSync2 , r . Fremote , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( filterCtx , r . Fremote , operations . GetLoggerOpt ( filterCtx ) . JSON , t )
filterCtx = predictDstFromLogger ( filterCtx )
2023-07-15 10:10:26 +02:00
checkNoErr ( Sync ( filterCtx , r . Fremote , FremoteSync2 , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( filterCtx , r . Fremote , operations . GetLoggerOpt ( filterCtx ) . JSON , t )
filterCtx = predictDstFromLogger ( filterCtx )
2022-06-01 19:24:54 +02:00
checkErr ( Sync ( ctx , r . Fremote , FremoteSync2 , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( filterCtx , r . Fremote , operations . GetLoggerOpt ( filterCtx ) . JSON , t )
filterCtx = predictDstFromLogger ( filterCtx )
2023-07-15 10:10:26 +02:00
checkErr ( Sync ( filterCtx , FremoteSync2 , FremoteSync2 , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( filterCtx , r . Fremote , operations . GetLoggerOpt ( filterCtx ) . JSON , t )
filterCtx = predictDstFromLogger ( filterCtx )
2022-06-01 19:24:54 +02:00
checkErr ( Sync ( ctx , FremoteSync2 , FremoteSync2 , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( filterCtx , r . Fremote , operations . GetLoggerOpt ( filterCtx ) . JSON , t )
filterCtx = predictDstFromLogger ( filterCtx )
2022-06-01 19:24:54 +02:00
2023-07-15 10:10:26 +02:00
checkNoErr ( Sync ( filterCtx , FremoteSync3 , r . Fremote , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( filterCtx , r . Fremote , operations . GetLoggerOpt ( filterCtx ) . JSON , t )
filterCtx = predictDstFromLogger ( filterCtx )
2023-07-15 10:10:26 +02:00
checkErr ( Sync ( ctx , FremoteSync3 , r . Fremote , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( filterCtx , r . Fremote , operations . GetLoggerOpt ( filterCtx ) . JSON , t )
filterCtx = predictDstFromLogger ( filterCtx )
2023-08-13 12:39:02 +02:00
// Destination is excluded so this test makes no sense
// checkNoErr(Sync(filterCtx, r.Fremote, FremoteSync3, false))
2022-06-01 19:24:54 +02:00
checkErr ( Sync ( ctx , r . Fremote , FremoteSync3 , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( filterCtx , r . Fremote , operations . GetLoggerOpt ( filterCtx ) . JSON , t )
filterCtx = predictDstFromLogger ( filterCtx )
2023-07-15 10:10:26 +02:00
checkErr ( Sync ( filterCtx , FremoteSync3 , FremoteSync3 , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( filterCtx , r . Fremote , operations . GetLoggerOpt ( filterCtx ) . JSON , t )
filterCtx = predictDstFromLogger ( filterCtx )
2022-06-01 19:24:54 +02:00
checkErr ( Sync ( ctx , FremoteSync3 , FremoteSync3 , false ) )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( filterCtx , r . Fremote , operations . GetLoggerOpt ( filterCtx ) . JSON , t )
2022-06-01 19:24:54 +02:00
}
2019-07-08 03:02:53 +02:00
// Test with CompareDest set
func TestSyncCompareDest ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2019-07-08 03:02:53 +02:00
r := fstest . NewRun ( t )
2020-11-16 04:04:29 +01:00
ci . CompareDest = [ ] string { r . FremoteName + "/CompareDest" }
2019-07-08 03:02:53 +02:00
2020-11-05 17:27:01 +01:00
fdst , err := fs . NewFs ( ctx , r . FremoteName + "/dst" )
2019-07-08 03:02:53 +02:00
require . NoError ( t , err )
// check empty dest, empty compare
file1 := r . WriteFile ( "one" , "one" , t1 )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
2019-07-08 03:02:53 +02:00
2019-07-22 21:11:46 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
// ctx = predictDstFromLogger(ctx) // not currently supported due to duplicate equal() checks
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , fdst , r . Flocal , false )
2023-10-01 11:02:56 +02:00
// testLoggerVsLsf(ctx, fdst, operations.GetLoggerOpt(ctx).JSON, t)
2019-07-08 03:02:53 +02:00
require . NoError ( t , err )
file1dst := file1
file1dst . Path = "dst/one"
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1dst )
2019-07-08 03:02:53 +02:00
// check old dest, empty compare
file1b := r . WriteFile ( "one" , "onet2" , t2 )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1dst )
r . CheckLocalItems ( t , file1b )
2019-07-08 03:02:53 +02:00
2019-07-22 21:11:46 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
// ctx = predictDstFromLogger(ctx)
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , fdst , r . Flocal , false )
2023-10-01 11:02:56 +02:00
// testLoggerVsLsf(ctx, fdst, operations.GetLoggerOpt(ctx).JSON, t)
2019-07-08 03:02:53 +02:00
require . NoError ( t , err )
file1bdst := file1b
file1bdst . Path = "dst/one"
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1bdst )
2019-07-08 03:02:53 +02:00
// check old dest, new compare
2020-11-05 17:27:01 +01:00
file3 := r . WriteObject ( ctx , "dst/one" , "one" , t1 )
file2 := r . WriteObject ( ctx , "CompareDest/one" , "onet2" , t2 )
2019-07-08 03:02:53 +02:00
file1c := r . WriteFile ( "one" , "onet2" , t2 )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file2 , file3 )
r . CheckLocalItems ( t , file1c )
2019-07-08 03:02:53 +02:00
2019-07-22 21:11:46 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
// ctx = predictDstFromLogger(ctx)
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , fdst , r . Flocal , false )
2023-10-01 11:02:56 +02:00
// testLoggerVsLsf(ctx, fdst, operations.GetLoggerOpt(ctx).JSON, t)
2019-07-08 03:02:53 +02:00
require . NoError ( t , err )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file2 , file3 )
2019-07-08 03:02:53 +02:00
// check empty dest, new compare
2020-11-05 17:27:01 +01:00
file4 := r . WriteObject ( ctx , "CompareDest/two" , "two" , t2 )
2019-07-08 03:02:53 +02:00
file5 := r . WriteFile ( "two" , "two" , t2 )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file2 , file3 , file4 )
r . CheckLocalItems ( t , file1c , file5 )
2019-07-08 03:02:53 +02:00
2019-07-22 21:11:46 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
// ctx = predictDstFromLogger(ctx)
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , fdst , r . Flocal , false )
2023-10-01 11:02:56 +02:00
// testLoggerVsLsf(ctx, fdst, operations.GetLoggerOpt(ctx).JSON, t)
2019-07-08 03:02:53 +02:00
require . NoError ( t , err )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file2 , file3 , file4 )
2019-07-08 03:02:53 +02:00
// check new dest, new compare
2019-07-22 21:11:46 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
// ctx = predictDstFromLogger(ctx)
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , fdst , r . Flocal , false )
2023-10-01 11:02:56 +02:00
// testLoggerVsLsf(ctx, fdst, operations.GetLoggerOpt(ctx).JSON, t)
2019-07-08 03:02:53 +02:00
require . NoError ( t , err )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file2 , file3 , file4 )
2019-07-08 03:02:53 +02:00
2021-07-07 16:08:47 +02:00
// Work out if we actually have hashes for uploaded files
haveHash := false
if ht := fdst . Hashes ( ) . GetOne ( ) ; ht != hash . None {
file2obj , err := fdst . NewObject ( ctx , "one" )
if err == nil {
file2objHash , err := file2obj . Hash ( ctx , ht )
if err == nil {
haveHash = file2objHash != ""
}
}
}
2021-06-14 22:19:12 +02:00
2021-07-07 16:08:47 +02:00
// check new dest, new compare, src timestamp differs
//
// we only check this if we the file we uploaded previously
// actually has a hash otherwise the differing timestamp is
// always copied.
if haveHash {
file5b := r . WriteFile ( "two" , "two" , t3 )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1c , file5b )
2021-07-07 16:08:47 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
// ctx = predictDstFromLogger(ctx)
2021-07-07 16:08:47 +02:00
err = Sync ( ctx , fdst , r . Flocal , false )
2023-10-01 11:02:56 +02:00
// testLoggerVsLsf(ctx, r.Fremote, operations.GetLoggerOpt(ctx).JSON, t)
2021-07-07 16:08:47 +02:00
require . NoError ( t , err )
2021-06-14 22:19:12 +02:00
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file2 , file3 , file4 )
2021-07-07 16:08:47 +02:00
} else {
t . Log ( "No hash on uploaded file so skipping compare timestamp test" )
}
2021-06-14 22:19:12 +02:00
2019-07-08 03:02:53 +02:00
// check empty dest, old compare
2021-06-14 22:19:12 +02:00
file5c := r . WriteFile ( "two" , "twot3" , t3 )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file2 , file3 , file4 )
r . CheckLocalItems ( t , file1c , file5c )
2019-07-08 03:02:53 +02:00
2019-07-22 21:11:46 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
// ctx = predictDstFromLogger(ctx)
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , fdst , r . Flocal , false )
2023-10-01 11:02:56 +02:00
// testLoggerVsLsf(ctx, r.Fremote, operations.GetLoggerOpt(ctx).JSON, t)
2019-07-08 03:02:53 +02:00
require . NoError ( t , err )
2021-06-14 22:19:12 +02:00
file5cdst := file5c
file5cdst . Path = "dst/two"
2019-07-08 03:02:53 +02:00
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file2 , file3 , file4 , file5cdst )
2019-07-08 03:02:53 +02:00
}
2020-11-16 04:04:29 +01:00
// Test with multiple CompareDest
func TestSyncMultipleCompareDest ( t * testing . T ) {
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2020-11-16 04:04:29 +01:00
r := fstest . NewRun ( t )
2021-11-09 12:43:36 +01:00
precision := fs . GetModifyWindow ( ctx , r . Fremote , r . Flocal )
2020-11-16 04:04:29 +01:00
ci . CompareDest = [ ] string { r . FremoteName + "/pre-dest1" , r . FremoteName + "/pre-dest2" }
// check empty dest, new compare
fsrc1 := r . WriteFile ( "1" , "1" , t1 )
fsrc2 := r . WriteFile ( "2" , "2" , t1 )
fsrc3 := r . WriteFile ( "3" , "3" , t1 )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , fsrc1 , fsrc2 , fsrc3 )
2020-11-16 04:04:29 +01:00
fdest1 := r . WriteObject ( ctx , "pre-dest1/1" , "1" , t1 )
fdest2 := r . WriteObject ( ctx , "pre-dest2/2" , "2" , t1 )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , fdest1 , fdest2 )
2020-11-16 04:04:29 +01:00
accounting . GlobalStats ( ) . ResetCounters ( )
fdst , err := fs . NewFs ( ctx , r . FremoteName + "/dest" )
require . NoError ( t , err )
2023-10-01 11:02:56 +02:00
// ctx = predictDstFromLogger(ctx)
2020-11-16 04:04:29 +01:00
require . NoError ( t , Sync ( ctx , fdst , r . Flocal , false ) )
2023-10-01 11:02:56 +02:00
// testLoggerVsLsf(ctx, fdst, operations.GetLoggerOpt(ctx).JSON, t)
2020-11-16 04:04:29 +01:00
fdest3 := fsrc3
fdest3 . Path = "dest/3"
2021-11-09 12:43:36 +01:00
fstest . CheckItemsWithPrecision ( t , fdst , precision , fsrc3 )
r . CheckRemoteItems ( t , fdest1 , fdest2 , fdest3 )
2020-11-16 04:04:29 +01:00
}
2019-07-08 03:02:53 +02:00
// Test with CopyDest set
func TestSyncCopyDest ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2019-07-08 03:02:53 +02:00
r := fstest . NewRun ( t )
if r . Fremote . Features ( ) . Copy == nil {
2020-10-13 23:43:40 +02:00
t . Skip ( "Skipping test as remote does not support server-side copy" )
2019-07-08 03:02:53 +02:00
}
2020-11-16 04:04:29 +01:00
ci . CopyDest = [ ] string { r . FremoteName + "/CopyDest" }
2019-07-08 03:02:53 +02:00
2020-11-05 17:27:01 +01:00
fdst , err := fs . NewFs ( ctx , r . FremoteName + "/dst" )
2019-07-08 03:02:53 +02:00
require . NoError ( t , err )
// check empty dest, empty copy
file1 := r . WriteFile ( "one" , "one" , t1 )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
2019-07-08 03:02:53 +02:00
2019-07-22 21:11:46 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-11-06 08:45:51 +01:00
// ctx = predictDstFromLogger(ctx)
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , fdst , r . Flocal , false )
2023-11-06 08:45:51 +01:00
// testLoggerVsLsf(ctx, r.Fremote, operations.GetLoggerOpt(ctx).JSON, t) // not currently supported
2019-07-08 03:02:53 +02:00
require . NoError ( t , err )
file1dst := file1
file1dst . Path = "dst/one"
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1dst )
2019-07-08 03:02:53 +02:00
// check old dest, empty copy
file1b := r . WriteFile ( "one" , "onet2" , t2 )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1dst )
r . CheckLocalItems ( t , file1b )
2019-07-08 03:02:53 +02:00
2019-07-22 21:11:46 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-11-06 08:45:51 +01:00
// ctx = predictDstFromLogger(ctx)
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , fdst , r . Flocal , false )
2023-11-06 08:45:51 +01:00
// testLoggerVsLsf(ctx, r.Fremote, operations.GetLoggerOpt(ctx).JSON, t)
2019-07-08 03:02:53 +02:00
require . NoError ( t , err )
file1bdst := file1b
file1bdst . Path = "dst/one"
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1bdst )
2019-07-08 03:02:53 +02:00
// check old dest, new copy, backup-dir
2020-11-05 12:33:32 +01:00
ci . BackupDir = r . FremoteName + "/BackupDir"
2019-07-08 03:02:53 +02:00
2020-11-05 17:27:01 +01:00
file3 := r . WriteObject ( ctx , "dst/one" , "one" , t1 )
file2 := r . WriteObject ( ctx , "CopyDest/one" , "onet2" , t2 )
2019-07-08 03:02:53 +02:00
file1c := r . WriteFile ( "one" , "onet2" , t2 )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file2 , file3 )
r . CheckLocalItems ( t , file1c )
2019-07-08 03:02:53 +02:00
2019-07-22 21:11:46 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-11-06 08:45:51 +01:00
// ctx = predictDstFromLogger(ctx)
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , fdst , r . Flocal , false )
2023-11-06 08:45:51 +01:00
// testLoggerVsLsf(ctx, r.Fremote, operations.GetLoggerOpt(ctx).JSON, t)
2019-07-08 03:02:53 +02:00
require . NoError ( t , err )
file2dst := file2
file2dst . Path = "dst/one"
file3 . Path = "BackupDir/one"
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file2 , file2dst , file3 )
2020-11-05 12:33:32 +01:00
ci . BackupDir = ""
2019-07-08 03:02:53 +02:00
// check empty dest, new copy
2020-11-05 17:27:01 +01:00
file4 := r . WriteObject ( ctx , "CopyDest/two" , "two" , t2 )
2019-07-08 03:02:53 +02:00
file5 := r . WriteFile ( "two" , "two" , t2 )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file2 , file2dst , file3 , file4 )
r . CheckLocalItems ( t , file1c , file5 )
2019-07-08 03:02:53 +02:00
2019-07-22 21:11:46 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-11-06 08:45:51 +01:00
// ctx = predictDstFromLogger(ctx)
// testLoggerVsLsf(ctx, r.Fremote, operations.GetLoggerOpt(ctx).JSON, t)
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , fdst , r . Flocal , false )
2019-07-08 03:02:53 +02:00
require . NoError ( t , err )
file4dst := file4
file4dst . Path = "dst/two"
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file2 , file2dst , file3 , file4 , file4dst )
2019-07-08 03:02:53 +02:00
// check new dest, new copy
2019-07-22 21:11:46 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-11-06 08:45:51 +01:00
// ctx = predictDstFromLogger(ctx)
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , fdst , r . Flocal , false )
2023-11-06 08:45:51 +01:00
// testLoggerVsLsf(ctx, r.Fremote, operations.GetLoggerOpt(ctx).JSON, t)
2019-07-08 03:02:53 +02:00
require . NoError ( t , err )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file2 , file2dst , file3 , file4 , file4dst )
2019-07-08 03:02:53 +02:00
// check empty dest, old copy
2020-11-05 17:27:01 +01:00
file6 := r . WriteObject ( ctx , "CopyDest/three" , "three" , t2 )
2019-07-08 03:02:53 +02:00
file7 := r . WriteFile ( "three" , "threet3" , t3 )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file2 , file2dst , file3 , file4 , file4dst , file6 )
r . CheckLocalItems ( t , file1c , file5 , file7 )
2019-07-08 03:02:53 +02:00
2019-07-22 21:11:46 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-11-06 08:45:51 +01:00
// ctx = predictDstFromLogger(ctx)
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , fdst , r . Flocal , false )
2023-11-06 08:45:51 +01:00
// testLoggerVsLsf(ctx, r.Fremote, operations.GetLoggerOpt(ctx).JSON, t)
2019-07-08 03:02:53 +02:00
require . NoError ( t , err )
file7dst := file7
file7dst . Path = "dst/three"
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file2 , file2dst , file3 , file4 , file4dst , file6 , file7dst )
2019-07-08 03:02:53 +02:00
}
2017-01-10 22:47:03 +01:00
// Test with BackupDir set
2020-10-04 17:38:29 +02:00
func testSyncBackupDir ( t * testing . T , backupDir string , suffix string , suffixKeepExtension bool ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2017-01-10 22:47:03 +01:00
2018-01-12 17:30:54 +01:00
if ! operations . CanServerSideMove ( r . Fremote ) {
2020-10-13 23:43:40 +02:00
t . Skip ( "Skipping test as remote does not support server-side move" )
2017-01-10 22:47:03 +01:00
}
2020-11-05 17:27:01 +01:00
r . Mkdir ( ctx , r . Fremote )
2017-01-10 22:47:03 +01:00
2020-10-04 17:38:29 +02:00
if backupDir != "" {
2020-11-05 12:33:32 +01:00
ci . BackupDir = r . FremoteName + "/" + backupDir
2020-10-04 17:38:29 +02:00
backupDir += "/"
} else {
2020-11-05 12:33:32 +01:00
ci . BackupDir = ""
2020-10-04 17:38:29 +02:00
backupDir = "dst/"
// Exclude the suffix from the sync otherwise the sync
// deletes the old backup files
flt , err := filter . NewFilter ( nil )
require . NoError ( t , err )
require . NoError ( t , flt . AddRule ( "- *" + suffix ) )
2020-11-26 18:10:41 +01:00
// Change the active filter
ctx = filter . ReplaceConfig ( ctx , flt )
2020-10-04 17:38:29 +02:00
}
2020-11-05 12:33:32 +01:00
ci . Suffix = suffix
ci . SuffixKeepExtension = suffixKeepExtension
2017-01-10 22:47:03 +01:00
2017-01-19 18:26:29 +01:00
// Make the setup so we have one, two, three in the dest
// and one (different), two (same) in the source
2020-11-05 17:27:01 +01:00
file1 := r . WriteObject ( ctx , "dst/one" , "one" , t1 )
file2 := r . WriteObject ( ctx , "dst/two" , "two" , t1 )
file3 := r . WriteObject ( ctx , "dst/three.txt" , "three" , t1 )
2017-01-19 18:26:29 +01:00
file2a := r . WriteFile ( "two" , "two" , t1 )
file1a := r . WriteFile ( "one" , "oneA" , t2 )
2017-01-10 22:47:03 +01:00
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1 , file2 , file3 )
r . CheckLocalItems ( t , file1a , file2a )
2017-01-10 22:47:03 +01:00
2020-11-05 17:27:01 +01:00
fdst , err := fs . NewFs ( ctx , r . FremoteName + "/dst" )
2017-01-10 22:47:03 +01:00
require . NoError ( t , err )
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , fdst , r . Flocal , false )
2017-01-10 22:47:03 +01:00
require . NoError ( t , err )
2017-01-19 18:26:29 +01:00
// one should be moved to the backup dir and the new one installed
2020-10-04 17:38:29 +02:00
file1 . Path = backupDir + "one" + suffix
2017-01-10 22:47:03 +01:00
file1a . Path = "dst/one"
2017-01-19 18:26:29 +01:00
// two should be unchanged
// three should be moved to the backup dir
2019-03-10 17:50:28 +01:00
if suffixKeepExtension {
2020-10-04 17:38:29 +02:00
file3 . Path = backupDir + "three" + suffix + ".txt"
2019-03-10 17:50:28 +01:00
} else {
2020-10-04 17:38:29 +02:00
file3 . Path = backupDir + "three.txt" + suffix
2019-03-10 17:50:28 +01:00
}
2017-01-10 22:47:03 +01:00
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1 , file2 , file3 , file1a )
2017-01-10 22:47:03 +01:00
2017-01-19 18:26:29 +01:00
// Now check what happens if we do it again
// Restore a different three and update one in the source
2020-11-05 17:27:01 +01:00
file3a := r . WriteObject ( ctx , "dst/three.txt" , "threeA" , t2 )
2017-01-19 18:26:29 +01:00
file1b := r . WriteFile ( "one" , "oneBB" , t3 )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1 , file2 , file3 , file1a , file3a )
2017-01-19 18:26:29 +01:00
// This should delete three and overwrite one again, checking
// the files got overwritten correctly in backup-dir
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , fdst , r . Flocal , false )
2017-01-19 18:26:29 +01:00
require . NoError ( t , err )
// one should be moved to the backup dir and the new one installed
2020-10-04 17:38:29 +02:00
file1a . Path = backupDir + "one" + suffix
2017-01-19 18:26:29 +01:00
file1b . Path = "dst/one"
// two should be unchanged
// three should be moved to the backup dir
2019-03-10 17:50:28 +01:00
if suffixKeepExtension {
2020-10-04 17:38:29 +02:00
file3a . Path = backupDir + "three" + suffix + ".txt"
2019-03-10 17:50:28 +01:00
} else {
2020-10-04 17:38:29 +02:00
file3a . Path = backupDir + "three.txt" + suffix
2019-03-10 17:50:28 +01:00
}
2017-01-19 18:26:29 +01:00
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1b , file2 , file3a , file1a )
2017-01-10 22:47:03 +01:00
}
2020-10-04 17:38:29 +02:00
func TestSyncBackupDir ( t * testing . T ) {
testSyncBackupDir ( t , "backup" , "" , false )
}
func TestSyncBackupDirWithSuffix ( t * testing . T ) {
testSyncBackupDir ( t , "backup" , ".bak" , false )
}
2020-02-28 17:56:33 +01:00
func TestSyncBackupDirWithSuffixKeepExtension ( t * testing . T ) {
2020-10-04 17:38:29 +02:00
testSyncBackupDir ( t , "backup" , "-2019-01-01" , true )
}
func TestSyncBackupDirSuffixOnly ( t * testing . T ) {
testSyncBackupDir ( t , "" , ".bak" , false )
2020-02-28 17:56:33 +01:00
}
2017-09-08 17:19:41 +02:00
2019-06-23 05:52:09 +02:00
// Test with Suffix set
func testSyncSuffix ( t * testing . T , suffix string , suffixKeepExtension bool ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2019-06-23 05:52:09 +02:00
r := fstest . NewRun ( t )
if ! operations . CanServerSideMove ( r . Fremote ) {
2020-10-13 23:43:40 +02:00
t . Skip ( "Skipping test as remote does not support server-side move" )
2019-06-23 05:52:09 +02:00
}
2020-11-05 17:27:01 +01:00
r . Mkdir ( ctx , r . Fremote )
2019-06-23 05:52:09 +02:00
2020-11-05 12:33:32 +01:00
ci . Suffix = suffix
ci . SuffixKeepExtension = suffixKeepExtension
2019-06-23 05:52:09 +02:00
// Make the setup so we have one, two, three in the dest
// and one (different), two (same) in the source
2020-11-05 17:27:01 +01:00
file1 := r . WriteObject ( ctx , "dst/one" , "one" , t1 )
file2 := r . WriteObject ( ctx , "dst/two" , "two" , t1 )
file3 := r . WriteObject ( ctx , "dst/three.txt" , "three" , t1 )
2019-06-23 05:52:09 +02:00
file2a := r . WriteFile ( "two" , "two" , t1 )
file1a := r . WriteFile ( "one" , "oneA" , t2 )
file3a := r . WriteFile ( "three.txt" , "threeA" , t1 )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1 , file2 , file3 )
r . CheckLocalItems ( t , file1a , file2a , file3a )
2019-06-23 05:52:09 +02:00
2020-11-05 17:27:01 +01:00
fdst , err := fs . NewFs ( ctx , r . FremoteName + "/dst" )
2019-06-23 05:52:09 +02:00
require . NoError ( t , err )
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2020-11-05 17:27:01 +01:00
err = operations . CopyFile ( ctx , fdst , r . Flocal , "one" , "one" )
2019-06-23 05:52:09 +02:00
require . NoError ( t , err )
2020-11-05 17:27:01 +01:00
err = operations . CopyFile ( ctx , fdst , r . Flocal , "two" , "two" )
2019-06-23 05:52:09 +02:00
require . NoError ( t , err )
2020-11-05 17:27:01 +01:00
err = operations . CopyFile ( ctx , fdst , r . Flocal , "three.txt" , "three.txt" )
2019-06-23 05:52:09 +02:00
require . NoError ( t , err )
// one should be moved to the backup dir and the new one installed
file1 . Path = "dst/one" + suffix
file1a . Path = "dst/one"
// two should be unchanged
// three should be moved to the backup dir
if suffixKeepExtension {
file3 . Path = "dst/three" + suffix + ".txt"
} else {
file3 . Path = "dst/three.txt" + suffix
}
file3a . Path = "dst/three.txt"
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1 , file2 , file3 , file1a , file3a )
2019-06-23 05:52:09 +02:00
// Now check what happens if we do it again
// Restore a different three and update one in the source
2019-07-03 18:36:22 +02:00
file3b := r . WriteFile ( "three.txt" , "threeBDifferentSize" , t3 )
2019-06-23 05:52:09 +02:00
file1b := r . WriteFile ( "one" , "oneBB" , t3 )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1 , file2 , file3 , file1a , file3a )
2019-06-23 05:52:09 +02:00
// This should delete three and overwrite one again, checking
// the files got overwritten correctly in backup-dir
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2020-11-05 17:27:01 +01:00
err = operations . CopyFile ( ctx , fdst , r . Flocal , "one" , "one" )
2019-06-23 05:52:09 +02:00
require . NoError ( t , err )
2020-11-05 17:27:01 +01:00
err = operations . CopyFile ( ctx , fdst , r . Flocal , "two" , "two" )
2019-06-23 05:52:09 +02:00
require . NoError ( t , err )
2020-11-05 17:27:01 +01:00
err = operations . CopyFile ( ctx , fdst , r . Flocal , "three.txt" , "three.txt" )
2019-06-23 05:52:09 +02:00
require . NoError ( t , err )
// one should be moved to the backup dir and the new one installed
file1a . Path = "dst/one" + suffix
file1b . Path = "dst/one"
// two should be unchanged
// three should be moved to the backup dir
if suffixKeepExtension {
file3a . Path = "dst/three" + suffix + ".txt"
} else {
file3a . Path = "dst/three.txt" + suffix
}
file3b . Path = "dst/three.txt"
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1b , file3b , file2 , file3a , file1a )
2019-06-23 05:52:09 +02:00
}
func TestSyncSuffix ( t * testing . T ) { testSyncSuffix ( t , ".bak" , false ) }
func TestSyncSuffixKeepExtension ( t * testing . T ) { testSyncSuffix ( t , "-2019-01-01" , true ) }
2017-09-08 17:19:41 +02:00
// Check we can sync two files with differing UTF-8 representations
func TestSyncUTFNorm ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2017-09-17 15:05:33 +02:00
if runtime . GOOS == "darwin" {
t . Skip ( "Can't test UTF normalization on OS X" )
}
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2017-09-08 17:19:41 +02:00
// Two strings with different unicode normalization (from OS X)
Encoding1 := "Testêé"
Encoding2 := "Testêé"
assert . NotEqual ( t , Encoding1 , Encoding2 )
assert . Equal ( t , norm . NFC . String ( Encoding1 ) , norm . NFC . String ( Encoding2 ) )
file1 := r . WriteFile ( Encoding1 , "This is a test" , t1 )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
2017-09-08 17:19:41 +02:00
2020-11-05 17:27:01 +01:00
file2 := r . WriteObject ( ctx , Encoding2 , "This is a old test" , t2 )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file2 )
2017-09-08 17:19:41 +02:00
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
// ctx = predictDstFromLogger(ctx)
2020-11-05 17:27:01 +01:00
err := Sync ( ctx , r . Fremote , r . Flocal , false )
2023-10-01 11:02:56 +02:00
// testLoggerVsLsf(ctx, r.Fremote, operations.GetLoggerOpt(ctx).JSON, t) // can't test this on macOS
2017-09-08 17:19:41 +02:00
require . NoError ( t , err )
// We should have transferred exactly one file, but kept the
// normalized state of the file.
2019-09-05 22:29:35 +02:00
assert . Equal ( t , toyFileTransfers ( r ) , accounting . GlobalStats ( ) . GetTransfers ( ) )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
2017-09-08 17:19:41 +02:00
file1 . Path = file2 . Path
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file1 )
2017-09-08 17:19:41 +02:00
}
2017-09-02 10:29:01 +02:00
// Test --immutable
func TestSyncImmutable ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2017-10-29 13:23:10 +01:00
r := fstest . NewRun ( t )
2017-09-02 10:29:01 +02:00
2020-11-05 12:33:32 +01:00
ci . Immutable = true
2017-09-02 10:29:01 +02:00
// Create file on source
file1 := r . WriteFile ( "existing" , "potato" , t1 )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
r . CheckRemoteItems ( t )
2017-09-02 10:29:01 +02:00
// Should succeed
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err := Sync ( ctx , r . Fremote , r . Flocal , false )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2017-09-02 10:29:01 +02:00
require . NoError ( t , err )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
r . CheckRemoteItems ( t , file1 )
2017-09-02 10:29:01 +02:00
// Modify file data and timestamp on source
2017-09-27 17:28:20 +02:00
file2 := r . WriteFile ( "existing" , "tomatoes" , t2 )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file2 )
r . CheckRemoteItems ( t , file1 )
2017-09-02 10:29:01 +02:00
// Should fail with ErrorImmutableModified and not modify local or remote files
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2020-11-05 17:27:01 +01:00
err = Sync ( ctx , r . Fremote , r . Flocal , false )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2017-09-02 10:29:01 +02:00
assert . EqualError ( t , err , fs . ErrorImmutableModified . Error ( ) )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file2 )
r . CheckRemoteItems ( t , file1 )
2017-09-02 10:29:01 +02:00
}
2018-04-24 10:48:35 +02:00
2019-06-03 22:12:10 +02:00
// Test --ignore-case-sync
func TestSyncIgnoreCase ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2019-06-03 22:12:10 +02:00
r := fstest . NewRun ( t )
// Only test if filesystems are case sensitive
if r . Fremote . Features ( ) . CaseInsensitive || r . Flocal . Features ( ) . CaseInsensitive {
t . Skip ( "Skipping test as local or remote are case-insensitive" )
}
2020-11-05 12:33:32 +01:00
ci . IgnoreCaseSync = true
2019-06-03 22:12:10 +02:00
// Create files with different filename casing
file1 := r . WriteFile ( "existing" , "potato" , t1 )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
2020-11-05 17:27:01 +01:00
file2 := r . WriteObject ( ctx , "EXISTING" , "potato" , t1 )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , file2 )
2019-06-03 22:12:10 +02:00
// Should not copy files that are differently-cased but otherwise identical
2019-07-18 12:13:54 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
// ctx = predictDstFromLogger(ctx)
2020-11-05 17:27:01 +01:00
err := Sync ( ctx , r . Fremote , r . Flocal , false )
2023-10-01 11:02:56 +02:00
// testLoggerVsLsf(ctx, r.Fremote, operations.GetLoggerOpt(ctx).JSON, t) // can't test this on macOS
2019-06-03 22:12:10 +02:00
require . NoError ( t , err )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 )
r . CheckRemoteItems ( t , file2 )
2019-06-03 22:12:10 +02:00
}
2023-10-09 04:59:22 +02:00
// Test --fix-case
func TestFixCase ( t * testing . T ) {
ctx := context . Background ( )
ctx , ci := fs . AddConfig ( ctx )
r := fstest . NewRun ( t )
// Only test if remote is case insensitive
if ! r . Fremote . Features ( ) . CaseInsensitive {
t . Skip ( "Skipping test as local or remote are case-sensitive" )
}
ci . FixCase = true
// Create files with different filename casing
file1a := r . WriteFile ( "existing" , "potato" , t1 )
file1b := r . WriteFile ( "existingbutdifferent" , "donut" , t1 )
file1c := r . WriteFile ( "subdira/subdirb/subdirc/hello" , "donut" , t1 )
file1d := r . WriteFile ( "subdira/subdirb/subdirc/subdird/filewithoutcasedifferences" , "donut" , t1 )
r . CheckLocalItems ( t , file1a , file1b , file1c , file1d )
file2a := r . WriteObject ( ctx , "EXISTING" , "potato" , t1 )
file2b := r . WriteObject ( ctx , "EXISTINGBUTDIFFERENT" , "lemonade" , t1 )
file2c := r . WriteObject ( ctx , "SUBDIRA/subdirb/SUBDIRC/HELLO" , "lemonade" , t1 )
file2d := r . WriteObject ( ctx , "SUBDIRA/subdirb/SUBDIRC/subdird/filewithoutcasedifferences" , "lemonade" , t1 )
r . CheckRemoteItems ( t , file2a , file2b , file2c , file2d )
// Should force rename of dest file that is differently-cased
accounting . GlobalStats ( ) . ResetCounters ( )
err := Sync ( ctx , r . Fremote , r . Flocal , false )
require . NoError ( t , err )
r . CheckLocalItems ( t , file1a , file1b , file1c , file1d )
r . CheckRemoteItems ( t , file1a , file1b , file1c , file1d )
}
2020-09-09 13:53:21 +02:00
// Test that aborting on --max-transfer works
func TestMaxTransfer ( t * testing . T ) {
2020-11-05 17:27:01 +01:00
ctx := context . Background ( )
2021-02-17 21:21:09 +01:00
ctx , ci := fs . AddConfig ( ctx )
2020-11-05 12:33:32 +01:00
ci . MaxTransfer = 3 * 1024
ci . Transfers = 1
ci . Checkers = 1
ci . CutoffMode = fs . CutoffModeHard
2018-04-24 10:48:35 +02:00
2020-09-09 13:53:21 +02:00
test := func ( t * testing . T , cutoff fs . CutoffMode ) {
r := fstest . NewRun ( t )
2020-11-05 12:33:32 +01:00
ci . CutoffMode = cutoff
2018-04-24 10:48:35 +02:00
2020-09-09 13:53:21 +02:00
if r . Fremote . Name ( ) != "local" {
t . Skip ( "This test only runs on local" )
}
2018-04-24 10:48:35 +02:00
2020-09-09 13:53:21 +02:00
// Create file on source
file1 := r . WriteFile ( "file1" , string ( make ( [ ] byte , 5 * 1024 ) ) , t1 )
file2 := r . WriteFile ( "file2" , string ( make ( [ ] byte , 2 * 1024 ) ) , t1 )
file3 := r . WriteFile ( "file3" , string ( make ( [ ] byte , 3 * 1024 ) ) , t1 )
2021-11-09 12:43:36 +01:00
r . CheckLocalItems ( t , file1 , file2 , file3 )
r . CheckRemoteItems ( t )
2020-09-09 13:53:21 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
2023-10-01 11:02:56 +02:00
// ctx = predictDstFromLogger(ctx) // not currently supported
2020-11-05 17:27:01 +01:00
err := Sync ( ctx , r . Fremote , r . Flocal , false )
2023-10-01 11:02:56 +02:00
// testLoggerVsLsf(ctx, r.Fremote, operations.GetLoggerOpt(ctx).JSON, t)
2020-09-09 13:53:21 +02:00
expectedErr := fserrors . FsError ( accounting . ErrorMaxTransferLimitReachedFatal )
if cutoff != fs . CutoffModeHard {
expectedErr = accounting . ErrorMaxTransferLimitReachedGraceful
}
fserrors . Count ( expectedErr )
assert . Equal ( t , expectedErr , err )
}
t . Run ( "Hard" , func ( t * testing . T ) { test ( t , fs . CutoffModeHard ) } )
t . Run ( "Soft" , func ( t * testing . T ) { test ( t , fs . CutoffModeSoft ) } )
t . Run ( "Cautious" , func ( t * testing . T ) { test ( t , fs . CutoffModeCautious ) } )
2018-04-24 10:48:35 +02:00
}
2021-07-07 15:50:19 +02:00
func testSyncConcurrent ( t * testing . T , subtest string ) {
const (
NFILES = 20
NCHECKERS = 4
NTRANSFERS = 4
)
ctx , ci := fs . AddConfig ( context . Background ( ) )
ci . Checkers = NCHECKERS
ci . Transfers = NTRANSFERS
r := fstest . NewRun ( t )
stats := accounting . GlobalStats ( )
itemsBefore := [ ] fstest . Item { }
itemsAfter := [ ] fstest . Item { }
for i := 0 ; i < NFILES ; i ++ {
nameBoth := fmt . Sprintf ( "both%d" , i )
nameOnly := fmt . Sprintf ( "only%d" , i )
switch subtest {
case "delete" :
fileBoth := r . WriteBoth ( ctx , nameBoth , "potato" , t1 )
fileOnly := r . WriteObject ( ctx , nameOnly , "potato" , t1 )
itemsBefore = append ( itemsBefore , fileBoth , fileOnly )
itemsAfter = append ( itemsAfter , fileBoth )
case "truncate" :
fileBoth := r . WriteBoth ( ctx , nameBoth , "potato" , t1 )
fileFull := r . WriteObject ( ctx , nameOnly , "potato" , t1 )
fileEmpty := r . WriteFile ( nameOnly , "" , t1 )
itemsBefore = append ( itemsBefore , fileBoth , fileFull )
itemsAfter = append ( itemsAfter , fileBoth , fileEmpty )
}
}
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , itemsBefore ... )
2021-07-07 15:50:19 +02:00
stats . ResetErrors ( )
2023-10-01 11:02:56 +02:00
ctx = predictDstFromLogger ( ctx )
2021-07-07 15:50:19 +02:00
err := Sync ( ctx , r . Fremote , r . Flocal , false )
2023-10-01 11:02:56 +02:00
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
2021-11-04 11:12:57 +01:00
if errors . Is ( err , fs . ErrorCantUploadEmptyFiles ) {
2021-10-23 12:35:20 +02:00
t . Skipf ( "Skip test because remote cannot upload empty files" )
}
2021-07-07 15:50:19 +02:00
assert . NoError ( t , err , "Sync must not return a error" )
assert . False ( t , stats . Errored ( ) , "Low level errors must not have happened" )
2021-11-09 12:43:36 +01:00
r . CheckRemoteItems ( t , itemsAfter ... )
2021-07-07 15:50:19 +02:00
}
func TestSyncConcurrentDelete ( t * testing . T ) {
testSyncConcurrent ( t , "delete" )
}
func TestSyncConcurrentTruncate ( t * testing . T ) {
testSyncConcurrent ( t , "truncate" )
}
2023-10-01 11:02:56 +02:00
2024-02-29 01:29:38 +01:00
// Tests that nothing is transferred when src and dst already match
// Run the same sync twice, ensure no action is taken the second time
2024-04-04 19:03:20 +02:00
func testNothingToTransfer ( t * testing . T , copyEmptySrcDirs bool ) {
2024-02-29 01:29:38 +01:00
accounting . GlobalStats ( ) . ResetCounters ( )
ctx , _ := fs . AddConfig ( context . Background ( ) )
r := fstest . NewRun ( t )
file1 := r . WriteFile ( "sub dir/hello world" , "hello world" , t1 )
file2 := r . WriteFile ( "sub dir2/very/very/very/very/very/nested/subdir/hello world" , "hello world" , t1 )
r . CheckLocalItems ( t , file1 , file2 )
_ , err := operations . SetDirModTime ( ctx , r . Flocal , nil , "sub dir" , t2 )
if err != nil && ! errors . Is ( err , fs . ErrorNotImplemented ) {
require . NoError ( t , err )
}
r . Mkdir ( ctx , r . Fremote )
_ , err = operations . MkdirModTime ( ctx , r . Fremote , "sub dir" , t3 )
require . NoError ( t , err )
// set logging
// (this checks log output as DirModtime operations do not yet have stats, and r.CheckDirectoryModTimes also does not tell us what actions were taken)
oldLogLevel := fs . GetConfig ( context . Background ( ) ) . LogLevel
defer func ( ) { fs . GetConfig ( context . Background ( ) ) . LogLevel = oldLogLevel } ( ) // reset to old val after test
// need to do this as fs.Infof only respects the globalConfig
fs . GetConfig ( context . Background ( ) ) . LogLevel = fs . LogLevelInfo
accounting . GlobalStats ( ) . ResetCounters ( )
ctx = predictDstFromLogger ( ctx )
output := bilib . CaptureOutput ( func ( ) {
2024-04-04 19:03:20 +02:00
err = CopyDir ( ctx , r . Fremote , r . Flocal , copyEmptySrcDirs )
2024-02-29 01:29:38 +01:00
require . NoError ( t , err )
} )
require . NotNil ( t , output )
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
r . CheckLocalItems ( t , file1 , file2 )
r . CheckRemoteItems ( t , file1 , file2 )
// Check that the modtimes of the directories are as expected
2024-04-17 17:55:17 +02:00
r . CheckDirectoryModTimes ( t , "sub dir" , "sub dir2" , "sub dir2/very" , "sub dir2/very/very" , "sub dir2/very/very/very/very/very/nested/subdir" )
2024-02-29 01:29:38 +01:00
// check that actions were taken
assert . True ( t , strings . Contains ( string ( output ) , "Copied" ) , ` expected to find at least one "Copied" log: ` + string ( output ) )
if r . Fremote . Features ( ) . DirSetModTime != nil || r . Fremote . Features ( ) . MkdirMetadata != nil {
assert . True ( t , strings . Contains ( string ( output ) , "Set directory modification time" ) , ` expected to find at least one "Set directory modification time" log: ` + string ( output ) )
}
assert . False ( t , strings . Contains ( string ( output ) , "There was nothing to transfer" ) , ` expected to find no "There was nothing to transfer" logs, but found one: ` + string ( output ) )
2024-03-08 15:45:48 +01:00
assert . True ( t , accounting . GlobalStats ( ) . GetTransfers ( ) >= 2 )
2024-02-29 01:29:38 +01:00
// run it again and make sure no actions were taken
accounting . GlobalStats ( ) . ResetCounters ( )
ctx = predictDstFromLogger ( ctx )
output = bilib . CaptureOutput ( func ( ) {
2024-04-04 19:03:20 +02:00
err = CopyDir ( ctx , r . Fremote , r . Flocal , copyEmptySrcDirs )
2024-02-29 01:29:38 +01:00
require . NoError ( t , err )
} )
require . NotNil ( t , output )
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
r . CheckLocalItems ( t , file1 , file2 )
r . CheckRemoteItems ( t , file1 , file2 )
// Check that the modtimes of the directories are as expected
2024-04-17 17:55:17 +02:00
r . CheckDirectoryModTimes ( t , "sub dir" , "sub dir2" , "sub dir2/very" , "sub dir2/very/very" , "sub dir2/very/very/very/very/very/nested/subdir" )
2024-02-29 01:29:38 +01:00
// check that actions were NOT taken
assert . False ( t , strings . Contains ( string ( output ) , "Copied" ) , ` expected to find no "Copied" logs, but found one: ` + string ( output ) )
if r . Fremote . Features ( ) . DirSetModTime != nil || r . Fremote . Features ( ) . MkdirMetadata != nil {
assert . False ( t , strings . Contains ( string ( output ) , "Set directory modification time" ) , ` expected to find no "Set directory modification time" logs, but found one: ` + string ( output ) )
2024-04-04 19:03:20 +02:00
assert . False ( t , strings . Contains ( string ( output ) , "Updated directory metadata" ) , ` expected to find no "Updated directory metadata" logs, but found one: ` + string ( output ) )
assert . False ( t , strings . Contains ( string ( output ) , "directory" ) , ` expected to find no "directory"-related logs, but found one: ` + string ( output ) ) // catch-all
2024-02-29 01:29:38 +01:00
}
assert . True ( t , strings . Contains ( string ( output ) , "There was nothing to transfer" ) , ` expected to find a "There was nothing to transfer" log: ` + string ( output ) )
assert . Equal ( t , int64 ( 0 ) , accounting . GlobalStats ( ) . GetTransfers ( ) )
2024-04-16 20:39:30 +02:00
2024-04-17 17:55:17 +02:00
// check nested empty dir behavior (FIXME: probably belongs in a separate test)
2024-04-16 20:39:30 +02:00
if r . Fremote . Features ( ) . DirSetModTime == nil && r . Fremote . Features ( ) . MkdirMetadata == nil {
return
}
file3 := r . WriteFile ( "sub dir2/sub dir3/hello world" , "hello again, world" , t1 )
_ , err = operations . SetDirModTime ( ctx , r . Flocal , nil , "sub dir2" , t1 )
assert . NoError ( t , err )
_ , err = operations . SetDirModTime ( ctx , r . Fremote , nil , "sub dir2" , t1 )
assert . NoError ( t , err )
2024-04-17 17:55:17 +02:00
_ , err = operations . MkdirModTime ( ctx , r . Flocal , "sub dirEmpty/sub dirEmpty2" , t2 )
assert . NoError ( t , err )
_ , err = operations . SetDirModTime ( ctx , r . Flocal , nil , "sub dirEmpty" , t2 )
assert . NoError ( t , err )
2024-04-16 20:39:30 +02:00
accounting . GlobalStats ( ) . ResetCounters ( )
ctx = predictDstFromLogger ( ctx )
output = bilib . CaptureOutput ( func ( ) {
err = CopyDir ( ctx , r . Fremote , r . Flocal , copyEmptySrcDirs )
require . NoError ( t , err )
} )
require . NotNil ( t , output )
testLoggerVsLsf ( ctx , r . Fremote , operations . GetLoggerOpt ( ctx ) . JSON , t )
r . CheckLocalItems ( t , file1 , file2 , file3 )
r . CheckRemoteItems ( t , file1 , file2 , file3 )
2024-04-17 17:55:17 +02:00
// Check that the modtimes of the directories are as expected
r . CheckDirectoryModTimes ( t , "sub dir" , "sub dir2" , "sub dir2/very" , "sub dir2/very/very" , "sub dir2/very/very/very/very/very/nested/subdir" , "sub dir2/sub dir3" )
if copyEmptySrcDirs {
r . CheckDirectoryModTimes ( t , "sub dirEmpty" , "sub dirEmpty/sub dirEmpty2" )
assert . True ( t , strings . Contains ( string ( output ) , "sub dirEmpty:" ) , ` expected to find at least one "sub dirEmpty:" log: ` + string ( output ) )
} else {
assert . False ( t , strings . Contains ( string ( output ) , "sub dirEmpty:" ) , ` expected to find no "sub dirEmpty:" logs, but found one (empty dir was synced and shouldn't have been): ` + string ( output ) )
}
2024-04-16 20:39:30 +02:00
assert . True ( t , strings . Contains ( string ( output ) , "sub dir3:" ) , ` expected to find at least one "sub dir3:" log: ` + string ( output ) )
2024-04-17 17:55:17 +02:00
assert . False ( t , strings . Contains ( string ( output ) , "sub dir2/very:" ) , ` expected to find no "sub dir2/very:" logs, but found one (unmodified dir was marked modified): ` + string ( output ) )
2024-02-29 01:29:38 +01:00
}
2024-04-04 19:03:20 +02:00
func TestNothingToTransferWithEmptyDirs ( t * testing . T ) {
testNothingToTransfer ( t , true )
}
func TestNothingToTransferWithoutEmptyDirs ( t * testing . T ) {
testNothingToTransfer ( t , false )
}
2023-10-01 11:02:56 +02:00
// for testing logger:
func predictDstFromLogger ( ctx context . Context ) context . Context {
opt := operations . NewLoggerOpt ( )
var lock mutex . Mutex
opt . LoggerFn = func ( ctx context . Context , sigil operations . Sigil , src , dst fs . DirEntry , err error ) {
lock . Lock ( )
defer lock . Unlock ( )
// ignore dirs for our purposes here
if err == fs . ErrorIsDir {
return
}
winner := operations . WinningSide ( ctx , sigil , src , dst , err )
if winner . Obj != nil {
file := winner . Obj
obj , ok := file . ( fs . ObjectInfo )
checksum := ""
2023-11-06 08:45:51 +01:00
timeFormat := "2006-01-02 15:04:05"
2023-10-01 11:02:56 +02:00
if ok {
if obj . Fs ( ) . Hashes ( ) . GetOne ( ) == hash . MD5 {
// skip if no MD5
2023-11-06 08:45:51 +01:00
checksum , _ = obj . Hash ( ctx , hash . MD5 )
2023-10-01 11:02:56 +02:00
}
2023-11-06 08:45:51 +01:00
timeFormat = operations . FormatForLSFPrecision ( obj . Fs ( ) . Precision ( ) )
2023-10-01 11:02:56 +02:00
}
errMsg := ""
if winner . Err != nil {
errMsg = ";" + winner . Err . Error ( )
}
2023-11-06 08:45:51 +01:00
operations . SyncFprintf ( opt . JSON , "%s;%s;%v;%s%s\n" , file . ModTime ( ctx ) . Local ( ) . Format ( timeFormat ) , checksum , file . Size ( ) , file . Remote ( ) , errMsg )
2023-10-01 11:02:56 +02:00
}
}
return operations . WithSyncLogger ( ctx , opt )
}
func DstLsf ( ctx context . Context , Fremote fs . Fs ) * bytes . Buffer {
var opt = operations . ListJSONOpt {
NoModTime : false ,
NoMimeType : true ,
DirsOnly : false ,
FilesOnly : true ,
Recurse : true ,
ShowHash : true ,
HashTypes : [ ] string { "MD5" } ,
}
var list operations . ListFormat
list . SetSeparator ( ";" )
timeFormat := operations . FormatForLSFPrecision ( Fremote . Precision ( ) )
list . AddModTime ( timeFormat )
list . AddHash ( hash . MD5 )
list . AddSize ( )
list . AddPath ( )
out := new ( bytes . Buffer )
err := operations . ListJSON ( ctx , Fremote , "" , & opt , func ( item * operations . ListJSONItem ) error {
_ , _ = fmt . Fprintln ( out , list . Format ( item ) )
return nil
} )
if err != nil {
fs . Errorf ( Fremote , "ListJSON error: %v" , err )
}
return out
}
func LoggerMatchesLsf ( logger , lsf * bytes . Buffer ) error {
loggerSplit := bytes . Split ( logger . Bytes ( ) , [ ] byte ( "\n" ) )
sort . SliceStable ( loggerSplit , func ( i int , j int ) bool { return string ( loggerSplit [ i ] ) < string ( loggerSplit [ j ] ) } )
lsfSplit := bytes . Split ( lsf . Bytes ( ) , [ ] byte ( "\n" ) )
sort . SliceStable ( lsfSplit , func ( i int , j int ) bool { return string ( lsfSplit [ i ] ) < string ( lsfSplit [ j ] ) } )
loggerJoined := bytes . Join ( loggerSplit , [ ] byte ( "\n" ) )
lsfJoined := bytes . Join ( lsfSplit , [ ] byte ( "\n" ) )
if bytes . Equal ( loggerJoined , lsfJoined ) {
return nil
}
Diff ( string ( loggerJoined ) , string ( lsfJoined ) )
return fmt . Errorf ( "logger does not match lsf! \nlogger: \n%s \nlsf: \n%s" , loggerJoined , lsfJoined )
}
func Diff ( rev1 , rev2 string ) {
fmt . Printf ( "Diff of %q and %q\n" , "logger" , "lsf" )
cmd := exec . Command ( "bash" , "-c" , fmt . Sprintf ( ` diff <(echo "%s") <(echo "%s") ` , rev1 , rev2 ) )
out , _ := cmd . Output ( )
_ , _ = os . Stdout . Write ( out )
}
func testLoggerVsLsf ( ctx context . Context , Fremote fs . Fs , logger * bytes . Buffer , t * testing . T ) {
var newlogger bytes . Buffer
canTestModtime := fs . GetModifyWindow ( ctx , Fremote ) != fs . ModTimeNotSupported
canTestHash := Fremote . Hashes ( ) . Contains ( hash . MD5 )
if ! canTestHash || ! canTestModtime {
loggerSplit := bytes . Split ( logger . Bytes ( ) , [ ] byte ( "\n" ) )
for i , line := range loggerSplit {
elements := bytes . Split ( line , [ ] byte ( ";" ) )
if len ( elements ) >= 2 {
if ! canTestModtime {
elements [ 0 ] = [ ] byte ( "" )
}
if ! canTestHash {
elements [ 1 ] = [ ] byte ( "" )
}
}
loggerSplit [ i ] = bytes . Join ( elements , [ ] byte ( ";" ) )
}
newlogger . Write ( bytes . Join ( loggerSplit , [ ] byte ( "\n" ) ) )
} else {
newlogger . Write ( logger . Bytes ( ) )
}
r := fstest . NewRun ( t )
if r . Flocal . Precision ( ) == Fremote . Precision ( ) && r . Flocal . Hashes ( ) . Contains ( hash . MD5 ) && canTestHash {
2023-11-06 08:45:51 +01:00
lsf := DstLsf ( ctx , Fremote )
err := LoggerMatchesLsf ( & newlogger , lsf )
2023-10-01 11:02:56 +02:00
require . NoError ( t , err )
}
}