mirror of https://github.com/rclone/rclone.git
fstest: add tests for coverage of optional methods for wrapping Fs
This commit is contained in:
parent
16d8014cbb
commit
2f21aa86b4
29
fs/fs.go
29
fs/fs.go
|
@ -370,6 +370,35 @@ type GetTierer interface {
|
||||||
GetTier() string
|
GetTier() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ObjectOptionalInterfaces returns the names of supported and
|
||||||
|
// unsupported optional interfaces for an Object
|
||||||
|
func ObjectOptionalInterfaces(o Object) (supported, unsupported []string) {
|
||||||
|
store := func(ok bool, name string) {
|
||||||
|
if ok {
|
||||||
|
supported = append(supported, name)
|
||||||
|
} else {
|
||||||
|
unsupported = append(unsupported, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok := o.(MimeTyper)
|
||||||
|
store(ok, "MimeType")
|
||||||
|
|
||||||
|
_, ok = o.(IDer)
|
||||||
|
store(ok, "ID")
|
||||||
|
|
||||||
|
_, ok = o.(ObjectUnWrapper)
|
||||||
|
store(ok, "UnWrap")
|
||||||
|
|
||||||
|
_, ok = o.(SetTierer)
|
||||||
|
store(ok, "SetTier")
|
||||||
|
|
||||||
|
_, ok = o.(GetTierer)
|
||||||
|
store(ok, "GetTier")
|
||||||
|
|
||||||
|
return supported, unsupported
|
||||||
|
}
|
||||||
|
|
||||||
// ListRCallback defines a callback function for ListR to use
|
// ListRCallback defines a callback function for ListR to use
|
||||||
//
|
//
|
||||||
// It is called for each tranche of entries read from the listing and
|
// It is called for each tranche of entries read from the listing and
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -241,13 +242,27 @@ type ExtraConfigItem struct{ Name, Key, Value string }
|
||||||
|
|
||||||
// Opt is options for Run
|
// Opt is options for Run
|
||||||
type Opt struct {
|
type Opt struct {
|
||||||
RemoteName string
|
RemoteName string
|
||||||
NilObject fs.Object
|
NilObject fs.Object
|
||||||
ExtraConfig []ExtraConfigItem
|
ExtraConfig []ExtraConfigItem
|
||||||
SkipBadWindowsCharacters bool // skips unusable characters for windows if set
|
SkipBadWindowsCharacters bool // skips unusable characters for windows if set
|
||||||
SkipFsMatch bool // if set skip exact matching of Fs value
|
SkipFsMatch bool // if set skip exact matching of Fs value
|
||||||
TiersToTest []string // List of tiers which can be tested in setTier test
|
TiersToTest []string // List of tiers which can be tested in setTier test
|
||||||
ChunkedUpload ChunkedUploadConfig
|
ChunkedUpload ChunkedUploadConfig
|
||||||
|
UnimplementableFsMethods []string // List of methods which can't be implemented in this wrapping Fs
|
||||||
|
UnimplementableObjectMethods []string // List of methods which can't be implemented in this wrapping Fs
|
||||||
|
SkipFsCheckWrap bool // if set skip FsCheckWrap
|
||||||
|
SkipObjectCheckWrap bool // if set skip ObjectCheckWrap
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns true if x is found in ss
|
||||||
|
func stringsContains(x string, ss []string) bool {
|
||||||
|
for _, s := range ss {
|
||||||
|
if x == s {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the basic integration tests for a remote using the options passed in.
|
// Run runs the basic integration tests for a remote using the options passed in.
|
||||||
|
@ -360,6 +375,34 @@ func Run(t *testing.T, opt *Opt) {
|
||||||
// Skip the rest if it failed
|
// Skip the rest if it failed
|
||||||
skipIfNotOk(t)
|
skipIfNotOk(t)
|
||||||
|
|
||||||
|
// Check to see if Fs that wrap other Fs implement all the optional methods
|
||||||
|
t.Run("FsCheckWrap", func(t *testing.T) {
|
||||||
|
skipIfNotOk(t)
|
||||||
|
if opt.SkipFsCheckWrap {
|
||||||
|
t.Skip("Skipping FsCheckWrap on this Fs")
|
||||||
|
}
|
||||||
|
ft := new(fs.Features).Fill(remote)
|
||||||
|
if ft.UnWrap == nil {
|
||||||
|
t.Skip("Not a wrapping Fs")
|
||||||
|
}
|
||||||
|
v := reflect.ValueOf(ft).Elem()
|
||||||
|
vType := v.Type()
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
vName := vType.Field(i).Name
|
||||||
|
if stringsContains(vName, opt.UnimplementableFsMethods) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
field := v.Field(i)
|
||||||
|
// skip the bools
|
||||||
|
if field.Type().Kind() == reflect.Bool {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if field.IsNil() {
|
||||||
|
t.Errorf("Missing Fs wrapper for %s", vName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// TestFsRmdirNotFound tests deleting a non existent directory
|
// TestFsRmdirNotFound tests deleting a non existent directory
|
||||||
t.Run("FsRmdirNotFound", func(t *testing.T) {
|
t.Run("FsRmdirNotFound", func(t *testing.T) {
|
||||||
skipIfNotOk(t)
|
skipIfNotOk(t)
|
||||||
|
@ -1367,6 +1410,25 @@ func Run(t *testing.T, opt *Opt) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Check to see if Fs that wrap other Objects implement all the optional methods
|
||||||
|
t.Run("ObjectCheckWrap", func(t *testing.T) {
|
||||||
|
skipIfNotOk(t)
|
||||||
|
if opt.SkipObjectCheckWrap {
|
||||||
|
t.Skip("Skipping FsCheckWrap on this Fs")
|
||||||
|
}
|
||||||
|
ft := new(fs.Features).Fill(remote)
|
||||||
|
if ft.UnWrap == nil {
|
||||||
|
t.Skip("Not a wrapping Fs")
|
||||||
|
}
|
||||||
|
obj := findObject(t, remote, file1.Path)
|
||||||
|
_, unsupported := fs.ObjectOptionalInterfaces(obj)
|
||||||
|
for _, name := range unsupported {
|
||||||
|
if !stringsContains(name, opt.UnimplementableObjectMethods) {
|
||||||
|
t.Errorf("Missing Object wrapper for %s", name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// TestObjectRemove tests Remove
|
// TestObjectRemove tests Remove
|
||||||
t.Run("ObjectRemove", func(t *testing.T) {
|
t.Run("ObjectRemove", func(t *testing.T) {
|
||||||
skipIfNotOk(t)
|
skipIfNotOk(t)
|
||||||
|
|
Loading…
Reference in New Issue