2020-04-09 23:43:34 +08:00
|
|
|
package crypt
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"context"
|
|
|
|
"crypto/md5"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/rclone/rclone/fs"
|
|
|
|
"github.com/rclone/rclone/fs/hash"
|
|
|
|
"github.com/rclone/rclone/fs/object"
|
|
|
|
"github.com/rclone/rclone/lib/random"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Create a temporary local fs to upload things from
|
|
|
|
|
2022-12-08 20:43:53 +08:00
|
|
|
func makeTempLocalFs(t *testing.T) (localFs fs.Fs) {
|
2020-11-05 23:18:51 +08:00
|
|
|
localFs, err := fs.TemporaryLocalFs(context.Background())
|
2020-04-09 23:43:34 +08:00
|
|
|
require.NoError(t, err)
|
2022-12-08 20:43:53 +08:00
|
|
|
t.Cleanup(func() {
|
2020-04-09 23:43:34 +08:00
|
|
|
require.NoError(t, localFs.Rmdir(context.Background(), ""))
|
2022-12-08 20:43:53 +08:00
|
|
|
})
|
|
|
|
return localFs
|
2020-04-09 23:43:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Upload a file to a remote
|
2022-12-08 20:43:53 +08:00
|
|
|
func uploadFile(t *testing.T, f fs.Fs, remote, contents string) (obj fs.Object) {
|
2020-04-09 23:43:34 +08:00
|
|
|
inBuf := bytes.NewBufferString(contents)
|
|
|
|
t1 := time.Date(2012, time.December, 17, 18, 32, 31, 0, time.UTC)
|
|
|
|
upSrc := object.NewStaticObjectInfo(remote, t1, int64(len(contents)), true, nil, nil)
|
|
|
|
obj, err := f.Put(context.Background(), inBuf, upSrc)
|
|
|
|
require.NoError(t, err)
|
2022-12-08 20:43:53 +08:00
|
|
|
t.Cleanup(func() {
|
2020-04-09 23:43:34 +08:00
|
|
|
require.NoError(t, obj.Remove(context.Background()))
|
2022-12-08 20:43:53 +08:00
|
|
|
})
|
|
|
|
return obj
|
2020-04-09 23:43:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Test the ObjectInfo
|
|
|
|
func testObjectInfo(t *testing.T, f *Fs, wrap bool) {
|
|
|
|
var (
|
|
|
|
contents = random.String(100)
|
|
|
|
path = "hash_test_object"
|
|
|
|
ctx = context.Background()
|
|
|
|
)
|
|
|
|
if wrap {
|
|
|
|
path = "_wrap"
|
|
|
|
}
|
|
|
|
|
2022-12-08 20:43:53 +08:00
|
|
|
localFs := makeTempLocalFs(t)
|
2020-04-09 23:43:34 +08:00
|
|
|
|
2022-12-08 20:43:53 +08:00
|
|
|
obj := uploadFile(t, localFs, path, contents)
|
2020-04-09 23:43:34 +08:00
|
|
|
|
|
|
|
// encrypt the data
|
|
|
|
inBuf := bytes.NewBufferString(contents)
|
|
|
|
var outBuf bytes.Buffer
|
|
|
|
enc, err := f.cipher.newEncrypter(inBuf, nil)
|
|
|
|
require.NoError(t, err)
|
|
|
|
nonce := enc.nonce // read the nonce at the start
|
|
|
|
_, err = io.Copy(&outBuf, enc)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
var oi fs.ObjectInfo = obj
|
|
|
|
if wrap {
|
2020-05-20 18:39:20 +08:00
|
|
|
// wrap the object in an fs.ObjectUnwrapper if required
|
2022-08-06 23:32:58 +08:00
|
|
|
oi = fs.NewOverrideRemote(oi, "new_remote")
|
2020-04-09 23:43:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// wrap the object in a crypt for upload using the nonce we
|
Spelling fixes
Fix spelling of: above, already, anonymous, associated,
authentication, bandwidth, because, between, blocks, calculate,
candidates, cautious, changelog, cleaner, clipboard, command,
completely, concurrently, considered, constructs, corrupt, current,
daemon, dependencies, deprecated, directory, dispatcher, download,
eligible, ellipsis, encrypter, endpoint, entrieslist, essentially,
existing writers, existing, expires, filesystem, flushing, frequently,
hierarchy, however, implementation, implements, inaccurate,
individually, insensitive, longer, maximum, metadata, modified,
multipart, namedirfirst, nextcloud, obscured, opened, optional,
owncloud, pacific, passphrase, password, permanently, persimmon,
positive, potato, protocol, quota, receiving, recommends, referring,
requires, revisited, satisfied, satisfies, satisfy, semver,
serialized, session, storage, strategies, stringlist, successful,
supported, surprise, temporarily, temporary, transactions, unneeded,
update, uploads, wrapped
Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
2020-10-09 08:17:24 +08:00
|
|
|
// saved from the encrypter
|
2020-04-09 23:43:34 +08:00
|
|
|
src := f.newObjectInfo(oi, nonce)
|
|
|
|
|
|
|
|
// Test ObjectInfo methods
|
2022-06-29 21:29:00 +08:00
|
|
|
if !f.opt.NoDataEncryption {
|
|
|
|
assert.Equal(t, int64(outBuf.Len()), src.Size())
|
|
|
|
}
|
2020-04-09 23:43:34 +08:00
|
|
|
assert.Equal(t, f, src.Fs())
|
|
|
|
assert.NotEqual(t, path, src.Remote())
|
|
|
|
|
|
|
|
// Test ObjectInfo.Hash
|
|
|
|
wantHash := md5.Sum(outBuf.Bytes())
|
|
|
|
gotHash, err := src.Hash(ctx, hash.MD5)
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, fmt.Sprintf("%x", wantHash), gotHash)
|
|
|
|
}
|
|
|
|
|
|
|
|
func testComputeHash(t *testing.T, f *Fs) {
|
|
|
|
var (
|
|
|
|
contents = random.String(100)
|
|
|
|
path = "compute_hash_test"
|
|
|
|
ctx = context.Background()
|
|
|
|
hashType = f.Fs.Hashes().GetOne()
|
|
|
|
)
|
|
|
|
|
|
|
|
if hashType == hash.None {
|
|
|
|
t.Skipf("%v: does not support hashes", f.Fs)
|
|
|
|
}
|
|
|
|
|
2022-12-08 20:43:53 +08:00
|
|
|
localFs := makeTempLocalFs(t)
|
2020-04-09 23:43:34 +08:00
|
|
|
|
|
|
|
// Upload a file to localFs as a test object
|
2022-12-08 20:43:53 +08:00
|
|
|
localObj := uploadFile(t, localFs, path, contents)
|
2020-04-09 23:43:34 +08:00
|
|
|
|
|
|
|
// Upload the same data to the remote Fs also
|
2022-12-08 20:43:53 +08:00
|
|
|
remoteObj := uploadFile(t, f, path, contents)
|
2020-04-09 23:43:34 +08:00
|
|
|
|
|
|
|
// Calculate the expected Hash of the remote object
|
|
|
|
computedHash, err := f.ComputeHash(ctx, remoteObj.(*Object), localObj, hashType)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Test computed hash matches remote object hash
|
|
|
|
remoteObjHash, err := remoteObj.(*Object).Object.Hash(ctx, hashType)
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, remoteObjHash, computedHash)
|
|
|
|
}
|
|
|
|
|
|
|
|
// InternalTest is called by fstests.Run to extra tests
|
|
|
|
func (f *Fs) InternalTest(t *testing.T) {
|
|
|
|
t.Run("ObjectInfo", func(t *testing.T) { testObjectInfo(t, f, false) })
|
|
|
|
t.Run("ObjectInfoWrap", func(t *testing.T) { testObjectInfo(t, f, true) })
|
|
|
|
t.Run("ComputeHash", func(t *testing.T) { testComputeHash(t, f) })
|
|
|
|
}
|