2015-09-22 17:47:16 +00:00
|
|
|
// Package fstests provides generic tests for testing the Fs and Object interfaces
|
2015-02-14 18:48:08 +00:00
|
|
|
//
|
|
|
|
// Run go generate to write the tests for the remotes
|
2015-09-22 17:47:16 +00:00
|
|
|
package fstests
|
2015-02-14 18:48:08 +00:00
|
|
|
|
|
|
|
//go:generate go run gen_tests.go
|
2014-07-24 21:50:11 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2015-08-15 14:40:18 +00:00
|
|
|
"flag"
|
2016-07-25 18:18:56 +00:00
|
|
|
"fmt"
|
2014-07-24 21:50:11 +00:00
|
|
|
"io"
|
2014-07-31 20:24:52 +00:00
|
|
|
"os"
|
2016-04-23 20:46:52 +00:00
|
|
|
"path"
|
2016-05-07 13:50:35 +00:00
|
|
|
"sort"
|
2014-07-31 20:24:52 +00:00
|
|
|
"strings"
|
2014-07-24 21:50:11 +00:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/ncw/rclone/fs"
|
|
|
|
"github.com/ncw/rclone/fstest"
|
2016-04-23 20:46:52 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
2014-07-24 21:50:11 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2015-09-22 17:47:16 +00:00
|
|
|
remote fs.Fs
|
|
|
|
// RemoteName should be set to the name of the remote for testing
|
2014-07-31 20:24:52 +00:00
|
|
|
RemoteName = ""
|
|
|
|
subRemoteName = ""
|
|
|
|
subRemoteLeaf = ""
|
2015-09-22 17:47:16 +00:00
|
|
|
// NilObject should be set to a nil Object from the Fs under test
|
|
|
|
NilObject fs.Object
|
2016-08-20 15:25:14 +00:00
|
|
|
// ExtraConfig is for adding config to a remote
|
|
|
|
ExtraConfig = []ExtraConfigItem{}
|
|
|
|
file1 = fstest.Item{
|
2014-07-24 21:50:11 +00:00
|
|
|
ModTime: fstest.Time("2001-02-03T04:05:06.499999999Z"),
|
|
|
|
Path: "file name.txt",
|
|
|
|
}
|
|
|
|
file2 = fstest.Item{
|
|
|
|
ModTime: fstest.Time("2001-02-03T04:05:10.123123123Z"),
|
2016-08-23 13:28:05 +00:00
|
|
|
Path: `hello? sausage/êé/Hello, 世界/ " ' @ < > & ? + ≠/z.txt`,
|
|
|
|
WinPath: `hello_ sausage/êé/Hello, 世界/ _ ' @ _ _ & _ + ≠/z.txt`,
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
2016-01-20 20:06:05 +00:00
|
|
|
verbose = flag.Bool("verbose", false, "Set to enable logging")
|
2015-11-07 09:48:46 +00:00
|
|
|
dumpHeaders = flag.Bool("dump-headers", false, "Dump HTTP headers - may contain sensitive info")
|
|
|
|
dumpBodies = flag.Bool("dump-bodies", false, "Dump HTTP headers and bodies - may contain sensitive info")
|
2014-07-24 21:50:11 +00:00
|
|
|
)
|
|
|
|
|
2016-08-20 15:25:14 +00:00
|
|
|
// ExtraConfigItem describes a config item added on the fly while testing
|
|
|
|
type ExtraConfigItem struct{ Name, Key, Value string }
|
|
|
|
|
2016-01-20 20:06:05 +00:00
|
|
|
const eventualConsistencyRetries = 10
|
|
|
|
|
2015-08-15 14:40:18 +00:00
|
|
|
func init() {
|
|
|
|
flag.StringVar(&RemoteName, "remote", "", "Set this to override the default remote name (eg s3:)")
|
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestInit tests basic intitialisation
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestInit(t *testing.T) {
|
2014-07-31 20:24:52 +00:00
|
|
|
var err error
|
2016-02-16 15:25:27 +00:00
|
|
|
|
|
|
|
// Never ask for passwords, fail instead.
|
|
|
|
// If your local config is encrypted set environment variable
|
|
|
|
// "RCLONE_CONFIG_PASS=hunter2" (or your password)
|
|
|
|
*fs.AskPassword = false
|
2014-07-24 21:50:11 +00:00
|
|
|
fs.LoadConfig()
|
2016-08-20 15:25:14 +00:00
|
|
|
// Set extra config if supplied
|
|
|
|
for _, item := range ExtraConfig {
|
|
|
|
fs.ConfigFile.SetValue(item.Name, item.Key, item.Value)
|
|
|
|
}
|
2016-01-20 20:06:05 +00:00
|
|
|
fs.Config.Verbose = *verbose
|
|
|
|
fs.Config.Quiet = !*verbose
|
2015-11-07 09:48:46 +00:00
|
|
|
fs.Config.DumpHeaders = *dumpHeaders
|
|
|
|
fs.Config.DumpBodies = *dumpBodies
|
2015-08-15 14:40:18 +00:00
|
|
|
t.Logf("Using remote %q", RemoteName)
|
2014-07-31 20:24:52 +00:00
|
|
|
if RemoteName == "" {
|
|
|
|
RemoteName, err = fstest.LocalRemote()
|
2016-06-29 16:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2014-07-31 20:24:52 +00:00
|
|
|
}
|
|
|
|
subRemoteName, subRemoteLeaf, err = fstest.RandomRemoteName(RemoteName)
|
2016-06-29 16:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2014-07-31 20:24:52 +00:00
|
|
|
|
|
|
|
remote, err = fs.NewFs(subRemoteName)
|
2015-09-22 17:47:16 +00:00
|
|
|
if err == fs.ErrorNotFoundInConfigFile {
|
2016-06-06 20:23:54 +00:00
|
|
|
t.Logf("Didn't find %q in config file - skipping tests", RemoteName)
|
2014-07-31 07:51:39 +00:00
|
|
|
return
|
|
|
|
}
|
2016-07-25 18:18:56 +00:00
|
|
|
require.NoError(t, err, fmt.Sprintf("unexpected error: %v", err))
|
2014-08-01 16:58:39 +00:00
|
|
|
fstest.TestMkdir(t, remote)
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func skipIfNotOk(t *testing.T) {
|
|
|
|
if remote == nil {
|
|
|
|
t.Skip("FS not configured")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestFsString tests the String method
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestFsString(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
|
|
|
str := remote.String()
|
2016-06-29 16:59:31 +00:00
|
|
|
require.NotEqual(t, str, "")
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestFsRmdirEmpty tests deleting an empty directory
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestFsRmdirEmpty(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
2014-08-01 16:58:39 +00:00
|
|
|
fstest.TestRmdir(t, remote)
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestFsRmdirNotFound tests deleting a non existent directory
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestFsRmdirNotFound(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
|
|
|
err := remote.Rmdir()
|
2016-06-29 16:59:31 +00:00
|
|
|
assert.Error(t, err, "Expecting error on Rmdir non existent")
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestFsMkdir tests tests making a directory
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestFsMkdir(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
2014-08-01 16:58:39 +00:00
|
|
|
fstest.TestMkdir(t, remote)
|
|
|
|
fstest.TestMkdir(t, remote)
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestFsListEmpty tests listing an empty directory
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestFsListEmpty(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
2014-08-01 16:58:39 +00:00
|
|
|
fstest.CheckListing(t, remote, []fstest.Item{})
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
2016-05-07 13:50:35 +00:00
|
|
|
// winPath converts a path into a windows safe path
|
|
|
|
func winPath(s string) string {
|
|
|
|
s = strings.Replace(s, "?", "_", -1)
|
|
|
|
s = strings.Replace(s, `"`, "_", -1)
|
|
|
|
s = strings.Replace(s, "<", "_", -1)
|
|
|
|
s = strings.Replace(s, ">", "_", -1)
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
|
|
|
// dirsToNames returns a sorted list of names
|
|
|
|
func dirsToNames(dirs []*fs.Dir) []string {
|
|
|
|
names := []string{}
|
|
|
|
for _, dir := range dirs {
|
|
|
|
names = append(names, winPath(dir.Name))
|
|
|
|
}
|
|
|
|
sort.Strings(names)
|
|
|
|
return names
|
|
|
|
}
|
|
|
|
|
|
|
|
// objsToNames returns a sorted list of object names
|
|
|
|
func objsToNames(objs []fs.Object) []string {
|
|
|
|
names := []string{}
|
|
|
|
for _, obj := range objs {
|
|
|
|
names = append(names, winPath(obj.Remote()))
|
|
|
|
}
|
|
|
|
sort.Strings(names)
|
|
|
|
return names
|
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestFsListDirEmpty tests listing the directories from an empty directory
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestFsListDirEmpty(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
2016-05-07 13:50:35 +00:00
|
|
|
objs, dirs, err := fs.NewLister().SetLevel(1).Start(remote, "").GetAll()
|
2016-04-23 20:46:52 +00:00
|
|
|
require.NoError(t, err)
|
2016-05-07 13:50:35 +00:00
|
|
|
assert.Equal(t, []string{}, objsToNames(objs))
|
|
|
|
assert.Equal(t, []string{}, dirsToNames(dirs))
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
2016-06-25 20:58:34 +00:00
|
|
|
// TestFsNewObjectNotFound tests not finding a object
|
|
|
|
func TestFsNewObjectNotFound(t *testing.T) {
|
2014-07-24 21:50:11 +00:00
|
|
|
skipIfNotOk(t)
|
2016-06-25 20:23:20 +00:00
|
|
|
// Object in an existing directory
|
|
|
|
o, err := remote.NewObject("potato")
|
|
|
|
assert.Nil(t, o)
|
|
|
|
assert.Equal(t, fs.ErrorObjectNotFound, err)
|
|
|
|
// Now try an object in a non existing directory
|
|
|
|
o, err = remote.NewObject("directory/not/found/potato")
|
|
|
|
assert.Nil(t, o)
|
|
|
|
assert.Equal(t, fs.ErrorObjectNotFound, err)
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func findObject(t *testing.T, Name string) fs.Object {
|
2015-12-30 10:46:04 +00:00
|
|
|
var obj fs.Object
|
2016-06-25 20:23:20 +00:00
|
|
|
var err error
|
2016-01-20 20:06:05 +00:00
|
|
|
for i := 1; i <= eventualConsistencyRetries; i++ {
|
2016-06-25 20:23:20 +00:00
|
|
|
obj, err = remote.NewObject(Name)
|
|
|
|
if err == nil {
|
2015-12-30 10:46:04 +00:00
|
|
|
break
|
|
|
|
}
|
2016-06-25 20:23:20 +00:00
|
|
|
t.Logf("Sleeping for 1 second for findObject eventual consistency: %d/%d (%v)", i, eventualConsistencyRetries, err)
|
2015-12-30 10:46:04 +00:00
|
|
|
time.Sleep(1 * time.Second)
|
|
|
|
}
|
2016-06-29 16:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2014-07-24 21:50:11 +00:00
|
|
|
return obj
|
|
|
|
}
|
|
|
|
|
|
|
|
func testPut(t *testing.T, file *fstest.Item) {
|
2016-05-07 13:50:35 +00:00
|
|
|
again:
|
2014-07-24 21:50:11 +00:00
|
|
|
buf := bytes.NewBufferString(fstest.RandomString(100))
|
2016-01-17 11:27:31 +00:00
|
|
|
hash := fs.NewMultiHasher()
|
2014-07-24 21:50:11 +00:00
|
|
|
in := io.TeeReader(buf, hash)
|
|
|
|
|
2016-05-07 13:50:35 +00:00
|
|
|
tries := 1
|
|
|
|
const maxTries = 10
|
2014-07-24 21:50:11 +00:00
|
|
|
file.Size = int64(buf.Len())
|
2016-02-18 11:35:25 +00:00
|
|
|
obji := fs.NewStaticObjectInfo(file.Path, file.ModTime, file.Size, true, nil, nil)
|
|
|
|
obj, err := remote.Put(in, obji)
|
2014-07-24 21:50:11 +00:00
|
|
|
if err != nil {
|
2016-05-07 13:50:35 +00:00
|
|
|
// Retry if err returned a retry error
|
2016-07-04 10:57:30 +00:00
|
|
|
if fs.IsRetryError(err) && tries < maxTries {
|
2016-05-07 13:50:35 +00:00
|
|
|
t.Logf("Put error: %v - low level retry %d/%d", err, tries, maxTries)
|
2016-07-12 18:41:34 +00:00
|
|
|
time.Sleep(2 * time.Second)
|
2016-05-07 13:50:35 +00:00
|
|
|
|
|
|
|
tries++
|
|
|
|
goto again
|
|
|
|
}
|
2016-07-25 18:18:56 +00:00
|
|
|
require.NoError(t, err, fmt.Sprintf("Put error: %v", err))
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
2016-01-17 11:27:31 +00:00
|
|
|
file.Hashes = hash.Sums()
|
2014-08-01 16:58:39 +00:00
|
|
|
file.Check(t, obj, remote.Precision())
|
2014-07-24 21:50:11 +00:00
|
|
|
// Re-read the object and check again
|
|
|
|
obj = findObject(t, file.Path)
|
2014-08-01 16:58:39 +00:00
|
|
|
file.Check(t, obj, remote.Precision())
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestFsPutFile1 tests putting a file
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestFsPutFile1(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
|
|
|
testPut(t, &file1)
|
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestFsPutFile2 tests putting a file into a subdirectory
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestFsPutFile2(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
|
|
|
testPut(t, &file2)
|
|
|
|
}
|
|
|
|
|
2016-06-12 14:06:27 +00:00
|
|
|
// TestFsUpdateFile1 tests updating file1 with new contents
|
|
|
|
func TestFsUpdateFile1(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
|
|
|
testPut(t, &file1)
|
|
|
|
// Note that the next test will check there are no duplicated file names
|
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestFsListDirFile2 tests the files are correctly uploaded
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestFsListDirFile2(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
2016-05-07 13:50:35 +00:00
|
|
|
var objNames, dirNames []string
|
2016-01-20 20:06:05 +00:00
|
|
|
for i := 1; i <= eventualConsistencyRetries; i++ {
|
2016-05-07 13:50:35 +00:00
|
|
|
objs, dirs, err := fs.NewLister().SetLevel(1).Start(remote, "").GetAll()
|
2016-04-23 20:46:52 +00:00
|
|
|
require.NoError(t, err)
|
2016-05-07 13:50:35 +00:00
|
|
|
objNames = objsToNames(objs)
|
|
|
|
dirNames = dirsToNames(dirs)
|
|
|
|
if len(objNames) >= 1 && len(dirNames) >= 1 {
|
2016-01-20 20:06:05 +00:00
|
|
|
break
|
|
|
|
}
|
|
|
|
t.Logf("Sleeping for 1 second for TestFsListDirFile2 eventual consistency: %d/%d", i, eventualConsistencyRetries)
|
|
|
|
time.Sleep(1 * time.Second)
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
2016-05-07 13:50:35 +00:00
|
|
|
assert.Equal(t, []string{`hello_ sausage`}, dirNames)
|
|
|
|
assert.Equal(t, []string{file1.Path}, objNames)
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestFsListDirRoot tests that DirList works in the root
|
2014-07-31 20:24:52 +00:00
|
|
|
func TestFsListDirRoot(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
|
|
|
rootRemote, err := fs.NewFs(RemoteName)
|
2016-06-29 16:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2016-04-23 20:46:52 +00:00
|
|
|
dirs, err := fs.NewLister().SetLevel(1).Start(rootRemote, "").GetDirs()
|
|
|
|
require.NoError(t, err)
|
2016-05-07 13:50:35 +00:00
|
|
|
assert.Contains(t, dirsToNames(dirs), subRemoteLeaf, "Remote leaf not found")
|
2014-07-31 20:24:52 +00:00
|
|
|
}
|
|
|
|
|
2016-04-23 20:46:52 +00:00
|
|
|
// TestFsListSubdir tests List works for a subdirectory
|
|
|
|
func TestFsListSubdir(t *testing.T) {
|
2014-07-31 22:20:39 +00:00
|
|
|
skipIfNotOk(t)
|
2016-05-30 18:44:15 +00:00
|
|
|
fileName := file2.Path
|
2016-08-24 21:21:34 +00:00
|
|
|
var err error
|
|
|
|
var objs []fs.Object
|
|
|
|
var dirs []*fs.Dir
|
|
|
|
for i := 0; i < 2; i++ {
|
|
|
|
dir, _ := path.Split(fileName)
|
|
|
|
dir = dir[:len(dir)-1]
|
|
|
|
objs, dirs, err = fs.NewLister().Start(remote, dir).GetAll()
|
|
|
|
if err != fs.ErrorDirNotFound {
|
|
|
|
break
|
|
|
|
}
|
2016-05-30 18:44:15 +00:00
|
|
|
fileName = file2.WinPath
|
2014-07-31 22:20:39 +00:00
|
|
|
}
|
2016-05-30 18:44:15 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, objs, 1)
|
|
|
|
assert.Equal(t, fileName, objs[0].Remote())
|
|
|
|
require.Len(t, dirs, 0)
|
2014-07-31 22:20:39 +00:00
|
|
|
}
|
|
|
|
|
2016-05-07 13:50:35 +00:00
|
|
|
// TestFsListLevel2 tests List works for 2 levels
|
|
|
|
func TestFsListLevel2(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
|
|
|
objs, dirs, err := fs.NewLister().SetLevel(2).Start(remote, "").GetAll()
|
|
|
|
if err == fs.ErrorLevelNotSupported {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, []string{file1.Path}, objsToNames(objs))
|
|
|
|
assert.Equal(t, []string{`hello_ sausage`, `hello_ sausage/êé`}, dirsToNames(dirs))
|
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestFsListFile1 tests file present
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestFsListFile1(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
2014-08-01 16:58:39 +00:00
|
|
|
fstest.CheckListing(t, remote, []fstest.Item{file1, file2})
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
2016-06-25 20:58:34 +00:00
|
|
|
// TestFsNewObject tests NewObject
|
|
|
|
func TestFsNewObject(t *testing.T) {
|
2014-07-24 21:50:11 +00:00
|
|
|
skipIfNotOk(t)
|
|
|
|
obj := findObject(t, file1.Path)
|
2014-08-01 16:58:39 +00:00
|
|
|
file1.Check(t, obj, remote.Precision())
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestFsListFile1and2 tests two files present
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestFsListFile1and2(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
2014-08-01 16:58:39 +00:00
|
|
|
fstest.CheckListing(t, remote, []fstest.Item{file1, file2})
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestFsCopy tests Copy
|
2015-02-14 18:48:08 +00:00
|
|
|
func TestFsCopy(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
|
|
|
|
|
|
|
// Check have Copy
|
|
|
|
_, ok := remote.(fs.Copier)
|
|
|
|
if !ok {
|
|
|
|
t.Skip("FS has no Copier interface")
|
|
|
|
}
|
|
|
|
|
|
|
|
var file1Copy = file1
|
|
|
|
file1Copy.Path += "-copy"
|
|
|
|
|
|
|
|
// do the copy
|
|
|
|
src := findObject(t, file1.Path)
|
|
|
|
dst, err := remote.(fs.Copier).Copy(src, file1Copy.Path)
|
2016-07-25 18:18:56 +00:00
|
|
|
if err == fs.ErrorCantCopy {
|
|
|
|
t.Skip("FS can't copy")
|
|
|
|
}
|
|
|
|
require.NoError(t, err, fmt.Sprintf("Error: %#v", err))
|
2015-02-14 18:48:08 +00:00
|
|
|
|
|
|
|
// check file exists in new listing
|
|
|
|
fstest.CheckListing(t, remote, []fstest.Item{file1, file2, file1Copy})
|
|
|
|
|
2016-01-17 11:27:31 +00:00
|
|
|
// Check dst lightly - list above has checked ModTime/Hashes
|
2016-06-29 16:59:31 +00:00
|
|
|
assert.Equal(t, file1Copy.Path, dst.Remote())
|
2015-02-14 18:48:08 +00:00
|
|
|
|
|
|
|
// Delete copy
|
|
|
|
err = dst.Remove()
|
2016-06-29 16:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2015-02-14 18:48:08 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestFsMove tests Move
|
2015-08-31 20:05:51 +00:00
|
|
|
func TestFsMove(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
|
|
|
|
|
|
|
// Check have Move
|
|
|
|
_, ok := remote.(fs.Mover)
|
|
|
|
if !ok {
|
|
|
|
t.Skip("FS has no Mover interface")
|
|
|
|
}
|
|
|
|
|
|
|
|
var file1Move = file1
|
|
|
|
file1Move.Path += "-move"
|
|
|
|
|
|
|
|
// do the move
|
|
|
|
src := findObject(t, file1.Path)
|
|
|
|
dst, err := remote.(fs.Mover).Move(src, file1Move.Path)
|
2016-07-25 18:18:56 +00:00
|
|
|
if err == fs.ErrorCantMove {
|
|
|
|
t.Skip("FS can't move")
|
|
|
|
}
|
2016-06-29 16:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2015-08-31 20:05:51 +00:00
|
|
|
|
|
|
|
// check file exists in new listing
|
|
|
|
fstest.CheckListing(t, remote, []fstest.Item{file2, file1Move})
|
|
|
|
|
2016-01-17 11:27:31 +00:00
|
|
|
// Check dst lightly - list above has checked ModTime/Hashes
|
2016-06-29 16:59:31 +00:00
|
|
|
assert.Equal(t, file1Move.Path, dst.Remote())
|
2015-08-31 20:05:51 +00:00
|
|
|
|
|
|
|
// move it back
|
|
|
|
src = findObject(t, file1Move.Path)
|
|
|
|
_, err = remote.(fs.Mover).Move(src, file1.Path)
|
2016-06-29 16:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2015-08-31 20:05:51 +00:00
|
|
|
|
|
|
|
// check file exists in new listing
|
|
|
|
fstest.CheckListing(t, remote, []fstest.Item{file2, file1})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move src to this remote using server side move operations.
|
|
|
|
//
|
|
|
|
// Will only be called if src.Fs().Name() == f.Name()
|
|
|
|
//
|
|
|
|
// If it isn't possible then return fs.ErrorCantDirMove
|
|
|
|
//
|
|
|
|
// If destination exists then return fs.ErrorDirExists
|
2015-09-22 17:47:16 +00:00
|
|
|
|
|
|
|
// TestFsDirMove tests DirMove
|
2015-08-31 20:05:51 +00:00
|
|
|
func TestFsDirMove(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
|
|
|
|
|
|
|
// Check have DirMove
|
|
|
|
_, ok := remote.(fs.DirMover)
|
|
|
|
if !ok {
|
|
|
|
t.Skip("FS has no DirMover interface")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check it can't move onto itself
|
|
|
|
err := remote.(fs.DirMover).DirMove(remote)
|
2016-06-29 16:59:31 +00:00
|
|
|
require.Equal(t, fs.ErrorDirExists, err)
|
2015-08-31 20:05:51 +00:00
|
|
|
|
|
|
|
// new remote
|
2016-07-11 10:36:46 +00:00
|
|
|
newRemote, _, removeNewRemote, err := fstest.RandomRemote(RemoteName, false)
|
2016-06-29 16:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2015-08-31 20:05:51 +00:00
|
|
|
defer removeNewRemote()
|
|
|
|
|
|
|
|
// try the move
|
|
|
|
err = newRemote.(fs.DirMover).DirMove(remote)
|
2016-06-29 16:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2015-08-31 20:05:51 +00:00
|
|
|
|
|
|
|
// check remotes
|
2015-09-11 09:37:12 +00:00
|
|
|
// FIXME: Prints errors.
|
2015-08-31 20:05:51 +00:00
|
|
|
fstest.CheckListing(t, remote, []fstest.Item{})
|
|
|
|
fstest.CheckListing(t, newRemote, []fstest.Item{file2, file1})
|
|
|
|
|
|
|
|
// move it back
|
|
|
|
err = remote.(fs.DirMover).DirMove(newRemote)
|
2016-06-29 16:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2015-08-31 20:05:51 +00:00
|
|
|
|
|
|
|
// check remotes
|
|
|
|
fstest.CheckListing(t, remote, []fstest.Item{file2, file1})
|
|
|
|
fstest.CheckListing(t, newRemote, []fstest.Item{})
|
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestFsRmdirFull tests removing a non empty directory
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestFsRmdirFull(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
|
|
|
err := remote.Rmdir()
|
2016-06-29 16:59:31 +00:00
|
|
|
require.Error(t, err, "Expecting error on RMdir on non empty remote")
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestFsPrecision tests the Precision of the Fs
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestFsPrecision(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
|
|
|
precision := remote.Precision()
|
2015-08-16 22:24:34 +00:00
|
|
|
if precision == fs.ModTimeNotSupported {
|
|
|
|
return
|
|
|
|
}
|
2014-07-24 21:50:11 +00:00
|
|
|
if precision > time.Second || precision < 0 {
|
|
|
|
t.Fatalf("Precision out of range %v", precision)
|
|
|
|
}
|
|
|
|
// FIXME check expected precision
|
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestObjectString tests the Object String method
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestObjectString(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
|
|
|
obj := findObject(t, file1.Path)
|
2016-06-29 16:59:31 +00:00
|
|
|
assert.Equal(t, file1.Path, obj.String())
|
|
|
|
assert.Equal(t, "<nil>", NilObject.String())
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestObjectFs tests the object can be found
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestObjectFs(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
|
|
|
obj := findObject(t, file1.Path)
|
2016-06-29 16:59:31 +00:00
|
|
|
if obj.Fs() != remote {
|
2015-11-08 15:29:58 +00:00
|
|
|
// Check to see if this wraps something else
|
|
|
|
if unwrap, ok := remote.(fs.UnWrapper); ok {
|
2016-06-29 16:59:31 +00:00
|
|
|
remote = unwrap.UnWrap()
|
2015-11-08 15:29:58 +00:00
|
|
|
}
|
|
|
|
}
|
2016-06-29 16:59:31 +00:00
|
|
|
assert.Equal(t, obj.Fs(), remote)
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestObjectRemote tests the Remote is correct
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestObjectRemote(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
|
|
|
obj := findObject(t, file1.Path)
|
2016-06-29 16:59:31 +00:00
|
|
|
assert.Equal(t, file1.Path, obj.Remote())
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
2016-01-17 11:27:31 +00:00
|
|
|
// TestObjectHashes checks all the hashes the object supports
|
|
|
|
func TestObjectHashes(t *testing.T) {
|
2014-07-24 21:50:11 +00:00
|
|
|
skipIfNotOk(t)
|
|
|
|
obj := findObject(t, file1.Path)
|
2016-01-17 11:27:31 +00:00
|
|
|
file1.CheckHashes(t, obj)
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestObjectModTime tests the ModTime of the object is correct
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestObjectModTime(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
|
|
|
obj := findObject(t, file1.Path)
|
2014-08-01 16:58:39 +00:00
|
|
|
file1.CheckModTime(t, obj, obj.ModTime(), remote.Precision())
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestObjectSetModTime tests that SetModTime works
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestObjectSetModTime(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
|
|
|
newModTime := fstest.Time("2011-12-13T14:15:16.999999999Z")
|
|
|
|
obj := findObject(t, file1.Path)
|
2016-03-22 15:23:37 +00:00
|
|
|
err := obj.SetModTime(newModTime)
|
|
|
|
if err == fs.ErrorCantSetModTime {
|
|
|
|
t.Log(err)
|
|
|
|
return
|
|
|
|
}
|
2016-06-29 16:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2014-07-24 21:50:11 +00:00
|
|
|
file1.ModTime = newModTime
|
2015-01-04 16:57:55 +00:00
|
|
|
file1.CheckModTime(t, obj, obj.ModTime(), remote.Precision())
|
2014-07-24 21:50:11 +00:00
|
|
|
// And make a new object and read it from there too
|
|
|
|
TestObjectModTime(t)
|
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestObjectSize tests that Size works
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestObjectSize(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
|
|
|
obj := findObject(t, file1.Path)
|
2016-06-29 16:59:31 +00:00
|
|
|
assert.Equal(t, file1.Size, obj.Size())
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestObjectOpen tests that Open works
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestObjectOpen(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
|
|
|
obj := findObject(t, file1.Path)
|
|
|
|
in, err := obj.Open()
|
2016-06-29 16:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2016-01-17 11:27:31 +00:00
|
|
|
hasher := fs.NewMultiHasher()
|
|
|
|
n, err := io.Copy(hasher, in)
|
2016-07-25 18:18:56 +00:00
|
|
|
require.NoError(t, err, fmt.Sprintf("hasher copy error: %v", err))
|
2016-06-29 16:59:31 +00:00
|
|
|
require.Equal(t, file1.Size, n, "Read wrong number of bytes")
|
2014-07-24 21:50:11 +00:00
|
|
|
err = in.Close()
|
2016-06-29 16:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2016-01-17 11:27:31 +00:00
|
|
|
// Check content of file by comparing the calculated hashes
|
|
|
|
for hashType, got := range hasher.Sums() {
|
2016-06-29 16:59:31 +00:00
|
|
|
assert.Equal(t, file1.Hashes[hashType], got)
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
2016-01-17 11:27:31 +00:00
|
|
|
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestObjectUpdate tests that Update works
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestObjectUpdate(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
|
|
|
buf := bytes.NewBufferString(fstest.RandomString(200))
|
2016-01-17 11:27:31 +00:00
|
|
|
hash := fs.NewMultiHasher()
|
2014-07-24 21:50:11 +00:00
|
|
|
in := io.TeeReader(buf, hash)
|
|
|
|
|
|
|
|
file1.Size = int64(buf.Len())
|
|
|
|
obj := findObject(t, file1.Path)
|
2016-08-05 22:42:49 +00:00
|
|
|
obji := fs.NewStaticObjectInfo(file1.Path, file1.ModTime, file1.Size, true, nil, obj.Fs())
|
2016-02-18 11:35:25 +00:00
|
|
|
err := obj.Update(in, obji)
|
2016-06-29 16:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2016-01-17 11:27:31 +00:00
|
|
|
file1.Hashes = hash.Sums()
|
2014-08-01 16:58:39 +00:00
|
|
|
file1.Check(t, obj, remote.Precision())
|
2014-07-24 21:50:11 +00:00
|
|
|
// Re-read the object and check again
|
|
|
|
obj = findObject(t, file1.Path)
|
2014-08-01 16:58:39 +00:00
|
|
|
file1.Check(t, obj, remote.Precision())
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestObjectStorable tests that Storable works
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestObjectStorable(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
|
|
|
obj := findObject(t, file1.Path)
|
2016-06-29 16:59:31 +00:00
|
|
|
require.NotNil(t, !obj.Storable(), "Expecting object to be storable")
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
2016-06-21 17:01:53 +00:00
|
|
|
// TestFsIsFile tests that an error is returned along with a valid fs
|
|
|
|
// which points to the parent directory.
|
|
|
|
func TestFsIsFile(t *testing.T) {
|
2014-07-31 20:24:52 +00:00
|
|
|
skipIfNotOk(t)
|
|
|
|
remoteName := subRemoteName + "/" + file2.Path
|
|
|
|
file2Copy := file2
|
|
|
|
file2Copy.Path = "z.txt"
|
|
|
|
fileRemote, err := fs.NewFs(remoteName)
|
2016-06-21 17:01:53 +00:00
|
|
|
assert.Equal(t, fs.ErrorIsFile, err)
|
2014-08-01 16:58:39 +00:00
|
|
|
fstest.CheckListing(t, fileRemote, []fstest.Item{file2Copy})
|
2014-07-31 20:24:52 +00:00
|
|
|
}
|
|
|
|
|
2016-06-21 17:01:53 +00:00
|
|
|
// TestFsIsFileNotFound tests that an error is not returned if no object is found
|
|
|
|
func TestFsIsFileNotFound(t *testing.T) {
|
2014-07-31 20:24:52 +00:00
|
|
|
skipIfNotOk(t)
|
|
|
|
remoteName := subRemoteName + "/not found.txt"
|
|
|
|
fileRemote, err := fs.NewFs(remoteName)
|
2016-06-29 16:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2014-08-01 16:58:39 +00:00
|
|
|
fstest.CheckListing(t, fileRemote, []fstest.Item{})
|
2014-07-31 20:24:52 +00:00
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestObjectRemove tests Remove
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestObjectRemove(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
|
|
|
obj := findObject(t, file1.Path)
|
|
|
|
err := obj.Remove()
|
2016-06-29 16:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2014-08-01 16:58:39 +00:00
|
|
|
fstest.CheckListing(t, remote, []fstest.Item{file2})
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestObjectPurge tests Purge
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestObjectPurge(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
2014-08-01 16:58:39 +00:00
|
|
|
fstest.TestPurge(t, remote)
|
2014-07-28 20:02:00 +00:00
|
|
|
err := fs.Purge(remote)
|
2016-06-29 16:59:31 +00:00
|
|
|
assert.Error(t, err, "Expecting error after on second purge")
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
|
2015-09-22 17:47:16 +00:00
|
|
|
// TestFinalise tidies up after the previous tests
|
2014-07-24 21:50:11 +00:00
|
|
|
func TestFinalise(t *testing.T) {
|
|
|
|
skipIfNotOk(t)
|
2014-07-31 20:24:52 +00:00
|
|
|
if strings.HasPrefix(RemoteName, "/") {
|
|
|
|
// Remove temp directory
|
|
|
|
err := os.Remove(RemoteName)
|
2016-06-29 16:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2014-07-24 21:50:11 +00:00
|
|
|
}
|
|
|
|
}
|