2017-09-13 12:09:48 +00:00
// +build ignore
/ *
2017-12-08 19:45:59 +00:00
* Minio Go Library for Amazon S3 Compatible Cloud Storage
* Copyright 2015 - 2017 Minio , Inc .
2017-09-13 12:09:48 +00:00
*
* Licensed under the Apache License , Version 2.0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an "AS IS" BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
* /
package main
import (
"bytes"
2017-12-08 19:45:59 +00:00
"context"
2017-09-13 12:09:48 +00:00
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"math/rand"
2017-12-08 19:45:59 +00:00
"mime/multipart"
2017-09-13 12:09:48 +00:00
"net/http"
"net/url"
"os"
2017-12-08 19:45:59 +00:00
"path/filepath"
2017-09-13 12:09:48 +00:00
"reflect"
2018-01-23 18:40:42 +00:00
"runtime"
2017-09-13 12:09:48 +00:00
"strconv"
"strings"
"time"
2017-12-08 19:45:59 +00:00
humanize "github.com/dustin/go-humanize"
2017-09-13 12:09:48 +00:00
minio "github.com/minio/minio-go"
log "github.com/sirupsen/logrus"
"github.com/minio/minio-go/pkg/encrypt"
)
const letterBytes = "abcdefghijklmnopqrstuvwxyz01234569"
const (
letterIdxBits = 6 // 6 bits to represent a letter index
letterIdxMask = 1 << letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
)
const (
serverEndpoint = "SERVER_ENDPOINT"
accessKey = "ACCESS_KEY"
secretKey = "SECRET_KEY"
enableHTTPS = "ENABLE_HTTPS"
)
type mintJSONFormatter struct {
}
func ( f * mintJSONFormatter ) Format ( entry * log . Entry ) ( [ ] byte , error ) {
data := make ( log . Fields , len ( entry . Data ) )
for k , v := range entry . Data {
switch v := v . ( type ) {
case error :
// Otherwise errors are ignored by `encoding/json`
// https://github.com/sirupsen/logrus/issues/137
data [ k ] = v . Error ( )
default :
data [ k ] = v
}
}
serialized , err := json . Marshal ( data )
if err != nil {
return nil , fmt . Errorf ( "Failed to marshal fields to JSON, %v" , err )
}
return append ( serialized , '\n' ) , nil
}
2018-01-23 18:40:42 +00:00
func cleanEmptyEntries ( fields log . Fields ) log . Fields {
cleanFields := log . Fields { }
for k , v := range fields {
if v != "" {
cleanFields [ k ] = v
}
}
return cleanFields
}
2017-09-13 12:09:48 +00:00
// log successful test runs
2018-01-23 18:40:42 +00:00
func successLogger ( testName string , function string , args map [ string ] interface { } , startTime time . Time ) * log . Entry {
2017-09-13 12:09:48 +00:00
// calculate the test case duration
duration := time . Since ( startTime )
// log with the fields as per mint
2018-01-23 18:40:42 +00:00
fields := log . Fields { "name" : "minio-go: " + testName , "function" : function , "args" : args , "duration" : duration . Nanoseconds ( ) / 1000000 , "status" : "PASS" }
return log . WithFields ( cleanEmptyEntries ( fields ) )
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// As few of the features are not available in Gateway(s) currently, Check if err value is NotImplemented,
// and log as NA in that case and continue execution. Otherwise log as failure and return
2018-01-23 18:40:42 +00:00
func logError ( testName string , function string , args map [ string ] interface { } , startTime time . Time , alert string , message string , err error ) {
2017-12-08 19:45:59 +00:00
// If server returns NotImplemented we assume it is gateway mode and hence log it as info and move on to next tests
// Special case for ComposeObject API as it is implemented on client side and adds specific error details like `Error in upload-part-copy` in
// addition to NotImplemented error returned from server
if isErrNotImplemented ( err ) {
2018-01-23 18:40:42 +00:00
ignoredLog ( testName , function , args , startTime , message ) . Info ( )
2017-12-08 19:45:59 +00:00
} else {
2018-01-23 18:40:42 +00:00
failureLog ( testName , function , args , startTime , alert , message , err ) . Fatal ( )
2017-12-08 19:45:59 +00:00
}
}
2017-09-13 12:09:48 +00:00
// log failed test runs
2018-01-23 18:40:42 +00:00
func failureLog ( testName string , function string , args map [ string ] interface { } , startTime time . Time , alert string , message string , err error ) * log . Entry {
2017-09-13 12:09:48 +00:00
// calculate the test case duration
duration := time . Since ( startTime )
var fields log . Fields
// log with the fields as per mint
if err != nil {
2018-01-23 18:40:42 +00:00
fields = log . Fields { "name" : "minio-go: " + testName , "function" : function , "args" : args ,
"duration" : duration . Nanoseconds ( ) / 1000000 , "status" : "FAIL" , "alert" : alert , "message" : message , "error" : err }
2017-09-13 12:09:48 +00:00
} else {
2018-01-23 18:40:42 +00:00
fields = log . Fields { "name" : "minio-go: " + testName , "function" : function , "args" : args ,
"duration" : duration . Nanoseconds ( ) / 1000000 , "status" : "FAIL" , "alert" : alert , "message" : message }
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
return log . WithFields ( cleanEmptyEntries ( fields ) )
2017-09-13 12:09:48 +00:00
}
// log not applicable test runs
2018-01-23 18:40:42 +00:00
func ignoredLog ( testName string , function string , args map [ string ] interface { } , startTime time . Time , alert string ) * log . Entry {
2017-09-13 12:09:48 +00:00
// calculate the test case duration
duration := time . Since ( startTime )
// log with the fields as per mint
2018-01-23 18:40:42 +00:00
fields := log . Fields { "name" : "minio-go: " + testName , "function" : function , "args" : args ,
"duration" : duration . Nanoseconds ( ) / 1000000 , "status" : "NA" , "alert" : alert }
return log . WithFields ( cleanEmptyEntries ( fields ) )
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Delete objects in given bucket, recursively
func cleanupBucket ( bucketName string , c * minio . Client ) error {
// Create a done channel to control 'ListObjectsV2' go routine.
doneCh := make ( chan struct { } )
// Exit cleanly upon return.
defer close ( doneCh )
// Iterate over all objects in the bucket via listObjectsV2 and delete
for objCh := range c . ListObjectsV2 ( bucketName , "" , true , doneCh ) {
if objCh . Err != nil {
return objCh . Err
}
if objCh . Key != "" {
err := c . RemoveObject ( bucketName , objCh . Key )
if err != nil {
return err
}
}
}
for objPartInfo := range c . ListIncompleteUploads ( bucketName , "" , true , doneCh ) {
if objPartInfo . Err != nil {
return objPartInfo . Err
}
if objPartInfo . Key != "" {
err := c . RemoveIncompleteUpload ( bucketName , objPartInfo . Key )
if err != nil {
return err
}
}
}
// objects are already deleted, clear the buckets now
err := c . RemoveBucket ( bucketName )
if err != nil {
return err
}
return err
}
func isErrNotImplemented ( err error ) bool {
return minio . ToErrorResponse ( err ) . Code == "NotImplemented"
}
2017-09-13 12:09:48 +00:00
func init ( ) {
// If server endpoint is not set, all tests default to
// using https://play.minio.io:9000
if os . Getenv ( serverEndpoint ) == "" {
os . Setenv ( serverEndpoint , "play.minio.io:9000" )
os . Setenv ( accessKey , "Q3AM3UQ867SPQQA43P2F" )
os . Setenv ( secretKey , "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG" )
os . Setenv ( enableHTTPS , "1" )
}
}
2017-12-08 19:45:59 +00:00
var mintDataDir = os . Getenv ( "MINT_DATA_DIR" )
2017-09-13 12:09:48 +00:00
2017-12-08 19:45:59 +00:00
func getMintDataDirFilePath ( filename string ) ( fp string ) {
if mintDataDir == "" {
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
return filepath . Join ( mintDataDir , filename )
2017-09-13 12:09:48 +00:00
}
type sizedReader struct {
io . Reader
size int
}
func ( l * sizedReader ) Size ( ) int {
return l . size
}
func ( l * sizedReader ) Close ( ) error {
return nil
}
type randomReader struct { seed [ ] byte }
func ( r * randomReader ) Read ( b [ ] byte ) ( int , error ) {
return copy ( b , bytes . Repeat ( r . seed , len ( b ) ) ) , nil
}
// read data from file if it exists or optionally create a buffer of particular size
2017-12-08 19:45:59 +00:00
func getDataReader ( fileName string ) io . ReadCloser {
if mintDataDir == "" {
size := dataFileMap [ fileName ]
2017-09-13 12:09:48 +00:00
return & sizedReader {
2017-12-08 19:45:59 +00:00
Reader : io . LimitReader ( & randomReader {
seed : [ ] byte ( "a" ) ,
} , int64 ( size ) ) ,
size : size ,
2017-09-13 12:09:48 +00:00
}
}
2017-12-08 19:45:59 +00:00
reader , _ := os . Open ( getMintDataDirFilePath ( fileName ) )
2017-09-13 12:09:48 +00:00
return reader
}
// randString generates random names and prepends them with a known prefix.
func randString ( n int , src rand . Source , prefix string ) string {
b := make ( [ ] byte , n )
// A rand.Int63() generates 63 random bits, enough for letterIdxMax letters!
for i , cache , remain := n - 1 , src . Int63 ( ) , letterIdxMax ; i >= 0 ; {
if remain == 0 {
cache , remain = src . Int63 ( ) , letterIdxMax
}
if idx := int ( cache & letterIdxMask ) ; idx < len ( letterBytes ) {
b [ i ] = letterBytes [ idx ]
i --
}
cache >>= letterIdxBits
remain --
}
return prefix + string ( b [ 0 : 30 - len ( prefix ) ] )
}
2017-12-08 19:45:59 +00:00
var dataFileMap = map [ string ] int {
"datafile-1-b" : 1 ,
"datafile-10-kB" : 10 * humanize . KiByte ,
"datafile-33-kB" : 33 * humanize . KiByte ,
"datafile-100-kB" : 100 * humanize . KiByte ,
"datafile-1.03-MB" : 1056 * humanize . KiByte ,
"datafile-1-MB" : 1 * humanize . MiByte ,
"datafile-5-MB" : 5 * humanize . MiByte ,
"datafile-6-MB" : 6 * humanize . MiByte ,
"datafile-11-MB" : 11 * humanize . MiByte ,
"datafile-65-MB" : 65 * humanize . MiByte ,
}
2018-01-23 18:40:42 +00:00
func isFullMode ( ) bool {
return os . Getenv ( "MINT_MODE" ) == "full"
}
func getFuncName ( ) string {
pc , _ , _ , _ := runtime . Caller ( 1 )
return strings . TrimPrefix ( runtime . FuncForPC ( pc ) . Name ( ) , "main." )
2017-09-13 12:09:48 +00:00
}
// Tests bucket re-create errors.
func testMakeBucketError ( ) {
region := "eu-central-1"
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-09-13 12:09:48 +00:00
function := "MakeBucket(bucketName, region)"
// initialize logging params
args := map [ string ] interface { } {
"bucketName" : "" ,
"region" : region ,
}
// skipping region functional tests for non s3 runs
if os . Getenv ( serverEndpoint ) != "s3.amazonaws.com" {
2018-01-23 18:40:42 +00:00
ignoredLog ( testName , function , args , startTime , "Skipped region functional tests for non s3 runs" ) . Info ( )
2017-09-13 12:09:48 +00:00
return
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . New (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket in 'eu-central-1'.
if err = c . MakeBucket ( bucketName , region ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket Failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if err = c . MakeBucket ( bucketName , region ) ; err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Bucket already exists" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Verify valid error response from server.
if minio . ToErrorResponse ( err ) . Code != "BucketAlreadyExists" &&
minio . ToErrorResponse ( err ) . Code != "BucketAlreadyOwnedByYou" {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Invalid error returned by server" , err )
2017-12-08 19:45:59 +00:00
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-12-08 19:45:59 +00:00
}
func testMetadataSizeLimit ( ) {
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-12-08 19:45:59 +00:00
function := "PutObject(bucketName, objectName, reader, objectSize, opts)"
args := map [ string ] interface { } {
"bucketName" : "" ,
"objectName" : "" ,
"opts.UserMetadata" : "" ,
}
rand . Seed ( startTime . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . New (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client creation failed" , err )
2017-12-08 19:45:59 +00:00
return
}
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-12-08 19:45:59 +00:00
args [ "bucketName" ] = bucketName
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
args [ "objectName" ] = objectName
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Make bucket failed" , err )
2017-12-08 19:45:59 +00:00
return
}
const HeaderSizeLimit = 8 * 1024
const UserMetadataLimit = 2 * 1024
// Meta-data greater than the 2 KB limit of AWS - PUT calls with this meta-data should fail
metadata := make ( map [ string ] string )
metadata [ "X-Amz-Meta-Mint-Test" ] = string ( bytes . Repeat ( [ ] byte ( "m" ) , 1 + UserMetadataLimit - len ( "X-Amz-Meta-Mint-Test" ) ) )
args [ "metadata" ] = fmt . Sprint ( metadata )
_ , err = c . PutObject ( bucketName , objectName , bytes . NewReader ( nil ) , 0 , minio . PutObjectOptions { UserMetadata : metadata } )
if err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Created object with user-defined metadata exceeding metadata size limits" , nil )
2017-12-08 19:45:59 +00:00
return
}
// Meta-data (headers) greater than the 8 KB limit of AWS - PUT calls with this meta-data should fail
metadata = make ( map [ string ] string )
metadata [ "X-Amz-Mint-Test" ] = string ( bytes . Repeat ( [ ] byte ( "m" ) , 1 + HeaderSizeLimit - len ( "X-Amz-Mint-Test" ) ) )
args [ "metadata" ] = fmt . Sprint ( metadata )
_ , err = c . PutObject ( bucketName , objectName , bytes . NewReader ( nil ) , 0 , minio . PutObjectOptions { UserMetadata : metadata } )
if err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Created object with headers exceeding header size limits" , nil )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Tests various bucket supported formats.
func testMakeBucketRegions ( ) {
region := "eu-central-1"
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-09-13 12:09:48 +00:00
function := "MakeBucket(bucketName, region)"
// initialize logging params
args := map [ string ] interface { } {
"bucketName" : "" ,
"region" : region ,
}
// skipping region functional tests for non s3 runs
if os . Getenv ( serverEndpoint ) != "s3.amazonaws.com" {
2018-01-23 18:40:42 +00:00
ignoredLog ( testName , function , args , startTime , "Skipped region functional tests for non s3 runs" ) . Info ( )
2017-09-13 12:09:48 +00:00
return
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . New (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket in 'eu-central-1'.
if err = c . MakeBucket ( bucketName , region ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Make a new bucket with '.' in its name, in 'us-west-2'. This
// request is internally staged into a path style instead of
// virtual host style.
region = "us-west-2"
args [ "region" ] = region
if err = c . MakeBucket ( bucketName + ".withperiod" , region ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName + ".withperiod" , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Test PutObject using a large data to trigger multipart readat
func testPutObjectReadAt ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-12-08 19:45:59 +00:00
function := "PutObject(bucketName, objectName, reader, opts)"
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } {
2017-12-08 19:45:59 +00:00
"bucketName" : "" ,
"objectName" : "" ,
"opts" : "objectContentType" ,
2017-09-13 12:09:48 +00:00
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . New (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Make bucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
bufSize := dataFileMap [ "datafile-65-MB" ]
var reader = getDataReader ( "datafile-65-MB" )
2017-09-13 12:09:48 +00:00
defer reader . Close ( )
// Save the data
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
args [ "objectName" ] = objectName
// Object content type
objectContentType := "binary/octet-stream"
args [ "objectContentType" ] = objectContentType
2017-12-08 19:45:59 +00:00
n , err := c . PutObject ( bucketName , objectName , reader , int64 ( bufSize ) , minio . PutObjectOptions { ContentType : objectContentType } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes returned by PutObject does not match, expected " + string ( bufSize ) + " got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Read the data back
2017-12-08 19:45:59 +00:00
r , err := c . GetObject ( bucketName , objectName , minio . GetObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Get Object failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
st , err := r . Stat ( )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Stat Object failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if st . Size != int64 ( bufSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , fmt . Sprintf ( "Number of bytes in stat does not match, expected %d got %d" , bufSize , st . Size ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-08-01 17:43:44 +00:00
if st . ContentType != objectContentType && st . ContentType != "application/octet-stream" {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Content types don't match" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if err := r . Close ( ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Object Close failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if err := r . Close ( ) ; err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Object is already closed, didn't return error on Close" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Test PutObject using a large data to trigger multipart readat
func testPutObjectWithMetadata ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-12-08 19:45:59 +00:00
function := "PutObject(bucketName, objectName, reader,size, opts)"
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } {
"bucketName" : "" ,
"objectName" : "" ,
2017-12-08 19:45:59 +00:00
"opts" : "minio.PutObjectOptions{UserMetadata: metadata, Progress: progress}" ,
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
if ! isFullMode ( ) {
ignoredLog ( testName , function , args , startTime , "Skipping functional tests for short/quick runs" ) . Info ( )
2017-09-13 12:09:48 +00:00
return
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . New (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Make bucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
bufSize := dataFileMap [ "datafile-65-MB" ]
var reader = getDataReader ( "datafile-65-MB" )
2017-09-13 12:09:48 +00:00
defer reader . Close ( )
// Save the data
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
args [ "objectName" ] = objectName
// Object custom metadata
customContentType := "custom/contenttype"
args [ "metadata" ] = map [ string ] [ ] string {
"Content-Type" : { customContentType } ,
}
2017-12-08 19:45:59 +00:00
n , err := c . PutObject ( bucketName , objectName , reader , int64 ( bufSize ) , minio . PutObjectOptions {
ContentType : customContentType } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes returned by PutObject does not match, expected " + string ( bufSize ) + " got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Read the data back
2017-12-08 19:45:59 +00:00
r , err := c . GetObject ( bucketName , objectName , minio . GetObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
st , err := r . Stat ( )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Stat failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if st . Size != int64 ( bufSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes returned by PutObject does not match GetObject, expected " + string ( bufSize ) + " got " + string ( st . Size ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-08-01 17:43:44 +00:00
if st . ContentType != customContentType && st . ContentType != "application/octet-stream" {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ContentType does not match, expected " + customContentType + " got " + st . ContentType , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if err := r . Close ( ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Object Close failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if err := r . Close ( ) ; err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Object already closed, should respond with error" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
2018-08-01 17:43:44 +00:00
func testPutObjectWithContentLanguage ( ) {
2017-09-13 12:09:48 +00:00
// initialize logging params
objectName := "test-object"
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2018-08-01 17:43:44 +00:00
function := "PutObject(bucketName, objectName, reader, size, opts)"
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } {
"bucketName" : "" ,
"objectName" : objectName ,
2017-12-08 19:45:59 +00:00
"size" : - 1 ,
"opts" : "" ,
2017-09-13 12:09:48 +00:00
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . NewV4 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-08-01 17:43:44 +00:00
data := bytes . Repeat ( [ ] byte ( "a" ) , int ( 0 ) )
n , err := c . PutObject ( bucketName , objectName , bytes . NewReader ( data ) , int64 ( 0 ) , minio . PutObjectOptions {
ContentLanguage : "en" ,
} )
if err != nil {
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
return
}
2017-09-13 12:09:48 +00:00
2018-08-01 17:43:44 +00:00
if n != 0 {
logError ( testName , function , args , startTime , "" , "Expected upload object '0' doesn't match with PutObject return value" , err )
return
}
2017-09-13 12:09:48 +00:00
2018-08-01 17:43:44 +00:00
objInfo , err := c . StatObject ( bucketName , objectName , minio . StatObjectOptions { } )
if err != nil {
logError ( testName , function , args , startTime , "" , "StatObject failed" , err )
return
}
if objInfo . Metadata . Get ( "Content-Language" ) != "en" {
logError ( testName , function , args , startTime , "" , "Expected content-language 'en' doesn't match with StatObject return value" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
2018-08-01 17:43:44 +00:00
// Test put object with streaming signature.
func testPutObjectStreaming ( ) {
2017-09-13 12:09:48 +00:00
// initialize logging params
2018-08-01 17:43:44 +00:00
objectName := "test-object"
2017-09-13 12:09:48 +00:00
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2018-08-01 17:43:44 +00:00
function := "PutObject(bucketName, objectName, reader,size,opts)"
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } {
2018-08-01 17:43:44 +00:00
"bucketName" : "" ,
"objectName" : objectName ,
"size" : - 1 ,
"opts" : "" ,
2017-09-13 12:09:48 +00:00
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
2018-08-01 17:43:44 +00:00
c , err := minio . NewV4 (
2017-09-13 12:09:48 +00:00
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-08-01 17:43:44 +00:00
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
2017-09-13 12:09:48 +00:00
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-08-01 17:43:44 +00:00
// Upload an object.
sizes := [ ] int64 { 0 , 64 * 1024 - 1 , 64 * 1024 }
2017-09-13 12:09:48 +00:00
2018-08-01 17:43:44 +00:00
for _ , size := range sizes {
data := bytes . Repeat ( [ ] byte ( "a" ) , int ( size ) )
n , err := c . PutObject ( bucketName , objectName , bytes . NewReader ( data ) , int64 ( size ) , minio . PutObjectOptions { } )
if err != nil {
logError ( testName , function , args , startTime , "" , "PutObjectStreaming failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2018-08-01 17:43:44 +00:00
if n != size {
logError ( testName , function , args , startTime , "" , "Expected upload object size doesn't match with PutObjectStreaming return value" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Test get object seeker from the end, using whence set to '2'.
func testGetObjectSeekEnd ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-09-13 12:09:48 +00:00
function := "GetObject(bucketName, objectName)"
2018-01-23 18:40:42 +00:00
args := map [ string ] interface { } { }
2017-09-13 12:09:48 +00:00
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . New (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Generate 33K of data.
2017-12-08 19:45:59 +00:00
bufSize := dataFileMap [ "datafile-33-kB" ]
var reader = getDataReader ( "datafile-33-kB" )
2017-09-13 12:09:48 +00:00
defer reader . Close ( )
// Save the data
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
args [ "objectName" ] = objectName
buf , err := ioutil . ReadAll ( reader )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAll failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
n , err := c . PutObject ( bucketName , objectName , bytes . NewReader ( buf ) , int64 ( len ( buf ) ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes read does not match, expected " + string ( int64 ( bufSize ) ) + " got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Read the data back
2017-12-08 19:45:59 +00:00
r , err := c . GetObject ( bucketName , objectName , minio . GetObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
st , err := r . Stat ( )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Stat failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if st . Size != int64 ( bufSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes read does not match, expected " + string ( int64 ( bufSize ) ) + " got " + string ( st . Size ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
pos , err := r . Seek ( - 100 , 2 )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Object Seek failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if pos != st . Size - 100 {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Incorrect position" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
buf2 := make ( [ ] byte , 100 )
m , err := io . ReadFull ( r , buf2 )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Error reading through io.ReadFull" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if m != len ( buf2 ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes dont match, expected " + string ( len ( buf2 ) ) + " got " + string ( m ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
hexBuf1 := fmt . Sprintf ( "%02x" , buf [ len ( buf ) - 100 : ] )
hexBuf2 := fmt . Sprintf ( "%02x" , buf2 [ : m ] )
if hexBuf1 != hexBuf2 {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Values at same index dont match" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
pos , err = r . Seek ( - 100 , 2 )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Object Seek failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if pos != st . Size - 100 {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Incorrect position" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if err = r . Close ( ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ObjectClose failed" , err )
2017-12-08 19:45:59 +00:00
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Test get object reader to not throw error on being closed twice.
func testGetObjectClosedTwice ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-09-13 12:09:48 +00:00
function := "GetObject(bucketName, objectName)"
2018-01-23 18:40:42 +00:00
args := map [ string ] interface { } { }
2017-09-13 12:09:48 +00:00
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . New (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Generate 33K of data.
2017-12-08 19:45:59 +00:00
bufSize := dataFileMap [ "datafile-33-kB" ]
var reader = getDataReader ( "datafile-33-kB" )
2017-09-13 12:09:48 +00:00
defer reader . Close ( )
// Save the data
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
args [ "objectName" ] = objectName
2017-12-08 19:45:59 +00:00
n , err := c . PutObject ( bucketName , objectName , reader , int64 ( bufSize ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject response doesn't match sent bytes, expected " + string ( int64 ( bufSize ) ) + " got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Read the data back
2017-12-08 19:45:59 +00:00
r , err := c . GetObject ( bucketName , objectName , minio . GetObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
st , err := r . Stat ( )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Stat failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if st . Size != int64 ( bufSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes in stat does not match, expected " + string ( int64 ( bufSize ) ) + " got " + string ( st . Size ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if err := r . Close ( ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Object Close failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if err := r . Close ( ) ; err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Already closed object. No error returned" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
// Test RemoveObjectsWithContext request context cancels after timeout
func testRemoveObjectsWithContext ( ) {
// Initialize logging params.
startTime := time . Now ( )
testName := getFuncName ( )
function := "RemoveObjectsWithContext(ctx, bucketName, objectsCh)"
args := map [ string ] interface { } {
"bucketName" : "" ,
}
// Seed random based on current tie.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client.
c , err := minio . New (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
return
}
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Enable tracing, write to stdout.
// c.TraceOn(os.Stderr)
// Generate a new random bucket name.
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
}
// Generate put data.
r := bytes . NewReader ( bytes . Repeat ( [ ] byte ( "a" ) , 8 ) )
// Multi remove of 20 objects.
nrObjects := 20
objectsCh := make ( chan string )
go func ( ) {
defer close ( objectsCh )
for i := 0 ; i < nrObjects ; i ++ {
objectName := "sample" + strconv . Itoa ( i ) + ".txt"
_ , err = c . PutObject ( bucketName , objectName , r , 8 , minio . PutObjectOptions { ContentType : "application/octet-stream" } )
if err != nil {
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
continue
}
objectsCh <- objectName
}
} ( )
// Set context to cancel in 1 nanosecond.
ctx , cancel := context . WithTimeout ( context . Background ( ) , 1 * time . Nanosecond )
args [ "ctx" ] = ctx
defer cancel ( )
// Call RemoveObjectsWithContext API with short timeout.
errorCh := c . RemoveObjectsWithContext ( ctx , bucketName , objectsCh )
// Check for error.
select {
case r := <- errorCh :
if r . Err == nil {
logError ( testName , function , args , startTime , "" , "RemoveObjectsWithContext should fail on short timeout" , err )
return
}
}
// Set context with longer timeout.
ctx , cancel = context . WithTimeout ( context . Background ( ) , 1 * time . Hour )
args [ "ctx" ] = ctx
defer cancel ( )
// Perform RemoveObjectsWithContext with the longer timeout. Expect the removals to succeed.
errorCh = c . RemoveObjectsWithContext ( ctx , bucketName , objectsCh )
select {
case r , more := <- errorCh :
if more || r . Err != nil {
logError ( testName , function , args , startTime , "" , "Unexpected error" , r . Err )
return
}
}
// Delete all objects and buckets.
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
return
}
successLogger ( testName , function , args , startTime ) . Info ( )
}
2017-09-13 12:09:48 +00:00
// Test removing multiple objects with Remove API
func testRemoveMultipleObjects ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-09-13 12:09:48 +00:00
function := "RemoveObjects(bucketName, objectsCh)"
args := map [ string ] interface { } {
"bucketName" : "" ,
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . New (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Enable tracing, write to stdout.
// c.TraceOn(os.Stderr)
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
r := bytes . NewReader ( bytes . Repeat ( [ ] byte ( "a" ) , 8 ) )
// Multi remove of 1100 objects
2018-01-23 18:40:42 +00:00
nrObjects := 200
2017-09-13 12:09:48 +00:00
objectsCh := make ( chan string )
go func ( ) {
defer close ( objectsCh )
// Upload objects and send them to objectsCh
for i := 0 ; i < nrObjects ; i ++ {
objectName := "sample" + strconv . Itoa ( i ) + ".txt"
2017-12-08 19:45:59 +00:00
_ , err = c . PutObject ( bucketName , objectName , r , 8 , minio . PutObjectOptions { ContentType : "application/octet-stream" } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
2017-09-13 12:09:48 +00:00
continue
}
objectsCh <- objectName
}
} ( )
// Call RemoveObjects API
errorCh := c . RemoveObjects ( bucketName , objectsCh )
// Check if errorCh doesn't receive any error
select {
case r , more := <- errorCh :
if more {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Unexpected error" , r . Err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Tests FPutObject of a big file to trigger multipart
func testFPutObjectMultipart ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-12-08 19:45:59 +00:00
function := "FPutObject(bucketName, objectName, fileName, opts)"
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } {
2017-12-08 19:45:59 +00:00
"bucketName" : "" ,
"objectName" : "" ,
"fileName" : "" ,
"opts" : "" ,
2017-09-13 12:09:48 +00:00
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . New (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Upload 4 parts to utilize all 3 'workers' in multipart and still have a part to upload.
2017-12-08 19:45:59 +00:00
var fileName = getMintDataDirFilePath ( "datafile-65-MB" )
if fileName == "" {
2017-09-13 12:09:48 +00:00
// Make a temp file with minPartSize bytes of data.
file , err := ioutil . TempFile ( os . TempDir ( ) , "FPutObjectTest" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "TempFile creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Upload 2 parts to utilize all 3 'workers' in multipart and still have a part to upload.
if _ , err = io . Copy ( file , getDataReader ( "datafile-65-MB" ) ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Copy failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if err = file . Close ( ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File Close failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
fileName = file . Name ( )
args [ "fileName" ] = fileName
}
2017-12-08 19:45:59 +00:00
totalSize := dataFileMap [ "datafile-65-MB" ]
2017-09-13 12:09:48 +00:00
// Set base object name
objectName := bucketName + "FPutObject" + "-standard"
args [ "objectName" ] = objectName
objectContentType := "testapplication/octet-stream"
args [ "objectContentType" ] = objectContentType
// Perform standard FPutObject with contentType provided (Expecting application/octet-stream)
2017-12-08 19:45:59 +00:00
n , err := c . FPutObject ( bucketName , objectName , fileName , minio . PutObjectOptions { ContentType : objectContentType } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "FPutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( totalSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "FPutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
r , err := c . GetObject ( bucketName , objectName , minio . GetObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
objInfo , err := r . Stat ( )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Unexpected error" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if objInfo . Size != int64 ( totalSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( totalSize ) ) + " got " + string ( objInfo . Size ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-08-01 17:43:44 +00:00
if objInfo . ContentType != objectContentType && objInfo . ContentType != "application/octet-stream" {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ContentType doesn't match" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Tests FPutObject with null contentType (default = application/octet-stream)
func testFPutObject ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-12-08 19:45:59 +00:00
function := "FPutObject(bucketName, objectName, fileName, opts)"
2018-01-23 18:40:42 +00:00
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } {
"bucketName" : "" ,
"objectName" : "" ,
2017-12-08 19:45:59 +00:00
"fileName" : "" ,
"opts" : "" ,
2017-09-13 12:09:48 +00:00
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . New (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
location := "us-east-1"
2017-09-13 12:09:48 +00:00
// Make a new bucket.
2018-01-23 18:40:42 +00:00
args [ "bucketName" ] = bucketName
args [ "location" ] = location
function = "MakeBucket()bucketName, location"
err = c . MakeBucket ( bucketName , location )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Upload 3 parts worth of data to use all 3 of multiparts 'workers' and have an extra part.
// Use different data in part for multipart tests to check parts are uploaded in correct order.
2017-12-08 19:45:59 +00:00
var fName = getMintDataDirFilePath ( "datafile-65-MB" )
if fName == "" {
2017-09-13 12:09:48 +00:00
// Make a temp file with minPartSize bytes of data.
file , err := ioutil . TempFile ( os . TempDir ( ) , "FPutObjectTest" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "TempFile creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Upload 3 parts to utilize all 3 'workers' in multipart and still have a part to upload.
if _ , err = io . Copy ( file , getDataReader ( "datafile-65-MB" ) ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File copy failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Close the file pro-actively for windows.
2017-12-08 19:45:59 +00:00
if err = file . Close ( ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File close failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
defer os . Remove ( file . Name ( ) )
2017-09-13 12:09:48 +00:00
fName = file . Name ( )
}
2017-12-08 19:45:59 +00:00
totalSize := dataFileMap [ "datafile-65-MB" ]
2017-09-13 12:09:48 +00:00
// Set base object name
2018-01-23 18:40:42 +00:00
function = "FPutObject(bucketName, objectName, fileName, opts)"
2017-09-13 12:09:48 +00:00
objectName := bucketName + "FPutObject"
2018-01-23 18:40:42 +00:00
args [ "objectName" ] = objectName + "-standard"
args [ "fileName" ] = fName
2017-12-08 19:45:59 +00:00
args [ "opts" ] = minio . PutObjectOptions { ContentType : "application/octet-stream" }
2017-09-13 12:09:48 +00:00
// Perform standard FPutObject with contentType provided (Expecting application/octet-stream)
2017-12-08 19:45:59 +00:00
n , err := c . FPutObject ( bucketName , objectName + "-standard" , fName , minio . PutObjectOptions { ContentType : "application/octet-stream" } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "FPutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( totalSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( totalSize ) + ", got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Perform FPutObject with no contentType provided (Expecting application/octet-stream)
2018-01-23 18:40:42 +00:00
args [ "objectName" ] = objectName + "-Octet"
2017-12-08 19:45:59 +00:00
n , err = c . FPutObject ( bucketName , objectName + "-Octet" , fName , minio . PutObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File close failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( totalSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( totalSize ) + ", got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
srcFile , err := os . Open ( fName )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File open failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
defer srcFile . Close ( )
// Add extension to temp file name
tmpFile , err := os . Create ( fName + ".gtar" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File create failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
defer tmpFile . Close ( )
_ , err = io . Copy ( tmpFile , srcFile )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File copy failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Perform FPutObject with no contentType provided (Expecting application/x-gtar)
2018-01-23 18:40:42 +00:00
args [ "objectName" ] = objectName + "-GTar"
2018-08-01 17:43:44 +00:00
args [ "opts" ] = minio . PutObjectOptions { }
2017-12-08 19:45:59 +00:00
n , err = c . FPutObject ( bucketName , objectName + "-GTar" , fName + ".gtar" , minio . PutObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "FPutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( totalSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( totalSize ) + ", got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Check headers
2018-01-23 18:40:42 +00:00
function = "StatObject(bucketName, objectName, opts)"
args [ "objectName" ] = objectName + "-standard"
2017-12-08 19:45:59 +00:00
rStandard , err := c . StatObject ( bucketName , objectName + "-standard" , minio . StatObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "StatObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if rStandard . ContentType != "application/octet-stream" {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ContentType does not match, expected application/octet-stream, got " + rStandard . ContentType , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
function = "StatObject(bucketName, objectName, opts)"
args [ "objectName" ] = objectName + "-Octet"
2017-12-08 19:45:59 +00:00
rOctet , err := c . StatObject ( bucketName , objectName + "-Octet" , minio . StatObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "StatObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if rOctet . ContentType != "application/octet-stream" {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ContentType does not match, expected application/octet-stream, got " + rOctet . ContentType , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
function = "StatObject(bucketName, objectName, opts)"
args [ "objectName" ] = objectName + "-GTar"
2017-12-08 19:45:59 +00:00
rGTar , err := c . StatObject ( bucketName , objectName + "-GTar" , minio . StatObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "StatObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-08-01 17:43:44 +00:00
if rGTar . ContentType != "application/x-gtar" && rGTar . ContentType != "application/octet-stream" {
logError ( testName , function , args , startTime , "" , "ContentType does not match, expected application/x-gtar or application/octet-stream, got " + rGTar . ContentType , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if err = os . Remove ( fName + ".gtar" ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File remove failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Tests FPutObjectWithContext request context cancels after timeout
func testFPutObjectWithContext ( ) {
2017-09-13 12:09:48 +00:00
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-12-08 19:45:59 +00:00
function := "FPutObject(bucketName, objectName, fileName, opts)"
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } {
"bucketName" : "" ,
"objectName" : "" ,
2017-12-08 19:45:59 +00:00
"fileName" : "" ,
"opts" : "" ,
2017-09-13 12:09:48 +00:00
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . New (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-12-08 19:45:59 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
}
// Upload 1 parts worth of data to use multipart upload.
// Use different data in part for multipart tests to check parts are uploaded in correct order.
var fName = getMintDataDirFilePath ( "datafile-1-MB" )
if fName == "" {
// Make a temp file with 1 MiB bytes of data.
file , err := ioutil . TempFile ( os . TempDir ( ) , "FPutObjectWithContextTest" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "TempFile creation failed" , err )
2017-12-08 19:45:59 +00:00
return
}
// Upload 1 parts to trigger multipart upload
if _ , err = io . Copy ( file , getDataReader ( "datafile-1-MB" ) ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File copy failed" , err )
2017-12-08 19:45:59 +00:00
return
}
// Close the file pro-actively for windows.
if err = file . Close ( ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File close failed" , err )
2017-12-08 19:45:59 +00:00
return
}
defer os . Remove ( file . Name ( ) )
fName = file . Name ( )
}
totalSize := dataFileMap [ "datafile-1-MB" ]
// Set base object name
objectName := bucketName + "FPutObjectWithContext"
args [ "objectName" ] = objectName
2018-01-23 18:40:42 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , 1 * time . Nanosecond )
2017-12-08 19:45:59 +00:00
args [ "ctx" ] = ctx
defer cancel ( )
// Perform standard FPutObjectWithContext with contentType provided (Expecting application/octet-stream)
_ , err = c . FPutObjectWithContext ( ctx , bucketName , objectName + "-Shorttimeout" , fName , minio . PutObjectOptions { ContentType : "application/octet-stream" } )
if err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "FPutObjectWithContext should fail on short timeout" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
ctx , cancel = context . WithTimeout ( context . Background ( ) , 1 * time . Hour )
2017-12-08 19:45:59 +00:00
defer cancel ( )
// Perform FPutObjectWithContext with a long timeout. Expect the put object to succeed
n , err := c . FPutObjectWithContext ( ctx , bucketName , objectName + "-Longtimeout" , fName , minio . PutObjectOptions { } )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "FPutObjectWithContext shouldn't fail on long timeout" , err )
2017-12-08 19:45:59 +00:00
return
}
if n != int64 ( totalSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( totalSize ) + ", got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
}
_ , err = c . StatObject ( bucketName , objectName + "-Longtimeout" , minio . StatObjectOptions { } )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "StatObject failed" , err )
2017-12-08 19:45:59 +00:00
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-12-08 19:45:59 +00:00
}
// Tests FPutObjectWithContext request context cancels after timeout
func testFPutObjectWithContextV2 ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-12-08 19:45:59 +00:00
function := "FPutObjectWithContext(ctx, bucketName, objectName, fileName, opts)"
args := map [ string ] interface { } {
"bucketName" : "" ,
"objectName" : "" ,
"opts" : "minio.PutObjectOptions{ContentType:objectContentType}" ,
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . NewV2 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-12-08 19:45:59 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
}
// Upload 1 parts worth of data to use multipart upload.
// Use different data in part for multipart tests to check parts are uploaded in correct order.
var fName = getMintDataDirFilePath ( "datafile-1-MB" )
if fName == "" {
// Make a temp file with 1 MiB bytes of data.
file , err := ioutil . TempFile ( os . TempDir ( ) , "FPutObjectWithContextTest" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Temp file creation failed" , err )
2017-12-08 19:45:59 +00:00
return
}
// Upload 1 parts to trigger multipart upload
if _ , err = io . Copy ( file , getDataReader ( "datafile-1-MB" ) ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File copy failed" , err )
2017-12-08 19:45:59 +00:00
return
}
// Close the file pro-actively for windows.
if err = file . Close ( ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File close failed" , err )
2017-12-08 19:45:59 +00:00
return
}
defer os . Remove ( file . Name ( ) )
fName = file . Name ( )
}
totalSize := dataFileMap [ "datafile-1-MB" ]
// Set base object name
objectName := bucketName + "FPutObjectWithContext"
args [ "objectName" ] = objectName
2018-01-23 18:40:42 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , 1 * time . Nanosecond )
2017-12-08 19:45:59 +00:00
args [ "ctx" ] = ctx
defer cancel ( )
// Perform standard FPutObjectWithContext with contentType provided (Expecting application/octet-stream)
_ , err = c . FPutObjectWithContext ( ctx , bucketName , objectName + "-Shorttimeout" , fName , minio . PutObjectOptions { ContentType : "application/octet-stream" } )
if err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "FPutObjectWithContext should fail on short timeout" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
ctx , cancel = context . WithTimeout ( context . Background ( ) , 1 * time . Hour )
2017-12-08 19:45:59 +00:00
defer cancel ( )
// Perform FPutObjectWithContext with a long timeout. Expect the put object to succeed
n , err := c . FPutObjectWithContext ( ctx , bucketName , objectName + "-Longtimeout" , fName , minio . PutObjectOptions { } )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "FPutObjectWithContext shouldn't fail on longer timeout" , err )
2017-12-08 19:45:59 +00:00
return
}
if n != int64 ( totalSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes does not match:wanted" + string ( totalSize ) + " got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
}
_ , err = c . StatObject ( bucketName , objectName + "-Longtimeout" , minio . StatObjectOptions { } )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "StatObject failed" , err )
2017-12-08 19:45:59 +00:00
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-12-08 19:45:59 +00:00
}
// Test validates putObject with context to see if request cancellation is honored.
func testPutObjectWithContext ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-12-08 19:45:59 +00:00
function := "PutObjectWithContext(ctx, bucketName, objectName, fileName, opts)"
args := map [ string ] interface { } {
"ctx" : "" ,
"bucketName" : "" ,
"objectName" : "" ,
"opts" : "" ,
}
// Instantiate new minio client object.
c , err := minio . NewV4 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Make a new bucket.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-12-08 19:45:59 +00:00
args [ "bucketName" ] = bucketName
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket call failed" , err )
2017-12-08 19:45:59 +00:00
return
}
bufSize := dataFileMap [ "datafile-33-kB" ]
var reader = getDataReader ( "datafile-33-kB" )
defer reader . Close ( )
objectName := fmt . Sprintf ( "test-file-%v" , rand . Uint32 ( ) )
args [ "objectName" ] = objectName
2018-01-23 18:40:42 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , 1 * time . Nanosecond )
2017-12-08 19:45:59 +00:00
args [ "ctx" ] = ctx
args [ "opts" ] = minio . PutObjectOptions { ContentType : "binary/octet-stream" }
defer cancel ( )
_ , err = c . PutObjectWithContext ( ctx , bucketName , objectName , reader , int64 ( bufSize ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
2018-01-23 18:40:42 +00:00
if err == nil {
logError ( testName , function , args , startTime , "" , "PutObjectWithContext should fail on short timeout" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
ctx , cancel = context . WithTimeout ( context . Background ( ) , 1 * time . Hour )
2017-12-08 19:45:59 +00:00
args [ "ctx" ] = ctx
defer cancel ( )
reader = getDataReader ( "datafile-33-kB" )
defer reader . Close ( )
_ , err = c . PutObjectWithContext ( ctx , bucketName , objectName , reader , int64 ( bufSize ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObjectWithContext with long timeout failed" , err )
2017-12-08 19:45:59 +00:00
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-12-08 19:45:59 +00:00
}
// Tests get object ReaderSeeker interface methods.
func testGetObjectReadSeekFunctional ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-12-08 19:45:59 +00:00
function := "GetObject(bucketName, objectName)"
2018-01-23 18:40:42 +00:00
args := map [ string ] interface { } { }
2017-12-08 19:45:59 +00:00
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . New (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
defer func ( ) {
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
return
}
} ( )
2017-09-13 12:09:48 +00:00
// Generate 33K of data.
2017-12-08 19:45:59 +00:00
bufSize := dataFileMap [ "datafile-33-kB" ]
var reader = getDataReader ( "datafile-33-kB" )
2017-09-13 12:09:48 +00:00
defer reader . Close ( )
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
args [ "objectName" ] = objectName
buf , err := ioutil . ReadAll ( reader )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAll failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Save the data
2017-12-08 19:45:59 +00:00
n , err := c . PutObject ( bucketName , objectName , bytes . NewReader ( buf ) , int64 ( len ( buf ) ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( bufSize ) ) + ", got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Read the data back
2017-12-08 19:45:59 +00:00
r , err := c . GetObject ( bucketName , objectName , minio . GetObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
st , err := r . Stat ( )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Stat object failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if st . Size != int64 ( bufSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( bufSize ) ) + ", got " + string ( st . Size ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// This following function helps us to compare data from the reader after seek
// with the data from the original buffer
cmpData := func ( r io . Reader , start , end int ) {
if end - start == 0 {
return
}
buffer := bytes . NewBuffer ( [ ] byte { } )
2017-12-08 19:45:59 +00:00
if _ , err := io . CopyN ( buffer , r , int64 ( bufSize ) ) ; err != nil {
2017-09-13 12:09:48 +00:00
if err != io . EOF {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "CopyN failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
}
if ! bytes . Equal ( buf [ start : end ] , buffer . Bytes ( ) ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Incorrect read bytes v/s original buffer" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
}
// Generic seek error for errors other than io.EOF
seekErr := errors . New ( "seek error" )
testCases := [ ] struct {
offset int64
whence int
pos int64
err error
shouldCmp bool
start int
end int
} {
// Start from offset 0, fetch data and compare
{ 0 , 0 , 0 , nil , true , 0 , 0 } ,
// Start from offset 2048, fetch data and compare
2017-12-08 19:45:59 +00:00
{ 2048 , 0 , 2048 , nil , true , 2048 , bufSize } ,
2017-09-13 12:09:48 +00:00
// Start from offset larger than possible
2017-12-08 19:45:59 +00:00
{ int64 ( bufSize ) + 1024 , 0 , 0 , seekErr , false , 0 , 0 } ,
2017-09-13 12:09:48 +00:00
// Move to offset 0 without comparing
{ 0 , 0 , 0 , nil , false , 0 , 0 } ,
// Move one step forward and compare
2017-12-08 19:45:59 +00:00
{ 1 , 1 , 1 , nil , true , 1 , bufSize } ,
2017-09-13 12:09:48 +00:00
// Move larger than possible
2017-12-08 19:45:59 +00:00
{ int64 ( bufSize ) , 1 , 0 , seekErr , false , 0 , 0 } ,
2017-09-13 12:09:48 +00:00
// Provide negative offset with CUR_SEEK
{ int64 ( - 1 ) , 1 , 0 , seekErr , false , 0 , 0 } ,
// Test with whence SEEK_END and with positive offset
2017-12-08 19:45:59 +00:00
{ 1024 , 2 , int64 ( bufSize ) - 1024 , io . EOF , true , 0 , 0 } ,
2017-09-13 12:09:48 +00:00
// Test with whence SEEK_END and with negative offset
2017-12-08 19:45:59 +00:00
{ - 1024 , 2 , int64 ( bufSize ) - 1024 , nil , true , bufSize - 1024 , bufSize } ,
2017-09-13 12:09:48 +00:00
// Test with whence SEEK_END and with large negative offset
2017-12-08 19:45:59 +00:00
{ - int64 ( bufSize ) * 2 , 2 , 0 , seekErr , true , 0 , 0 } ,
2017-09-13 12:09:48 +00:00
}
for i , testCase := range testCases {
// Perform seek operation
n , err := r . Seek ( testCase . offset , testCase . whence )
// We expect an error
if testCase . err == seekErr && err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Test " + string ( i + 1 ) + ", unexpected err value: expected: " + testCase . err . Error ( ) + ", found: " + err . Error ( ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// We expect a specific error
if testCase . err != seekErr && testCase . err != err {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Test " + string ( i + 1 ) + ", unexpected err value: expected: " + testCase . err . Error ( ) + ", found: " + err . Error ( ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// If we expect an error go to the next loop
if testCase . err != nil {
continue
}
// Check the returned seek pos
if n != testCase . pos {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Test " + string ( i + 1 ) + ", number of bytes seeked does not match, expected " + string ( testCase . pos ) + ", got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Compare only if shouldCmp is activated
if testCase . shouldCmp {
cmpData ( r , testCase . start , testCase . end )
}
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Tests get object ReaderAt interface methods.
func testGetObjectReadAtFunctional ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-09-13 12:09:48 +00:00
function := "GetObject(bucketName, objectName)"
2018-01-23 18:40:42 +00:00
args := map [ string ] interface { } { }
2017-09-13 12:09:48 +00:00
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . New (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Generate 33K of data.
2017-12-08 19:45:59 +00:00
bufSize := dataFileMap [ "datafile-33-kB" ]
var reader = getDataReader ( "datafile-33-kB" )
2017-09-13 12:09:48 +00:00
defer reader . Close ( )
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
args [ "objectName" ] = objectName
buf , err := ioutil . ReadAll ( reader )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAll failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Save the data
2017-12-08 19:45:59 +00:00
n , err := c . PutObject ( bucketName , objectName , bytes . NewReader ( buf ) , int64 ( len ( buf ) ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( bufSize ) ) + ", got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// read the data back
2017-12-08 19:45:59 +00:00
r , err := c . GetObject ( bucketName , objectName , minio . GetObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
offset := int64 ( 2048 )
// read directly
buf1 := make ( [ ] byte , 512 )
buf2 := make ( [ ] byte , 512 )
buf3 := make ( [ ] byte , 512 )
buf4 := make ( [ ] byte , 512 )
2018-03-30 10:33:40 +00:00
// Test readAt before stat is called such that objectInfo doesn't change.
2017-09-13 12:09:48 +00:00
m , err := r . ReadAt ( buf1 , offset )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAt failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if m != len ( buf1 ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAt read shorter bytes before reaching EOF, expected " + string ( len ( buf1 ) ) + ", got " + string ( m ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( buf1 , buf [ offset : offset + 512 ] ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Incorrect read between two ReadAt from same offset" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
offset += 512
st , err := r . Stat ( )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Stat failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if st . Size != int64 ( bufSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes in stat does not match, expected " + string ( int64 ( bufSize ) ) + ", got " + string ( st . Size ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
m , err = r . ReadAt ( buf2 , offset )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAt failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if m != len ( buf2 ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAt read shorter bytes before reaching EOF, expected " + string ( len ( buf2 ) ) + ", got " + string ( m ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( buf2 , buf [ offset : offset + 512 ] ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Incorrect read between two ReadAt from same offset" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
2017-09-13 12:09:48 +00:00
offset += 512
m , err = r . ReadAt ( buf3 , offset )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAt failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if m != len ( buf3 ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAt read shorter bytes before reaching EOF, expected " + string ( len ( buf3 ) ) + ", got " + string ( m ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( buf3 , buf [ offset : offset + 512 ] ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Incorrect read between two ReadAt from same offset" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
offset += 512
m , err = r . ReadAt ( buf4 , offset )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAt failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if m != len ( buf4 ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAt read shorter bytes before reaching EOF, expected " + string ( len ( buf4 ) ) + ", got " + string ( m ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( buf4 , buf [ offset : offset + 512 ] ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Incorrect read between two ReadAt from same offset" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
buf5 := make ( [ ] byte , n )
// Read the whole object.
m , err = r . ReadAt ( buf5 , 0 )
if err != nil {
if err != io . EOF {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAt failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
}
if m != len ( buf5 ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAt read shorter bytes before reaching EOF, expected " + string ( len ( buf5 ) ) + ", got " + string ( m ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( buf , buf5 ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Incorrect data read in GetObject, than what was previously uploaded" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
buf6 := make ( [ ] byte , n + 1 )
// Read the whole object and beyond.
_ , err = r . ReadAt ( buf6 , 0 )
if err != nil {
if err != io . EOF {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAt failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Test Presigned Post Policy
func testPresignedPostPolicy ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-09-13 12:09:48 +00:00
function := "PresignedPostPolicy(policy)"
args := map [ string ] interface { } {
"policy" : "" ,
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object
c , err := minio . NewV4 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
// Make a new bucket in 'us-east-1' (source bucket).
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Generate 33K of data.
2017-12-08 19:45:59 +00:00
bufSize := dataFileMap [ "datafile-33-kB" ]
var reader = getDataReader ( "datafile-33-kB" )
2017-09-13 12:09:48 +00:00
defer reader . Close ( )
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
2018-09-03 18:23:56 +00:00
// Azure requires the key to not start with a number
metadataKey := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "user" )
2017-12-08 19:45:59 +00:00
metadataValue := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
2017-09-13 12:09:48 +00:00
buf , err := ioutil . ReadAll ( reader )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAll failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Save the data
2017-12-08 19:45:59 +00:00
n , err := c . PutObject ( bucketName , objectName , bytes . NewReader ( buf ) , int64 ( len ( buf ) ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( bufSize ) ) + " got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
policy := minio . NewPostPolicy ( )
if err := policy . SetBucket ( "" ) ; err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetBucket did not fail for invalid conditions" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if err := policy . SetKey ( "" ) ; err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetKey did not fail for invalid conditions" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if err := policy . SetKeyStartsWith ( "" ) ; err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetKeyStartsWith did not fail for invalid conditions" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if err := policy . SetExpires ( time . Date ( 1 , time . January , 1 , 0 , 0 , 0 , 0 , time . UTC ) ) ; err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetExpires did not fail for invalid conditions" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if err := policy . SetContentType ( "" ) ; err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetContentType did not fail for invalid conditions" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if err := policy . SetContentLengthRange ( 1024 * 1024 , 1024 ) ; err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetContentLengthRange did not fail for invalid conditions" , err )
2017-12-08 19:45:59 +00:00
return
}
if err := policy . SetUserMetadata ( "" , "" ) ; err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetUserMetadata did not fail for invalid conditions" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
policy . SetBucket ( bucketName )
policy . SetKey ( objectName )
policy . SetExpires ( time . Now ( ) . UTC ( ) . AddDate ( 0 , 0 , 10 ) ) // expires in 10 days
2017-12-08 19:45:59 +00:00
policy . SetContentType ( "binary/octet-stream" )
policy . SetContentLengthRange ( 10 , 1024 * 1024 )
policy . SetUserMetadata ( metadataKey , metadataValue )
args [ "policy" ] = policy . String ( )
2017-09-13 12:09:48 +00:00
2017-12-08 19:45:59 +00:00
presignedPostPolicyURL , formData , err := c . PresignedPostPolicy ( policy )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedPostPolicy failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
var formBuf bytes . Buffer
writer := multipart . NewWriter ( & formBuf )
for k , v := range formData {
writer . WriteField ( k , v )
}
2017-09-13 12:09:48 +00:00
2017-12-08 19:45:59 +00:00
// Get a 33KB file to upload and test if set post policy works
var filePath = getMintDataDirFilePath ( "datafile-33-kB" )
if filePath == "" {
// Make a temp file with 33 KB data.
file , err := ioutil . TempFile ( os . TempDir ( ) , "PresignedPostPolicyTest" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "TempFile creation failed" , err )
2017-12-08 19:45:59 +00:00
return
}
if _ , err = io . Copy ( file , getDataReader ( "datafile-33-kB" ) ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Copy failed" , err )
2017-12-08 19:45:59 +00:00
return
}
if err = file . Close ( ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File Close failed" , err )
2017-12-08 19:45:59 +00:00
return
}
filePath = file . Name ( )
}
// add file to post request
f , err := os . Open ( filePath )
defer f . Close ( )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File open failed" , err )
2017-12-08 19:45:59 +00:00
return
}
w , err := writer . CreateFormFile ( "file" , filePath )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "CreateFormFile failed" , err )
2017-12-08 19:45:59 +00:00
return
}
_ , err = io . Copy ( w , f )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Copy failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
writer . Close ( )
2017-09-13 12:09:48 +00:00
2017-12-08 19:45:59 +00:00
// make post request with correct form data
res , err := http . Post ( presignedPostPolicyURL . String ( ) , writer . FormDataContentType ( ) , bytes . NewReader ( formBuf . Bytes ( ) ) )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Http request failed" , err )
2017-12-08 19:45:59 +00:00
return
}
defer res . Body . Close ( )
if res . StatusCode != http . StatusNoContent {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Http request failed" , errors . New ( res . Status ) )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// expected path should be absolute path of the object
var scheme string
if mustParseBool ( os . Getenv ( enableHTTPS ) ) {
scheme = "https://"
} else {
scheme = "http://"
}
expectedLocation := scheme + os . Getenv ( serverEndpoint ) + "/" + bucketName + "/" + objectName
2018-03-30 10:33:40 +00:00
expectedLocationBucketDNS := scheme + bucketName + "." + os . Getenv ( serverEndpoint ) + "/" + objectName
2017-12-08 19:45:59 +00:00
if val , ok := res . Header [ "Location" ] ; ok {
2018-03-30 10:33:40 +00:00
if val [ 0 ] != expectedLocation && val [ 0 ] != expectedLocationBucketDNS {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Location in header response is incorrect" , err )
2017-12-08 19:45:59 +00:00
return
}
} else {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Location not found in header response" , err )
2017-12-08 19:45:59 +00:00
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Tests copy object
func testCopyObject ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-09-13 12:09:48 +00:00
function := "CopyObject(dst, src)"
2018-01-23 18:40:42 +00:00
args := map [ string ] interface { } { }
2017-09-13 12:09:48 +00:00
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object
c , err := minio . NewV4 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
// Make a new bucket in 'us-east-1' (source bucket).
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Make a new bucket in 'us-east-1' (destination bucket).
err = c . MakeBucket ( bucketName + "-copy" , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Generate 33K of data.
2017-12-08 19:45:59 +00:00
bufSize := dataFileMap [ "datafile-33-kB" ]
var reader = getDataReader ( "datafile-33-kB" )
2017-09-13 12:09:48 +00:00
// Save the data
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
2017-12-08 19:45:59 +00:00
n , err := c . PutObject ( bucketName , objectName , reader , int64 ( bufSize ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( bufSize ) ) + ", got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
r , err := c . GetObject ( bucketName , objectName , minio . GetObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Check the various fields of source object against destination object.
objInfo , err := r . Stat ( )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Stat failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Copy Source
src := minio . NewSourceInfo ( bucketName , objectName , nil )
2018-01-23 18:40:42 +00:00
args [ "src" ] = src
2017-09-13 12:09:48 +00:00
// Set copy conditions.
// All invalid conditions first.
err = src . SetModifiedSinceCond ( time . Date ( 1 , time . January , 1 , 0 , 0 , 0 , 0 , time . UTC ) )
if err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetModifiedSinceCond did not fail for invalid conditions" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
err = src . SetUnmodifiedSinceCond ( time . Date ( 1 , time . January , 1 , 0 , 0 , 0 , 0 , time . UTC ) )
if err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetUnmodifiedSinceCond did not fail for invalid conditions" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
err = src . SetMatchETagCond ( "" )
if err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetMatchETagCond did not fail for invalid conditions" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
err = src . SetMatchETagExceptCond ( "" )
if err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetMatchETagExceptCond did not fail for invalid conditions" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
err = src . SetModifiedSinceCond ( time . Date ( 2014 , time . April , 0 , 0 , 0 , 0 , 0 , time . UTC ) )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetModifiedSinceCond failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
err = src . SetMatchETagCond ( objInfo . ETag )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetMatchETagCond failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
dst , err := minio . NewDestinationInfo ( bucketName + "-copy" , objectName + "-copy" , nil , nil )
args [ "dst" ] = dst
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "NewDestinationInfo failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
// Perform the Copy
err = c . CopyObject ( dst , src )
if err != nil {
logError ( testName , function , args , startTime , "" , "CopyObject failed" , err )
return
}
// Source object
r , err = c . GetObject ( bucketName , objectName , minio . GetObjectOptions { } )
if err != nil {
logError ( testName , function , args , startTime , "" , "GetObject failed" , err )
return
}
// Destination object
readerCopy , err := c . GetObject ( bucketName + "-copy" , objectName + "-copy" , minio . GetObjectOptions { } )
if err != nil {
logError ( testName , function , args , startTime , "" , "GetObject failed" , err )
return
}
// Check the various fields of source object against destination object.
objInfo , err = r . Stat ( )
if err != nil {
logError ( testName , function , args , startTime , "" , "Stat failed" , err )
return
}
objInfoCopy , err := readerCopy . Stat ( )
if err != nil {
logError ( testName , function , args , startTime , "" , "Stat failed" , err )
return
}
if objInfo . Size != objInfoCopy . Size {
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( objInfoCopy . Size ) + ", got " + string ( objInfo . Size ) , err )
return
}
// Close all the get readers before proceeding with CopyObject operations.
r . Close ( )
readerCopy . Close ( )
// CopyObject again but with wrong conditions
src = minio . NewSourceInfo ( bucketName , objectName , nil )
err = src . SetUnmodifiedSinceCond ( time . Date ( 2014 , time . April , 0 , 0 , 0 , 0 , 0 , time . UTC ) )
if err != nil {
logError ( testName , function , args , startTime , "" , "SetUnmodifiedSinceCond failed" , err )
return
}
err = src . SetMatchETagExceptCond ( objInfo . ETag )
if err != nil {
logError ( testName , function , args , startTime , "" , "SetMatchETagExceptCond failed" , err )
return
}
// Perform the Copy which should fail
err = c . CopyObject ( dst , src )
if err == nil {
logError ( testName , function , args , startTime , "" , "CopyObject did not fail for invalid conditions" , err )
return
}
// Perform the Copy which should update only metadata.
src = minio . NewSourceInfo ( bucketName , objectName , nil )
dst , err = minio . NewDestinationInfo ( bucketName , objectName , nil , map [ string ] string {
"Copy" : "should be same" ,
} )
args [ "dst" ] = dst
args [ "src" ] = src
if err != nil {
logError ( testName , function , args , startTime , "" , "NewDestinationInfo failed" , err )
return
}
err = c . CopyObject ( dst , src )
if err != nil {
logError ( testName , function , args , startTime , "" , "CopyObject shouldn't fail" , err )
return
}
2018-08-01 17:43:44 +00:00
oi , err := c . StatObject ( bucketName , objectName , minio . StatObjectOptions { } )
if err != nil {
logError ( testName , function , args , startTime , "" , "StatObject failed" , err )
return
}
2018-03-30 10:33:40 +00:00
stOpts := minio . StatObjectOptions { }
2018-08-01 17:43:44 +00:00
stOpts . SetMatchETag ( oi . ETag )
2018-03-30 10:33:40 +00:00
objInfo , err = c . StatObject ( bucketName , objectName , stOpts )
if err != nil {
logError ( testName , function , args , startTime , "" , "CopyObject ETag should match and not fail" , err )
return
}
if objInfo . Metadata . Get ( "x-amz-meta-copy" ) != "should be same" {
logError ( testName , function , args , startTime , "" , "CopyObject modified metadata should match" , err )
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
return
}
if err = cleanupBucket ( bucketName + "-copy" , c ) ; err != nil {
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
return
}
successLogger ( testName , function , args , startTime ) . Info ( )
}
// Tests SSE-C get object ReaderSeeker interface methods.
func testEncryptedGetObjectReadSeekFunctional ( ) {
// initialize logging params
startTime := time . Now ( )
testName := getFuncName ( )
function := "GetObject(bucketName, objectName)"
args := map [ string ] interface { } { }
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . New (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
return
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
return
}
defer func ( ) {
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
return
}
} ( )
// Generate 65MiB of data.
bufSize := dataFileMap [ "datafile-65-MB" ]
var reader = getDataReader ( "datafile-65-MB" )
defer reader . Close ( )
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
args [ "objectName" ] = objectName
buf , err := ioutil . ReadAll ( reader )
if err != nil {
logError ( testName , function , args , startTime , "" , "ReadAll failed" , err )
return
}
// Save the data
n , err := c . PutObject ( bucketName , objectName , bytes . NewReader ( buf ) , int64 ( len ( buf ) ) , minio . PutObjectOptions {
ContentType : "binary/octet-stream" ,
ServerSideEncryption : encrypt . DefaultPBKDF ( [ ] byte ( "correct horse battery staple" ) , [ ] byte ( bucketName + objectName ) ) ,
} )
if err != nil {
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
return
}
if n != int64 ( bufSize ) {
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( bufSize ) ) + ", got " + string ( n ) , err )
return
}
// Read the data back
r , err := c . GetObject ( bucketName , objectName , minio . GetObjectOptions {
ServerSideEncryption : encrypt . DefaultPBKDF ( [ ] byte ( "correct horse battery staple" ) , [ ] byte ( bucketName + objectName ) ) ,
} )
if err != nil {
logError ( testName , function , args , startTime , "" , "GetObject failed" , err )
return
}
defer r . Close ( )
st , err := r . Stat ( )
if err != nil {
logError ( testName , function , args , startTime , "" , "Stat object failed" , err )
return
}
if st . Size != int64 ( bufSize ) {
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( bufSize ) ) + ", got " + string ( st . Size ) , err )
return
}
// This following function helps us to compare data from the reader after seek
// with the data from the original buffer
cmpData := func ( r io . Reader , start , end int ) {
if end - start == 0 {
return
}
buffer := bytes . NewBuffer ( [ ] byte { } )
if _ , err := io . CopyN ( buffer , r , int64 ( bufSize ) ) ; err != nil {
if err != io . EOF {
logError ( testName , function , args , startTime , "" , "CopyN failed" , err )
return
}
}
if ! bytes . Equal ( buf [ start : end ] , buffer . Bytes ( ) ) {
logError ( testName , function , args , startTime , "" , "Incorrect read bytes v/s original buffer" , err )
return
}
}
testCases := [ ] struct {
offset int64
whence int
pos int64
err error
shouldCmp bool
start int
end int
} {
// Start from offset 0, fetch data and compare
{ 0 , 0 , 0 , nil , true , 0 , 0 } ,
// Start from offset 2048, fetch data and compare
{ 2048 , 0 , 2048 , nil , true , 2048 , bufSize } ,
// Start from offset larger than possible
{ int64 ( bufSize ) + 1024 , 0 , 0 , io . EOF , false , 0 , 0 } ,
// Move to offset 0 without comparing
{ 0 , 0 , 0 , nil , false , 0 , 0 } ,
// Move one step forward and compare
{ 1 , 1 , 1 , nil , true , 1 , bufSize } ,
// Move larger than possible
{ int64 ( bufSize ) , 1 , 0 , io . EOF , false , 0 , 0 } ,
// Provide negative offset with CUR_SEEK
{ int64 ( - 1 ) , 1 , 0 , fmt . Errorf ( "Negative position not allowed for 1" ) , false , 0 , 0 } ,
// Test with whence SEEK_END and with positive offset
{ 1024 , 2 , 0 , io . EOF , false , 0 , 0 } ,
// Test with whence SEEK_END and with negative offset
{ - 1024 , 2 , int64 ( bufSize ) - 1024 , nil , true , bufSize - 1024 , bufSize } ,
// Test with whence SEEK_END and with large negative offset
{ - int64 ( bufSize ) * 2 , 2 , 0 , fmt . Errorf ( "Seeking at negative offset not allowed for 2" ) , false , 0 , 0 } ,
// Test with invalid whence
{ 0 , 3 , 0 , fmt . Errorf ( "Invalid whence 3" ) , false , 0 , 0 } ,
}
for i , testCase := range testCases {
// Perform seek operation
n , err := r . Seek ( testCase . offset , testCase . whence )
if err != nil && testCase . err == nil {
// We expected success.
logError ( testName , function , args , startTime , "" ,
fmt . Sprintf ( "Test %d, unexpected err value: expected: %s, found: %s" , i + 1 , testCase . err , err ) , err )
return
}
if err == nil && testCase . err != nil {
// We expected failure, but got success.
logError ( testName , function , args , startTime , "" ,
fmt . Sprintf ( "Test %d, unexpected err value: expected: %s, found: %s" , i + 1 , testCase . err , err ) , err )
return
}
if err != nil && testCase . err != nil {
if err . Error ( ) != testCase . err . Error ( ) {
// We expect a specific error
logError ( testName , function , args , startTime , "" ,
fmt . Sprintf ( "Test %d, unexpected err value: expected: %s, found: %s" , i + 1 , testCase . err , err ) , err )
return
}
}
// Check the returned seek pos
if n != testCase . pos {
logError ( testName , function , args , startTime , "" ,
fmt . Sprintf ( "Test %d, number of bytes seeked does not match, expected %d, got %d" , i + 1 , testCase . pos , n ) , err )
return
}
// Compare only if shouldCmp is activated
if testCase . shouldCmp {
cmpData ( r , testCase . start , testCase . end )
}
}
successLogger ( testName , function , args , startTime ) . Info ( )
}
// Tests SSE-C get object ReaderAt interface methods.
func testEncryptedGetObjectReadAtFunctional ( ) {
// initialize logging params
startTime := time . Now ( )
testName := getFuncName ( )
function := "GetObject(bucketName, objectName)"
args := map [ string ] interface { } { }
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . New (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
return
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
return
}
// Generate 65MiB of data.
bufSize := dataFileMap [ "datafile-65-MB" ]
var reader = getDataReader ( "datafile-65-MB" )
defer reader . Close ( )
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
args [ "objectName" ] = objectName
buf , err := ioutil . ReadAll ( reader )
if err != nil {
logError ( testName , function , args , startTime , "" , "ReadAll failed" , err )
return
}
// Save the data
n , err := c . PutObject ( bucketName , objectName , bytes . NewReader ( buf ) , int64 ( len ( buf ) ) , minio . PutObjectOptions {
ContentType : "binary/octet-stream" ,
ServerSideEncryption : encrypt . DefaultPBKDF ( [ ] byte ( "correct horse battery staple" ) , [ ] byte ( bucketName + objectName ) ) ,
} )
if err != nil {
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
return
}
if n != int64 ( bufSize ) {
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( bufSize ) ) + ", got " + string ( n ) , err )
return
}
// read the data back
r , err := c . GetObject ( bucketName , objectName , minio . GetObjectOptions {
ServerSideEncryption : encrypt . DefaultPBKDF ( [ ] byte ( "correct horse battery staple" ) , [ ] byte ( bucketName + objectName ) ) ,
} )
if err != nil {
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
return
}
defer r . Close ( )
offset := int64 ( 2048 )
// read directly
buf1 := make ( [ ] byte , 512 )
buf2 := make ( [ ] byte , 512 )
buf3 := make ( [ ] byte , 512 )
buf4 := make ( [ ] byte , 512 )
// Test readAt before stat is called such that objectInfo doesn't change.
m , err := r . ReadAt ( buf1 , offset )
if err != nil {
logError ( testName , function , args , startTime , "" , "ReadAt failed" , err )
return
}
if m != len ( buf1 ) {
logError ( testName , function , args , startTime , "" , "ReadAt read shorter bytes before reaching EOF, expected " + string ( len ( buf1 ) ) + ", got " + string ( m ) , err )
return
}
if ! bytes . Equal ( buf1 , buf [ offset : offset + 512 ] ) {
logError ( testName , function , args , startTime , "" , "Incorrect read between two ReadAt from same offset" , err )
return
}
offset += 512
st , err := r . Stat ( )
if err != nil {
logError ( testName , function , args , startTime , "" , "Stat failed" , err )
return
}
if st . Size != int64 ( bufSize ) {
logError ( testName , function , args , startTime , "" , "Number of bytes in stat does not match, expected " + string ( int64 ( bufSize ) ) + ", got " + string ( st . Size ) , err )
return
}
m , err = r . ReadAt ( buf2 , offset )
if err != nil {
logError ( testName , function , args , startTime , "" , "ReadAt failed" , err )
return
}
if m != len ( buf2 ) {
logError ( testName , function , args , startTime , "" , "ReadAt read shorter bytes before reaching EOF, expected " + string ( len ( buf2 ) ) + ", got " + string ( m ) , err )
return
}
if ! bytes . Equal ( buf2 , buf [ offset : offset + 512 ] ) {
logError ( testName , function , args , startTime , "" , "Incorrect read between two ReadAt from same offset" , err )
return
}
offset += 512
m , err = r . ReadAt ( buf3 , offset )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-03-30 10:33:40 +00:00
logError ( testName , function , args , startTime , "" , "ReadAt failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
if m != len ( buf3 ) {
logError ( testName , function , args , startTime , "" , "ReadAt read shorter bytes before reaching EOF, expected " + string ( len ( buf3 ) ) + ", got " + string ( m ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
if ! bytes . Equal ( buf3 , buf [ offset : offset + 512 ] ) {
logError ( testName , function , args , startTime , "" , "Incorrect read between two ReadAt from same offset" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
offset += 512
m , err = r . ReadAt ( buf4 , offset )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-03-30 10:33:40 +00:00
logError ( testName , function , args , startTime , "" , "ReadAt failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
if m != len ( buf4 ) {
logError ( testName , function , args , startTime , "" , "ReadAt read shorter bytes before reaching EOF, expected " + string ( len ( buf4 ) ) + ", got " + string ( m ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
if ! bytes . Equal ( buf4 , buf [ offset : offset + 512 ] ) {
logError ( testName , function , args , startTime , "" , "Incorrect read between two ReadAt from same offset" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
buf5 := make ( [ ] byte , n )
// Read the whole object.
m , err = r . ReadAt ( buf5 , 0 )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-03-30 10:33:40 +00:00
if err != io . EOF {
logError ( testName , function , args , startTime , "" , "ReadAt failed" , err )
return
}
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
if m != len ( buf5 ) {
logError ( testName , function , args , startTime , "" , "ReadAt read shorter bytes before reaching EOF, expected " + string ( len ( buf5 ) ) + ", got " + string ( m ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
if ! bytes . Equal ( buf , buf5 ) {
logError ( testName , function , args , startTime , "" , "Incorrect data read in GetObject, than what was previously uploaded" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
buf6 := make ( [ ] byte , n + 1 )
// Read the whole object and beyond.
_ , err = r . ReadAt ( buf6 , 0 )
if err != nil {
if err != io . EOF {
logError ( testName , function , args , startTime , "" , "ReadAt failed" , err )
return
}
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-12-08 19:45:59 +00:00
}
// TestEncryptionPutGet tests client side encryption
func testEncryptionPutGet ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2018-03-30 10:33:40 +00:00
function := "PutEncryptedObject(bucketName, objectName, reader, sse)"
2017-12-08 19:45:59 +00:00
args := map [ string ] interface { } {
2018-03-30 10:33:40 +00:00
"bucketName" : "" ,
"objectName" : "" ,
"sse" : "" ,
2017-12-08 19:45:59 +00:00
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object
c , err := minio . NewV4 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-12-08 19:45:59 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
testCases := [ ] struct {
2018-03-30 10:33:40 +00:00
buf [ ] byte
2017-12-08 19:45:59 +00:00
} {
2018-03-30 10:33:40 +00:00
{ buf : bytes . Repeat ( [ ] byte ( "F" ) , 1 ) } ,
{ buf : bytes . Repeat ( [ ] byte ( "F" ) , 15 ) } ,
{ buf : bytes . Repeat ( [ ] byte ( "F" ) , 16 ) } ,
{ buf : bytes . Repeat ( [ ] byte ( "F" ) , 17 ) } ,
{ buf : bytes . Repeat ( [ ] byte ( "F" ) , 31 ) } ,
{ buf : bytes . Repeat ( [ ] byte ( "F" ) , 32 ) } ,
{ buf : bytes . Repeat ( [ ] byte ( "F" ) , 33 ) } ,
{ buf : bytes . Repeat ( [ ] byte ( "F" ) , 1024 ) } ,
{ buf : bytes . Repeat ( [ ] byte ( "F" ) , 1024 * 2 ) } ,
{ buf : bytes . Repeat ( [ ] byte ( "F" ) , 1024 * 1024 ) } ,
2017-12-08 19:45:59 +00:00
}
2018-03-30 10:33:40 +00:00
const password = "correct horse battery staple" // https://xkcd.com/936/
2017-12-08 19:45:59 +00:00
for i , testCase := range testCases {
// Generate a random object name
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
args [ "objectName" ] = objectName
// Secured object
2018-03-30 10:33:40 +00:00
sse := encrypt . DefaultPBKDF ( [ ] byte ( password ) , [ ] byte ( bucketName + objectName ) )
args [ "sse" ] = sse
2017-12-08 19:45:59 +00:00
// Put encrypted data
2018-03-30 10:33:40 +00:00
_ , err = c . PutObject ( bucketName , objectName , bytes . NewReader ( testCase . buf ) , int64 ( len ( testCase . buf ) ) , minio . PutObjectOptions { ServerSideEncryption : sse } )
2017-12-08 19:45:59 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutEncryptedObject failed" , err )
2017-12-08 19:45:59 +00:00
return
}
// Read the data back
2018-03-30 10:33:40 +00:00
r , err := c . GetObject ( bucketName , objectName , minio . GetObjectOptions { ServerSideEncryption : sse } )
2017-12-08 19:45:59 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetEncryptedObject failed" , err )
2017-12-08 19:45:59 +00:00
return
}
defer r . Close ( )
// Compare the sent object with the received one
recvBuffer := bytes . NewBuffer ( [ ] byte { } )
if _ , err = io . Copy ( recvBuffer , r ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Test " + string ( i + 1 ) + ", error: " + err . Error ( ) , err )
2017-12-08 19:45:59 +00:00
return
}
if recvBuffer . Len ( ) != len ( testCase . buf ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Test " + string ( i + 1 ) + ", Number of bytes of received object does not match, expected " + string ( len ( testCase . buf ) ) + ", got " + string ( recvBuffer . Len ( ) ) , err )
2017-12-08 19:45:59 +00:00
return
}
if ! bytes . Equal ( testCase . buf , recvBuffer . Bytes ( ) ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Test " + string ( i + 1 ) + ", Encrypted sent is not equal to decrypted, expected " + string ( testCase . buf ) + ", got " + string ( recvBuffer . Bytes ( ) ) , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-12-08 19:45:59 +00:00
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// TestEncryptionFPut tests client side encryption
func testEncryptionFPut ( ) {
2017-09-13 12:09:48 +00:00
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2018-03-30 10:33:40 +00:00
function := "FPutEncryptedObject(bucketName, objectName, filePath, contentType, sse)"
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } {
2018-03-30 10:33:40 +00:00
"bucketName" : "" ,
"objectName" : "" ,
"filePath" : "" ,
"contentType" : "" ,
"sse" : "" ,
2017-09-13 12:09:48 +00:00
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object
c , err := minio . NewV4 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Object custom metadata
customContentType := "custom/contenttype"
args [ "metadata" ] = customContentType
testCases := [ ] struct {
2018-03-30 10:33:40 +00:00
buf [ ] byte
2017-09-13 12:09:48 +00:00
} {
2018-03-30 10:33:40 +00:00
{ buf : bytes . Repeat ( [ ] byte ( "F" ) , 0 ) } ,
{ buf : bytes . Repeat ( [ ] byte ( "F" ) , 1 ) } ,
{ buf : bytes . Repeat ( [ ] byte ( "F" ) , 15 ) } ,
{ buf : bytes . Repeat ( [ ] byte ( "F" ) , 16 ) } ,
{ buf : bytes . Repeat ( [ ] byte ( "F" ) , 17 ) } ,
{ buf : bytes . Repeat ( [ ] byte ( "F" ) , 31 ) } ,
{ buf : bytes . Repeat ( [ ] byte ( "F" ) , 32 ) } ,
{ buf : bytes . Repeat ( [ ] byte ( "F" ) , 33 ) } ,
{ buf : bytes . Repeat ( [ ] byte ( "F" ) , 1024 ) } ,
{ buf : bytes . Repeat ( [ ] byte ( "F" ) , 1024 * 2 ) } ,
{ buf : bytes . Repeat ( [ ] byte ( "F" ) , 1024 * 1024 ) } ,
}
const password = "correct horse battery staple" // https://xkcd.com/936/
2017-09-13 12:09:48 +00:00
for i , testCase := range testCases {
// Generate a random object name
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
args [ "objectName" ] = objectName
// Secured object
2018-03-30 10:33:40 +00:00
sse := encrypt . DefaultPBKDF ( [ ] byte ( password ) , [ ] byte ( bucketName + objectName ) )
args [ "sse" ] = sse
2017-09-13 12:09:48 +00:00
2017-12-08 19:45:59 +00:00
// Generate a random file name.
fileName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
file , err := os . Create ( fileName )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "file create failed" , err )
2017-12-08 19:45:59 +00:00
return
}
_ , err = file . Write ( testCase . buf )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "file write failed" , err )
2017-12-08 19:45:59 +00:00
return
}
file . Close ( )
// Put encrypted data
2018-03-30 10:33:40 +00:00
if _ , err = c . FPutObject ( bucketName , objectName , fileName , minio . PutObjectOptions { ServerSideEncryption : sse } ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "FPutEncryptedObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Read the data back
2018-03-30 10:33:40 +00:00
r , err := c . GetObject ( bucketName , objectName , minio . GetObjectOptions { ServerSideEncryption : sse } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetEncryptedObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
defer r . Close ( )
// Compare the sent object with the received one
recvBuffer := bytes . NewBuffer ( [ ] byte { } )
if _ , err = io . Copy ( recvBuffer , r ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Test " + string ( i + 1 ) + ", error: " + err . Error ( ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if recvBuffer . Len ( ) != len ( testCase . buf ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Test " + string ( i + 1 ) + ", Number of bytes of received object does not match, expected " + string ( len ( testCase . buf ) ) + ", got " + string ( recvBuffer . Len ( ) ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( testCase . buf , recvBuffer . Bytes ( ) ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Test " + string ( i + 1 ) + ", Encrypted sent is not equal to decrypted, expected " + string ( testCase . buf ) + ", got " + string ( recvBuffer . Bytes ( ) ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if err = os . Remove ( fileName ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File remove failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
func testBucketNotification ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-09-13 12:09:48 +00:00
function := "SetBucketNotification(bucketName)"
args := map [ string ] interface { } {
"bucketName" : "" ,
}
if os . Getenv ( "NOTIFY_BUCKET" ) == "" ||
os . Getenv ( "NOTIFY_SERVICE" ) == "" ||
os . Getenv ( "NOTIFY_REGION" ) == "" ||
os . Getenv ( "NOTIFY_ACCOUNTID" ) == "" ||
os . Getenv ( "NOTIFY_RESOURCE" ) == "" {
2018-01-23 18:40:42 +00:00
ignoredLog ( testName , function , args , startTime , "Skipped notification test as it is not configured" ) . Info ( )
2017-09-13 12:09:48 +00:00
return
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
c , err := minio . New (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable to debug
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
bucketName := os . Getenv ( "NOTIFY_BUCKET" )
args [ "bucketName" ] = bucketName
topicArn := minio . NewArn ( "aws" , os . Getenv ( "NOTIFY_SERVICE" ) , os . Getenv ( "NOTIFY_REGION" ) , os . Getenv ( "NOTIFY_ACCOUNTID" ) , os . Getenv ( "NOTIFY_RESOURCE" ) )
queueArn := minio . NewArn ( "aws" , "dummy-service" , "dummy-region" , "dummy-accountid" , "dummy-resource" )
topicConfig := minio . NewNotificationConfig ( topicArn )
topicConfig . AddEvents ( minio . ObjectCreatedAll , minio . ObjectRemovedAll )
topicConfig . AddFilterSuffix ( "jpg" )
queueConfig := minio . NewNotificationConfig ( queueArn )
queueConfig . AddEvents ( minio . ObjectCreatedAll )
queueConfig . AddFilterPrefix ( "photos/" )
bNotification := minio . BucketNotification { }
bNotification . AddTopic ( topicConfig )
// Add the same topicConfig again, should have no effect
// because it is duplicated
bNotification . AddTopic ( topicConfig )
if len ( bNotification . TopicConfigs ) != 1 {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Duplicate entry added" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Add and remove a queue config
bNotification . AddQueue ( queueConfig )
bNotification . RemoveQueueByArn ( queueArn )
err = c . SetBucketNotification ( bucketName , bNotification )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetBucketNotification failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
bNotification , err = c . GetBucketNotification ( bucketName )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetBucketNotification failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if len ( bNotification . TopicConfigs ) != 1 {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Topic config is empty" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if bNotification . TopicConfigs [ 0 ] . Filter . S3Key . FilterRules [ 0 ] . Value != "jpg" {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Couldn't get the suffix" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
err = c . RemoveAllBucketNotification ( bucketName )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "RemoveAllBucketNotification failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Tests comprehensive list of all methods.
func testFunctional ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-09-13 12:09:48 +00:00
function := "testFunctional()"
2018-03-30 10:33:40 +00:00
functionAll := ""
2018-01-23 18:40:42 +00:00
args := map [ string ] interface { } { }
2017-09-13 12:09:48 +00:00
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
c , err := minio . New (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , nil , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable to debug
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
// Make a new bucket.
function = "MakeBucket(bucketName, region)"
2018-03-30 10:33:40 +00:00
functionAll = "MakeBucket(bucketName, region)"
2018-01-23 18:40:42 +00:00
args [ "bucketName" ] = bucketName
err = c . MakeBucket ( bucketName , "us-east-1" )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Generate a random file name.
fileName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
file , err := os . Create ( fileName )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
for i := 0 ; i < 3 ; i ++ {
buf := make ( [ ] byte , rand . Intn ( 1 << 19 ) )
_ , err = file . Write ( buf )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File write failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
}
file . Close ( )
// Verify if bucket exits and you have access.
var exists bool
function = "BucketExists(bucketName)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2017-09-13 12:09:48 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
}
2018-01-23 18:40:42 +00:00
exists , err = c . BucketExists ( bucketName )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "BucketExists failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if ! exists {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Could not find the bucket" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Asserting the default bucket policy.
2018-08-01 17:43:44 +00:00
function = "GetBucketPolicy(bucketName)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2017-09-13 12:09:48 +00:00
args = map [ string ] interface { } {
2018-08-01 17:43:44 +00:00
"bucketName" : bucketName ,
2017-09-13 12:09:48 +00:00
}
2018-08-01 17:43:44 +00:00
nilPolicy , err := c . GetBucketPolicy ( bucketName )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetBucketPolicy failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-08-01 17:43:44 +00:00
if nilPolicy != "" {
logError ( testName , function , args , startTime , "" , "policy should be set to nil" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
2017-09-13 12:09:48 +00:00
// Set the bucket policy to 'public readonly'.
2018-08-01 17:43:44 +00:00
function = "SetBucketPolicy(bucketName, readOnlyPolicy)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2018-08-01 17:43:44 +00:00
readOnlyPolicy := ` { "Version":"2012-10-17","Statement":[ { "Effect":"Allow","Principal": { "AWS":["*"]},"Action":["s3:ListBucket"],"Resource":["arn:aws:s3::: ` + bucketName + ` "]}]} `
2017-09-13 12:09:48 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
2018-08-01 17:43:44 +00:00
"bucketPolicy" : readOnlyPolicy ,
2017-09-13 12:09:48 +00:00
}
2018-08-01 17:43:44 +00:00
err = c . SetBucketPolicy ( bucketName , readOnlyPolicy )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetBucketPolicy failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// should return policy `readonly`.
2018-08-01 17:43:44 +00:00
function = "GetBucketPolicy(bucketName)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2017-09-13 12:09:48 +00:00
args = map [ string ] interface { } {
2018-08-01 17:43:44 +00:00
"bucketName" : bucketName ,
2017-09-13 12:09:48 +00:00
}
2018-08-01 17:43:44 +00:00
_ , err = c . GetBucketPolicy ( bucketName )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetBucketPolicy failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Make the bucket 'public writeonly'.
2018-08-01 17:43:44 +00:00
function = "SetBucketPolicy(bucketName, writeOnlyPolicy)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2018-08-01 17:43:44 +00:00
writeOnlyPolicy := ` { "Version":"2012-10-17","Statement":[ { "Effect":"Allow","Principal": { "AWS":["*"]},"Action":["s3:ListBucketMultipartUploads"],"Resource":["arn:aws:s3::: ` + bucketName + ` "]}]} `
2017-09-13 12:09:48 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
2018-08-01 17:43:44 +00:00
"bucketPolicy" : writeOnlyPolicy ,
2017-09-13 12:09:48 +00:00
}
2018-08-01 17:43:44 +00:00
err = c . SetBucketPolicy ( bucketName , writeOnlyPolicy )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetBucketPolicy failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// should return policy `writeonly`.
2018-08-01 17:43:44 +00:00
function = "GetBucketPolicy(bucketName)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2017-09-13 12:09:48 +00:00
args = map [ string ] interface { } {
2018-08-01 17:43:44 +00:00
"bucketName" : bucketName ,
2017-09-13 12:09:48 +00:00
}
2018-08-01 17:43:44 +00:00
_ , err = c . GetBucketPolicy ( bucketName )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetBucketPolicy failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-08-01 17:43:44 +00:00
2017-09-13 12:09:48 +00:00
// Make the bucket 'public read/write'.
2018-08-01 17:43:44 +00:00
function = "SetBucketPolicy(bucketName, readWritePolicy)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2018-08-01 17:43:44 +00:00
readWritePolicy := ` { "Version":"2012-10-17","Statement":[ { "Effect":"Allow","Principal": { "AWS":["*"]},"Action":["s3:ListBucket","s3:ListBucketMultipartUploads"],"Resource":["arn:aws:s3::: ` + bucketName + ` "]}]} `
2017-09-13 12:09:48 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
2018-08-01 17:43:44 +00:00
"bucketPolicy" : readWritePolicy ,
2017-09-13 12:09:48 +00:00
}
2018-08-01 17:43:44 +00:00
err = c . SetBucketPolicy ( bucketName , readWritePolicy )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetBucketPolicy failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// should return policy `readwrite`.
2018-08-01 17:43:44 +00:00
function = "GetBucketPolicy(bucketName)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2017-09-13 12:09:48 +00:00
args = map [ string ] interface { } {
2018-08-01 17:43:44 +00:00
"bucketName" : bucketName ,
2017-09-13 12:09:48 +00:00
}
2018-08-01 17:43:44 +00:00
_ , err = c . GetBucketPolicy ( bucketName )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetBucketPolicy failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-08-01 17:43:44 +00:00
2017-09-13 12:09:48 +00:00
// List all buckets.
function = "ListBuckets()"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2017-09-13 12:09:48 +00:00
args = nil
2018-01-23 18:40:42 +00:00
buckets , err := c . ListBuckets ( )
2017-09-13 12:09:48 +00:00
if len ( buckets ) == 0 {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Found bucket list to be empty" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ListBuckets failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Verify if previously created bucket is listed in list buckets.
bucketFound := false
for _ , bucket := range buckets {
if bucket . Name == bucketName {
bucketFound = true
}
}
// If bucket not found error out.
if ! bucketFound {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Bucket: " + bucketName + " not found" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
objectName := bucketName + "unique"
// Generate data
buf := bytes . Repeat ( [ ] byte ( "f" ) , 1 << 19 )
function = "PutObject(bucketName, objectName, reader, contentType)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2017-09-13 12:09:48 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName ,
"contentType" : "" ,
}
2017-12-08 19:45:59 +00:00
n , err := c . PutObject ( bucketName , objectName , bytes . NewReader ( buf ) , int64 ( len ( buf ) ) , minio . PutObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( len ( buf ) ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Length doesn't match, expected " + string ( int64 ( len ( buf ) ) ) + " got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName + "-nolength" ,
"contentType" : "binary/octet-stream" ,
}
2017-12-08 19:45:59 +00:00
n , err = c . PutObject ( bucketName , objectName + "-nolength" , bytes . NewReader ( buf ) , int64 ( len ( buf ) ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( len ( buf ) ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Length doesn't match, expected " + string ( int64 ( len ( buf ) ) ) + " got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Instantiate a done channel to close all listing.
doneCh := make ( chan struct { } )
defer close ( doneCh )
objFound := false
isRecursive := true // Recursive is true.
function = "ListObjects(bucketName, objectName, isRecursive, doneCh)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2017-09-13 12:09:48 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName ,
"isRecursive" : isRecursive ,
}
for obj := range c . ListObjects ( bucketName , objectName , isRecursive , doneCh ) {
if obj . Key == objectName {
objFound = true
break
}
}
if ! objFound {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Object " + objectName + " not found" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
objFound = false
isRecursive = true // Recursive is true.
function = "ListObjectsV2(bucketName, objectName, isRecursive, doneCh)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2017-09-13 12:09:48 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName ,
"isRecursive" : isRecursive ,
}
for obj := range c . ListObjectsV2 ( bucketName , objectName , isRecursive , doneCh ) {
if obj . Key == objectName {
objFound = true
break
}
}
if ! objFound {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Object " + objectName + " not found" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
incompObjNotFound := true
function = "ListIncompleteUploads(bucketName, objectName, isRecursive, doneCh)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2017-09-13 12:09:48 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName ,
"isRecursive" : isRecursive ,
}
for objIncompl := range c . ListIncompleteUploads ( bucketName , objectName , isRecursive , doneCh ) {
if objIncompl . Key != "" {
incompObjNotFound = false
break
}
}
if ! incompObjNotFound {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Unexpected dangling incomplete upload found" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
function = "GetObject(bucketName, objectName)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2017-09-13 12:09:48 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName ,
}
2018-01-23 18:40:42 +00:00
newReader , err := c . GetObject ( bucketName , objectName , minio . GetObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
newReadBytes , err := ioutil . ReadAll ( newReader )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAll failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( newReadBytes , buf ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetObject bytes mismatch" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
newReader . Close ( )
2017-09-13 12:09:48 +00:00
function = "FGetObject(bucketName, objectName, fileName)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2017-09-13 12:09:48 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName ,
"fileName" : fileName + "-f" ,
}
2018-01-23 18:40:42 +00:00
err = c . FGetObject ( bucketName , objectName , fileName + "-f" , minio . GetObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "FGetObject failed" , err )
2017-12-08 19:45:59 +00:00
return
}
function = "PresignedHeadObject(bucketName, objectName, expires, reqParams)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2017-12-08 19:45:59 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : "" ,
"expires" : 3600 * time . Second ,
}
if _ , err = c . PresignedHeadObject ( bucketName , "" , 3600 * time . Second , nil ) ; err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedHeadObject success" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Generate presigned HEAD object url.
function = "PresignedHeadObject(bucketName, objectName, expires, reqParams)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2017-09-13 12:09:48 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName ,
"expires" : 3600 * time . Second ,
}
2018-01-23 18:40:42 +00:00
presignedHeadURL , err := c . PresignedHeadObject ( bucketName , objectName , 3600 * time . Second , nil )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedHeadObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Verify if presigned url works.
resp , err := http . Head ( presignedHeadURL . String ( ) )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedHeadObject response incorrect" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if resp . StatusCode != http . StatusOK {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedHeadObject response incorrect, status " + string ( resp . StatusCode ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if resp . Header . Get ( "ETag" ) == "" {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedHeadObject response incorrect" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
resp . Body . Close ( )
2017-12-08 19:45:59 +00:00
function = "PresignedGetObject(bucketName, objectName, expires, reqParams)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2017-12-08 19:45:59 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : "" ,
"expires" : 3600 * time . Second ,
}
2018-01-23 18:40:42 +00:00
_ , err = c . PresignedGetObject ( bucketName , "" , 3600 * time . Second , nil )
2017-12-08 19:45:59 +00:00
if err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedGetObject success" , err )
2017-12-08 19:45:59 +00:00
return
}
2017-09-13 12:09:48 +00:00
// Generate presigned GET object url.
function = "PresignedGetObject(bucketName, objectName, expires, reqParams)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2017-09-13 12:09:48 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName ,
"expires" : 3600 * time . Second ,
}
2018-01-23 18:40:42 +00:00
presignedGetURL , err := c . PresignedGetObject ( bucketName , objectName , 3600 * time . Second , nil )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedGetObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Verify if presigned url works.
resp , err = http . Get ( presignedGetURL . String ( ) )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedGetObject response incorrect" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if resp . StatusCode != http . StatusOK {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedGetObject response incorrect, status " + string ( resp . StatusCode ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
newPresignedBytes , err := ioutil . ReadAll ( resp . Body )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedGetObject response incorrect" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
resp . Body . Close ( )
if ! bytes . Equal ( newPresignedBytes , buf ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedGetObject response incorrect" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Set request parameters.
reqParams := make ( url . Values )
reqParams . Set ( "response-content-disposition" , "attachment; filename=\"test.txt\"" )
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName ,
"expires" : 3600 * time . Second ,
"reqParams" : reqParams ,
}
2018-01-23 18:40:42 +00:00
presignedGetURL , err = c . PresignedGetObject ( bucketName , objectName , 3600 * time . Second , reqParams )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedGetObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Verify if presigned url works.
resp , err = http . Get ( presignedGetURL . String ( ) )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedGetObject response incorrect" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if resp . StatusCode != http . StatusOK {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedGetObject response incorrect, status " + string ( resp . StatusCode ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
newPresignedBytes , err = ioutil . ReadAll ( resp . Body )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedGetObject response incorrect" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( newPresignedBytes , buf ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Bytes mismatch for presigned GET URL" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if resp . Header . Get ( "Content-Disposition" ) != "attachment; filename=\"test.txt\"" {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "wrong Content-Disposition received " + string ( resp . Header . Get ( "Content-Disposition" ) ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
function = "PresignedPutObject(bucketName, objectName, expires)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2017-12-08 19:45:59 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : "" ,
"expires" : 3600 * time . Second ,
}
2018-01-23 18:40:42 +00:00
_ , err = c . PresignedPutObject ( bucketName , "" , 3600 * time . Second )
2017-12-08 19:45:59 +00:00
if err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedPutObject success" , err )
2017-12-08 19:45:59 +00:00
return
}
2017-09-13 12:09:48 +00:00
function = "PresignedPutObject(bucketName, objectName, expires)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2017-09-13 12:09:48 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
2018-01-23 18:40:42 +00:00
"objectName" : objectName + "-presigned" ,
2017-09-13 12:09:48 +00:00
"expires" : 3600 * time . Second ,
}
2018-01-23 18:40:42 +00:00
presignedPutURL , err := c . PresignedPutObject ( bucketName , objectName + "-presigned" , 3600 * time . Second )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedPutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
buf = bytes . Repeat ( [ ] byte ( "g" ) , 1 << 19 )
req , err := http . NewRequest ( "PUT" , presignedPutURL . String ( ) , bytes . NewReader ( buf ) )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Couldn't make HTTP request with PresignedPutObject URL" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
httpClient := & http . Client {
// Setting a sensible time out of 30secs to wait for response
// headers. Request is pro-actively cancelled after 30secs
// with no response.
Timeout : 30 * time . Second ,
Transport : http . DefaultTransport ,
}
resp , err = httpClient . Do ( req )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedPutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
newReader , err = c . GetObject ( bucketName , objectName + "-presigned" , minio . GetObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetObject after PresignedPutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
newReadBytes , err = ioutil . ReadAll ( newReader )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAll after GetObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( newReadBytes , buf ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Bytes mismatch" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
function = "RemoveObject(bucketName, objectName)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2017-09-13 12:09:48 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName ,
}
2018-01-23 18:40:42 +00:00
err = c . RemoveObject ( bucketName , objectName )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "RemoveObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
args [ "objectName" ] = objectName + "-f"
2018-01-23 18:40:42 +00:00
err = c . RemoveObject ( bucketName , objectName + "-f" )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "RemoveObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
args [ "objectName" ] = objectName + "-nolength"
2018-01-23 18:40:42 +00:00
err = c . RemoveObject ( bucketName , objectName + "-nolength" )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "RemoveObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
args [ "objectName" ] = objectName + "-presigned"
2018-01-23 18:40:42 +00:00
err = c . RemoveObject ( bucketName , objectName + "-presigned" )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "RemoveObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
function = "RemoveBucket(bucketName)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2017-09-13 12:09:48 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
}
2018-01-23 18:40:42 +00:00
err = c . RemoveBucket ( bucketName )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "RemoveBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
err = c . RemoveBucket ( bucketName )
if err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "RemoveBucket did not fail for invalid bucket name" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if err . Error ( ) != "The specified bucket does not exist" {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "RemoveBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
2017-09-13 12:09:48 +00:00
if err = os . Remove ( fileName ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File Remove failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if err = os . Remove ( fileName + "-f" ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File Remove failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
successLogger ( testName , functionAll , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Test for validating GetObject Reader* methods functioning when the
// object is modified in the object store.
2018-01-23 18:40:42 +00:00
func testGetObjectModified ( ) {
2017-09-13 12:09:48 +00:00
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-09-13 12:09:48 +00:00
function := "GetObject(bucketName, objectName)"
2018-01-23 18:40:42 +00:00
args := map [ string ] interface { } { }
2017-09-13 12:09:48 +00:00
// Instantiate new minio client object.
c , err := minio . NewV4 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
2018-01-23 18:40:42 +00:00
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Make a new bucket.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
args [ "bucketName" ] = bucketName
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
defer c . RemoveBucket ( bucketName )
// Upload an object.
objectName := "myobject"
2018-01-23 18:40:42 +00:00
args [ "objectName" ] = objectName
2017-09-13 12:09:48 +00:00
content := "helloworld"
2017-12-08 19:45:59 +00:00
_ , err = c . PutObject ( bucketName , objectName , strings . NewReader ( content ) , int64 ( len ( content ) ) , minio . PutObjectOptions { ContentType : "application/text" } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Failed to upload " + objectName + ", to bucket " + bucketName , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
defer c . RemoveObject ( bucketName , objectName )
2017-12-08 19:45:59 +00:00
reader , err := c . GetObject ( bucketName , objectName , minio . GetObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Failed to GetObject " + objectName + ", from bucket " + bucketName , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
defer reader . Close ( )
// Read a few bytes of the object.
b := make ( [ ] byte , 5 )
n , err := reader . ReadAt ( b , 0 )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Failed to read object " + objectName + ", from bucket " + bucketName + " at an offset" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Upload different contents to the same object while object is being read.
newContent := "goodbyeworld"
2017-12-08 19:45:59 +00:00
_ , err = c . PutObject ( bucketName , objectName , strings . NewReader ( newContent ) , int64 ( len ( newContent ) ) , minio . PutObjectOptions { ContentType : "application/text" } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Failed to upload " + objectName + ", to bucket " + bucketName , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Confirm that a Stat() call in between doesn't change the Object's cached etag.
_ , err = reader . Stat ( )
expectedError := "At least one of the pre-conditions you specified did not hold"
if err . Error ( ) != expectedError {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Expected Stat to fail with error " + expectedError + ", but received " + err . Error ( ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Read again only to find object contents have been modified since last read.
_ , err = reader . ReadAt ( b , int64 ( n ) )
if err . Error ( ) != expectedError {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Expected ReadAt to fail with error " + expectedError + ", but received " + err . Error ( ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Test validates putObject to upload a file seeked at a given offset.
func testPutObjectUploadSeekedObject ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-09-13 12:09:48 +00:00
function := "PutObject(bucketName, objectName, fileToUpload, contentType)"
args := map [ string ] interface { } {
"bucketName" : "" ,
"objectName" : "" ,
"fileToUpload" : "" ,
"contentType" : "binary/octet-stream" ,
}
// Instantiate new minio client object.
c , err := minio . NewV4 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Make a new bucket.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
args [ "bucketName" ] = bucketName
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
defer c . RemoveBucket ( bucketName )
2017-12-08 19:45:59 +00:00
var tempfile * os . File
2017-09-13 12:09:48 +00:00
2017-12-08 19:45:59 +00:00
if fileName := getMintDataDirFilePath ( "datafile-100-kB" ) ; fileName != "" {
tempfile , err = os . Open ( fileName )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File open failed" , err )
2017-12-08 19:45:59 +00:00
return
}
args [ "fileToUpload" ] = fileName
2017-09-13 12:09:48 +00:00
} else {
2017-12-08 19:45:59 +00:00
tempfile , err = ioutil . TempFile ( "" , "minio-go-upload-test-" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "TempFile create failed" , err )
2017-12-08 19:45:59 +00:00
return
}
args [ "fileToUpload" ] = tempfile . Name ( )
// Generate 100kB data
if _ , err = io . Copy ( tempfile , getDataReader ( "datafile-100-kB" ) ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File copy failed" , err )
2017-12-08 19:45:59 +00:00
return
}
defer os . Remove ( tempfile . Name ( ) )
2017-09-13 12:09:48 +00:00
2017-12-08 19:45:59 +00:00
// Seek back to the beginning of the file.
tempfile . Seek ( 0 , 0 )
}
var length = 100 * humanize . KiByte
2017-09-13 12:09:48 +00:00
objectName := fmt . Sprintf ( "test-file-%v" , rand . Uint32 ( ) )
args [ "objectName" ] = objectName
offset := length / 2
2017-12-08 19:45:59 +00:00
if _ , err = tempfile . Seek ( int64 ( offset ) , 0 ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "TempFile seek failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
n , err := c . PutObject ( bucketName , objectName , tempfile , int64 ( length - offset ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( length - offset ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , fmt . Sprintf ( "Invalid length returned, expected %d got %d" , int64 ( length - offset ) , n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
tempfile . Close ( )
2017-12-08 19:45:59 +00:00
obj , err := c . GetObject ( bucketName , objectName , minio . GetObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
defer obj . Close ( )
2017-09-13 12:09:48 +00:00
n , err = obj . Seek ( int64 ( offset ) , 0 )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Seek failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( offset ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , fmt . Sprintf ( "Invalid offset returned, expected %d got %d" , int64 ( offset ) , n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
n , err = c . PutObject ( bucketName , objectName + "getobject" , obj , int64 ( length - offset ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( length - offset ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , fmt . Sprintf ( "Invalid offset returned, expected %d got %d" , int64 ( length - offset ) , n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Tests bucket re-create errors.
func testMakeBucketErrorV2 ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-09-13 12:09:48 +00:00
function := "MakeBucket(bucketName, region)"
args := map [ string ] interface { } {
"bucketName" : "" ,
"region" : "eu-west-1" ,
}
if os . Getenv ( serverEndpoint ) != "s3.amazonaws.com" {
2018-01-23 18:40:42 +00:00
ignoredLog ( testName , function , args , startTime , "Skipped region functional tests for non s3 runs" ) . Info ( )
2017-09-13 12:09:48 +00:00
return
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . NewV2 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio v2 client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
region := "eu-west-1"
2017-09-13 12:09:48 +00:00
args [ "bucketName" ] = bucketName
2018-01-23 18:40:42 +00:00
args [ "region" ] = region
2017-09-13 12:09:48 +00:00
// Make a new bucket in 'eu-west-1'.
2018-01-23 18:40:42 +00:00
if err = c . MakeBucket ( bucketName , region ) ; err != nil {
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
if err = c . MakeBucket ( bucketName , region ) ; err == nil {
logError ( testName , function , args , startTime , "" , "MakeBucket did not fail for existing bucket name" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Verify valid error response from server.
if minio . ToErrorResponse ( err ) . Code != "BucketAlreadyExists" &&
minio . ToErrorResponse ( err ) . Code != "BucketAlreadyOwnedByYou" {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Invalid error returned by server" , err )
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Test get object reader to not throw error on being closed twice.
func testGetObjectClosedTwiceV2 ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-09-13 12:09:48 +00:00
function := "MakeBucket(bucketName, region)"
args := map [ string ] interface { } {
"bucketName" : "" ,
"region" : "eu-west-1" ,
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . NewV2 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio v2 client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Generate 33K of data.
2017-12-08 19:45:59 +00:00
bufSize := dataFileMap [ "datafile-33-kB" ]
var reader = getDataReader ( "datafile-33-kB" )
2017-09-13 12:09:48 +00:00
defer reader . Close ( )
// Save the data
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
args [ "objectName" ] = objectName
2017-12-08 19:45:59 +00:00
n , err := c . PutObject ( bucketName , objectName , reader , int64 ( bufSize ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( bufSize ) + " got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Read the data back
2017-12-08 19:45:59 +00:00
r , err := c . GetObject ( bucketName , objectName , minio . GetObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
st , err := r . Stat ( )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Stat failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if st . Size != int64 ( bufSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( bufSize ) + " got " + string ( st . Size ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if err := r . Close ( ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Stat failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if err := r . Close ( ) ; err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Object is already closed, should return error" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Tests FPutObject hidden contentType setting
func testFPutObjectV2 ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-12-08 19:45:59 +00:00
function := "FPutObject(bucketName, objectName, fileName, opts)"
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } {
2017-12-08 19:45:59 +00:00
"bucketName" : "" ,
"objectName" : "" ,
"fileName" : "" ,
"opts" : "" ,
2017-09-13 12:09:48 +00:00
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . NewV2 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio v2 client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Make a temp file with 11*1024*1024 bytes of data.
file , err := ioutil . TempFile ( os . TempDir ( ) , "FPutObjectTest" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "TempFile creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
r := bytes . NewReader ( bytes . Repeat ( [ ] byte ( "b" ) , 11 * 1024 * 1024 ) )
n , err := io . CopyN ( file , r , 11 * 1024 * 1024 )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Copy failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( 11 * 1024 * 1024 ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( 11 * 1024 * 1024 ) ) + " got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Close the file pro-actively for windows.
err = file . Close ( )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File close failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Set base object name
objectName := bucketName + "FPutObject"
args [ "objectName" ] = objectName
args [ "fileName" ] = file . Name ( )
// Perform standard FPutObject with contentType provided (Expecting application/octet-stream)
2017-12-08 19:45:59 +00:00
n , err = c . FPutObject ( bucketName , objectName + "-standard" , file . Name ( ) , minio . PutObjectOptions { ContentType : "application/octet-stream" } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "FPutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( 11 * 1024 * 1024 ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( 11 * 1024 * 1024 ) ) + " got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Perform FPutObject with no contentType provided (Expecting application/octet-stream)
args [ "objectName" ] = objectName + "-Octet"
args [ "contentType" ] = ""
2017-12-08 19:45:59 +00:00
n , err = c . FPutObject ( bucketName , objectName + "-Octet" , file . Name ( ) , minio . PutObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "FPutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( 11 * 1024 * 1024 ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( 11 * 1024 * 1024 ) ) + " got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Add extension to temp file name
fileName := file . Name ( )
err = os . Rename ( file . Name ( ) , fileName + ".gtar" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Rename failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Perform FPutObject with no contentType provided (Expecting application/x-gtar)
args [ "objectName" ] = objectName + "-Octet"
args [ "contentType" ] = ""
args [ "fileName" ] = fileName + ".gtar"
2017-12-08 19:45:59 +00:00
n , err = c . FPutObject ( bucketName , objectName + "-GTar" , fileName + ".gtar" , minio . PutObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "FPutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( 11 * 1024 * 1024 ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( 11 * 1024 * 1024 ) ) + " got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Check headers
2017-12-08 19:45:59 +00:00
rStandard , err := c . StatObject ( bucketName , objectName + "-standard" , minio . StatObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "StatObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if rStandard . ContentType != "application/octet-stream" {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Content-Type headers mismatched, expected: application/octet-stream , got " + rStandard . ContentType , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
rOctet , err := c . StatObject ( bucketName , objectName + "-Octet" , minio . StatObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "StatObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if rOctet . ContentType != "application/octet-stream" {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Content-Type headers mismatched, expected: application/octet-stream , got " + rOctet . ContentType , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
rGTar , err := c . StatObject ( bucketName , objectName + "-GTar" , minio . StatObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "StatObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-08-01 17:43:44 +00:00
if rGTar . ContentType != "application/x-gtar" && rGTar . ContentType != "application/octet-stream" {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Content-Type headers mismatched, expected: application/x-gtar , got " + rGTar . ContentType , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
err = os . Remove ( fileName + ".gtar" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File remove failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Tests various bucket supported formats.
func testMakeBucketRegionsV2 ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-09-13 12:09:48 +00:00
function := "MakeBucket(bucketName, region)"
args := map [ string ] interface { } {
"bucketName" : "" ,
"region" : "eu-west-1" ,
}
if os . Getenv ( serverEndpoint ) != "s3.amazonaws.com" {
2018-01-23 18:40:42 +00:00
ignoredLog ( testName , function , args , startTime , "Skipped region functional tests for non s3 runs" ) . Info ( )
2017-09-13 12:09:48 +00:00
return
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . NewV2 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio v2 client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket in 'eu-central-1'.
if err = c . MakeBucket ( bucketName , "eu-west-1" ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Make a new bucket with '.' in its name, in 'us-west-2'. This
// request is internally staged into a path style instead of
// virtual host style.
if err = c . MakeBucket ( bucketName + ".withperiod" , "us-west-2" ) ; err != nil {
args [ "bucketName" ] = bucketName + ".withperiod"
args [ "region" ] = "us-west-2"
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName + ".withperiod" , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Tests get object ReaderSeeker interface methods.
func testGetObjectReadSeekFunctionalV2 ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-09-13 12:09:48 +00:00
function := "GetObject(bucketName, objectName)"
2018-01-23 18:40:42 +00:00
args := map [ string ] interface { } { }
2017-09-13 12:09:48 +00:00
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . NewV2 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio v2 client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Generate 33K of data.
2017-12-08 19:45:59 +00:00
bufSize := dataFileMap [ "datafile-33-kB" ]
var reader = getDataReader ( "datafile-33-kB" )
2017-09-13 12:09:48 +00:00
defer reader . Close ( )
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
args [ "objectName" ] = objectName
buf , err := ioutil . ReadAll ( reader )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAll failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Save the data.
2017-12-08 19:45:59 +00:00
n , err := c . PutObject ( bucketName , objectName , bytes . NewReader ( buf ) , int64 ( bufSize ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( bufSize ) ) + " got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Read the data back
2017-12-08 19:45:59 +00:00
r , err := c . GetObject ( bucketName , objectName , minio . GetObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
defer r . Close ( )
2017-09-13 12:09:48 +00:00
st , err := r . Stat ( )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Stat failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if st . Size != int64 ( bufSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes in stat does not match, expected " + string ( int64 ( bufSize ) ) + " got " + string ( st . Size ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
offset := int64 ( 2048 )
n , err = r . Seek ( offset , 0 )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Seek failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if n != offset {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of seeked bytes does not match, expected " + string ( offset ) + " got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
n , err = r . Seek ( 0 , 1 )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Seek failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if n != offset {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of seeked bytes does not match, expected " + string ( offset ) + " got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
_ , err = r . Seek ( offset , 2 )
if err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Seek on positive offset for whence '2' should error out" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
n , err = r . Seek ( - offset , 2 )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Seek failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if n != st . Size - offset {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of seeked bytes does not match, expected " + string ( st . Size - offset ) + " got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
var buffer1 bytes . Buffer
if _ , err = io . CopyN ( & buffer1 , r , st . Size ) ; err != nil {
if err != io . EOF {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Copy failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
}
if ! bytes . Equal ( buf [ len ( buf ) - int ( offset ) : ] , buffer1 . Bytes ( ) ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Incorrect read bytes v/s original buffer" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Seek again and read again.
n , err = r . Seek ( offset - 1 , 0 )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Seek failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if n != ( offset - 1 ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of seeked bytes does not match, expected " + string ( offset - 1 ) + " got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
var buffer2 bytes . Buffer
if _ , err = io . CopyN ( & buffer2 , r , st . Size ) ; err != nil {
if err != io . EOF {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Copy failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
}
// Verify now lesser bytes.
if ! bytes . Equal ( buf [ 2047 : ] , buffer2 . Bytes ( ) ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Incorrect read bytes v/s original buffer" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Tests get object ReaderAt interface methods.
func testGetObjectReadAtFunctionalV2 ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-09-13 12:09:48 +00:00
function := "GetObject(bucketName, objectName)"
2018-01-23 18:40:42 +00:00
args := map [ string ] interface { } { }
2017-09-13 12:09:48 +00:00
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . NewV2 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio v2 client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Generate 33K of data.
2017-12-08 19:45:59 +00:00
bufSize := dataFileMap [ "datafile-33-kB" ]
var reader = getDataReader ( "datafile-33-kB" )
2017-09-13 12:09:48 +00:00
defer reader . Close ( )
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
args [ "objectName" ] = objectName
buf , err := ioutil . ReadAll ( reader )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAll failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Save the data
2017-12-08 19:45:59 +00:00
n , err := c . PutObject ( bucketName , objectName , bytes . NewReader ( buf ) , int64 ( bufSize ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( bufSize ) + " got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Read the data back
2017-12-08 19:45:59 +00:00
r , err := c . GetObject ( bucketName , objectName , minio . GetObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
defer r . Close ( )
2017-09-13 12:09:48 +00:00
st , err := r . Stat ( )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Stat failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if st . Size != int64 ( bufSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( bufSize ) + " got " + string ( st . Size ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
offset := int64 ( 2048 )
// Read directly
buf2 := make ( [ ] byte , 512 )
buf3 := make ( [ ] byte , 512 )
buf4 := make ( [ ] byte , 512 )
m , err := r . ReadAt ( buf2 , offset )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAt failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if m != len ( buf2 ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAt read shorter bytes before reaching EOF, expected " + string ( len ( buf2 ) ) + " got " + string ( m ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( buf2 , buf [ offset : offset + 512 ] ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Incorrect read between two ReadAt from same offset" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
offset += 512
m , err = r . ReadAt ( buf3 , offset )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAt failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if m != len ( buf3 ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAt read shorter bytes before reaching EOF, expected " + string ( len ( buf3 ) ) + " got " + string ( m ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( buf3 , buf [ offset : offset + 512 ] ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Incorrect read between two ReadAt from same offset" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
offset += 512
m , err = r . ReadAt ( buf4 , offset )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAt failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if m != len ( buf4 ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAt read shorter bytes before reaching EOF, expected " + string ( len ( buf4 ) ) + " got " + string ( m ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( buf4 , buf [ offset : offset + 512 ] ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Incorrect read between two ReadAt from same offset" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
buf5 := make ( [ ] byte , n )
// Read the whole object.
m , err = r . ReadAt ( buf5 , 0 )
if err != nil {
if err != io . EOF {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAt failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
}
if m != len ( buf5 ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAt read shorter bytes before reaching EOF, expected " + string ( len ( buf5 ) ) + " got " + string ( m ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( buf , buf5 ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Incorrect data read in GetObject, than what was previously uploaded" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
buf6 := make ( [ ] byte , n + 1 )
// Read the whole object and beyond.
_ , err = r . ReadAt ( buf6 , 0 )
if err != nil {
if err != io . EOF {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAt failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Tests copy object
func testCopyObjectV2 ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-09-13 12:09:48 +00:00
function := "CopyObject(destination, source)"
2018-01-23 18:40:42 +00:00
args := map [ string ] interface { } { }
2017-09-13 12:09:48 +00:00
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object
c , err := minio . NewV2 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio v2 client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
// Make a new bucket in 'us-east-1' (source bucket).
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Make a new bucket in 'us-east-1' (destination bucket).
err = c . MakeBucket ( bucketName + "-copy" , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Generate 33K of data.
2017-12-08 19:45:59 +00:00
bufSize := dataFileMap [ "datafile-33-kB" ]
var reader = getDataReader ( "datafile-33-kB" )
2017-09-13 12:09:48 +00:00
defer reader . Close ( )
// Save the data
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
2017-12-08 19:45:59 +00:00
n , err := c . PutObject ( bucketName , objectName , reader , int64 ( bufSize ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( bufSize ) ) + " got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
r , err := c . GetObject ( bucketName , objectName , minio . GetObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Check the various fields of source object against destination object.
objInfo , err := r . Stat ( )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Stat failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
r . Close ( )
2017-09-13 12:09:48 +00:00
// Copy Source
src := minio . NewSourceInfo ( bucketName , objectName , nil )
2018-01-23 18:40:42 +00:00
args [ "source" ] = src
2017-09-13 12:09:48 +00:00
// Set copy conditions.
// All invalid conditions first.
err = src . SetModifiedSinceCond ( time . Date ( 1 , time . January , 1 , 0 , 0 , 0 , 0 , time . UTC ) )
if err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetModifiedSinceCond did not fail for invalid conditions" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
err = src . SetUnmodifiedSinceCond ( time . Date ( 1 , time . January , 1 , 0 , 0 , 0 , 0 , time . UTC ) )
if err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetUnmodifiedSinceCond did not fail for invalid conditions" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
err = src . SetMatchETagCond ( "" )
if err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetMatchETagCond did not fail for invalid conditions" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
err = src . SetMatchETagExceptCond ( "" )
if err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetMatchETagExceptCond did not fail for invalid conditions" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
err = src . SetModifiedSinceCond ( time . Date ( 2014 , time . April , 0 , 0 , 0 , 0 , 0 , time . UTC ) )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetModifiedSinceCond failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
err = src . SetMatchETagCond ( objInfo . ETag )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetMatchETagCond failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
dst , err := minio . NewDestinationInfo ( bucketName + "-copy" , objectName + "-copy" , nil , nil )
2018-01-23 18:40:42 +00:00
args [ "destination" ] = dst
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "NewDestinationInfo failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Perform the Copy
err = c . CopyObject ( dst , src )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "CopyObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Source object
2017-12-08 19:45:59 +00:00
r , err = c . GetObject ( bucketName , objectName , minio . GetObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Destination object
2017-12-08 19:45:59 +00:00
readerCopy , err := c . GetObject ( bucketName + "-copy" , objectName + "-copy" , minio . GetObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Check the various fields of source object against destination object.
objInfo , err = r . Stat ( )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Stat failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
objInfoCopy , err := readerCopy . Stat ( )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Stat failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if objInfo . Size != objInfoCopy . Size {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes does not match, expected " + string ( objInfoCopy . Size ) + " got " + string ( objInfo . Size ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
// Close all the readers.
r . Close ( )
readerCopy . Close ( )
2017-09-13 12:09:48 +00:00
// CopyObject again but with wrong conditions
src = minio . NewSourceInfo ( bucketName , objectName , nil )
err = src . SetUnmodifiedSinceCond ( time . Date ( 2014 , time . April , 0 , 0 , 0 , 0 , 0 , time . UTC ) )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetUnmodifiedSinceCond failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
err = src . SetMatchETagExceptCond ( objInfo . ETag )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetMatchETagExceptCond failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Perform the Copy which should fail
err = c . CopyObject ( dst , src )
if err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "CopyObject did not fail for invalid conditions" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if err = cleanupBucket ( bucketName + "-copy" , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
func testComposeObjectErrorCasesWrapper ( c * minio . Client ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
function := "ComposeObject(destination, sourceList)"
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } { }
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
// Make a new bucket in 'us-east-1' (source bucket).
err := c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Test that more than 10K source objects cannot be
// concatenated.
srcArr := [ 10001 ] minio . SourceInfo { }
srcSlice := srcArr [ : ]
dst , err := minio . NewDestinationInfo ( bucketName , "object" , nil , nil )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "NewDestinationInfo failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
args [ "destination" ] = dst
// Just explain about srcArr in args["sourceList"]
// to stop having 10,001 null headers logged
args [ "sourceList" ] = "source array of 10,001 elements"
2017-09-13 12:09:48 +00:00
if err := c . ComposeObject ( dst , srcSlice ) ; err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Expected error in ComposeObject" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
} else if err . Error ( ) != "There must be as least one and up to 10000 source objects." {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Got unexpected error" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Create a source with invalid offset spec and check that
// error is returned:
// 1. Create the source object.
const badSrcSize = 5 * 1024 * 1024
buf := bytes . Repeat ( [ ] byte ( "1" ) , badSrcSize )
2017-12-08 19:45:59 +00:00
_ , err = c . PutObject ( bucketName , "badObject" , bytes . NewReader ( buf ) , int64 ( len ( buf ) ) , minio . PutObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// 2. Set invalid range spec on the object (going beyond
// object size)
badSrc := minio . NewSourceInfo ( bucketName , "badObject" , nil )
err = badSrc . SetRange ( 1 , badSrcSize )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Setting NewSourceInfo failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// 3. ComposeObject call should fail.
if err := c . ComposeObject ( dst , [ ] minio . SourceInfo { badSrc } ) ; err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ComposeObject expected to fail" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
} else if ! strings . Contains ( err . Error ( ) , "has invalid segment-to-copy" ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Got invalid error" , err )
2017-12-08 19:45:59 +00:00
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Test expected error cases
func testComposeObjectErrorCasesV2 ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
function := "ComposeObject(destination, sourceList)"
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } { }
// Instantiate new minio client object
c , err := minio . NewV2 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio v2 client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
testComposeObjectErrorCasesWrapper ( c )
}
func testComposeMultipleSources ( c * minio . Client ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
function := "ComposeObject(destination, sourceList)"
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } {
"destination" : "" ,
2018-01-23 18:40:42 +00:00
"sourceList" : "" ,
2017-09-13 12:09:48 +00:00
}
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
// Make a new bucket in 'us-east-1' (source bucket).
err := c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Upload a small source object
const srcSize = 1024 * 1024 * 5
buf := bytes . Repeat ( [ ] byte ( "1" ) , srcSize )
2017-12-08 19:45:59 +00:00
_ , err = c . PutObject ( bucketName , "srcObject" , bytes . NewReader ( buf ) , int64 ( srcSize ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// We will append 10 copies of the object.
srcs := [ ] minio . SourceInfo { }
for i := 0 ; i < 10 ; i ++ {
srcs = append ( srcs , minio . NewSourceInfo ( bucketName , "srcObject" , nil ) )
}
// make the last part very small
err = srcs [ 9 ] . SetRange ( 0 , 0 )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetRange failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
args [ "sourceList" ] = srcs
2017-09-13 12:09:48 +00:00
dst , err := minio . NewDestinationInfo ( bucketName , "dstObject" , nil , nil )
args [ "destination" ] = dst
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "NewDestinationInfo failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
err = c . ComposeObject ( dst , srcs )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ComposeObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
objProps , err := c . StatObject ( bucketName , "dstObject" , minio . StatObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "StatObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if objProps . Size != 9 * srcSize + 1 {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Size mismatched! Expected " + string ( 10000 * srcSize ) + " got " + string ( objProps . Size ) , err )
2017-12-08 19:45:59 +00:00
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Test concatenating multiple objects objects
func testCompose10KSourcesV2 ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
function := "ComposeObject(destination, sourceList)"
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } { }
// Instantiate new minio client object
c , err := minio . NewV2 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio v2 client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
testComposeMultipleSources ( c )
}
2018-03-30 10:33:40 +00:00
func testEncryptedEmptyObject ( ) {
// initialize logging params
startTime := time . Now ( )
testName := getFuncName ( )
function := "PutObject(bucketName, objectName, reader, objectSize, opts)"
args := map [ string ] interface { } { }
// Instantiate new minio client object
c , err := minio . NewV4 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
logError ( testName , function , args , startTime , "" , "Minio v4 client object creation failed" , err )
return
}
// Generate a new random bucket name.
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
args [ "bucketName" ] = bucketName
// Make a new bucket in 'us-east-1' (source bucket).
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
return
}
sse := encrypt . DefaultPBKDF ( [ ] byte ( "correct horse battery staple" ) , [ ] byte ( bucketName + "object" ) )
// 1. create an sse-c encrypted object to copy by uploading
const srcSize = 0
var buf [ ] byte // Empty buffer
args [ "objectName" ] = "object"
_ , err = c . PutObject ( bucketName , "object" , bytes . NewReader ( buf ) , int64 ( len ( buf ) ) , minio . PutObjectOptions { ServerSideEncryption : sse } )
if err != nil {
logError ( testName , function , args , startTime , "" , "PutObject call failed" , err )
return
}
// 2. Test CopyObject for an empty object
dstInfo , err := minio . NewDestinationInfo ( bucketName , "new-object" , sse , nil )
if err != nil {
args [ "objectName" ] = "new-object"
function = "NewDestinationInfo(bucketName, objectName, sse, userMetadata)"
logError ( testName , function , args , startTime , "" , "NewDestinationInfo failed" , err )
return
}
srcInfo := minio . NewSourceInfo ( bucketName , "object" , sse )
if err = c . CopyObject ( dstInfo , srcInfo ) ; err != nil {
function = "CopyObject(dstInfo, srcInfo)"
logError ( testName , function , map [ string ] interface { } { } , startTime , "" , "CopyObject failed" , err )
return
}
// 3. Test Key rotation
newSSE := encrypt . DefaultPBKDF ( [ ] byte ( "Don't Panic" ) , [ ] byte ( bucketName + "new-object" ) )
dstInfo , err = minio . NewDestinationInfo ( bucketName , "new-object" , newSSE , nil )
if err != nil {
args [ "objectName" ] = "new-object"
function = "NewDestinationInfo(bucketName, objectName, encryptSSEC, userMetadata)"
logError ( testName , function , args , startTime , "" , "NewDestinationInfo failed" , err )
return
}
srcInfo = minio . NewSourceInfo ( bucketName , "new-object" , sse )
if err = c . CopyObject ( dstInfo , srcInfo ) ; err != nil {
function = "CopyObject(dstInfo, srcInfo)"
logError ( testName , function , map [ string ] interface { } { } , startTime , "" , "CopyObject with key rotation failed" , err )
return
}
// 4. Download the object.
reader , err := c . GetObject ( bucketName , "new-object" , minio . GetObjectOptions { ServerSideEncryption : newSSE } )
if err != nil {
logError ( testName , function , args , startTime , "" , "GetObject failed" , err )
return
}
defer reader . Close ( )
decBytes , err := ioutil . ReadAll ( reader )
if err != nil {
logError ( testName , function , map [ string ] interface { } { } , startTime , "" , "ReadAll failed" , err )
return
}
if ! bytes . Equal ( decBytes , buf ) {
logError ( testName , function , map [ string ] interface { } { } , startTime , "" , "Downloaded object doesn't match the empty encrypted object" , err )
return
}
// Delete all objects and buckets
delete ( args , "objectName" )
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
return
}
successLogger ( testName , function , args , startTime ) . Info ( )
}
2017-09-13 12:09:48 +00:00
func testEncryptedCopyObjectWrapper ( c * minio . Client ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
function := "CopyObject(destination, source)"
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } { }
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
// Make a new bucket in 'us-east-1' (source bucket).
err := c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
sseSrc := encrypt . DefaultPBKDF ( [ ] byte ( "correct horse battery staple" ) , [ ] byte ( bucketName + "srcObject" ) )
sseDst := encrypt . DefaultPBKDF ( [ ] byte ( "correct horse battery staple" ) , [ ] byte ( bucketName + "dstObject" ) )
2017-09-13 12:09:48 +00:00
// 1. create an sse-c encrypted object to copy by uploading
const srcSize = 1024 * 1024
buf := bytes . Repeat ( [ ] byte ( "abcde" ) , srcSize ) // gives a buffer of 5MiB
2018-03-30 10:33:40 +00:00
_ , err = c . PutObject ( bucketName , "srcObject" , bytes . NewReader ( buf ) , int64 ( len ( buf ) ) , minio . PutObjectOptions {
ServerSideEncryption : sseSrc ,
} )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject call failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// 2. copy object and change encryption key
2018-03-30 10:33:40 +00:00
src := minio . NewSourceInfo ( bucketName , "srcObject" , sseSrc )
2018-01-23 18:40:42 +00:00
args [ "source" ] = src
2018-03-30 10:33:40 +00:00
dst , err := minio . NewDestinationInfo ( bucketName , "dstObject" , sseDst , nil )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "NewDestinationInfo failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
args [ "destination" ] = dst
2017-09-13 12:09:48 +00:00
err = c . CopyObject ( dst , src )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "CopyObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// 3. get copied object and check if content is equal
coreClient := minio . Core { c }
2018-03-30 10:33:40 +00:00
reader , _ , err := coreClient . GetObject ( bucketName , "dstObject" , minio . GetObjectOptions { ServerSideEncryption : sseDst } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
decBytes , err := ioutil . ReadAll ( reader )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAll failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( decBytes , buf ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Downloaded object mismatched for encrypted object" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-03-30 10:33:40 +00:00
reader . Close ( )
// Test key rotation for source object in-place.
newSSE := encrypt . DefaultPBKDF ( [ ] byte ( "Don't Panic" ) , [ ] byte ( bucketName + "srcObject" ) ) // replace key
dst , err = minio . NewDestinationInfo ( bucketName , "srcObject" , newSSE , nil )
if err != nil {
logError ( testName , function , args , startTime , "" , "NewDestinationInfo failed" , err )
return
}
args [ "destination" ] = dst
err = c . CopyObject ( dst , src )
if err != nil {
logError ( testName , function , args , startTime , "" , "CopyObject failed" , err )
return
}
// Get copied object and check if content is equal
reader , _ , err = coreClient . GetObject ( bucketName , "srcObject" , minio . GetObjectOptions { ServerSideEncryption : newSSE } )
if err != nil {
logError ( testName , function , args , startTime , "" , "GetObject failed" , err )
return
}
decBytes , err = ioutil . ReadAll ( reader )
if err != nil {
logError ( testName , function , args , startTime , "" , "ReadAll failed" , err )
return
}
if ! bytes . Equal ( decBytes , buf ) {
logError ( testName , function , args , startTime , "" , "Downloaded object mismatched for encrypted object" , err )
return
}
reader . Close ( )
// Test in-place decryption.
dst , err = minio . NewDestinationInfo ( bucketName , "srcObject" , nil , nil )
if err != nil {
logError ( testName , function , args , startTime , "" , "NewDestinationInfo failed" , err )
return
}
args [ "destination" ] = dst
src = minio . NewSourceInfo ( bucketName , "srcObject" , newSSE )
args [ "source" ] = src
err = c . CopyObject ( dst , src )
if err != nil {
logError ( testName , function , args , startTime , "" , "CopyObject failed" , err )
return
}
// Get copied decrypted object and check if content is equal
reader , _ , err = coreClient . GetObject ( bucketName , "srcObject" , minio . GetObjectOptions { } )
if err != nil {
logError ( testName , function , args , startTime , "" , "GetObject failed" , err )
return
}
defer reader . Close ( )
decBytes , err = ioutil . ReadAll ( reader )
if err != nil {
logError ( testName , function , args , startTime , "" , "ReadAll failed" , err )
return
}
if ! bytes . Equal ( decBytes , buf ) {
logError ( testName , function , args , startTime , "" , "Downloaded object mismatched for encrypted object" , err )
return
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Test encrypted copy object
func testEncryptedCopyObject ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
function := "CopyObject(destination, source)"
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } { }
// Instantiate new minio client object
c , err := minio . NewV4 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio v2 client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// c.TraceOn(os.Stderr)
testEncryptedCopyObjectWrapper ( c )
}
// Test encrypted copy object
func testEncryptedCopyObjectV2 ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
function := "CopyObject(destination, source)"
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } { }
// Instantiate new minio client object
c , err := minio . NewV2 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio v2 client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
// c.TraceOn(os.Stderr)
2017-09-13 12:09:48 +00:00
testEncryptedCopyObjectWrapper ( c )
}
2018-08-01 17:43:44 +00:00
func testDecryptedCopyObject ( ) {
// initialize logging params
startTime := time . Now ( )
testName := getFuncName ( )
function := "CopyObject(destination, source)"
args := map [ string ] interface { } { }
// Instantiate new minio client object
c , err := minio . New (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
logError ( testName , function , args , startTime , "" , "Minio v2 client object creation failed" , err )
return
}
bucketName , objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" ) , "object"
if err = c . MakeBucket ( bucketName , "us-east-1" ) ; err != nil {
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
return
}
encryption := encrypt . DefaultPBKDF ( [ ] byte ( "correct horse battery staple" ) , [ ] byte ( bucketName + objectName ) )
_ , err = c . PutObject ( bucketName , objectName , bytes . NewReader ( bytes . Repeat ( [ ] byte ( "a" ) , 1024 * 1024 ) ) , 1024 * 1024 , minio . PutObjectOptions {
ServerSideEncryption : encryption ,
} )
if err != nil {
logError ( testName , function , args , startTime , "" , "PutObject call failed" , err )
return
}
src := minio . NewSourceInfo ( bucketName , objectName , encrypt . SSECopy ( encryption ) )
args [ "source" ] = src
dst , err := minio . NewDestinationInfo ( bucketName , "decrypted-" + objectName , nil , nil )
if err != nil {
logError ( testName , function , args , startTime , "" , "NewDestinationInfo failed" , err )
return
}
args [ "destination" ] = dst
if err = c . CopyObject ( dst , src ) ; err != nil {
logError ( testName , function , args , startTime , "" , "CopyObject failed" , err )
return
}
if _ , err = c . GetObject ( bucketName , "decrypted-" + objectName , minio . GetObjectOptions { } ) ; err != nil {
logError ( testName , function , args , startTime , "" , "GetObject failed" , err )
return
}
successLogger ( testName , function , args , startTime ) . Info ( )
}
2017-09-13 12:09:48 +00:00
func testUserMetadataCopying ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
function := "CopyObject(destination, source)"
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } { }
// Instantiate new minio client object
c , err := minio . NewV4 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// c.TraceOn(os.Stderr)
testUserMetadataCopyingWrapper ( c )
}
func testUserMetadataCopyingWrapper ( c * minio . Client ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-09-13 12:09:48 +00:00
function := "CopyObject(destination, source)"
2018-01-23 18:40:42 +00:00
args := map [ string ] interface { } { }
2017-09-13 12:09:48 +00:00
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
// Make a new bucket in 'us-east-1' (source bucket).
err := c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
fetchMeta := func ( object string ) ( h http . Header ) {
2017-12-08 19:45:59 +00:00
objInfo , err := c . StatObject ( bucketName , object , minio . StatObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Stat failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
h = make ( http . Header )
for k , vs := range objInfo . Metadata {
if strings . HasPrefix ( strings . ToLower ( k ) , "x-amz-meta-" ) {
for _ , v := range vs {
h . Add ( k , v )
}
}
}
return h
}
// 1. create a client encrypted object to copy by uploading
const srcSize = 1024 * 1024
buf := bytes . Repeat ( [ ] byte ( "abcde" ) , srcSize ) // gives a buffer of 5MiB
metadata := make ( http . Header )
metadata . Set ( "x-amz-meta-myheader" , "myvalue" )
2017-12-08 19:45:59 +00:00
m := make ( map [ string ] string )
m [ "x-amz-meta-myheader" ] = "myvalue"
_ , err = c . PutObject ( bucketName , "srcObject" ,
bytes . NewReader ( buf ) , int64 ( len ( buf ) ) , minio . PutObjectOptions { UserMetadata : m } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObjectWithMetadata failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if ! reflect . DeepEqual ( metadata , fetchMeta ( "srcObject" ) ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Metadata match failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// 2. create source
src := minio . NewSourceInfo ( bucketName , "srcObject" , nil )
// 2.1 create destination with metadata set
dst1 , err := minio . NewDestinationInfo ( bucketName , "dstObject-1" , nil , map [ string ] string { "notmyheader" : "notmyvalue" } )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "NewDestinationInfo failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// 3. Check that copying to an object with metadata set resets
// the headers on the copy.
args [ "source" ] = src
2018-01-23 18:40:42 +00:00
args [ "destination" ] = dst1
err = c . CopyObject ( dst1 , src )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "CopyObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
expectedHeaders := make ( http . Header )
expectedHeaders . Set ( "x-amz-meta-notmyheader" , "notmyvalue" )
if ! reflect . DeepEqual ( expectedHeaders , fetchMeta ( "dstObject-1" ) ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Metadata match failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// 4. create destination with no metadata set and same source
dst2 , err := minio . NewDestinationInfo ( bucketName , "dstObject-2" , nil , nil )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "NewDestinationInfo failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
src = minio . NewSourceInfo ( bucketName , "srcObject" , nil )
// 5. Check that copying to an object with no metadata set,
// copies metadata.
args [ "source" ] = src
2018-01-23 18:40:42 +00:00
args [ "destination" ] = dst2
err = c . CopyObject ( dst2 , src )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "CopyObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
expectedHeaders = metadata
if ! reflect . DeepEqual ( expectedHeaders , fetchMeta ( "dstObject-2" ) ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Metadata match failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// 6. Compose a pair of sources.
srcs := [ ] minio . SourceInfo {
minio . NewSourceInfo ( bucketName , "srcObject" , nil ) ,
minio . NewSourceInfo ( bucketName , "srcObject" , nil ) ,
}
dst3 , err := minio . NewDestinationInfo ( bucketName , "dstObject-3" , nil , nil )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "NewDestinationInfo failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
function = "ComposeObject(destination, sources)"
args [ "source" ] = srcs
2018-01-23 18:40:42 +00:00
args [ "destination" ] = dst3
err = c . ComposeObject ( dst3 , srcs )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ComposeObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Check that no headers are copied in this case
if ! reflect . DeepEqual ( make ( http . Header ) , fetchMeta ( "dstObject-3" ) ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Metadata match failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// 7. Compose a pair of sources with dest user metadata set.
srcs = [ ] minio . SourceInfo {
minio . NewSourceInfo ( bucketName , "srcObject" , nil ) ,
minio . NewSourceInfo ( bucketName , "srcObject" , nil ) ,
}
dst4 , err := minio . NewDestinationInfo ( bucketName , "dstObject-4" , nil , map [ string ] string { "notmyheader" : "notmyvalue" } )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "NewDestinationInfo failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
function = "ComposeObject(destination, sources)"
args [ "source" ] = srcs
2018-01-23 18:40:42 +00:00
args [ "destination" ] = dst4
err = c . ComposeObject ( dst4 , srcs )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ComposeObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Check that no headers are copied in this case
expectedHeaders = make ( http . Header )
expectedHeaders . Set ( "x-amz-meta-notmyheader" , "notmyvalue" )
if ! reflect . DeepEqual ( expectedHeaders , fetchMeta ( "dstObject-4" ) ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Metadata match failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
func testUserMetadataCopyingV2 ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
function := "CopyObject(destination, source)"
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } { }
// Instantiate new minio client object
c , err := minio . NewV2 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client v2 object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// c.TraceOn(os.Stderr)
testUserMetadataCopyingWrapper ( c )
}
2018-01-23 18:40:42 +00:00
func testStorageClassMetadataPutObject ( ) {
// initialize logging params
startTime := time . Now ( )
function := "testStorageClassMetadataPutObject()"
args := map [ string ] interface { } { }
testName := getFuncName ( )
// Instantiate new minio client object
c , err := minio . NewV4 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
logError ( testName , function , args , startTime , "" , "Minio v4 client object creation failed" , err )
return
}
// Generate a new random bucket name.
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test" )
// Make a new bucket in 'us-east-1' (source bucket).
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
return
}
fetchMeta := func ( object string ) ( h http . Header ) {
objInfo , err := c . StatObject ( bucketName , object , minio . StatObjectOptions { } )
if err != nil {
logError ( testName , function , args , startTime , "" , "Stat failed" , err )
return
}
h = make ( http . Header )
for k , vs := range objInfo . Metadata {
if strings . HasPrefix ( strings . ToLower ( k ) , "x-amz-storage-class" ) {
for _ , v := range vs {
h . Add ( k , v )
}
}
}
return h
}
metadata := make ( http . Header )
metadata . Set ( "x-amz-storage-class" , "REDUCED_REDUNDANCY" )
emptyMetadata := make ( http . Header )
const srcSize = 1024 * 1024
buf := bytes . Repeat ( [ ] byte ( "abcde" ) , srcSize ) // gives a buffer of 1MiB
_ , err = c . PutObject ( bucketName , "srcObjectRRSClass" ,
bytes . NewReader ( buf ) , int64 ( len ( buf ) ) , minio . PutObjectOptions { StorageClass : "REDUCED_REDUNDANCY" } )
if err != nil {
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
return
}
// Get the returned metadata
returnedMeta := fetchMeta ( "srcObjectRRSClass" )
// The response metada should either be equal to metadata (with REDUCED_REDUNDANCY) or emptyMetadata (in case of gateways)
if ! reflect . DeepEqual ( metadata , returnedMeta ) && ! reflect . DeepEqual ( emptyMetadata , returnedMeta ) {
logError ( testName , function , args , startTime , "" , "Metadata match failed" , err )
return
}
metadata = make ( http . Header )
metadata . Set ( "x-amz-storage-class" , "STANDARD" )
_ , err = c . PutObject ( bucketName , "srcObjectSSClass" ,
bytes . NewReader ( buf ) , int64 ( len ( buf ) ) , minio . PutObjectOptions { StorageClass : "STANDARD" } )
if err != nil {
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
return
}
if reflect . DeepEqual ( metadata , fetchMeta ( "srcObjectSSClass" ) ) {
logError ( testName , function , args , startTime , "" , "Metadata verification failed, STANDARD storage class should not be a part of response metadata" , err )
return
}
2018-08-01 17:43:44 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
return
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
}
func testStorageClassInvalidMetadataPutObject ( ) {
// initialize logging params
startTime := time . Now ( )
function := "testStorageClassInvalidMetadataPutObject()"
args := map [ string ] interface { } { }
testName := getFuncName ( )
// Instantiate new minio client object
c , err := minio . NewV4 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
logError ( testName , function , args , startTime , "" , "Minio v4 client object creation failed" , err )
return
}
// Generate a new random bucket name.
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test" )
// Make a new bucket in 'us-east-1' (source bucket).
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
return
}
const srcSize = 1024 * 1024
buf := bytes . Repeat ( [ ] byte ( "abcde" ) , srcSize ) // gives a buffer of 1MiB
_ , err = c . PutObject ( bucketName , "srcObjectRRSClass" ,
bytes . NewReader ( buf ) , int64 ( len ( buf ) ) , minio . PutObjectOptions { StorageClass : "INVALID_STORAGE_CLASS" } )
if err == nil {
logError ( testName , function , args , startTime , "" , "PutObject with invalid storage class passed, was expected to fail" , err )
return
}
2018-08-01 17:43:44 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
return
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
}
func testStorageClassMetadataCopyObject ( ) {
// initialize logging params
startTime := time . Now ( )
function := "testStorageClassMetadataCopyObject()"
args := map [ string ] interface { } { }
testName := getFuncName ( )
// Instantiate new minio client object
c , err := minio . NewV4 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
logError ( testName , function , args , startTime , "" , "Minio v4 client object creation failed" , err )
return
}
// Generate a new random bucket name.
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test" )
// Make a new bucket in 'us-east-1' (source bucket).
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
return
}
fetchMeta := func ( object string ) ( h http . Header ) {
objInfo , err := c . StatObject ( bucketName , object , minio . StatObjectOptions { } )
if err != nil {
logError ( testName , function , args , startTime , "" , "Stat failed" , err )
return
}
h = make ( http . Header )
for k , vs := range objInfo . Metadata {
if strings . HasPrefix ( strings . ToLower ( k ) , "x-amz-storage-class" ) {
for _ , v := range vs {
h . Add ( k , v )
}
}
}
return h
}
metadata := make ( http . Header )
metadata . Set ( "x-amz-storage-class" , "REDUCED_REDUNDANCY" )
emptyMetadata := make ( http . Header )
const srcSize = 1024 * 1024
buf := bytes . Repeat ( [ ] byte ( "abcde" ) , srcSize )
// Put an object with RRS Storage class
_ , err = c . PutObject ( bucketName , "srcObjectRRSClass" ,
bytes . NewReader ( buf ) , int64 ( len ( buf ) ) , minio . PutObjectOptions { StorageClass : "REDUCED_REDUNDANCY" } )
if err != nil {
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
return
}
// Make server side copy of object uploaded in previous step
src := minio . NewSourceInfo ( bucketName , "srcObjectRRSClass" , nil )
dst , err := minio . NewDestinationInfo ( bucketName , "srcObjectRRSClassCopy" , nil , nil )
c . CopyObject ( dst , src )
// Get the returned metadata
returnedMeta := fetchMeta ( "srcObjectRRSClassCopy" )
// The response metada should either be equal to metadata (with REDUCED_REDUNDANCY) or emptyMetadata (in case of gateways)
if ! reflect . DeepEqual ( metadata , returnedMeta ) && ! reflect . DeepEqual ( emptyMetadata , returnedMeta ) {
logError ( testName , function , args , startTime , "" , "Metadata match failed" , err )
return
}
metadata = make ( http . Header )
metadata . Set ( "x-amz-storage-class" , "STANDARD" )
// Put an object with Standard Storage class
_ , err = c . PutObject ( bucketName , "srcObjectSSClass" ,
bytes . NewReader ( buf ) , int64 ( len ( buf ) ) , minio . PutObjectOptions { StorageClass : "STANDARD" } )
if err != nil {
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
return
}
// Make server side copy of object uploaded in previous step
src = minio . NewSourceInfo ( bucketName , "srcObjectSSClass" , nil )
dst , err = minio . NewDestinationInfo ( bucketName , "srcObjectSSClassCopy" , nil , nil )
c . CopyObject ( dst , src )
// Fetch the meta data of copied object
if reflect . DeepEqual ( metadata , fetchMeta ( "srcObjectSSClassCopy" ) ) {
logError ( testName , function , args , startTime , "" , "Metadata verification failed, STANDARD storage class should not be a part of response metadata" , err )
return
}
2018-08-01 17:43:44 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
return
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
}
2017-09-13 12:09:48 +00:00
// Test put object with size -1 byte object.
func testPutObjectNoLengthV2 ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-12-08 19:45:59 +00:00
function := "PutObject(bucketName, objectName, reader, size, opts)"
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } {
"bucketName" : "" ,
"objectName" : "" ,
"size" : - 1 ,
2017-12-08 19:45:59 +00:00
"opts" : "" ,
2017-09-13 12:09:48 +00:00
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . NewV2 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client v2 object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
objectName := bucketName + "unique"
args [ "objectName" ] = objectName
2017-12-08 19:45:59 +00:00
bufSize := dataFileMap [ "datafile-65-MB" ]
var reader = getDataReader ( "datafile-65-MB" )
2017-09-13 12:09:48 +00:00
defer reader . Close ( )
2018-01-23 18:40:42 +00:00
args [ "size" ] = bufSize
2017-09-13 12:09:48 +00:00
// Upload an object.
2017-12-08 19:45:59 +00:00
n , err := c . PutObject ( bucketName , objectName , reader , - 1 , minio . PutObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObjectWithSize failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Expected upload object size " + string ( bufSize ) + " got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Test put objects of unknown size.
func testPutObjectsUnknownV2 ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-12-08 19:45:59 +00:00
function := "PutObject(bucketName, objectName, reader,size,opts)"
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } {
"bucketName" : "" ,
"objectName" : "" ,
2017-12-08 19:45:59 +00:00
"size" : "" ,
"opts" : "" ,
2017-09-13 12:09:48 +00:00
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . NewV2 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client v2 object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-09-13 12:09:48 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Issues are revealed by trying to upload multiple files of unknown size
// sequentially (on 4GB machines)
for i := 1 ; i <= 4 ; i ++ {
// Simulate that we could be receiving byte slices of data that we want
// to upload as a file
rpipe , wpipe := io . Pipe ( )
defer rpipe . Close ( )
go func ( ) {
b := [ ] byte ( "test" )
wpipe . Write ( b )
wpipe . Close ( )
} ( )
// Upload the object.
objectName := fmt . Sprintf ( "%sunique%d" , bucketName , i )
args [ "objectName" ] = objectName
2017-12-08 19:45:59 +00:00
n , err := c . PutObject ( bucketName , objectName , rpipe , - 1 , minio . PutObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObjectStreaming failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
args [ "size" ] = n
2017-09-13 12:09:48 +00:00
if n != int64 ( 4 ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Expected upload object size " + string ( 4 ) + " got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Test put object with 0 byte object.
func testPutObject0ByteV2 ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-12-08 19:45:59 +00:00
function := "PutObject(bucketName, objectName, reader, size, opts)"
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } {
"bucketName" : "" ,
"objectName" : "" ,
"size" : 0 ,
2017-12-08 19:45:59 +00:00
"opts" : "" ,
2017-09-13 12:09:48 +00:00
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . NewV2 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client v2 object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-12-08 19:45:59 +00:00
args [ "bucketName" ] = bucketName
2017-09-13 12:09:48 +00:00
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
objectName := bucketName + "unique"
2017-12-08 19:45:59 +00:00
args [ "objectName" ] = objectName
args [ "opts" ] = minio . PutObjectOptions { }
2017-09-13 12:09:48 +00:00
// Upload an object.
2017-12-08 19:45:59 +00:00
n , err := c . PutObject ( bucketName , objectName , bytes . NewReader ( [ ] byte ( "" ) ) , 0 , minio . PutObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObjectWithSize failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if n != 0 {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Expected upload object size 0 but got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
// Test expected error cases
func testComposeObjectErrorCases ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
function := "ComposeObject(destination, sourceList)"
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } { }
// Instantiate new minio client object
c , err := minio . NewV4 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
testComposeObjectErrorCasesWrapper ( c )
}
// Test concatenating 10K objects
func testCompose10KSources ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
function := "ComposeObject(destination, sourceList)"
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } { }
// Instantiate new minio client object
c , err := minio . NewV4 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
testComposeMultipleSources ( c )
}
// Tests comprehensive list of all methods.
func testFunctionalV2 ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-09-13 12:09:48 +00:00
function := "testFunctionalV2()"
2018-03-30 10:33:40 +00:00
functionAll := ""
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } { }
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
c , err := minio . NewV2 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client v2 object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Enable to debug
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
location := "us-east-1"
2017-09-13 12:09:48 +00:00
// Make a new bucket.
2018-01-23 18:40:42 +00:00
function = "MakeBucket(bucketName, location)"
2018-03-30 10:33:40 +00:00
functionAll = "MakeBucket(bucketName, location)"
2018-01-23 18:40:42 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"location" : location ,
}
err = c . MakeBucket ( bucketName , location )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Generate a random file name.
fileName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
file , err := os . Create ( fileName )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "file create failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
for i := 0 ; i < 3 ; i ++ {
buf := make ( [ ] byte , rand . Intn ( 1 << 19 ) )
_ , err = file . Write ( buf )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "file write failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
}
file . Close ( )
// Verify if bucket exits and you have access.
var exists bool
2018-01-23 18:40:42 +00:00
function = "BucketExists(bucketName)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2018-01-23 18:40:42 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
}
2017-09-13 12:09:48 +00:00
exists , err = c . BucketExists ( bucketName )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "BucketExists failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if ! exists {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Could not find existing bucket " + bucketName , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Make the bucket 'public read/write'.
2018-08-01 17:43:44 +00:00
function = "SetBucketPolicy(bucketName, bucketPolicy)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2018-08-01 17:43:44 +00:00
readWritePolicy := ` { "Version": "2012-10-17","Statement": [ { "Action": ["s3:ListBucketMultipartUploads", "s3:ListBucket"],"Effect": "Allow","Principal": { "AWS": ["*"]},"Resource": ["arn:aws:s3::: ` + bucketName + ` "],"Sid": ""}]} `
2018-01-23 18:40:42 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
2018-08-01 17:43:44 +00:00
"bucketPolicy" : readWritePolicy ,
2018-01-23 18:40:42 +00:00
}
2018-08-01 17:43:44 +00:00
err = c . SetBucketPolicy ( bucketName , readWritePolicy )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "SetBucketPolicy failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// List all buckets.
2018-01-23 18:40:42 +00:00
function = "ListBuckets()"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2018-01-23 18:40:42 +00:00
args = nil
2017-09-13 12:09:48 +00:00
buckets , err := c . ListBuckets ( )
if len ( buckets ) == 0 {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "List buckets cannot be empty" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ListBuckets failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Verify if previously created bucket is listed in list buckets.
bucketFound := false
for _ , bucket := range buckets {
if bucket . Name == bucketName {
bucketFound = true
}
}
// If bucket not found error out.
if ! bucketFound {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Bucket " + bucketName + "not found" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
objectName := bucketName + "unique"
// Generate data
buf := bytes . Repeat ( [ ] byte ( "n" ) , rand . Intn ( 1 << 19 ) )
2018-01-23 18:40:42 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName ,
"contentType" : "" ,
}
2017-12-08 19:45:59 +00:00
n , err := c . PutObject ( bucketName , objectName , bytes . NewReader ( buf ) , int64 ( len ( buf ) ) , minio . PutObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( len ( buf ) ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Expected uploaded object length " + string ( len ( buf ) ) + " got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-08-01 17:43:44 +00:00
objectNameNoLength := objectName + "-nolength"
args [ "objectName" ] = objectNameNoLength
n , err = c . PutObject ( bucketName , objectNameNoLength , bytes . NewReader ( buf ) , int64 ( len ( buf ) ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( len ( buf ) ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Expected uploaded object length " + string ( len ( buf ) ) + " got " + string ( n ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Instantiate a done channel to close all listing.
doneCh := make ( chan struct { } )
defer close ( doneCh )
objFound := false
isRecursive := true // Recursive is true.
2018-01-23 18:40:42 +00:00
function = "ListObjects(bucketName, objectName, isRecursive, doneCh)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2018-01-23 18:40:42 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName ,
"isRecursive" : isRecursive ,
2017-09-13 12:09:48 +00:00
}
for obj := range c . ListObjects ( bucketName , objectName , isRecursive , doneCh ) {
if obj . Key == objectName {
objFound = true
break
}
}
if ! objFound {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Could not find existing object " + objectName , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
incompObjNotFound := true
2018-01-23 18:40:42 +00:00
function = "ListIncompleteUploads(bucketName, objectName, isRecursive, doneCh)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2018-01-23 18:40:42 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName ,
"isRecursive" : isRecursive ,
}
2017-09-13 12:09:48 +00:00
for objIncompl := range c . ListIncompleteUploads ( bucketName , objectName , isRecursive , doneCh ) {
if objIncompl . Key != "" {
incompObjNotFound = false
break
}
}
if ! incompObjNotFound {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Unexpected dangling incomplete upload found" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
function = "GetObject(bucketName, objectName)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2018-01-23 18:40:42 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName ,
}
2017-12-08 19:45:59 +00:00
newReader , err := c . GetObject ( bucketName , objectName , minio . GetObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
newReadBytes , err := ioutil . ReadAll ( newReader )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAll failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
newReader . Close ( )
2017-09-13 12:09:48 +00:00
if ! bytes . Equal ( newReadBytes , buf ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Bytes mismatch" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
function = "FGetObject(bucketName, objectName, fileName)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2018-01-23 18:40:42 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName ,
"fileName" : fileName + "-f" ,
}
2017-12-08 19:45:59 +00:00
err = c . FGetObject ( bucketName , objectName , fileName + "-f" , minio . GetObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "FgetObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Generate presigned HEAD object url.
2018-01-23 18:40:42 +00:00
function = "PresignedHeadObject(bucketName, objectName, expires, reqParams)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2018-01-23 18:40:42 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName ,
"expires" : 3600 * time . Second ,
}
2017-09-13 12:09:48 +00:00
presignedHeadURL , err := c . PresignedHeadObject ( bucketName , objectName , 3600 * time . Second , nil )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedHeadObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Verify if presigned url works.
resp , err := http . Head ( presignedHeadURL . String ( ) )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedHeadObject URL head request failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if resp . StatusCode != http . StatusOK {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedHeadObject URL returns status " + string ( resp . StatusCode ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if resp . Header . Get ( "ETag" ) == "" {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Got empty ETag" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
resp . Body . Close ( )
// Generate presigned GET object url.
2018-01-23 18:40:42 +00:00
function = "PresignedGetObject(bucketName, objectName, expires, reqParams)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2018-01-23 18:40:42 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName ,
"expires" : 3600 * time . Second ,
}
2017-09-13 12:09:48 +00:00
presignedGetURL , err := c . PresignedGetObject ( bucketName , objectName , 3600 * time . Second , nil )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedGetObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Verify if presigned url works.
resp , err = http . Get ( presignedGetURL . String ( ) )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedGetObject URL GET request failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if resp . StatusCode != http . StatusOK {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedGetObject URL returns status " + string ( resp . StatusCode ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
newPresignedBytes , err := ioutil . ReadAll ( resp . Body )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAll failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
resp . Body . Close ( )
if ! bytes . Equal ( newPresignedBytes , buf ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Bytes mismatch" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Set request parameters.
reqParams := make ( url . Values )
reqParams . Set ( "response-content-disposition" , "attachment; filename=\"test.txt\"" )
// Generate presigned GET object url.
2018-01-23 18:40:42 +00:00
args [ "reqParams" ] = reqParams
2017-09-13 12:09:48 +00:00
presignedGetURL , err = c . PresignedGetObject ( bucketName , objectName , 3600 * time . Second , reqParams )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedGetObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Verify if presigned url works.
resp , err = http . Get ( presignedGetURL . String ( ) )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedGetObject URL GET request failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if resp . StatusCode != http . StatusOK {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedGetObject URL returns status " + string ( resp . StatusCode ) , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
newPresignedBytes , err = ioutil . ReadAll ( resp . Body )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAll failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( newPresignedBytes , buf ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Bytes mismatch" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
// Verify content disposition.
if resp . Header . Get ( "Content-Disposition" ) != "attachment; filename=\"test.txt\"" {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "wrong Content-Disposition received " , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
function = "PresignedPutObject(bucketName, objectName, expires)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2018-01-23 18:40:42 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName + "-presigned" ,
"expires" : 3600 * time . Second ,
}
2017-09-13 12:09:48 +00:00
presignedPutURL , err := c . PresignedPutObject ( bucketName , objectName + "-presigned" , 3600 * time . Second )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PresignedPutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
2017-09-13 12:09:48 +00:00
// Generate data more than 32K
buf = bytes . Repeat ( [ ] byte ( "1" ) , rand . Intn ( 1 << 10 ) + 32 * 1024 )
req , err := http . NewRequest ( "PUT" , presignedPutURL . String ( ) , bytes . NewReader ( buf ) )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "HTTP request to PresignedPutObject URL failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
httpClient := & http . Client {
// Setting a sensible time out of 30secs to wait for response
// headers. Request is pro-actively cancelled after 30secs
// with no response.
Timeout : 30 * time . Second ,
Transport : http . DefaultTransport ,
}
resp , err = httpClient . Do ( req )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "HTTP request to PresignedPutObject URL failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-01-23 18:40:42 +00:00
function = "GetObject(bucketName, objectName)"
2018-03-30 10:33:40 +00:00
functionAll += ", " + function
2018-01-23 18:40:42 +00:00
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName + "-presigned" ,
}
2017-12-08 19:45:59 +00:00
newReader , err = c . GetObject ( bucketName , objectName + "-presigned" , minio . GetObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetObject failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
newReadBytes , err = ioutil . ReadAll ( newReader )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "ReadAll failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
newReader . Close ( )
2017-09-13 12:09:48 +00:00
if ! bytes . Equal ( newReadBytes , buf ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Bytes mismatch" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
2017-09-13 12:09:48 +00:00
if err = os . Remove ( fileName ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File remove failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
if err = os . Remove ( fileName + "-f" ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "File removes failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2018-03-30 10:33:40 +00:00
successLogger ( testName , functionAll , args , startTime ) . Info ( )
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Test get object with GetObjectWithContext
func testGetObjectWithContext ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-12-08 19:45:59 +00:00
function := "GetObjectWithContext(ctx, bucketName, objectName)"
args := map [ string ] interface { } {
"ctx" : "" ,
"bucketName" : "" ,
"objectName" : "" ,
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . NewV4 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
2017-09-13 12:09:48 +00:00
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client v4 object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-12-08 19:45:59 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
}
bufSize := dataFileMap [ "datafile-33-kB" ]
var reader = getDataReader ( "datafile-33-kB" )
defer reader . Close ( )
// Save the data
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
args [ "objectName" ] = objectName
_ , err = c . PutObject ( bucketName , objectName , reader , int64 ( bufSize ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , 1 * time . Nanosecond )
2017-12-08 19:45:59 +00:00
args [ "ctx" ] = ctx
defer cancel ( )
r , err := c . GetObjectWithContext ( ctx , bucketName , objectName , minio . GetObjectOptions { } )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetObjectWithContext failed unexpectedly" , err )
return
}
2018-03-30 10:33:40 +00:00
2018-01-23 18:40:42 +00:00
if _ , err = r . Stat ( ) ; err == nil {
logError ( testName , function , args , startTime , "" , "GetObjectWithContext should fail on short timeout" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-03-30 10:33:40 +00:00
r . Close ( )
2018-01-23 18:40:42 +00:00
ctx , cancel = context . WithTimeout ( context . Background ( ) , 1 * time . Hour )
2017-12-08 19:45:59 +00:00
args [ "ctx" ] = ctx
defer cancel ( )
// Read the data back
r , err = c . GetObjectWithContext ( ctx , bucketName , objectName , minio . GetObjectOptions { } )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetObjectWithContext failed" , err )
2017-12-08 19:45:59 +00:00
return
}
st , err := r . Stat ( )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "object Stat call failed" , err )
2017-12-08 19:45:59 +00:00
return
}
if st . Size != int64 ( bufSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes in stat does not match: want " + string ( bufSize ) + ", got" + string ( st . Size ) , err )
2017-12-08 19:45:59 +00:00
return
}
if err := r . Close ( ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "object Close() call failed" , err )
2017-12-08 19:45:59 +00:00
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-12-08 19:45:59 +00:00
}
// Test get object with FGetObjectWithContext
func testFGetObjectWithContext ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-12-08 19:45:59 +00:00
function := "FGetObjectWithContext(ctx, bucketName, objectName, fileName)"
args := map [ string ] interface { } {
"ctx" : "" ,
"bucketName" : "" ,
"objectName" : "" ,
"fileName" : "" ,
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . NewV4 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client v4 object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-12-08 19:45:59 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
}
bufSize := dataFileMap [ "datafile-1-MB" ]
var reader = getDataReader ( "datafile-1-MB" )
defer reader . Close ( )
// Save the data
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
args [ "objectName" ] = objectName
_ , err = c . PutObject ( bucketName , objectName , reader , int64 ( bufSize ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , 1 * time . Nanosecond )
2017-12-08 19:45:59 +00:00
args [ "ctx" ] = ctx
defer cancel ( )
fileName := "tempfile-context"
args [ "fileName" ] = fileName
// Read the data back
err = c . FGetObjectWithContext ( ctx , bucketName , objectName , fileName + "-f" , minio . GetObjectOptions { } )
if err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "FGetObjectWithContext should fail on short timeout" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
ctx , cancel = context . WithTimeout ( context . Background ( ) , 1 * time . Hour )
2017-12-08 19:45:59 +00:00
defer cancel ( )
// Read the data back
err = c . FGetObjectWithContext ( ctx , bucketName , objectName , fileName + "-fcontext" , minio . GetObjectOptions { } )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "FGetObjectWithContext with long timeout failed" , err )
2017-12-08 19:45:59 +00:00
return
}
if err = os . Remove ( fileName + "-fcontext" ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Remove file failed" , err )
2017-12-08 19:45:59 +00:00
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-12-08 19:45:59 +00:00
}
2018-09-03 18:23:56 +00:00
// Test get object ACLs with GetObjectACL
func testGetObjectACL ( ) {
// initialize logging params
startTime := time . Now ( )
testName := getFuncName ( )
function := "GetObjectACL(bucketName, objectName)"
args := map [ string ] interface { } {
"bucketName" : "" ,
"objectName" : "" ,
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// skipping region functional tests for non s3 runs
if os . Getenv ( serverEndpoint ) != "s3.amazonaws.com" {
ignoredLog ( testName , function , args , startTime , "Skipped region functional tests for non s3 runs" ) . Info ( )
return
}
// Instantiate new minio client object.
c , err := minio . NewV4 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
logError ( testName , function , args , startTime , "" , "Minio client v4 object creation failed" , err )
return
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
return
}
bufSize := dataFileMap [ "datafile-1-MB" ]
var reader = getDataReader ( "datafile-1-MB" )
defer reader . Close ( )
// Save the data
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
args [ "objectName" ] = objectName
// Add meta data to add a canned acl
metaData := map [ string ] string {
"X-Amz-Acl" : "public-read-write" ,
}
_ , err = c . PutObject ( bucketName , objectName , reader , int64 ( bufSize ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" , UserMetadata : metaData } )
if err != nil {
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
return
}
// Read the data back
objectInfo , getObjectACLErr := c . GetObjectACL ( bucketName , objectName )
if getObjectACLErr == nil {
logError ( testName , function , args , startTime , "" , "GetObjectACL fail" , getObjectACLErr )
return
}
s , ok := objectInfo . Metadata [ "X-Amz-Acl" ]
if ! ok {
logError ( testName , function , args , startTime , "" , "GetObjectACL fail unable to find \"X-Amz-Acl\"" , nil )
return
}
if len ( s ) != 1 {
logError ( testName , function , args , startTime , "" , "GetObjectACL fail \"X-Amz-Acl\" canned acl expected \"1\" got " + fmt . Sprintf ( ` "%d" ` , len ( s ) ) , nil )
return
}
if s [ 0 ] != "public-read-write" {
logError ( testName , function , args , startTime , "" , "GetObjectACL fail \"X-Amz-Acl\" expected \"public-read-write\" but got" + fmt . Sprintf ( "%q" , s [ 0 ] ) , nil )
return
}
bufSize = dataFileMap [ "datafile-1-MB" ]
var reader2 = getDataReader ( "datafile-1-MB" )
defer reader2 . Close ( )
// Save the data
objectName = randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
args [ "objectName" ] = objectName
// Add meta data to add a canned acl
metaData = map [ string ] string {
"X-Amz-Grant-Read" : "id=fooread@minio.go" ,
"X-Amz-Grant-Write" : "id=foowrite@minio.go" ,
}
_ , err = c . PutObject ( bucketName , objectName , reader2 , int64 ( bufSize ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" , UserMetadata : metaData } )
if err != nil {
logError ( testName , function , args , startTime , "" , "PutObject failed" , err )
return
}
// Read the data back
objectInfo , getObjectACLErr = c . GetObjectACL ( bucketName , objectName )
if getObjectACLErr == nil {
logError ( testName , function , args , startTime , "" , "GetObjectACL fail" , getObjectACLErr )
return
}
if len ( objectInfo . Metadata ) != 3 {
logError ( testName , function , args , startTime , "" , "GetObjectACL fail expected \"3\" ACLs but got " + fmt . Sprintf ( ` "%d" ` , len ( objectInfo . Metadata ) ) , nil )
return
}
s , ok = objectInfo . Metadata [ "X-Amz-Grant-Read" ]
if ! ok {
logError ( testName , function , args , startTime , "" , "GetObjectACL fail unable to find \"X-Amz-Grant-Read\"" , nil )
return
}
if len ( s ) != 1 {
logError ( testName , function , args , startTime , "" , "GetObjectACL fail \"X-Amz-Grant-Read\" acl expected \"1\" got " + fmt . Sprintf ( ` "%d" ` , len ( s ) ) , nil )
return
}
if s [ 0 ] != "fooread@minio.go" {
logError ( testName , function , args , startTime , "" , "GetObjectACL fail \"X-Amz-Grant-Read\" acl expected \"fooread@minio.go\" got " + fmt . Sprintf ( "%q" , s ) , nil )
return
}
s , ok = objectInfo . Metadata [ "X-Amz-Grant-Write" ]
if ! ok {
logError ( testName , function , args , startTime , "" , "GetObjectACL fail unable to find \"X-Amz-Grant-Write\"" , nil )
return
}
if len ( s ) != 1 {
logError ( testName , function , args , startTime , "" , "GetObjectACL fail \"X-Amz-Grant-Write\" acl expected \"1\" got " + fmt . Sprintf ( ` "%d" ` , len ( s ) ) , nil )
return
}
if s [ 0 ] != "foowrite@minio.go" {
logError ( testName , function , args , startTime , "" , "GetObjectACL fail \"X-Amz-Grant-Write\" acl expected \"foowrite@minio.go\" got " + fmt . Sprintf ( "%q" , s ) , nil )
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
return
}
successLogger ( testName , function , args , startTime ) . Info ( )
}
2017-12-08 19:45:59 +00:00
// Test validates putObject with context to see if request cancellation is honored for V2.
func testPutObjectWithContextV2 ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-12-08 19:45:59 +00:00
function := "PutObjectWithContext(ctx, bucketName, objectName, reader, size, opts)"
args := map [ string ] interface { } {
"ctx" : "" ,
"bucketName" : "" ,
"objectName" : "" ,
2018-01-23 18:40:42 +00:00
"size" : "" ,
2017-12-08 19:45:59 +00:00
"opts" : "" ,
}
// Instantiate new minio client object.
c , err := minio . NewV2 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client v2 object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Make a new bucket.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-12-08 19:45:59 +00:00
args [ "bucketName" ] = bucketName
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
}
defer c . RemoveBucket ( bucketName )
bufSize := dataFileMap [ "datatfile-33-kB" ]
var reader = getDataReader ( "datafile-33-kB" )
defer reader . Close ( )
objectName := fmt . Sprintf ( "test-file-%v" , rand . Uint32 ( ) )
args [ "objectName" ] = objectName
ctx , cancel := context . WithTimeout ( context . Background ( ) , 30 * time . Second )
args [ "ctx" ] = ctx
2018-01-23 18:40:42 +00:00
args [ "size" ] = bufSize
2017-12-08 19:45:59 +00:00
defer cancel ( )
_ , err = c . PutObjectWithContext ( ctx , bucketName , objectName , reader , int64 ( bufSize ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObjectWithContext with short timeout failed" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
ctx , cancel = context . WithTimeout ( context . Background ( ) , 1 * time . Hour )
2017-12-08 19:45:59 +00:00
args [ "ctx" ] = ctx
defer cancel ( )
reader = getDataReader ( "datafile-33-kB" )
defer reader . Close ( )
_ , err = c . PutObjectWithContext ( ctx , bucketName , objectName , reader , int64 ( bufSize ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObjectWithContext with long timeout failed" , err )
2017-12-08 19:45:59 +00:00
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-12-08 19:45:59 +00:00
}
// Test get object with GetObjectWithContext
func testGetObjectWithContextV2 ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-12-08 19:45:59 +00:00
function := "GetObjectWithContext(ctx, bucketName, objectName)"
args := map [ string ] interface { } {
"ctx" : "" ,
"bucketName" : "" ,
"objectName" : "" ,
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . NewV2 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client v2 object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-12-08 19:45:59 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
2017-12-08 19:45:59 +00:00
return
}
bufSize := dataFileMap [ "datafile-33-kB" ]
var reader = getDataReader ( "datafile-33-kB" )
defer reader . Close ( )
// Save the data
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
args [ "objectName" ] = objectName
_ , err = c . PutObject ( bucketName , objectName , reader , int64 ( bufSize ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject call failed" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , 1 * time . Nanosecond )
2017-12-08 19:45:59 +00:00
args [ "ctx" ] = ctx
defer cancel ( )
r , err := c . GetObjectWithContext ( ctx , bucketName , objectName , minio . GetObjectOptions { } )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetObjectWithContext failed unexpectedly" , err )
return
}
if _ , err = r . Stat ( ) ; err == nil {
logError ( testName , function , args , startTime , "" , "GetObjectWithContext should fail on short timeout" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-03-30 10:33:40 +00:00
r . Close ( )
2018-01-23 18:40:42 +00:00
ctx , cancel = context . WithTimeout ( context . Background ( ) , 1 * time . Hour )
2017-12-08 19:45:59 +00:00
defer cancel ( )
// Read the data back
r , err = c . GetObjectWithContext ( ctx , bucketName , objectName , minio . GetObjectOptions { } )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "GetObjectWithContext shouldn't fail on longer timeout" , err )
2017-12-08 19:45:59 +00:00
return
}
st , err := r . Stat ( )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "object Stat call failed" , err )
2017-12-08 19:45:59 +00:00
return
}
if st . Size != int64 ( bufSize ) {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Number of bytes in stat does not match, expected " + string ( bufSize ) + " got " + string ( st . Size ) , err )
2017-12-08 19:45:59 +00:00
return
}
if err := r . Close ( ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , " object Close() call failed" , err )
2017-12-08 19:45:59 +00:00
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-12-08 19:45:59 +00:00
}
// Test get object with FGetObjectWithContext
func testFGetObjectWithContextV2 ( ) {
// initialize logging params
startTime := time . Now ( )
2018-01-23 18:40:42 +00:00
testName := getFuncName ( )
2017-12-08 19:45:59 +00:00
function := "FGetObjectWithContext(ctx, bucketName, objectName,fileName)"
args := map [ string ] interface { } {
2018-01-23 18:40:42 +00:00
"ctx" : "" ,
2017-12-08 19:45:59 +00:00
"bucketName" : "" ,
"objectName" : "" ,
"fileName" : "" ,
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . NewV2 (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Minio client v2 object creation failed" , err )
2017-12-08 19:45:59 +00:00
return
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
2018-01-23 18:40:42 +00:00
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
2017-12-08 19:45:59 +00:00
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "MakeBucket call failed" , err )
2017-12-08 19:45:59 +00:00
return
}
bufSize := dataFileMap [ "datatfile-1-MB" ]
var reader = getDataReader ( "datafile-1-MB" )
defer reader . Close ( )
// Save the data
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
args [ "objectName" ] = objectName
_ , err = c . PutObject ( bucketName , objectName , reader , int64 ( bufSize ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "PutObject call failed" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , 1 * time . Nanosecond )
2017-12-08 19:45:59 +00:00
args [ "ctx" ] = ctx
defer cancel ( )
fileName := "tempfile-context"
args [ "fileName" ] = fileName
// Read the data back
err = c . FGetObjectWithContext ( ctx , bucketName , objectName , fileName + "-f" , minio . GetObjectOptions { } )
if err == nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "FGetObjectWithContext should fail on short timeout" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
ctx , cancel = context . WithTimeout ( context . Background ( ) , 1 * time . Hour )
2017-12-08 19:45:59 +00:00
defer cancel ( )
// Read the data back
err = c . FGetObjectWithContext ( ctx , bucketName , objectName , fileName + "-fcontext" , minio . GetObjectOptions { } )
if err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "FGetObjectWithContext call shouldn't fail on long timeout" , err )
2017-12-08 19:45:59 +00:00
return
}
if err = os . Remove ( fileName + "-fcontext" ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Remove file failed" , err )
2017-12-08 19:45:59 +00:00
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
2018-01-23 18:40:42 +00:00
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
2017-12-08 19:45:59 +00:00
return
}
2018-01-23 18:40:42 +00:00
successLogger ( testName , function , args , startTime ) . Info ( )
2017-12-08 19:45:59 +00:00
}
2018-08-01 17:43:44 +00:00
// Test list object v1 and V2 storage class fields
func testListObjects ( ) {
// initialize logging params
startTime := time . Now ( )
testName := getFuncName ( )
function := "ListObjects(bucketName, objectPrefix, recursive, doneCh)"
args := map [ string ] interface { } {
"bucketName" : "" ,
"objectPrefix" : "" ,
"recursive" : "true" ,
}
// Seed random based on current time.
rand . Seed ( time . Now ( ) . Unix ( ) )
// Instantiate new minio client object.
c , err := minio . New (
os . Getenv ( serverEndpoint ) ,
os . Getenv ( accessKey ) ,
os . Getenv ( secretKey ) ,
mustParseBool ( os . Getenv ( enableHTTPS ) ) ,
)
if err != nil {
logError ( testName , function , args , startTime , "" , "Minio client v4 object creation failed" , err )
return
}
// Enable tracing, write to stderr.
// c.TraceOn(os.Stderr)
// Set user agent.
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
// Generate a new random bucket name.
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test-" )
args [ "bucketName" ] = bucketName
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
logError ( testName , function , args , startTime , "" , "MakeBucket failed" , err )
return
}
bufSize := dataFileMap [ "datafile-33-kB" ]
var reader = getDataReader ( "datafile-33-kB" )
defer reader . Close ( )
// Save the data
objectName1 := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
_ , err = c . PutObject ( bucketName , objectName1 , reader , int64 ( bufSize ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" , StorageClass : "STANDARD" } )
if err != nil {
logError ( testName , function , args , startTime , "" , "PutObject1 call failed" , err )
return
}
bufSize1 := dataFileMap [ "datafile-33-kB" ]
var reader1 = getDataReader ( "datafile-33-kB" )
defer reader1 . Close ( )
objectName2 := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
_ , err = c . PutObject ( bucketName , objectName2 , reader1 , int64 ( bufSize1 ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" , StorageClass : "REDUCED_REDUNDANCY" } )
if err != nil {
logError ( testName , function , args , startTime , "" , "PutObject2 call failed" , err )
return
}
// Create a done channel to control 'ListObjects' go routine.
doneCh := make ( chan struct { } )
// Exit cleanly upon return.
defer close ( doneCh )
// check for storage-class from ListObjects result
for objInfo := range c . ListObjects ( bucketName , "" , true , doneCh ) {
if objInfo . Err != nil {
logError ( testName , function , args , startTime , "" , "ListObjects failed unexpectedly" , err )
return
}
if objInfo . Key == objectName1 && objInfo . StorageClass != "STANDARD" {
// Ignored as Gateways (Azure/GCS etc) wont return storage class
ignoredLog ( testName , function , args , startTime , "ListObjects doesn't return expected storage class" ) . Info ( )
}
if objInfo . Key == objectName2 && objInfo . StorageClass != "REDUCED_REDUNDANCY" {
// Ignored as Gateways (Azure/GCS etc) wont return storage class
ignoredLog ( testName , function , args , startTime , "ListObjects doesn't return expected storage class" ) . Info ( )
}
}
// check for storage-class from ListObjectsV2 result
for objInfo := range c . ListObjectsV2 ( bucketName , "" , true , doneCh ) {
if objInfo . Err != nil {
logError ( testName , function , args , startTime , "" , "ListObjectsV2 failed unexpectedly" , err )
return
}
if objInfo . Key == objectName1 && objInfo . StorageClass != "STANDARD" {
// Ignored as Gateways (Azure/GCS etc) wont return storage class
ignoredLog ( testName , function , args , startTime , "ListObjectsV2 doesn't return expected storage class" ) . Info ( )
}
if objInfo . Key == objectName2 && objInfo . StorageClass != "REDUCED_REDUNDANCY" {
// Ignored as Gateways (Azure/GCS etc) wont return storage class
ignoredLog ( testName , function , args , startTime , "ListObjectsV2 doesn't return expected storage class" ) . Info ( )
}
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( testName , function , args , startTime , "" , "Cleanup failed" , err )
return
}
successLogger ( testName , function , args , startTime ) . Info ( )
}
2017-12-08 19:45:59 +00:00
// Convert string to bool and always return false if any error
func mustParseBool ( str string ) bool {
b , err := strconv . ParseBool ( str )
if err != nil {
return false
}
return b
}
func main ( ) {
// Output to stdout instead of the default stderr
log . SetOutput ( os . Stdout )
// create custom formatter
mintFormatter := mintJSONFormatter { }
// set custom formatter
log . SetFormatter ( & mintFormatter )
// log Info or above -- success cases are Info level, failures are Fatal level
log . SetLevel ( log . InfoLevel )
tls := mustParseBool ( os . Getenv ( enableHTTPS ) )
// execute tests
2018-01-23 18:40:42 +00:00
if isFullMode ( ) {
2017-12-08 19:45:59 +00:00
testMakeBucketErrorV2 ( )
testGetObjectClosedTwiceV2 ( )
testFPutObjectV2 ( )
testMakeBucketRegionsV2 ( )
testGetObjectReadSeekFunctionalV2 ( )
testGetObjectReadAtFunctionalV2 ( )
testCopyObjectV2 ( )
testFunctionalV2 ( )
testComposeObjectErrorCasesV2 ( )
testCompose10KSourcesV2 ( )
2017-09-13 12:09:48 +00:00
testUserMetadataCopyingV2 ( )
testPutObject0ByteV2 ( )
testPutObjectNoLengthV2 ( )
testPutObjectsUnknownV2 ( )
2017-12-08 19:45:59 +00:00
testGetObjectWithContextV2 ( )
testFPutObjectWithContextV2 ( )
testFGetObjectWithContextV2 ( )
testPutObjectWithContextV2 ( )
2017-09-13 12:09:48 +00:00
testMakeBucketError ( )
testMakeBucketRegions ( )
testPutObjectWithMetadata ( )
testPutObjectReadAt ( )
testPutObjectStreaming ( )
testGetObjectSeekEnd ( )
testGetObjectClosedTwice ( )
testRemoveMultipleObjects ( )
testFPutObjectMultipart ( )
testFPutObject ( )
testGetObjectReadSeekFunctional ( )
testGetObjectReadAtFunctional ( )
testPresignedPostPolicy ( )
testCopyObject ( )
testComposeObjectErrorCases ( )
testCompose10KSources ( )
testUserMetadataCopying ( )
testBucketNotification ( )
testFunctional ( )
2018-01-23 18:40:42 +00:00
testGetObjectModified ( )
2017-09-13 12:09:48 +00:00
testPutObjectUploadSeekedObject ( )
2017-12-08 19:45:59 +00:00
testGetObjectWithContext ( )
testFPutObjectWithContext ( )
testFGetObjectWithContext ( )
2018-09-03 18:23:56 +00:00
testGetObjectACL ( )
2017-12-08 19:45:59 +00:00
testPutObjectWithContext ( )
2018-01-23 18:40:42 +00:00
testStorageClassMetadataPutObject ( )
testStorageClassInvalidMetadataPutObject ( )
testStorageClassMetadataCopyObject ( )
2018-08-01 17:43:44 +00:00
testPutObjectWithContentLanguage ( )
testListObjects ( )
2017-12-08 19:45:59 +00:00
// SSE-C tests will only work over TLS connection.
if tls {
2018-03-30 10:33:40 +00:00
testEncryptionPutGet ( )
testEncryptionFPut ( )
testEncryptedGetObjectReadAtFunctional ( )
testEncryptedGetObjectReadSeekFunctional ( )
2017-12-08 19:45:59 +00:00
testEncryptedCopyObjectV2 ( )
testEncryptedCopyObject ( )
2018-03-30 10:33:40 +00:00
testEncryptedEmptyObject ( )
2018-08-01 17:43:44 +00:00
testDecryptedCopyObject ( )
2017-12-08 19:45:59 +00:00
}
2017-09-13 12:09:48 +00:00
} else {
testFunctional ( )
testFunctionalV2 ( )
}
}