github.com/10XDev/rclone@v1.52.3-0.20200626220027-16af9ab76b2a/backend/crypt/crypt_internal_test.go (about) 1 package crypt 2 3 import ( 4 "bytes" 5 "context" 6 "crypto/md5" 7 "fmt" 8 "io" 9 "testing" 10 "time" 11 12 "github.com/rclone/rclone/fs" 13 "github.com/rclone/rclone/fs/hash" 14 "github.com/rclone/rclone/fs/object" 15 "github.com/rclone/rclone/lib/random" 16 "github.com/stretchr/testify/assert" 17 "github.com/stretchr/testify/require" 18 ) 19 20 type testWrapper struct { 21 fs.ObjectInfo 22 } 23 24 // UnWrap returns the Object that this Object is wrapping or nil if it 25 // isn't wrapping anything 26 func (o testWrapper) UnWrap() fs.Object { 27 if o, ok := o.ObjectInfo.(fs.Object); ok { 28 return o 29 } 30 return nil 31 } 32 33 // Create a temporary local fs to upload things from 34 35 func makeTempLocalFs(t *testing.T) (localFs fs.Fs, cleanup func()) { 36 localFs, err := fs.TemporaryLocalFs() 37 require.NoError(t, err) 38 cleanup = func() { 39 require.NoError(t, localFs.Rmdir(context.Background(), "")) 40 } 41 return localFs, cleanup 42 } 43 44 // Upload a file to a remote 45 func uploadFile(t *testing.T, f fs.Fs, remote, contents string) (obj fs.Object, cleanup func()) { 46 inBuf := bytes.NewBufferString(contents) 47 t1 := time.Date(2012, time.December, 17, 18, 32, 31, 0, time.UTC) 48 upSrc := object.NewStaticObjectInfo(remote, t1, int64(len(contents)), true, nil, nil) 49 obj, err := f.Put(context.Background(), inBuf, upSrc) 50 require.NoError(t, err) 51 cleanup = func() { 52 require.NoError(t, obj.Remove(context.Background())) 53 } 54 return obj, cleanup 55 } 56 57 // Test the ObjectInfo 58 func testObjectInfo(t *testing.T, f *Fs, wrap bool) { 59 var ( 60 contents = random.String(100) 61 path = "hash_test_object" 62 ctx = context.Background() 63 ) 64 if wrap { 65 path = "_wrap" 66 } 67 68 localFs, cleanupLocalFs := makeTempLocalFs(t) 69 defer cleanupLocalFs() 70 71 obj, cleanupObj := uploadFile(t, localFs, path, contents) 72 defer cleanupObj() 73 74 // encrypt the data 75 inBuf := bytes.NewBufferString(contents) 76 var outBuf bytes.Buffer 77 enc, err := f.cipher.newEncrypter(inBuf, nil) 78 require.NoError(t, err) 79 nonce := enc.nonce // read the nonce at the start 80 _, err = io.Copy(&outBuf, enc) 81 require.NoError(t, err) 82 83 var oi fs.ObjectInfo = obj 84 if wrap { 85 // wrap the object in an fs.ObjectUnwrapper if required 86 oi = testWrapper{oi} 87 } 88 89 // wrap the object in a crypt for upload using the nonce we 90 // saved from the encryptor 91 src := f.newObjectInfo(oi, nonce) 92 93 // Test ObjectInfo methods 94 assert.Equal(t, int64(outBuf.Len()), src.Size()) 95 assert.Equal(t, f, src.Fs()) 96 assert.NotEqual(t, path, src.Remote()) 97 98 // Test ObjectInfo.Hash 99 wantHash := md5.Sum(outBuf.Bytes()) 100 gotHash, err := src.Hash(ctx, hash.MD5) 101 require.NoError(t, err) 102 assert.Equal(t, fmt.Sprintf("%x", wantHash), gotHash) 103 } 104 105 func testComputeHash(t *testing.T, f *Fs) { 106 var ( 107 contents = random.String(100) 108 path = "compute_hash_test" 109 ctx = context.Background() 110 hashType = f.Fs.Hashes().GetOne() 111 ) 112 113 if hashType == hash.None { 114 t.Skipf("%v: does not support hashes", f.Fs) 115 } 116 117 localFs, cleanupLocalFs := makeTempLocalFs(t) 118 defer cleanupLocalFs() 119 120 // Upload a file to localFs as a test object 121 localObj, cleanupLocalObj := uploadFile(t, localFs, path, contents) 122 defer cleanupLocalObj() 123 124 // Upload the same data to the remote Fs also 125 remoteObj, cleanupRemoteObj := uploadFile(t, f, path, contents) 126 defer cleanupRemoteObj() 127 128 // Calculate the expected Hash of the remote object 129 computedHash, err := f.ComputeHash(ctx, remoteObj.(*Object), localObj, hashType) 130 require.NoError(t, err) 131 132 // Test computed hash matches remote object hash 133 remoteObjHash, err := remoteObj.(*Object).Object.Hash(ctx, hashType) 134 require.NoError(t, err) 135 assert.Equal(t, remoteObjHash, computedHash) 136 } 137 138 // InternalTest is called by fstests.Run to extra tests 139 func (f *Fs) InternalTest(t *testing.T) { 140 t.Run("ObjectInfo", func(t *testing.T) { testObjectInfo(t, f, false) }) 141 t.Run("ObjectInfoWrap", func(t *testing.T) { testObjectInfo(t, f, true) }) 142 t.Run("ComputeHash", func(t *testing.T) { testComputeHash(t, f) }) 143 }