mirror of
https://github.com/rclone/rclone.git
synced 2025-07-04 14:30:18 +02:00
.github
backend
alias
all
azureblob
azurefiles
b2
box
cache
chunker
combine
compress
crypt
drive
dropbox
fichier
filefabric
ftp
googlecloudstorage
googlephotos
hasher
hdfs
hidrive
http
imagekit
internetarchive
jottacloud
koofr
linkbox
local
mailru
mega
memory
netstorage
onedrive
opendrive
oracleobjectstorage
pcloud
pikpak
premiumizeme
protondrive
putio
qingstor
quatrix
s3
seafile
sftp
sharefile
sia
smb
storj
sugarsync
swift
auth.go
swift.go
swift_internal_test.go
swift_test.go
union
uptobox
webdav
yandex
zoho
bin
cmd
cmdtest
contrib
docs
fs
fstest
graphics
lib
librclone
vfs
.gitattributes
.gitignore
.golangci.yml
CONTRIBUTING.md
COPYING
Dockerfile
MAINTAINERS.md
MANUAL.html
MANUAL.md
MANUAL.txt
Makefile
README.md
RELEASE.md
VERSION
go.mod
go.sum
notes.txt
rclone.1
rclone.go
As of Go 1.16, the same functionality is now provided by package io or package os, and those implementations should be preferred in new code.
193 lines
5.4 KiB
Go
193 lines
5.4 KiB
Go
// Test Swift filesystem interface
|
|
package swift
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"errors"
|
|
"io"
|
|
"testing"
|
|
|
|
"github.com/ncw/swift/v2"
|
|
"github.com/rclone/rclone/fs"
|
|
"github.com/rclone/rclone/fs/hash"
|
|
"github.com/rclone/rclone/fs/object"
|
|
"github.com/rclone/rclone/fstest"
|
|
"github.com/rclone/rclone/fstest/fstests"
|
|
"github.com/rclone/rclone/lib/random"
|
|
"github.com/rclone/rclone/lib/readers"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// TestIntegration runs integration tests against the remote
|
|
func TestIntegration(t *testing.T) {
|
|
fstests.Run(t, &fstests.Opt{
|
|
RemoteName: "TestSwiftAIO:",
|
|
NilObject: (*Object)(nil),
|
|
})
|
|
}
|
|
|
|
func (f *Fs) SetUploadChunkSize(cs fs.SizeSuffix) (fs.SizeSuffix, error) {
|
|
return f.setUploadChunkSize(cs)
|
|
}
|
|
|
|
var _ fstests.SetUploadChunkSizer = (*Fs)(nil)
|
|
|
|
// Check that PutStream works with NoChunk as it is the major code
|
|
// deviation
|
|
func (f *Fs) testNoChunk(t *testing.T) {
|
|
ctx := context.Background()
|
|
f.opt.NoChunk = true
|
|
defer func() {
|
|
f.opt.NoChunk = false
|
|
}()
|
|
|
|
file := fstest.Item{
|
|
ModTime: fstest.Time("2001-02-03T04:05:06.499999999Z"),
|
|
Path: "piped data no chunk.txt",
|
|
Size: -1, // use unknown size during upload
|
|
}
|
|
|
|
const contentSize = 100
|
|
|
|
contents := random.String(contentSize)
|
|
buf := bytes.NewBufferString(contents)
|
|
uploadHash := hash.NewMultiHasher()
|
|
in := io.TeeReader(buf, uploadHash)
|
|
|
|
file.Size = -1
|
|
obji := object.NewStaticObjectInfo(file.Path, file.ModTime, file.Size, true, nil, nil)
|
|
obj, err := f.Features().PutStream(ctx, in, obji)
|
|
require.NoError(t, err)
|
|
|
|
file.Hashes = uploadHash.Sums()
|
|
file.Size = int64(contentSize) // use correct size when checking
|
|
file.Check(t, obj, f.Precision())
|
|
|
|
// Re-read the object and check again
|
|
obj, err = f.NewObject(ctx, file.Path)
|
|
require.NoError(t, err)
|
|
file.Check(t, obj, f.Precision())
|
|
|
|
// Delete the object
|
|
assert.NoError(t, obj.Remove(ctx))
|
|
}
|
|
|
|
// Additional tests that aren't in the framework
|
|
func (f *Fs) InternalTest(t *testing.T) {
|
|
t.Run("NoChunk", f.testNoChunk)
|
|
t.Run("WithChunk", f.testWithChunk)
|
|
t.Run("WithChunkFail", f.testWithChunkFail)
|
|
t.Run("CopyLargeObject", f.testCopyLargeObject)
|
|
}
|
|
|
|
func (f *Fs) testWithChunk(t *testing.T) {
|
|
preConfChunkSize := f.opt.ChunkSize
|
|
preConfChunk := f.opt.NoChunk
|
|
f.opt.NoChunk = false
|
|
f.opt.ChunkSize = 1024 * fs.SizeSuffixBase
|
|
defer func() {
|
|
//restore old config after test
|
|
f.opt.ChunkSize = preConfChunkSize
|
|
f.opt.NoChunk = preConfChunk
|
|
}()
|
|
|
|
file := fstest.Item{
|
|
ModTime: fstest.Time("2020-12-31T04:05:06.499999999Z"),
|
|
Path: "piped data chunk.txt",
|
|
Size: -1, // use unknown size during upload
|
|
}
|
|
const contentSize = 2048
|
|
contents := random.String(contentSize)
|
|
buf := bytes.NewBufferString(contents)
|
|
uploadHash := hash.NewMultiHasher()
|
|
in := io.TeeReader(buf, uploadHash)
|
|
|
|
file.Size = -1
|
|
obji := object.NewStaticObjectInfo(file.Path, file.ModTime, file.Size, true, nil, nil)
|
|
ctx := context.TODO()
|
|
obj, err := f.Features().PutStream(ctx, in, obji)
|
|
require.NoError(t, err)
|
|
require.NotEmpty(t, obj)
|
|
}
|
|
|
|
func (f *Fs) testWithChunkFail(t *testing.T) {
|
|
preConfChunkSize := f.opt.ChunkSize
|
|
preConfChunk := f.opt.NoChunk
|
|
f.opt.NoChunk = false
|
|
f.opt.ChunkSize = 1024 * fs.SizeSuffixBase
|
|
segmentContainer := f.root + "_segments"
|
|
defer func() {
|
|
//restore config
|
|
f.opt.ChunkSize = preConfChunkSize
|
|
f.opt.NoChunk = preConfChunk
|
|
}()
|
|
path := "piped data chunk with error.txt"
|
|
file := fstest.Item{
|
|
ModTime: fstest.Time("2021-01-04T03:46:00.499999999Z"),
|
|
Path: path,
|
|
Size: -1, // use unknown size during upload
|
|
}
|
|
const contentSize = 4096
|
|
const errPosition = 3072
|
|
contents := random.String(contentSize)
|
|
buf := bytes.NewBufferString(contents[:errPosition])
|
|
errMessage := "potato"
|
|
er := &readers.ErrorReader{Err: errors.New(errMessage)}
|
|
in := io.NopCloser(io.MultiReader(buf, er))
|
|
|
|
file.Size = contentSize
|
|
obji := object.NewStaticObjectInfo(file.Path, file.ModTime, file.Size, true, nil, nil)
|
|
ctx := context.TODO()
|
|
_, err := f.Features().PutStream(ctx, in, obji)
|
|
// error is potato
|
|
require.NotNil(t, err)
|
|
require.Equal(t, errMessage, err.Error())
|
|
_, _, err = f.c.Object(ctx, f.rootContainer, path)
|
|
assert.Equal(t, swift.ObjectNotFound, err)
|
|
prefix := path
|
|
objs, err := f.c.Objects(ctx, segmentContainer, &swift.ObjectsOpts{
|
|
Prefix: prefix,
|
|
})
|
|
require.NoError(t, err)
|
|
require.Empty(t, objs)
|
|
}
|
|
|
|
func (f *Fs) testCopyLargeObject(t *testing.T) {
|
|
preConfChunkSize := f.opt.ChunkSize
|
|
preConfChunk := f.opt.NoChunk
|
|
f.opt.NoChunk = false
|
|
f.opt.ChunkSize = 1024 * fs.SizeSuffixBase
|
|
defer func() {
|
|
//restore old config after test
|
|
f.opt.ChunkSize = preConfChunkSize
|
|
f.opt.NoChunk = preConfChunk
|
|
}()
|
|
|
|
file := fstest.Item{
|
|
ModTime: fstest.Time("2020-12-31T04:05:06.499999999Z"),
|
|
Path: "large.txt",
|
|
Size: -1, // use unknown size during upload
|
|
}
|
|
const contentSize = 2048
|
|
contents := random.String(contentSize)
|
|
buf := bytes.NewBufferString(contents)
|
|
uploadHash := hash.NewMultiHasher()
|
|
in := io.TeeReader(buf, uploadHash)
|
|
|
|
file.Size = -1
|
|
obji := object.NewStaticObjectInfo(file.Path, file.ModTime, file.Size, true, nil, nil)
|
|
ctx := context.TODO()
|
|
obj, err := f.Features().PutStream(ctx, in, obji)
|
|
require.NoError(t, err)
|
|
require.NotEmpty(t, obj)
|
|
remoteTarget := "large.txt (copy)"
|
|
objTarget, err := f.Features().Copy(ctx, obj, remoteTarget)
|
|
require.NoError(t, err)
|
|
require.NotEmpty(t, objTarget)
|
|
require.Equal(t, obj.Size(), objTarget.Size())
|
|
}
|
|
|
|
var _ fstests.InternalTester = (*Fs)(nil)
|