Fix region setting in presigned url functions (#107)

- Also split out live server tests into individual functions
This commit is contained in:
Aditya Manthramurthy 2019-02-26 15:45:36 -08:00 committed by GitHub
parent c8a32ad217
commit 0fc264bbc2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 360 additions and 342 deletions

View File

@ -107,9 +107,10 @@ makePresignedUrl expiry method bucket object region extraQuery extraHeaders = do
-- object REST API AWS S3 documentation.
presignedPutObjectUrl :: Bucket -> Object -> UrlExpiry -> HT.RequestHeaders
-> Minio ByteString
presignedPutObjectUrl bucket object expirySeconds extraHeaders =
presignedPutObjectUrl bucket object expirySeconds extraHeaders = do
region <- asks (Just . connectRegion . mcConnInfo)
makePresignedUrl expirySeconds HT.methodPut
(Just bucket) (Just object) Nothing [] extraHeaders
(Just bucket) (Just object) region [] extraHeaders
-- | Generate a URL with authentication signature to GET (download) an
-- object. All extra query parameters and headers passed here will be
@ -122,9 +123,10 @@ presignedPutObjectUrl bucket object expirySeconds extraHeaders =
-- to the GET object REST API AWS S3 documentation.
presignedGetObjectUrl :: Bucket -> Object -> UrlExpiry -> HT.Query
-> HT.RequestHeaders -> Minio ByteString
presignedGetObjectUrl bucket object expirySeconds extraQuery extraHeaders =
presignedGetObjectUrl bucket object expirySeconds extraQuery extraHeaders = do
region <- asks (Just . connectRegion . mcConnInfo)
makePresignedUrl expirySeconds HT.methodGet
(Just bucket) (Just object) Nothing extraQuery extraHeaders
(Just bucket) (Just object) region extraQuery extraHeaders
-- | Generate a URL with authentication signature to make a HEAD
-- request on an object. This is used to fetch metadata about an
@ -135,9 +137,10 @@ presignedGetObjectUrl bucket object expirySeconds extraQuery extraHeaders =
-- object REST API AWS S3 documentation.
presignedHeadObjectUrl :: Bucket -> Object -> UrlExpiry
-> HT.RequestHeaders -> Minio ByteString
presignedHeadObjectUrl bucket object expirySeconds extraHeaders =
presignedHeadObjectUrl bucket object expirySeconds extraHeaders = do
region <- asks (Just . connectRegion . mcConnInfo)
makePresignedUrl expirySeconds HT.methodHead
(Just bucket) (Just object) Nothing [] extraHeaders
(Just bucket) (Just object) region [] extraHeaders
-- | Represents individual conditions in a Post Policy document.
data PostPolicyCondition = PPCStartsWith Text Text

View File

@ -308,357 +308,113 @@ liveServerUnitTests = testGroup "Unit tests against a live server"
, lowLevelMultipartTest
, putObjectSizeTest
, putObjectNoSizeTest
, funTestWithBucket "Multipart Tests" $
\step bucket -> do
step "Prepare for putObjectInternal with non-seekable file, with size."
step "Upload multipart file."
let mb80 = 80 * 1024 * 1024
obj = "mpart"
void $ putObjectInternal bucket obj defaultPutObjectOptions $ ODFile "/dev/zero" (Just mb80)
step "Retrieve and verify file size"
destFile <- mkRandFile 0
fGetObject bucket obj destFile defaultGetObjectOptions
gotSize <- withNewHandle destFile getFileSize
liftIO $ gotSize == Right (Just mb80) @?
"Wrong file size of put file after getting"
step "Cleanup actions"
removeObject bucket obj
step "cleanup"
removeObject bucket "big"
step "Prepare for removeIncompleteUpload"
-- low-level multipart operation tests.
let object = "newmpupload"
kb5 = 5 * 1024
step "create new multipart upload"
uid <- newMultipartUpload bucket object []
liftIO $ (T.length uid > 0) @? "Got an empty multipartUpload Id."
randFile <- mkRandFile kb5
step "upload 2 parts"
forM_ [1,2] $ \partNum -> do
h <- liftIO $ SIO.openBinaryFile randFile SIO.ReadMode
void $ putObjectPart bucket object uid partNum [] $ PayloadH h 0 kb5
step "remove ongoing upload"
removeIncompleteUpload bucket object
uploads <- C.runConduit $ listIncompleteUploads bucket (Just object) False
C..| sinkList
liftIO $ (null uploads) @? "removeIncompleteUploads didn't complete successfully"
, funTestWithBucket "putObject contentType tests" $ \step bucket -> do
step "fPutObject content type test"
let object = "xxx-content-type"
size1 = 100 :: Int64
step "create server object with content-type"
inputFile <- mkRandFile size1
fPutObject bucket object inputFile defaultPutObjectOptions {
pooContentType = Just "application/javascript"
}
-- retrieve obj info to check
oi <- headObject bucket object
let m = oiMetadata oi
step "Validate content-type"
liftIO $ assertEqual "Content-Type did not match" (Just "application/javascript") (Map.lookup "Content-Type" m)
step "upload object with content-encoding set to identity"
fPutObject bucket object inputFile defaultPutObjectOptions {
pooContentEncoding = Just "identity"
}
oiCE <- headObject bucket object
let m' = oiMetadata oiCE
step "Validate content-encoding"
liftIO $ assertEqual "Content-Encoding did not match" (Just "identity")
(Map.lookup "Content-Encoding" m')
step "Cleanup actions"
removeObject bucket object
, funTestWithBucket "putObject contentLanguage tests" $ \step bucket -> do
step "fPutObject content language test"
let object = "xxx-content-language"
size1 = 100 :: Int64
step "create server object with content-language"
inputFile <- mkRandFile size1
fPutObject bucket object inputFile defaultPutObjectOptions {
pooContentLanguage = Just "en-US"
}
-- retrieve obj info to check
oi <- headObject bucket object
let m = oiMetadata oi
step "Validate content-language"
liftIO $ assertEqual "content-language did not match" (Just "en-US")
(Map.lookup "Content-Language" m)
step "Cleanup actions"
removeObject bucket object
, funTestWithBucket "putObject storageClass tests" $ \step bucket -> do
step "fPutObject storage class test"
let object = "xxx-storage-class-standard"
object' = "xxx-storage-class-reduced"
object'' = "xxx-storage-class-invalid"
size1 = 100 :: Int64
size0 = 0 :: Int64
step "create server objects with storageClass"
inputFile <- mkRandFile size1
inputFile' <- mkRandFile size1
inputFile'' <- mkRandFile size0
fPutObject bucket object inputFile defaultPutObjectOptions {
pooStorageClass = Just "STANDARD"
}
fPutObject bucket object' inputFile' defaultPutObjectOptions {
pooStorageClass = Just "REDUCED_REDUNDANCY"
}
removeObject bucket object
-- retrieve obj info to check
oi' <- headObject bucket object'
let m' = oiMetadata oi'
step "Validate x-amz-storage-class rrs"
liftIO $ assertEqual "storageClass did not match" (Just "REDUCED_REDUNDANCY")
(Map.lookup "X-Amz-Storage-Class" m')
fpE <- try $ fPutObject bucket object'' inputFile'' defaultPutObjectOptions {
pooStorageClass = Just "INVALID_STORAGE_CLASS"
}
case fpE of
Left exn -> liftIO $ exn @?= ServiceErr "InvalidStorageClass" "Invalid storage class."
_ -> return ()
step "Cleanup actions"
removeObject bucket object'
, funTestWithBucket "copyObject related tests" $ \step bucket -> do
step "copyObjectSingle basic tests"
let object = "xxx"
objCopy = "xxxCopy"
size1 = 100 :: Int64
step "create server object to copy"
inputFile <- mkRandFile size1
fPutObject bucket object inputFile defaultPutObjectOptions
step "copy object"
let srcInfo = defaultSourceInfo { srcBucket = bucket, srcObject = object}
(etag, modTime) <- copyObjectSingle bucket objCopy srcInfo []
-- retrieve obj info to check
oi <- headObject bucket objCopy
let t = oiModTime oi
let e = oiETag oi
let s = oiSize oi
let isMTimeDiffOk = abs (diffUTCTime modTime t) < 1.0
liftIO $ (s == size1 && e == etag && isMTimeDiffOk) @?
"Copied object did not match expected."
step "cleanup actions"
removeObject bucket object
removeObject bucket objCopy
step "copyObjectPart basic tests"
let srcObj = "XXX"
copyObj = "XXXCopy"
step "Prepare"
let mb15 = 15 * 1024 * 1024
mb5 = 5 * 1024 * 1024
randFile <- mkRandFile mb15
fPutObject bucket srcObj randFile defaultPutObjectOptions
step "create new multipart upload"
uid <- newMultipartUpload bucket copyObj []
liftIO $ (T.length uid > 0) @? "Got an empty multipartUpload Id."
step "put object parts 1-3"
let srcInfo' = defaultSourceInfo { srcBucket = bucket, srcObject = srcObj }
dstInfo' = defaultDestinationInfo { dstBucket = bucket, dstObject = copyObj }
parts <- forM [1..3] $ \p -> do
(etag', _) <- copyObjectPart dstInfo' srcInfo'{
srcRange = Just $ (,) ((p-1)*mb5) ((p-1)*mb5 + (mb5 - 1))
} uid (fromIntegral p) []
return (fromIntegral p, etag')
step "complete multipart"
void $ completeMultipartUpload bucket copyObj uid parts
step "verify copied object size"
oi' <- headObject bucket copyObj
let s' = oiSize oi'
liftIO $ (s' == mb15) @? "Size failed to match"
step "Cleanup actions"
removeObject bucket srcObj
removeObject bucket copyObj
step "copyObject basic tests"
let srcs = ["XXX", "XXXL"]
copyObjs = ["XXXCopy", "XXXLCopy"]
sizes = map (* (1024 * 1024)) [15, 65]
step "Prepare"
forM_ (zip srcs sizes) $ \(src, size) -> do
inputFile' <- mkRandFile size
fPutObject bucket src inputFile' defaultPutObjectOptions
step "make small and large object copy"
forM_ (zip copyObjs srcs) $ \(cp, src) ->
copyObject defaultDestinationInfo {dstBucket = bucket, dstObject = cp} defaultSourceInfo {srcBucket = bucket, srcObject = src}
step "verify uploaded objects"
uploadedSizes <- fmap oiSize <$> forM copyObjs (headObject bucket)
liftIO $ (sizes == uploadedSizes) @? "Uploaded obj sizes failed to match"
forM_ (srcs ++ copyObjs) (removeObject bucket)
step "copyObject with offset test "
let src = "XXX"
size = 15 * 1024 * 1024
step "Prepare"
inputFile' <- mkRandFile size
fPutObject bucket src inputFile' defaultPutObjectOptions
step "copy last 10MiB of object"
copyObject defaultDestinationInfo { dstBucket = bucket, dstObject = copyObj } defaultSourceInfo {
srcBucket = bucket
, srcObject = src
, srcRange = Just $ (,) (5 * 1024 * 1024) (size - 1)
}
step "verify uploaded object"
cSize <- oiSize <$> headObject bucket copyObj
liftIO $ (cSize == 10 * 1024 * 1024) @? "Uploaded obj size mismatched!"
forM_ [src, copyObj] (removeObject bucket)
, multipartTest
, putObjectContentTypeTest
, putObjectContentLanguageTest
, putObjectStorageClassTest
, copyObjectTests
, presignedUrlFunTest
, presignedPostPolicyFunTest
, bucketPolicyFunTest
]
basicTests :: TestTree
basicTests = funTestWithBucket "Basic tests" $ \step bucket -> do
step "getService works and contains the test bucket."
buckets <- getService
unless (length (filter (== bucket) $ map biName buckets) == 1) $
liftIO $
assertFailure ("The bucket " ++ show bucket ++
" was expected to exist.")
basicTests = funTestWithBucket "Basic tests" $
\step bucket -> do
step "getService works and contains the test bucket."
buckets <- getService
unless (length (filter (== bucket) $ map biName buckets) == 1) $
liftIO $
assertFailure ("The bucket " ++ show bucket ++
" was expected to exist.")
step "makeBucket again to check if BucketAlreadyOwnedByYou exception is raised."
mbE <- try $ makeBucket bucket Nothing
case mbE of
Left exn -> liftIO $ exn @?= BucketAlreadyOwnedByYou
step "makeBucket again to check if BucketAlreadyOwnedByYou exception is raised."
mbE <- try $ makeBucket bucket Nothing
case mbE of
Left exn -> liftIO $ exn @?= BucketAlreadyOwnedByYou
_ -> return ()
step "makeBucket with an invalid bucket name and check for appropriate exception."
invalidMBE <- try $ makeBucket "invalidBucketName" Nothing
case invalidMBE of
Left exn -> liftIO $ exn @?= MErrVInvalidBucketName "invalidBucketName"
_ -> return ()
step "getLocation works"
region <- getLocation bucket
liftIO $ region == "us-east-1" @? ("Got unexpected region => " ++ show region)
step "singlepart putObject works"
fPutObject bucket "lsb-release" "/etc/lsb-release" defaultPutObjectOptions
step "fPutObject onto a non-existent bucket and check for NoSuchBucket exception"
fpE <- try $ fPutObject "nosuchbucket" "lsb-release" "/etc/lsb-release" defaultPutObjectOptions
case fpE of
Left exn -> liftIO $ exn @?= NoSuchBucket
_ -> return ()
outFile <- mkRandFile 0
step "simple fGetObject works"
fGetObject bucket "lsb-release" outFile defaultGetObjectOptions
let unmodifiedTime = UTCTime (fromGregorian 2010 11 26) 69857
step "fGetObject an object which is modified now but requesting as un-modified in past, check for exception"
resE <- try $ fGetObject bucket "lsb-release" outFile defaultGetObjectOptions {
gooIfUnmodifiedSince = (Just unmodifiedTime)
}
case resE of
Left exn -> liftIO $ exn @?= ServiceErr "PreconditionFailed" "At least one of the pre-conditions you specified did not hold"
_ -> return ()
step "fGetObject an object with no matching etag, check for exception"
resE1 <- try $ fGetObject bucket "lsb-release" outFile defaultGetObjectOptions {
gooIfMatch = (Just "invalid-etag")
}
case resE1 of
Left exn -> liftIO $ exn @?= ServiceErr "PreconditionFailed" "At least one of the pre-conditions you specified did not hold"
_ -> return ()
step "fGetObject an object with no valid range, check for exception"
resE2 <- try $ fGetObject bucket "lsb-release" outFile defaultGetObjectOptions {
gooRange = (Just $ HT.ByteRangeFromTo 100 200)
}
case resE2 of
Left exn -> liftIO $ exn @?= ServiceErr "InvalidRange" "The requested range is not satisfiable"
_ -> return ()
step "makeBucket with an invalid bucket name and check for appropriate exception."
invalidMBE <- try $ makeBucket "invalidBucketName" Nothing
case invalidMBE of
Left exn -> liftIO $ exn @?= MErrVInvalidBucketName "invalidBucketName"
_ -> return ()
step "fGetObject on object with a valid range"
fGetObject bucket "lsb-release" outFile defaultGetObjectOptions {
gooRange = (Just $ HT.ByteRangeFrom 1)
}
step "getLocation works"
region <- getLocation bucket
liftIO $ region == "us-east-1" @? ("Got unexpected region => " ++ show region)
step "fGetObject a non-existent object and check for NoSuchKey exception"
resE3 <- try $ fGetObject bucket "noSuchKey" outFile defaultGetObjectOptions
case resE3 of
Left exn -> liftIO $ exn @?= NoSuchKey
_ -> return ()
step "singlepart putObject works"
fPutObject bucket "lsb-release" "/etc/lsb-release" defaultPutObjectOptions
step "create new multipart upload works"
uid <- newMultipartUpload bucket "newmpupload" []
liftIO $ (T.length uid > 0) @? ("Got an empty multipartUpload Id.")
step "fPutObject onto a non-existent bucket and check for NoSuchBucket exception"
fpE <- try $ fPutObject "nosuchbucket" "lsb-release" "/etc/lsb-release" defaultPutObjectOptions
case fpE of
Left exn -> liftIO $ exn @?= NoSuchBucket
_ -> return ()
step "abort a new multipart upload works"
abortMultipartUpload bucket "newmpupload" uid
outFile <- mkRandFile 0
step "simple fGetObject works"
fGetObject bucket "lsb-release" outFile defaultGetObjectOptions
step "delete object works"
deleteObject bucket "lsb-release"
let unmodifiedTime = UTCTime (fromGregorian 2010 11 26) 69857
step "fGetObject an object which is modified now but requesting as un-modified in past, check for exception"
resE <- try $ fGetObject bucket "lsb-release" outFile defaultGetObjectOptions {
gooIfUnmodifiedSince = (Just unmodifiedTime)
}
case resE of
Left exn -> liftIO $ exn @?= ServiceErr "PreconditionFailed" "At least one of the pre-conditions you specified did not hold"
_ -> return ()
step "statObject test"
let object = "sample"
step "create an object"
inputFile <- mkRandFile 0
fPutObject bucket object inputFile defaultPutObjectOptions
step "fGetObject an object with no matching etag, check for exception"
resE1 <- try $ fGetObject bucket "lsb-release" outFile defaultGetObjectOptions {
gooIfMatch = (Just "invalid-etag")
}
case resE1 of
Left exn -> liftIO $ exn @?= ServiceErr "PreconditionFailed" "At least one of the pre-conditions you specified did not hold"
_ -> return ()
step "get metadata of the object"
res <- statObject bucket object
liftIO $ (oiSize res) @?= 0
step "fGetObject an object with no valid range, check for exception"
resE2 <- try $ fGetObject bucket "lsb-release" outFile defaultGetObjectOptions {
gooRange = (Just $ HT.ByteRangeFromTo 100 200)
}
case resE2 of
Left exn -> liftIO $ exn @?= ServiceErr "InvalidRange" "The requested range is not satisfiable"
_ -> return ()
step "fGetObject on object with a valid range"
fGetObject bucket "lsb-release" outFile defaultGetObjectOptions {
gooRange = (Just $ HT.ByteRangeFrom 1)
}
step "fGetObject a non-existent object and check for NoSuchKey exception"
resE3 <- try $ fGetObject bucket "noSuchKey" outFile defaultGetObjectOptions
case resE3 of
Left exn -> liftIO $ exn @?= NoSuchKey
_ -> return ()
step "create new multipart upload works"
uid <- newMultipartUpload bucket "newmpupload" []
liftIO $ (T.length uid > 0) @? ("Got an empty multipartUpload Id.")
step "abort a new multipart upload works"
abortMultipartUpload bucket "newmpupload" uid
step "delete object works"
deleteObject bucket "lsb-release"
step "statObject test"
let object = "sample"
step "create an object"
inputFile <- mkRandFile 0
fPutObject bucket object inputFile defaultPutObjectOptions
step "get metadata of the object"
res <- statObject bucket object
liftIO $ (oiSize res) @?= 0
step "delete object"
deleteObject bucket object
step "delete object"
deleteObject bucket object
presignedUrlFunTest :: TestTree
presignedUrlFunTest = funTestWithBucket "presigned Url tests" $
@ -695,7 +451,7 @@ presignedUrlFunTest = funTestWithBucket "presigned Url tests" $
"presigned put and get got mismatched data"
step "PUT object presigned - presignedPutObjectURL"
putUrl2 <- presignedPutObjectUrl bucket obj2 3600 []
putUrl2 <- presignedPutObjectUrl bucket obj2 604800 []
let size2 = 1200
testFile <- mkRandFile size2
@ -834,3 +590,262 @@ bucketPolicyFunTest = funTestWithBucket "Bucket Policy tests" $
step "delete bucket policy"
setBucketPolicy bucket T.empty
multipartTest :: TestTree
multipartTest = funTestWithBucket "Multipart Tests" $
\step bucket -> do
step "Prepare for putObjectInternal with non-seekable file, with size."
step "Upload multipart file."
let mb80 = 80 * 1024 * 1024
obj = "mpart"
void $ putObjectInternal bucket obj defaultPutObjectOptions $ ODFile "/dev/zero" (Just mb80)
step "Retrieve and verify file size"
destFile <- mkRandFile 0
fGetObject bucket obj destFile defaultGetObjectOptions
gotSize <- withNewHandle destFile getFileSize
liftIO $ gotSize == Right (Just mb80) @?
"Wrong file size of put file after getting"
step "Cleanup actions"
removeObject bucket obj
step "cleanup"
removeObject bucket "big"
step "Prepare for removeIncompleteUpload"
-- low-level multipart operation tests.
let object = "newmpupload"
kb5 = 5 * 1024
step "create new multipart upload"
uid <- newMultipartUpload bucket object []
liftIO $ (T.length uid > 0) @? "Got an empty multipartUpload Id."
randFile <- mkRandFile kb5
step "upload 2 parts"
forM_ [1,2] $ \partNum -> do
h <- liftIO $ SIO.openBinaryFile randFile SIO.ReadMode
void $ putObjectPart bucket object uid partNum [] $ PayloadH h 0 kb5
step "remove ongoing upload"
removeIncompleteUpload bucket object
uploads <- C.runConduit $ listIncompleteUploads bucket (Just object) False
C..| sinkList
liftIO $ (null uploads) @? "removeIncompleteUploads didn't complete successfully"
putObjectContentTypeTest :: TestTree
putObjectContentTypeTest = funTestWithBucket "putObject contentType tests" $
\step bucket -> do
step "fPutObject content type test"
let object = "xxx-content-type"
size1 = 100 :: Int64
step "create server object with content-type"
inputFile <- mkRandFile size1
fPutObject bucket object inputFile defaultPutObjectOptions {
pooContentType = Just "application/javascript"
}
-- retrieve obj info to check
oi <- headObject bucket object
let m = oiMetadata oi
step "Validate content-type"
liftIO $ assertEqual "Content-Type did not match" (Just "application/javascript") (Map.lookup "Content-Type" m)
step "upload object with content-encoding set to identity"
fPutObject bucket object inputFile defaultPutObjectOptions {
pooContentEncoding = Just "identity"
}
oiCE <- headObject bucket object
let m' = oiMetadata oiCE
step "Validate content-encoding"
liftIO $ assertEqual "Content-Encoding did not match" (Just "identity")
(Map.lookup "Content-Encoding" m')
step "Cleanup actions"
removeObject bucket object
putObjectContentLanguageTest :: TestTree
putObjectContentLanguageTest = funTestWithBucket "putObject contentLanguage tests" $
\step bucket -> do
step "fPutObject content language test"
let object = "xxx-content-language"
size1 = 100 :: Int64
step "create server object with content-language"
inputFile <- mkRandFile size1
fPutObject bucket object inputFile defaultPutObjectOptions {
pooContentLanguage = Just "en-US"
}
-- retrieve obj info to check
oi <- headObject bucket object
let m = oiMetadata oi
step "Validate content-language"
liftIO $ assertEqual "content-language did not match" (Just "en-US")
(Map.lookup "Content-Language" m)
step "Cleanup actions"
removeObject bucket object
putObjectStorageClassTest :: TestTree
putObjectStorageClassTest = funTestWithBucket "putObject storageClass tests" $
\step bucket -> do
step "fPutObject storage class test"
let object = "xxx-storage-class-standard"
object' = "xxx-storage-class-reduced"
object'' = "xxx-storage-class-invalid"
size1 = 100 :: Int64
size0 = 0 :: Int64
step "create server objects with storageClass"
inputFile <- mkRandFile size1
inputFile' <- mkRandFile size1
inputFile'' <- mkRandFile size0
fPutObject bucket object inputFile defaultPutObjectOptions {
pooStorageClass = Just "STANDARD"
}
fPutObject bucket object' inputFile' defaultPutObjectOptions {
pooStorageClass = Just "REDUCED_REDUNDANCY"
}
removeObject bucket object
-- retrieve obj info to check
oi' <- headObject bucket object'
let m' = oiMetadata oi'
step "Validate x-amz-storage-class rrs"
liftIO $ assertEqual "storageClass did not match" (Just "REDUCED_REDUNDANCY")
(Map.lookup "X-Amz-Storage-Class" m')
fpE <- try $ fPutObject bucket object'' inputFile'' defaultPutObjectOptions {
pooStorageClass = Just "INVALID_STORAGE_CLASS"
}
case fpE of
Left exn -> liftIO $ exn @?= ServiceErr "InvalidStorageClass" "Invalid storage class."
_ -> return ()
step "Cleanup actions"
removeObject bucket object'
copyObjectTests :: TestTree
copyObjectTests = funTestWithBucket "copyObject related tests" $
\step bucket -> do
step "copyObjectSingle basic tests"
let object = "xxx"
objCopy = "xxxCopy"
size1 = 100 :: Int64
step "create server object to copy"
inputFile <- mkRandFile size1
fPutObject bucket object inputFile defaultPutObjectOptions
step "copy object"
let srcInfo = defaultSourceInfo { srcBucket = bucket, srcObject = object}
(etag, modTime) <- copyObjectSingle bucket objCopy srcInfo []
-- retrieve obj info to check
oi <- headObject bucket objCopy
let t = oiModTime oi
let e = oiETag oi
let s = oiSize oi
let isMTimeDiffOk = abs (diffUTCTime modTime t) < 1.0
liftIO $ (s == size1 && e == etag && isMTimeDiffOk) @?
"Copied object did not match expected."
step "cleanup actions"
removeObject bucket object
removeObject bucket objCopy
step "copyObjectPart basic tests"
let srcObj = "XXX"
copyObj = "XXXCopy"
step "Prepare"
let mb15 = 15 * 1024 * 1024
mb5 = 5 * 1024 * 1024
randFile <- mkRandFile mb15
fPutObject bucket srcObj randFile defaultPutObjectOptions
step "create new multipart upload"
uid <- newMultipartUpload bucket copyObj []
liftIO $ (T.length uid > 0) @? "Got an empty multipartUpload Id."
step "put object parts 1-3"
let srcInfo' = defaultSourceInfo { srcBucket = bucket, srcObject = srcObj }
dstInfo' = defaultDestinationInfo { dstBucket = bucket, dstObject = copyObj }
parts <- forM [1..3] $ \p -> do
(etag', _) <- copyObjectPart dstInfo' srcInfo'{
srcRange = Just $ (,) ((p-1)*mb5) ((p-1)*mb5 + (mb5 - 1))
} uid (fromIntegral p) []
return (fromIntegral p, etag')
step "complete multipart"
void $ completeMultipartUpload bucket copyObj uid parts
step "verify copied object size"
oi' <- headObject bucket copyObj
let s' = oiSize oi'
liftIO $ (s' == mb15) @? "Size failed to match"
step "Cleanup actions"
removeObject bucket srcObj
removeObject bucket copyObj
step "copyObject basic tests"
let srcs = ["XXX", "XXXL"]
copyObjs = ["XXXCopy", "XXXLCopy"]
sizes = map (* (1024 * 1024)) [15, 65]
step "Prepare"
forM_ (zip srcs sizes) $ \(src, size) -> do
inputFile' <- mkRandFile size
fPutObject bucket src inputFile' defaultPutObjectOptions
step "make small and large object copy"
forM_ (zip copyObjs srcs) $ \(cp, src) ->
copyObject defaultDestinationInfo {dstBucket = bucket, dstObject = cp} defaultSourceInfo {srcBucket = bucket, srcObject = src}
step "verify uploaded objects"
uploadedSizes <- fmap oiSize <$> forM copyObjs (headObject bucket)
liftIO $ (sizes == uploadedSizes) @? "Uploaded obj sizes failed to match"
forM_ (srcs ++ copyObjs) (removeObject bucket)
step "copyObject with offset test "
let src = "XXX"
size = 15 * 1024 * 1024
step "Prepare"
inputFile' <- mkRandFile size
fPutObject bucket src inputFile' defaultPutObjectOptions
step "copy last 10MiB of object"
copyObject defaultDestinationInfo { dstBucket = bucket, dstObject = copyObj } defaultSourceInfo {
srcBucket = bucket
, srcObject = src
, srcRange = Just $ (,) (5 * 1024 * 1024) (size - 1)
}
step "verify uploaded object"
cSize <- oiSize <$> headObject bucket copyObj
liftIO $ (cSize == 10 * 1024 * 1024) @? "Uploaded obj size mismatched!"
forM_ [src, copyObj] (removeObject bucket)