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/hex"
"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"
"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"
"github.com/minio/minio-go/pkg/policy"
)
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
}
// log successful test runs
func successLogger ( function string , args map [ string ] interface { } , startTime time . Time ) * log . Entry {
// calculate the test case duration
duration := time . Since ( startTime )
// log with the fields as per mint
fields := log . Fields { "name" : "minio-go" , "function" : function , "args" : args , "duration" : duration . Nanoseconds ( ) / 1000000 , "status" : "pass" }
return log . WithFields ( fields )
}
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
func logError ( function string , args map [ string ] interface { } , startTime time . Time , alert string , message string , err error ) {
// 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 ) {
ignoredLog ( function , args , startTime , message ) . Info ( )
} else {
failureLog ( function , args , startTime , alert , message , err ) . Fatal ( )
}
}
2017-09-13 12:09:48 +00:00
// log failed test runs
func failureLog ( function string , args map [ string ] interface { } , startTime time . Time , alert string , message string , err error ) * log . Entry {
// calculate the test case duration
duration := time . Since ( startTime )
var fields log . Fields
// log with the fields as per mint
if err != nil {
fields = log . Fields { "name" : "minio-go" , "function" : function , "args" : args ,
"duration" : duration . Nanoseconds ( ) / 1000000 , "status" : "fail" , "alert" : alert , "message" : message , "error" : err }
} else {
fields = log . Fields { "name" : "minio-go" , "function" : function , "args" : args ,
"duration" : duration . Nanoseconds ( ) / 1000000 , "status" : "fail" , "alert" : alert , "message" : message }
}
return log . WithFields ( fields )
}
// log not applicable test runs
func ignoredLog ( function string , args map [ string ] interface { } , startTime time . Time , message string ) * log . Entry {
// calculate the test case duration
duration := time . Since ( startTime )
// log with the fields as per mint
fields := log . Fields { "name" : "minio-go" , "function" : function , "args" : args ,
"duration" : duration . Nanoseconds ( ) / 1000000 , "status" : "na" , "message" : message }
return log . WithFields ( fields )
}
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 ,
}
2017-09-13 12:09:48 +00:00
func isQuickMode ( ) bool {
return os . Getenv ( "MODE" ) == "quick"
}
// Tests bucket re-create errors.
func testMakeBucketError ( ) {
region := "eu-central-1"
// initialize logging params
startTime := time . Now ( )
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" {
ignoredLog ( function , args , startTime , "Skipped region functional tests for non s3 runs" ) . Info ( )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client creation failed" , err )
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.
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test" )
args [ "bucketName" ] = bucketName
// Make a new bucket in 'eu-central-1'.
if err = c . MakeBucket ( bucketName , region ) ; err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket Failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if err = c . MakeBucket ( bucketName , region ) ; err == nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Bucket already exists" , err )
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" {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Invalid error returned by server" , err )
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
}
successLogger ( function , args , startTime ) . Info ( )
}
func testMetadataSizeLimit ( ) {
startTime := time . Now ( )
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 {
logError ( function , args , startTime , "" , "Minio client creation failed" , err )
return
}
c . SetAppInfo ( "Minio-go-FunctionalTest" , "0.1.0" )
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test" )
args [ "bucketName" ] = bucketName
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
args [ "objectName" ] = objectName
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
logError ( function , args , startTime , "" , "Make bucket failed" , err )
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 {
logError ( function , args , startTime , "" , "Created object with user-defined metadata exceeding metadata size limits" , nil )
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 {
logError ( function , args , startTime , "" , "Created object with headers exceeding header size limits" , nil )
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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
2017-09-13 12:09:48 +00:00
}
successLogger ( function , args , startTime ) . Info ( )
}
// Tests various bucket supported formats.
func testMakeBucketRegions ( ) {
region := "eu-central-1"
// initialize logging params
startTime := time . Now ( )
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" {
ignoredLog ( function , args , startTime , "Skipped region functional tests for non s3 runs" ) . Info ( )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client creation failed" , err )
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.
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test" )
args [ "bucketName" ] = bucketName
// Make a new bucket in 'eu-central-1'.
if err = c . MakeBucket ( bucketName , region ) ; err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , 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 + ".withperiod" , c ) ; err != nil {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
2017-09-13 12:09:48 +00:00
}
successLogger ( function , args , startTime ) . Info ( )
}
// Test PutObject using a large data to trigger multipart readat
func testPutObjectReadAt ( ) {
// initialize logging params
startTime := time . Now ( )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client object creation failed" , err )
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.
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Make bucket failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
logError ( function , args , startTime , "" , "Number of bytes returned by PutObject does not match, expected " + string ( bufSize ) + " got " + string ( n ) , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Get Object failed" , err )
return
2017-09-13 12:09:48 +00:00
}
st , err := r . Stat ( )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Stat Object failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if st . Size != int64 ( bufSize ) {
logError ( function , args , startTime , "" , fmt . Sprintf ( "Number of bytes in stat does not match, expected %d got %d" , bufSize , st . Size ) , err )
return
2017-09-13 12:09:48 +00:00
}
if st . ContentType != objectContentType {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Content types don't match" , err )
return
2017-09-13 12:09:48 +00:00
}
if err := r . Close ( ) ; err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Object Close failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if err := r . Close ( ) ; err == nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Object is already closed, didn't return error on Close" , 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
2017-09-13 12:09:48 +00:00
}
successLogger ( function , args , startTime ) . Info ( )
}
// Test PutObject using a large data to trigger multipart readat
func testPutObjectWithMetadata ( ) {
// initialize logging params
startTime := time . Now ( )
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
}
if isQuickMode ( ) {
ignoredLog ( function , args , startTime , "Skipping functional tests for short runs" ) . Info ( )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client object creation failed" , err )
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.
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Make bucket failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
logError ( function , args , startTime , "" , "Number of bytes returned by PutObject does not match, expected " + string ( bufSize ) + " got " + string ( n ) , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
st , err := r . Stat ( )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Stat failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if st . Size != int64 ( bufSize ) {
logError ( function , args , startTime , "" , "Number of bytes returned by PutObject does not match GetObject, expected " + string ( bufSize ) + " got " + string ( st . Size ) , err )
return
2017-09-13 12:09:48 +00:00
}
if st . ContentType != customContentType {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ContentType does not match, expected " + customContentType + " got " + st . ContentType , err )
return
2017-09-13 12:09:48 +00:00
}
if err := r . Close ( ) ; err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Object Close failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if err := r . Close ( ) ; err == nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Object already closed, should respond with error" , 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
2017-09-13 12:09:48 +00:00
}
successLogger ( function , args , startTime ) . Info ( )
}
// Test put object with streaming signature.
func testPutObjectStreaming ( ) {
// initialize logging params
objectName := "test-object"
startTime := time . Now ( )
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" : 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client object creation failed" , err )
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.
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// Upload an object.
sizes := [ ] int64 { 0 , 64 * 1024 - 1 , 64 * 1024 }
for _ , size := range sizes {
data := bytes . Repeat ( [ ] byte ( "a" ) , int ( size ) )
2017-12-08 19:45:59 +00:00
n , err := c . PutObject ( bucketName , objectName , bytes . NewReader ( data ) , int64 ( size ) , minio . PutObjectOptions { } )
2017-09-13 12:09:48 +00:00
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObjectStreaming failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if n != size {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Expected upload object size doesn't match with PutObjectStreaming 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
2017-09-13 12:09:48 +00:00
}
successLogger ( function , args , startTime ) . Info ( )
}
// Test listing partially uploaded objects.
func testListPartiallyUploaded ( ) {
// initialize logging params
startTime := time . Now ( )
function := "ListIncompleteUploads(bucketName, objectName, isRecursive, doneCh)"
args := map [ string ] interface { } {
"bucketName" : "" ,
"objectName" : "" ,
"isRecursive" : "" ,
}
// 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client object creation failed" , err )
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.
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
bufSize := dataFileMap [ "datafile-65-MB" ]
r := bytes . NewReader ( bytes . Repeat ( [ ] byte ( "0" ) , bufSize * 2 ) )
2017-09-13 12:09:48 +00:00
reader , writer := io . Pipe ( )
go func ( ) {
i := 0
for i < 25 {
2017-12-08 19:45:59 +00:00
_ , cerr := io . CopyN ( writer , r , ( int64 ( bufSize ) * 2 ) / 25 )
2017-09-13 12:09:48 +00:00
if cerr != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Copy failed" , err )
return
2017-09-13 12:09:48 +00:00
}
i ++
r . Seek ( 0 , 0 )
}
writer . CloseWithError ( errors . New ( "proactively closed to be verified later" ) )
} ( )
objectName := bucketName + "-resumable"
args [ "objectName" ] = objectName
2017-12-08 19:45:59 +00:00
_ , err = c . PutObject ( bucketName , objectName , reader , int64 ( bufSize * 2 ) , minio . PutObjectOptions { ContentType : "application/octet-stream" } )
2017-09-13 12:09:48 +00:00
if err == nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject should fail" , err )
return
2017-09-13 12:09:48 +00:00
}
if ! strings . Contains ( err . Error ( ) , "proactively closed to be verified later" ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "String not found in PutObject output" , err )
return
2017-09-13 12:09:48 +00:00
}
doneCh := make ( chan struct { } )
defer close ( doneCh )
isRecursive := true
args [ "isRecursive" ] = isRecursive
multiPartObjectCh := c . ListIncompleteUploads ( bucketName , objectName , isRecursive , doneCh )
for multiPartObject := range multiPartObjectCh {
if multiPartObject . Err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Multipart object error" , multiPartObject . 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
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
successLogger ( function , args , startTime ) . Info ( )
}
// Test get object seeker from the end, using whence set to '2'.
func testGetObjectSeekEnd ( ) {
// initialize logging params
startTime := time . Now ( )
function := "GetObject(bucketName, objectName)"
args := map [ string ] interface { } {
"bucketName" : "" ,
"objectName" : "" ,
}
// 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client object creation failed" , err )
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.
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket 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 ( )
// Save the data
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
args [ "objectName" ] = objectName
buf , err := ioutil . ReadAll ( reader )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAll failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
logError ( function , args , startTime , "" , "Number of bytes read does not match, expected " + string ( int64 ( bufSize ) ) + " got " + string ( n ) , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
st , err := r . Stat ( )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Stat failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if st . Size != int64 ( bufSize ) {
logError ( function , args , startTime , "" , "Number of bytes read does not match, expected " + string ( int64 ( bufSize ) ) + " got " + string ( st . Size ) , err )
return
2017-09-13 12:09:48 +00:00
}
pos , err := r . Seek ( - 100 , 2 )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Object Seek failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if pos != st . Size - 100 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Incorrect position" , err )
return
2017-09-13 12:09:48 +00:00
}
buf2 := make ( [ ] byte , 100 )
m , err := io . ReadFull ( r , buf2 )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Error reading through io.ReadFull" , err )
return
2017-09-13 12:09:48 +00:00
}
if m != len ( buf2 ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Number of bytes dont match, expected " + string ( len ( buf2 ) ) + " got " + string ( m ) , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Values at same index dont match" , err )
return
2017-09-13 12:09:48 +00:00
}
pos , err = r . Seek ( - 100 , 2 )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Object Seek failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if pos != st . Size - 100 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Incorrect position" , err )
return
2017-09-13 12:09:48 +00:00
}
if err = r . Close ( ) ; err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ObjectClose failed" , err )
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
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
successLogger ( function , args , startTime ) . Info ( )
}
// Test get object reader to not throw error on being closed twice.
func testGetObjectClosedTwice ( ) {
// initialize logging params
startTime := time . Now ( )
function := "GetObject(bucketName, objectName)"
args := map [ string ] interface { } {
"bucketName" : "" ,
"objectName" : "" ,
}
// 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client object creation failed" , err )
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.
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket 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 ( )
// 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
logError ( function , args , startTime , "" , "PutObject response doesn't match sent bytes, expected " + string ( int64 ( bufSize ) ) + " got " + string ( n ) , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
st , err := r . Stat ( )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Stat failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if st . Size != int64 ( bufSize ) {
logError ( function , args , startTime , "" , "Number of bytes in stat does not match, expected " + string ( int64 ( bufSize ) ) + " got " + string ( st . Size ) , err )
return
2017-09-13 12:09:48 +00:00
}
if err := r . Close ( ) ; err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Object Close failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if err := r . Close ( ) ; err == nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Already closed object. No error returned" , 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
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
successLogger ( function , args , startTime ) . Info ( )
}
// Test removing multiple objects with Remove API
func testRemoveMultipleObjects ( ) {
// initialize logging params
startTime := time . Now ( )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client object creation failed" , err )
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.
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
return
2017-09-13 12:09:48 +00:00
}
r := bytes . NewReader ( bytes . Repeat ( [ ] byte ( "a" ) , 8 ) )
// Multi remove of 1100 objects
nrObjects := 1100
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 {
2017-12-08 19:45:59 +00:00
logError ( 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Unexpected error" , r . 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
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
successLogger ( function , args , startTime ) . Info ( )
}
// Tests removing partially uploaded objects.
func testRemovePartiallyUploaded ( ) {
// initialize logging params
startTime := time . Now ( )
function := "RemoveIncompleteUpload(bucketName, objectName)"
args := map [ string ] interface { } {
"bucketName" : "" ,
"objectName" : "" ,
}
// 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client object creation failed" , err )
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.
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
return
2017-09-13 12:09:48 +00:00
}
r := bytes . NewReader ( bytes . Repeat ( [ ] byte ( "a" ) , 128 * 1024 ) )
reader , writer := io . Pipe ( )
go func ( ) {
i := 0
for i < 25 {
_ , cerr := io . CopyN ( writer , r , 128 * 1024 )
if cerr != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Copy failed" , err )
return
2017-09-13 12:09:48 +00:00
}
i ++
r . Seek ( 0 , 0 )
}
writer . CloseWithError ( errors . New ( "proactively closed to be verified later" ) )
} ( )
objectName := bucketName + "-resumable"
args [ "objectName" ] = objectName
2017-12-08 19:45:59 +00:00
_ , err = c . PutObject ( bucketName , objectName , reader , 128 * 1024 , minio . PutObjectOptions { ContentType : "application/octet-stream" } )
2017-09-13 12:09:48 +00:00
if err == nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject should fail" , err )
return
2017-09-13 12:09:48 +00:00
}
if ! strings . Contains ( err . Error ( ) , "proactively closed to be verified later" ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "String not found" , err )
return
2017-09-13 12:09:48 +00:00
}
err = c . RemoveIncompleteUpload ( bucketName , objectName )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "RemoveIncompleteUpload failed" , 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
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
successLogger ( function , args , startTime ) . Info ( )
}
// Tests FPutObject of a big file to trigger multipart
func testFPutObjectMultipart ( ) {
// initialize logging params
startTime := time . Now ( )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client object creation failed" , err )
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.
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "TempFile creation failed" , err )
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 {
logError ( function , args , startTime , "" , "Copy failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if err = file . Close ( ) ; err != nil {
logError ( function , args , startTime , "" , "File Close failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "FPutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( totalSize ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "FPutObject failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
objInfo , err := r . Stat ( )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Unexpected error" , err )
return
2017-09-13 12:09:48 +00:00
}
if objInfo . Size != int64 ( totalSize ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( totalSize ) ) + " got " + string ( objInfo . Size ) , err )
return
2017-09-13 12:09:48 +00:00
}
if objInfo . ContentType != objectContentType {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ContentType doesn't match" , 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
2017-09-13 12:09:48 +00:00
}
successLogger ( function , args , startTime ) . Info ( )
}
// Tests FPutObject with null contentType (default = application/octet-stream)
func testFPutObject ( ) {
// initialize logging params
startTime := time . Now ( )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client object creation failed" , err )
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.
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "TempFile creation failed" , err )
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 {
logError ( function , args , startTime , "" , "File copy failed" , err )
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 {
logError ( function , args , startTime , "" , "File close failed" , err )
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
objectName := bucketName + "FPutObject"
args [ "objectName" ] = objectName
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "FPutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( totalSize ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Number of bytes does not match, expected " + string ( totalSize ) + ", got " + string ( n ) , err )
return
2017-09-13 12:09:48 +00:00
}
// Perform FPutObject with no contentType provided (Expecting application/octet-stream)
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "File close failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( totalSize ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Number of bytes does not match, expected " + string ( totalSize ) + ", got " + string ( n ) , err )
return
2017-09-13 12:09:48 +00:00
}
srcFile , err := os . Open ( fName )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "File open failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "File create failed" , err )
return
2017-09-13 12:09:48 +00:00
}
defer tmpFile . Close ( )
_ , err = io . Copy ( tmpFile , srcFile )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "File copy failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// Perform FPutObject with no contentType provided (Expecting application/x-gtar)
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "FPutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( totalSize ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Number of bytes does not match, expected " + string ( totalSize ) + ", got " + string ( n ) , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "StatObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if rStandard . ContentType != "application/octet-stream" {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ContentType does not match, expected application/octet-stream, got " + rStandard . ContentType , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "StatObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if rOctet . ContentType != "application/octet-stream" {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ContentType does not match, expected application/octet-stream, got " + rStandard . ContentType , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "StatObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if rGTar . ContentType != "application/x-gtar" {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ContentType does not match, expected application/x-gtar, got " + rStandard . ContentType , 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
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 {
logError ( function , args , startTime , "" , "File remove failed" , err )
return
2017-09-13 12:09:48 +00:00
}
successLogger ( function , args , startTime ) . Info ( )
}
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 ( )
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 {
2017-12-08 19:45:59 +00:00
logError ( 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 ( function , args , startTime , "" , "MakeBucket failed" , err )
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 {
logError ( function , args , startTime , "" , "TempFile creation failed" , err )
return
}
// Upload 1 parts to trigger multipart upload
if _ , err = io . Copy ( file , getDataReader ( "datafile-1-MB" ) ) ; err != nil {
logError ( function , args , startTime , "" , "File copy failed" , err )
return
}
// Close the file pro-actively for windows.
if err = file . Close ( ) ; err != nil {
logError ( function , args , startTime , "" , "File close failed" , err )
return
}
defer os . Remove ( file . Name ( ) )
fName = file . Name ( )
}
totalSize := dataFileMap [ "datafile-1-MB" ]
// Set base object name
objectName := bucketName + "FPutObjectWithContext"
args [ "objectName" ] = objectName
ctx , cancel := context . WithTimeout ( context . Background ( ) , 10 * time . Millisecond )
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 {
logError ( function , args , startTime , "" , "Request context cancellation failed" , err )
return
}
ctx , cancel = context . WithTimeout ( context . Background ( ) , 10 * time . Minute )
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 {
logError ( function , args , startTime , "" , "FPutObjectWithContext failed" , err )
return
}
if n != int64 ( totalSize ) {
logError ( function , args , startTime , "" , "Number of bytes does not match, expected " + string ( totalSize ) + ", got " + string ( n ) , err )
return
}
_ , err = c . StatObject ( bucketName , objectName + "-Longtimeout" , minio . StatObjectOptions { } )
if err != nil {
logError ( function , args , startTime , "" , "StatObject failed" , err )
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
}
successLogger ( function , args , startTime ) . Info ( )
}
// Tests FPutObjectWithContext request context cancels after timeout
func testFPutObjectWithContextV2 ( ) {
// initialize logging params
startTime := time . Now ( )
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 {
logError ( 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 ( function , args , startTime , "" , "MakeBucket failed" , err )
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 {
logError ( function , args , startTime , "" , "Temp file creation failed" , err )
return
}
// Upload 1 parts to trigger multipart upload
if _ , err = io . Copy ( file , getDataReader ( "datafile-1-MB" ) ) ; err != nil {
logError ( function , args , startTime , "" , "File copy failed" , err )
return
}
// Close the file pro-actively for windows.
if err = file . Close ( ) ; err != nil {
logError ( function , args , startTime , "" , "File close failed" , err )
return
}
defer os . Remove ( file . Name ( ) )
fName = file . Name ( )
}
totalSize := dataFileMap [ "datafile-1-MB" ]
// Set base object name
objectName := bucketName + "FPutObjectWithContext"
args [ "objectName" ] = objectName
ctx , cancel := context . WithTimeout ( context . Background ( ) , 2 * time . Millisecond )
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 {
logError ( function , args , startTime , "" , "FPutObjectWithContext with short timeout failed" , err )
return
}
ctx , cancel = context . WithTimeout ( context . Background ( ) , 10 * time . Minute )
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 {
logError ( function , args , startTime , "" , "FPutObjectWithContext with long timeout failed" , err )
return
}
if n != int64 ( totalSize ) {
logError ( function , args , startTime , "" , "Number of bytes does not match:wanted" + string ( totalSize ) + " got " + string ( n ) , err )
return
}
_ , err = c . StatObject ( bucketName , objectName + "-Longtimeout" , minio . StatObjectOptions { } )
if err != nil {
logError ( function , args , startTime , "" , "StatObject failed" , err )
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
}
successLogger ( function , args , startTime ) . Info ( )
}
// Test validates putObject with context to see if request cancellation is honored.
func testPutObjectWithContext ( ) {
// initialize logging params
startTime := time . Now ( )
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 {
logError ( 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" )
// Make a new bucket.
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test" )
args [ "bucketName" ] = bucketName
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
logError ( function , args , startTime , "" , "MakeBucket call failed" , err )
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
ctx , cancel := context . WithTimeout ( context . Background ( ) , 30 * time . Second )
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" } )
if err != nil {
logError ( function , args , startTime , "" , "PutObjectWithContext with short timeout failed" , err )
return
}
ctx , cancel = context . WithTimeout ( context . Background ( ) , 3 * time . Minute )
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 {
logError ( function , args , startTime , "" , "PutObjectWithContext with long timeout failed" , err )
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
}
successLogger ( function , args , startTime ) . Info ( )
}
// Tests get object ReaderSeeker interface methods.
func testGetObjectReadSeekFunctional ( ) {
// initialize logging params
startTime := time . Now ( )
function := "GetObject(bucketName, objectName)"
args := map [ string ] interface { } {
"bucketName" : "" ,
"objectName" : "" ,
}
// 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 ( function , args , startTime , "" , "Minio client object creation failed" , err )
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.
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAll failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
logError ( function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( bufSize ) ) + ", got " + string ( n ) , err )
return
2017-09-13 12:09:48 +00:00
}
defer func ( ) {
2017-12-08 19:45:59 +00:00
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
st , err := r . Stat ( )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Stat object failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if st . Size != int64 ( bufSize ) {
logError ( function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( bufSize ) ) + ", got " + string ( st . Size ) , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "CopyN failed" , err )
return
2017-09-13 12:09:48 +00:00
}
}
if ! bytes . Equal ( buf [ start : end ] , buffer . Bytes ( ) ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Incorrect read bytes v/s original buffer" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Test " + string ( i + 1 ) + ", unexpected err value: expected: " + testCase . err . Error ( ) + ", found: " + err . Error ( ) , err )
return
2017-09-13 12:09:48 +00:00
}
// We expect a specific error
if testCase . err != seekErr && testCase . err != err {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Test " + string ( i + 1 ) + ", unexpected err value: expected: " + testCase . err . Error ( ) + ", found: " + err . Error ( ) , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Test " + string ( i + 1 ) + ", number of bytes seeked does not match, expected " + string ( testCase . pos ) + ", got " + string ( n ) , err )
return
2017-09-13 12:09:48 +00:00
}
// Compare only if shouldCmp is activated
if testCase . shouldCmp {
cmpData ( r , testCase . start , testCase . end )
}
}
successLogger ( function , args , startTime ) . Info ( )
}
// Tests get object ReaderAt interface methods.
func testGetObjectReadAtFunctional ( ) {
// initialize logging params
startTime := time . Now ( )
function := "GetObject(bucketName, objectName)"
args := map [ string ] interface { } {
"bucketName" : "" ,
"objectName" : "" ,
}
// 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client object creation failed" , err )
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.
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAll failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
logError ( function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( bufSize ) ) + ", got " + string ( n ) , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject failed" , err )
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 )
// Test readAt before stat is called.
m , err := r . ReadAt ( buf1 , offset )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAt failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if m != len ( buf1 ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAt read shorter bytes before reaching EOF, expected " + string ( len ( buf1 ) ) + ", got " + string ( m ) , err )
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( buf1 , buf [ offset : offset + 512 ] ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Incorrect read between two ReadAt from same offset" , err )
return
2017-09-13 12:09:48 +00:00
}
offset += 512
st , err := r . Stat ( )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Stat failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if st . Size != int64 ( bufSize ) {
logError ( function , args , startTime , "" , "Number of bytes in stat does not match, expected " + string ( int64 ( bufSize ) ) + ", got " + string ( st . Size ) , err )
return
2017-09-13 12:09:48 +00:00
}
m , err = r . ReadAt ( buf2 , offset )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAt failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if m != len ( buf2 ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAt read shorter bytes before reaching EOF, expected " + string ( len ( buf2 ) ) + ", got " + string ( m ) , err )
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( buf2 , buf [ offset : offset + 512 ] ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Incorrect read between two ReadAt from same offset" , err )
return
2017-09-13 12:09:48 +00:00
}
offset += 512
m , err = r . ReadAt ( buf3 , offset )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAt failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if m != len ( buf3 ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAt read shorter bytes before reaching EOF, expected " + string ( len ( buf3 ) ) + ", got " + string ( m ) , err )
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( buf3 , buf [ offset : offset + 512 ] ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Incorrect read between two ReadAt from same offset" , err )
return
2017-09-13 12:09:48 +00:00
}
offset += 512
m , err = r . ReadAt ( buf4 , offset )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAt failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if m != len ( buf4 ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAt read shorter bytes before reaching EOF, expected " + string ( len ( buf4 ) ) + ", got " + string ( m ) , err )
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( buf4 , buf [ offset : offset + 512 ] ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Incorrect read between two ReadAt from same offset" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAt failed" , err )
return
2017-09-13 12:09:48 +00:00
}
}
if m != len ( buf5 ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAt read shorter bytes before reaching EOF, expected " + string ( len ( buf5 ) ) + ", got " + string ( m ) , err )
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( buf , buf5 ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Incorrect data read in GetObject, than what was previously uploaded" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAt failed" , 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
2017-09-13 12:09:48 +00:00
}
successLogger ( function , args , startTime ) . Info ( )
}
// Test Presigned Post Policy
func testPresignedPostPolicy ( ) {
// initialize logging params
startTime := time . Now ( )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client object creation failed" , err )
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.
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket 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 ( ) ) , "" )
2017-12-08 19:45:59 +00:00
metadataKey := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
metadataValue := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
2017-09-13 12:09:48 +00:00
buf , err := ioutil . ReadAll ( reader )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAll failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
logError ( function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( bufSize ) ) + " got " + string ( n ) , err )
return
2017-09-13 12:09:48 +00:00
}
policy := minio . NewPostPolicy ( )
if err := policy . SetBucket ( "" ) ; err == nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetBucket did not fail for invalid conditions" , err )
return
2017-09-13 12:09:48 +00:00
}
if err := policy . SetKey ( "" ) ; err == nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetKey did not fail for invalid conditions" , err )
return
2017-09-13 12:09:48 +00:00
}
if err := policy . SetKeyStartsWith ( "" ) ; err == nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetKeyStartsWith did not fail for invalid conditions" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetExpires did not fail for invalid conditions" , err )
return
2017-09-13 12:09:48 +00:00
}
if err := policy . SetContentType ( "" ) ; err == nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetContentType did not fail for invalid conditions" , err )
return
2017-09-13 12:09:48 +00:00
}
if err := policy . SetContentLengthRange ( 1024 * 1024 , 1024 ) ; err == nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetContentLengthRange did not fail for invalid conditions" , err )
return
}
if err := policy . SetUserMetadata ( "" , "" ) ; err == nil {
logError ( function , args , startTime , "" , "SetUserMetadata did not fail for invalid conditions" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedPostPolicy failed" , err )
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 {
logError ( function , args , startTime , "" , "TempFile creation failed" , err )
return
}
if _ , err = io . Copy ( file , getDataReader ( "datafile-33-kB" ) ) ; err != nil {
logError ( function , args , startTime , "" , "Copy failed" , err )
return
}
if err = file . Close ( ) ; err != nil {
logError ( function , args , startTime , "" , "File Close failed" , err )
return
}
filePath = file . Name ( )
}
// add file to post request
f , err := os . Open ( filePath )
defer f . Close ( )
if err != nil {
logError ( function , args , startTime , "" , "File open failed" , err )
return
}
w , err := writer . CreateFormFile ( "file" , filePath )
if err != nil {
logError ( function , args , startTime , "" , "CreateFormFile failed" , err )
return
}
_ , err = io . Copy ( w , f )
2017-09-13 12:09:48 +00:00
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Copy failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Http request failed" , err )
return
}
defer res . Body . Close ( )
if res . StatusCode != http . StatusNoContent {
logError ( function , args , startTime , "" , "Http request failed" , errors . New ( res . Status ) )
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
if val , ok := res . Header [ "Location" ] ; ok {
if val [ 0 ] != expectedLocation {
logError ( function , args , startTime , "" , "Location in header response is incorrect" , err )
return
}
} else {
logError ( function , args , startTime , "" , "Location not found in header response" , err )
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
}
2017-09-13 12:09:48 +00:00
successLogger ( function , args , startTime ) . Info ( )
}
// Tests copy object
func testCopyObject ( ) {
// initialize logging params
startTime := time . Now ( )
function := "CopyObject(dst, src)"
args := map [ string ] interface { } {
"dst" : "" ,
"src" : "" ,
}
// 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client object creation failed" , err )
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.
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket 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
// 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
logError ( function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( bufSize ) ) + ", got " + string ( n ) , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetObject failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Stat failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// Copy Source
src := minio . NewSourceInfo ( bucketName , objectName , nil )
// 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetModifiedSinceCond did not fail for invalid conditions" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetUnmodifiedSinceCond did not fail for invalid conditions" , err )
return
2017-09-13 12:09:48 +00:00
}
err = src . SetMatchETagCond ( "" )
if err == nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetMatchETagCond did not fail for invalid conditions" , err )
return
2017-09-13 12:09:48 +00:00
}
err = src . SetMatchETagExceptCond ( "" )
if err == nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetMatchETagExceptCond did not fail for invalid conditions" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetModifiedSinceCond failed" , err )
return
2017-09-13 12:09:48 +00:00
}
err = src . SetMatchETagCond ( objInfo . ETag )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetMatchETagCond failed" , err )
return
2017-09-13 12:09:48 +00:00
}
args [ "src" ] = src
dst , err := minio . NewDestinationInfo ( bucketName + "-copy" , objectName + "-copy" , nil , nil )
args [ "dst" ] = dst
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "NewDestinationInfo failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// Perform the Copy
err = c . CopyObject ( dst , src )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "CopyObject failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetObject failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetObject failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Stat failed" , err )
return
2017-09-13 12:09:48 +00:00
}
objInfoCopy , err := readerCopy . Stat ( )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Stat failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if objInfo . Size != objInfoCopy . Size {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Number of bytes does not match, expected " + string ( objInfoCopy . Size ) + ", got " + string ( objInfo . Size ) , err )
return
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetUnmodifiedSinceCond failed" , err )
return
2017-09-13 12:09:48 +00:00
}
err = src . SetMatchETagExceptCond ( objInfo . ETag )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetMatchETagExceptCond failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// Perform the Copy which should fail
err = c . CopyObject ( dst , src )
if err == nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "CopyObject did not fail for invalid conditions" , 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
}
if err = cleanupBucket ( bucketName + "-copy" , c ) ; err != nil {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
}
successLogger ( function , args , startTime ) . Info ( )
}
// TestEncryptionPutGet tests client side encryption
func testEncryptionPutGet ( ) {
// initialize logging params
startTime := time . Now ( )
function := "PutEncryptedObject(bucketName, objectName, reader, cbcMaterials, metadata, progress)"
args := map [ string ] interface { } {
"bucketName" : "" ,
"objectName" : "" ,
"cbcMaterials" : "" ,
"metadata" : "" ,
}
// 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client object creation failed" , err )
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.
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" )
2017-09-13 12:09:48 +00:00
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Generate a symmetric key
symKey := encrypt . NewSymmetricKey ( [ ] byte ( "my-secret-key-00" ) )
// Generate an assymmetric key from predefine public and private certificates
privateKey , err := hex . DecodeString (
"30820277020100300d06092a864886f70d0101010500048202613082025d" +
"0201000281810087b42ea73243a3576dc4c0b6fa245d339582dfdbddc20c" +
"bb8ab666385034d997210c54ba79275c51162a1221c3fb1a4c7c61131ca6" +
"5563b319d83474ef5e803fbfa7e52b889e1893b02586b724250de7ac6351" +
"cc0b7c638c980acec0a07020a78eed7eaa471eca4b92071394e061346c06" +
"15ccce2f465dee2080a89e43f29b5702030100010281801dd5770c3af8b3" +
"c85cd18cacad81a11bde1acfac3eac92b00866e142301fee565365aa9af4" +
"57baebf8bb7711054d071319a51dd6869aef3848ce477a0dc5f0dbc0c336" +
"5814b24c820491ae2bb3c707229a654427e03307fec683e6b27856688f08" +
"bdaa88054c5eeeb773793ff7543ee0fb0e2ad716856f2777f809ef7e6fa4" +
"41024100ca6b1edf89e8a8f93cce4b98c76c6990a09eb0d32ad9d3d04fbf" +
"0b026fa935c44f0a1c05dd96df192143b7bda8b110ec8ace28927181fd8c" +
"d2f17330b9b63535024100aba0260afb41489451baaeba423bee39bcbd1e" +
"f63dd44ee2d466d2453e683bf46d019a8baead3a2c7fca987988eb4d565e" +
"27d6be34605953f5034e4faeec9bdb0241009db2cb00b8be8c36710aff96" +
"6d77a6dec86419baca9d9e09a2b761ea69f7d82db2ae5b9aae4246599bb2" +
"d849684d5ab40e8802cfe4a2b358ad56f2b939561d2902404e0ead9ecafd" +
"bb33f22414fa13cbcc22a86bdf9c212ce1a01af894e3f76952f36d6c904c" +
"bd6a7e0de52550c9ddf31f1e8bfe5495f79e66a25fca5c20b3af5b870241" +
"0083456232aa58a8c45e5b110494599bda8dbe6a094683a0539ddd24e19d" +
"47684263bbe285ad953d725942d670b8f290d50c0bca3d1dc9688569f1d5" +
"9945cb5c7d" )
if err != nil {
logError ( function , args , startTime , "" , "DecodeString for symmetric Key generation failed" , err )
return
}
publicKey , err := hex . DecodeString ( "30819f300d06092a864886f70d010101050003818d003081890281810087" +
"b42ea73243a3576dc4c0b6fa245d339582dfdbddc20cbb8ab666385034d9" +
"97210c54ba79275c51162a1221c3fb1a4c7c61131ca65563b319d83474ef" +
"5e803fbfa7e52b889e1893b02586b724250de7ac6351cc0b7c638c980ace" +
"c0a07020a78eed7eaa471eca4b92071394e061346c0615ccce2f465dee20" +
"80a89e43f29b570203010001" )
2017-09-13 12:09:48 +00:00
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "DecodeString for symmetric Key generation failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
// Generate an asymmetric key
asymKey , err := encrypt . NewAsymmetricKey ( privateKey , publicKey )
2017-09-13 12:09:48 +00:00
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "NewAsymmetricKey for symmetric Key generation failed" , err )
return
}
testCases := [ ] struct {
buf [ ] byte
encKey encrypt . Key
} {
{ encKey : symKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 0 ) } ,
{ encKey : symKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 1 ) } ,
{ encKey : symKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 15 ) } ,
{ encKey : symKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 16 ) } ,
{ encKey : symKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 17 ) } ,
{ encKey : symKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 31 ) } ,
{ encKey : symKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 32 ) } ,
{ encKey : symKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 33 ) } ,
{ encKey : symKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 1024 ) } ,
{ encKey : symKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 1024 * 2 ) } ,
{ encKey : symKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 1024 * 1024 ) } ,
{ encKey : asymKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 0 ) } ,
{ encKey : asymKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 1 ) } ,
{ encKey : asymKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 16 ) } ,
{ encKey : asymKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 32 ) } ,
{ encKey : asymKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 1024 ) } ,
{ encKey : asymKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 1024 * 1024 ) } ,
}
for i , testCase := range testCases {
// Generate a random object name
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
args [ "objectName" ] = objectName
// Secured object
cbcMaterials , err := encrypt . NewCBCSecureMaterials ( testCase . encKey )
args [ "cbcMaterials" ] = cbcMaterials
if err != nil {
logError ( function , args , startTime , "" , "NewCBCSecureMaterials failed" , err )
return
}
// Put encrypted data
_ , err = c . PutEncryptedObject ( bucketName , objectName , bytes . NewReader ( testCase . buf ) , cbcMaterials )
if err != nil {
logError ( function , args , startTime , "" , "PutEncryptedObject failed" , err )
return
}
// Read the data back
r , err := c . GetEncryptedObject ( bucketName , objectName , cbcMaterials )
if err != nil {
logError ( function , args , startTime , "" , "GetEncryptedObject failed" , err )
return
}
defer r . Close ( )
// Compare the sent object with the received one
recvBuffer := bytes . NewBuffer ( [ ] byte { } )
if _ , err = io . Copy ( recvBuffer , r ) ; err != nil {
logError ( function , args , startTime , "" , "Test " + string ( i + 1 ) + ", error: " + err . Error ( ) , err )
return
}
if recvBuffer . Len ( ) != len ( testCase . buf ) {
logError ( 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 )
return
}
if ! bytes . Equal ( testCase . buf , recvBuffer . Bytes ( ) ) {
logError ( function , args , startTime , "" , "Test " + string ( i + 1 ) + ", Encrypted sent is not equal to decrypted, expected " + string ( testCase . buf ) + ", got " + string ( recvBuffer . Bytes ( ) ) , err )
return
}
successLogger ( function , args , startTime ) . Info ( )
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
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
successLogger ( function , args , startTime ) . Info ( )
}
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 ( )
2017-12-08 19:45:59 +00:00
function := "FPutEncryptedObject(bucketName, objectName, filePath, contentType, cbcMaterials)"
2017-09-13 12:09:48 +00:00
args := map [ string ] interface { } {
"bucketName" : "" ,
"objectName" : "" ,
2017-12-08 19:45:59 +00:00
"filePath" : "" ,
"contentType" : "" ,
2017-09-13 12:09:48 +00:00
"cbcMaterials" : "" ,
}
// 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client object creation failed" , err )
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.
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// Generate a symmetric key
symKey := encrypt . NewSymmetricKey ( [ ] byte ( "my-secret-key-00" ) )
// Generate an assymmetric key from predefine public and private certificates
privateKey , err := hex . DecodeString (
"30820277020100300d06092a864886f70d0101010500048202613082025d" +
"0201000281810087b42ea73243a3576dc4c0b6fa245d339582dfdbddc20c" +
"bb8ab666385034d997210c54ba79275c51162a1221c3fb1a4c7c61131ca6" +
"5563b319d83474ef5e803fbfa7e52b889e1893b02586b724250de7ac6351" +
"cc0b7c638c980acec0a07020a78eed7eaa471eca4b92071394e061346c06" +
"15ccce2f465dee2080a89e43f29b5702030100010281801dd5770c3af8b3" +
"c85cd18cacad81a11bde1acfac3eac92b00866e142301fee565365aa9af4" +
"57baebf8bb7711054d071319a51dd6869aef3848ce477a0dc5f0dbc0c336" +
"5814b24c820491ae2bb3c707229a654427e03307fec683e6b27856688f08" +
"bdaa88054c5eeeb773793ff7543ee0fb0e2ad716856f2777f809ef7e6fa4" +
"41024100ca6b1edf89e8a8f93cce4b98c76c6990a09eb0d32ad9d3d04fbf" +
"0b026fa935c44f0a1c05dd96df192143b7bda8b110ec8ace28927181fd8c" +
"d2f17330b9b63535024100aba0260afb41489451baaeba423bee39bcbd1e" +
"f63dd44ee2d466d2453e683bf46d019a8baead3a2c7fca987988eb4d565e" +
"27d6be34605953f5034e4faeec9bdb0241009db2cb00b8be8c36710aff96" +
"6d77a6dec86419baca9d9e09a2b761ea69f7d82db2ae5b9aae4246599bb2" +
"d849684d5ab40e8802cfe4a2b358ad56f2b939561d2902404e0ead9ecafd" +
"bb33f22414fa13cbcc22a86bdf9c212ce1a01af894e3f76952f36d6c904c" +
"bd6a7e0de52550c9ddf31f1e8bfe5495f79e66a25fca5c20b3af5b870241" +
"0083456232aa58a8c45e5b110494599bda8dbe6a094683a0539ddd24e19d" +
"47684263bbe285ad953d725942d670b8f290d50c0bca3d1dc9688569f1d5" +
"9945cb5c7d" )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "DecodeString for symmetric Key generation failed" , err )
return
2017-09-13 12:09:48 +00:00
}
publicKey , err := hex . DecodeString ( "30819f300d06092a864886f70d010101050003818d003081890281810087" +
"b42ea73243a3576dc4c0b6fa245d339582dfdbddc20cbb8ab666385034d9" +
"97210c54ba79275c51162a1221c3fb1a4c7c61131ca65563b319d83474ef" +
"5e803fbfa7e52b889e1893b02586b724250de7ac6351cc0b7c638c980ace" +
"c0a07020a78eed7eaa471eca4b92071394e061346c0615ccce2f465dee20" +
"80a89e43f29b570203010001" )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "DecodeString for symmetric Key generation failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// Generate an asymmetric key
asymKey , err := encrypt . NewAsymmetricKey ( privateKey , publicKey )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "NewAsymmetricKey for symmetric Key generation failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// Object custom metadata
customContentType := "custom/contenttype"
args [ "metadata" ] = customContentType
testCases := [ ] struct {
buf [ ] byte
encKey encrypt . Key
} {
{ encKey : symKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 0 ) } ,
{ encKey : symKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 1 ) } ,
{ encKey : symKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 15 ) } ,
{ encKey : symKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 16 ) } ,
{ encKey : symKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 17 ) } ,
{ encKey : symKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 31 ) } ,
{ encKey : symKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 32 ) } ,
{ encKey : symKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 33 ) } ,
{ encKey : symKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 1024 ) } ,
{ encKey : symKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 1024 * 2 ) } ,
{ encKey : symKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 1024 * 1024 ) } ,
{ encKey : asymKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 0 ) } ,
{ encKey : asymKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 1 ) } ,
{ encKey : asymKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 16 ) } ,
{ encKey : asymKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 32 ) } ,
{ encKey : asymKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 1024 ) } ,
{ encKey : asymKey , buf : bytes . Repeat ( [ ] byte ( "F" ) , 1024 * 1024 ) } ,
}
for i , testCase := range testCases {
// Generate a random object name
objectName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "" )
args [ "objectName" ] = objectName
// Secured object
cbcMaterials , err := encrypt . NewCBCSecureMaterials ( testCase . encKey )
args [ "cbcMaterials" ] = cbcMaterials
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "NewCBCSecureMaterials failed" , err )
return
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 {
logError ( function , args , startTime , "" , "file create failed" , err )
return
}
_ , err = file . Write ( testCase . buf )
2017-09-13 12:09:48 +00:00
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "file write failed" , err )
return
}
file . Close ( )
// Put encrypted data
if _ , err = c . FPutEncryptedObject ( bucketName , objectName , fileName , cbcMaterials ) ; err != nil {
logError ( function , args , startTime , "" , "FPutEncryptedObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// Read the data back
r , err := c . GetEncryptedObject ( bucketName , objectName , cbcMaterials )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetEncryptedObject failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Test " + string ( i + 1 ) + ", error: " + err . Error ( ) , err )
return
2017-09-13 12:09:48 +00:00
}
if recvBuffer . Len ( ) != len ( testCase . buf ) {
2017-12-08 19:45:59 +00:00
logError ( 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 )
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( testCase . buf , recvBuffer . Bytes ( ) ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Test " + string ( i + 1 ) + ", Encrypted sent is not equal to decrypted, expected " + string ( testCase . buf ) + ", got " + string ( recvBuffer . Bytes ( ) ) , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if err = os . Remove ( fileName ) ; err != nil {
logError ( function , args , startTime , "" , "File remove failed" , 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
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
successLogger ( function , args , startTime ) . Info ( )
}
func testBucketNotification ( ) {
// initialize logging params
startTime := time . Now ( )
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" ) == "" {
ignoredLog ( function , args , startTime , "Skipped notification test as it is not configured" ) . Info ( )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client object creation failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Duplicate entry added" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetBucketNotification failed" , err )
return
2017-09-13 12:09:48 +00:00
}
bNotification , err = c . GetBucketNotification ( bucketName )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetBucketNotification failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if len ( bNotification . TopicConfigs ) != 1 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Topic config is empty" , err )
return
2017-09-13 12:09:48 +00:00
}
if bNotification . TopicConfigs [ 0 ] . Filter . S3Key . FilterRules [ 0 ] . Value != "jpg" {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Couldn't get the suffix" , err )
return
2017-09-13 12:09:48 +00:00
}
err = c . RemoveAllBucketNotification ( bucketName )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "RemoveAllBucketNotification failed" , 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
}
2017-09-13 12:09:48 +00:00
successLogger ( function , args , startTime ) . Info ( )
}
// Tests comprehensive list of all methods.
func testFunctional ( ) {
// initialize logging params
startTime := time . Now ( )
function := "testFunctional()"
// 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 {
2017-12-08 19:45:59 +00:00
logError ( function , nil , startTime , "" , "Minio client object creation failed" , err )
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.
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test" )
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
function = "MakeBucket(bucketName, region)"
args := map [ string ] interface { } {
"bucketName" : bucketName ,
}
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "File creation failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "File write failed" , err )
return
2017-09-13 12:09:48 +00:00
}
}
file . Close ( )
// Verify if bucket exits and you have access.
var exists bool
exists , err = c . BucketExists ( bucketName )
function = "BucketExists(bucketName)"
args = map [ string ] interface { } {
"bucketName" : bucketName ,
}
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "BucketExists failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if ! exists {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Could not find the bucket" , err )
return
2017-09-13 12:09:48 +00:00
}
// Asserting the default bucket policy.
policyAccess , err := c . GetBucketPolicy ( bucketName , "" )
function = "GetBucketPolicy(bucketName, objectPrefix)"
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectPrefix" : "" ,
}
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetBucketPolicy failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if policyAccess != "none" {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "policy should be set to none" , err )
return
2017-09-13 12:09:48 +00:00
}
// Set the bucket policy to 'public readonly'.
err = c . SetBucketPolicy ( bucketName , "" , policy . BucketPolicyReadOnly )
function = "SetBucketPolicy(bucketName, objectPrefix, bucketPolicy)"
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectPrefix" : "" ,
"bucketPolicy" : policy . BucketPolicyReadOnly ,
}
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetBucketPolicy failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// should return policy `readonly`.
policyAccess , err = c . GetBucketPolicy ( bucketName , "" )
function = "GetBucketPolicy(bucketName, objectPrefix)"
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectPrefix" : "" ,
}
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetBucketPolicy failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if policyAccess != "readonly" {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "policy should be set to readonly" , err )
return
2017-09-13 12:09:48 +00:00
}
// Make the bucket 'public writeonly'.
err = c . SetBucketPolicy ( bucketName , "" , policy . BucketPolicyWriteOnly )
function = "SetBucketPolicy(bucketName, objectPrefix, bucketPolicy)"
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectPrefix" : "" ,
"bucketPolicy" : policy . BucketPolicyWriteOnly ,
}
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetBucketPolicy failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// should return policy `writeonly`.
policyAccess , err = c . GetBucketPolicy ( bucketName , "" )
function = "GetBucketPolicy(bucketName, objectPrefix)"
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectPrefix" : "" ,
}
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetBucketPolicy failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if policyAccess != "writeonly" {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "policy should be set to writeonly" , err )
return
2017-09-13 12:09:48 +00:00
}
// Make the bucket 'public read/write'.
err = c . SetBucketPolicy ( bucketName , "" , policy . BucketPolicyReadWrite )
function = "SetBucketPolicy(bucketName, objectPrefix, bucketPolicy)"
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectPrefix" : "" ,
"bucketPolicy" : policy . BucketPolicyReadWrite ,
}
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetBucketPolicy failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// should return policy `readwrite`.
policyAccess , err = c . GetBucketPolicy ( bucketName , "" )
function = "GetBucketPolicy(bucketName, objectPrefix)"
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectPrefix" : "" ,
}
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetBucketPolicy failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if policyAccess != "readwrite" {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "policy should be set to readwrite" , err )
return
2017-09-13 12:09:48 +00:00
}
// List all buckets.
buckets , err := c . ListBuckets ( )
function = "ListBuckets()"
args = nil
if len ( buckets ) == 0 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Found bucket list to be empty" , err )
return
2017-09-13 12:09:48 +00:00
}
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ListBuckets failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Bucket: " + bucketName + " not found" , err )
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)"
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( len ( buf ) ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Length doesn't match, expected " + string ( int64 ( len ( buf ) ) ) + " got " + string ( n ) , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( len ( buf ) ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Length doesn't match, expected " + string ( int64 ( len ( buf ) ) ) + " got " + string ( n ) , err )
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)"
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Object " + objectName + " not found" , err )
return
2017-09-13 12:09:48 +00:00
}
objFound = false
isRecursive = true // Recursive is true.
function = "ListObjectsV2(bucketName, objectName, isRecursive, doneCh)"
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Object " + objectName + " not found" , err )
return
2017-09-13 12:09:48 +00:00
}
incompObjNotFound := true
function = "ListIncompleteUploads(bucketName, objectName, isRecursive, doneCh)"
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Unexpected dangling incomplete upload found" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
newReader , err := c . GetObject ( bucketName , objectName , minio . GetObjectOptions { } )
2017-09-13 12:09:48 +00:00
function = "GetObject(bucketName, objectName)"
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName ,
}
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
newReadBytes , err := ioutil . ReadAll ( newReader )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAll failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( newReadBytes , buf ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetObject bytes mismatch" , err )
return
2017-09-13 12:09:48 +00:00
}
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
function = "FGetObject(bucketName, objectName, fileName)"
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName ,
"fileName" : fileName + "-f" ,
}
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "FGetObject failed" , err )
return
}
function = "PresignedHeadObject(bucketName, objectName, expires, reqParams)"
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : "" ,
"expires" : 3600 * time . Second ,
}
if _ , err = c . PresignedHeadObject ( bucketName , "" , 3600 * time . Second , nil ) ; err == nil {
logError ( function , args , startTime , "" , "PresignedHeadObject success" , err )
return
2017-09-13 12:09:48 +00:00
}
// Generate presigned HEAD object url.
presignedHeadURL , err := c . PresignedHeadObject ( bucketName , objectName , 3600 * time . Second , nil )
function = "PresignedHeadObject(bucketName, objectName, expires, reqParams)"
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName ,
"expires" : 3600 * time . Second ,
}
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedHeadObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// Verify if presigned url works.
resp , err := http . Head ( presignedHeadURL . String ( ) )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedHeadObject response incorrect" , err )
return
2017-09-13 12:09:48 +00:00
}
if resp . StatusCode != http . StatusOK {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedHeadObject response incorrect, status " + string ( resp . StatusCode ) , err )
return
2017-09-13 12:09:48 +00:00
}
if resp . Header . Get ( "ETag" ) == "" {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedHeadObject response incorrect" , err )
return
2017-09-13 12:09:48 +00:00
}
resp . Body . Close ( )
2017-12-08 19:45:59 +00:00
_ , err = c . PresignedGetObject ( bucketName , "" , 3600 * time . Second , nil )
function = "PresignedGetObject(bucketName, objectName, expires, reqParams)"
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : "" ,
"expires" : 3600 * time . Second ,
}
if err == nil {
logError ( function , args , startTime , "" , "PresignedGetObject success" , err )
return
}
2017-09-13 12:09:48 +00:00
// Generate presigned GET object url.
presignedGetURL , err := c . PresignedGetObject ( bucketName , objectName , 3600 * time . Second , nil )
function = "PresignedGetObject(bucketName, objectName, expires, reqParams)"
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName ,
"expires" : 3600 * time . Second ,
}
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedGetObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// Verify if presigned url works.
resp , err = http . Get ( presignedGetURL . String ( ) )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedGetObject response incorrect" , err )
return
2017-09-13 12:09:48 +00:00
}
if resp . StatusCode != http . StatusOK {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedGetObject response incorrect, status " + string ( resp . StatusCode ) , err )
return
2017-09-13 12:09:48 +00:00
}
newPresignedBytes , err := ioutil . ReadAll ( resp . Body )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedGetObject response incorrect" , err )
return
2017-09-13 12:09:48 +00:00
}
resp . Body . Close ( )
if ! bytes . Equal ( newPresignedBytes , buf ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedGetObject response incorrect" , err )
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\"" )
presignedGetURL , err = c . PresignedGetObject ( bucketName , objectName , 3600 * time . Second , reqParams )
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName ,
"expires" : 3600 * time . Second ,
"reqParams" : reqParams ,
}
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedGetObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// Verify if presigned url works.
resp , err = http . Get ( presignedGetURL . String ( ) )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedGetObject response incorrect" , err )
return
2017-09-13 12:09:48 +00:00
}
if resp . StatusCode != http . StatusOK {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedGetObject response incorrect, status " + string ( resp . StatusCode ) , err )
return
2017-09-13 12:09:48 +00:00
}
newPresignedBytes , err = ioutil . ReadAll ( resp . Body )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedGetObject response incorrect" , err )
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( newPresignedBytes , buf ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Bytes mismatch for presigned GET URL" , err )
return
2017-09-13 12:09:48 +00:00
}
if resp . Header . Get ( "Content-Disposition" ) != "attachment; filename=\"test.txt\"" {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "wrong Content-Disposition received " + string ( resp . Header . Get ( "Content-Disposition" ) ) , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
_ , err = c . PresignedPutObject ( bucketName , "" , 3600 * time . Second )
function = "PresignedPutObject(bucketName, objectName, expires)"
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : "" ,
"expires" : 3600 * time . Second ,
}
if err == nil {
logError ( function , args , startTime , "" , "PresignedPutObject success" , err )
return
}
2017-09-13 12:09:48 +00:00
2017-12-08 19:45:59 +00:00
presignedPutURL , err := c . PresignedPutObject ( bucketName , objectName + "-presigned" , 3600 * time . Second )
2017-09-13 12:09:48 +00:00
function = "PresignedPutObject(bucketName, objectName, expires)"
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName ,
"expires" : 3600 * time . Second ,
}
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedPutObject failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Couldn't make HTTP request with PresignedPutObject URL" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedPutObject failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetObject after PresignedPutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
newReadBytes , err = ioutil . ReadAll ( newReader )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAll after GetObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( newReadBytes , buf ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Bytes mismatch" , err )
return
2017-09-13 12:09:48 +00:00
}
err = c . RemoveObject ( bucketName , objectName )
function = "RemoveObject(bucketName, objectName)"
args = map [ string ] interface { } {
"bucketName" : bucketName ,
"objectName" : objectName ,
}
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "RemoveObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
err = c . RemoveObject ( bucketName , objectName + "-f" )
args [ "objectName" ] = objectName + "-f"
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "RemoveObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
err = c . RemoveObject ( bucketName , objectName + "-nolength" )
args [ "objectName" ] = objectName + "-nolength"
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "RemoveObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
err = c . RemoveObject ( bucketName , objectName + "-presigned" )
args [ "objectName" ] = objectName + "-presigned"
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "RemoveObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
err = c . RemoveBucket ( bucketName )
function = "RemoveBucket(bucketName)"
args = map [ string ] interface { } {
"bucketName" : bucketName ,
}
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "RemoveBucket failed" , err )
return
2017-09-13 12:09:48 +00:00
}
err = c . RemoveBucket ( bucketName )
if err == nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "RemoveBucket did not fail for invalid bucket name" , err )
return
2017-09-13 12:09:48 +00:00
}
if err . Error ( ) != "The specified bucket does not exist" {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "RemoveBucket failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "File Remove failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if err = os . Remove ( fileName + "-f" ) ; err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "File Remove failed" , err )
return
2017-09-13 12:09:48 +00:00
}
function = "testFunctional()"
successLogger ( function , args , startTime ) . Info ( )
}
// Test for validating GetObject Reader* methods functioning when the
// object is modified in the object store.
func testGetObjectObjectModified ( ) {
// initialize logging params
startTime := time . Now ( )
function := "GetObject(bucketName, objectName)"
args := map [ string ] interface { } {
"bucketName" : "" ,
"objectName" : "" ,
}
// 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client object creation failed" , err )
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.
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test" )
args [ "bucketName" ] = bucketName
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
return
2017-09-13 12:09:48 +00:00
}
defer c . RemoveBucket ( bucketName )
// Upload an object.
objectName := "myobject"
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Failed to upload " + objectName + ", to bucket " + bucketName , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Failed to GetObject " + objectName + ", from bucket " + bucketName , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Failed to read object " + objectName + ", from bucket " + bucketName + " at an offset" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Failed to upload " + objectName + ", to bucket " + bucketName , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Expected Stat to fail with error " + expectedError + ", but received " + err . Error ( ) , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Expected ReadAt to fail with error " + expectedError + ", but received " + err . Error ( ) , 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
}
2017-09-13 12:09:48 +00:00
successLogger ( function , args , startTime ) . Info ( )
}
// Test validates putObject to upload a file seeked at a given offset.
func testPutObjectUploadSeekedObject ( ) {
// initialize logging params
startTime := time . Now ( )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client object creation failed" , err )
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.
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test" )
args [ "bucketName" ] = bucketName
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
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 {
logError ( function , args , startTime , "" , "File open failed" , err )
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 {
logError ( function , args , startTime , "" , "TempFile create failed" , err )
return
}
args [ "fileToUpload" ] = tempfile . Name ( )
// Generate 100kB data
if _ , err = io . Copy ( tempfile , getDataReader ( "datafile-100-kB" ) ) ; err != nil {
logError ( function , args , startTime , "" , "File copy failed" , err )
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 {
logError ( function , args , startTime , "" , "TempFile seek failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( length - offset ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , fmt . Sprintf ( "Invalid length returned, expected %d got %d" , int64 ( length - offset ) , n ) , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
n , err = obj . Seek ( int64 ( offset ) , 0 )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Seek failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( offset ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , fmt . Sprintf ( "Invalid offset returned, expected %d got %d" , int64 ( offset ) , n ) , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( length - offset ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , fmt . Sprintf ( "Invalid offset returned, expected %d got %d" , int64 ( length - offset ) , n ) , 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
2017-09-13 12:09:48 +00:00
}
successLogger ( function , args , startTime ) . Info ( )
}
// Tests bucket re-create errors.
func testMakeBucketErrorV2 ( ) {
// initialize logging params
startTime := time . Now ( )
function := "MakeBucket(bucketName, region)"
args := map [ string ] interface { } {
"bucketName" : "" ,
"region" : "eu-west-1" ,
}
if os . Getenv ( serverEndpoint ) != "s3.amazonaws.com" {
ignoredLog ( function , args , startTime , "Skipped region functional tests for non s3 runs" ) . Info ( )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio v2 client object creation failed" , err )
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.
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test" )
args [ "bucketName" ] = bucketName
// Make a new bucket in 'eu-west-1'.
if err = c . MakeBucket ( bucketName , "eu-west-1" ) ; err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if err = c . MakeBucket ( bucketName , "eu-west-1" ) ; err == nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket did not fail for existing bucket name" , err )
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" {
2017-12-08 19:45:59 +00:00
logError ( 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
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
successLogger ( function , args , startTime ) . Info ( )
}
// Test get object reader to not throw error on being closed twice.
func testGetObjectClosedTwiceV2 ( ) {
// initialize logging params
startTime := time . Now ( )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio v2 client object creation failed" , err )
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.
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket 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 ( )
// 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
logError ( function , args , startTime , "" , "Number of bytes does not match, expected " + string ( bufSize ) + " got " + string ( n ) , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
st , err := r . Stat ( )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Stat failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if st . Size != int64 ( bufSize ) {
logError ( function , args , startTime , "" , "Number of bytes does not match, expected " + string ( bufSize ) + " got " + string ( st . Size ) , err )
return
2017-09-13 12:09:48 +00:00
}
if err := r . Close ( ) ; err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Stat failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if err := r . Close ( ) ; err == nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Object is already closed, should return error" , 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
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
successLogger ( function , args , startTime ) . Info ( )
}
// Tests removing partially uploaded objects.
func testRemovePartiallyUploadedV2 ( ) {
// initialize logging params
startTime := time . Now ( )
function := "RemoveIncompleteUpload(bucketName, objectName)"
args := map [ string ] interface { } {
"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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio v2 client object creation failed" , err )
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.
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
return
2017-09-13 12:09:48 +00:00
}
r := bytes . NewReader ( bytes . Repeat ( [ ] byte ( "a" ) , 128 * 1024 ) )
reader , writer := io . Pipe ( )
go func ( ) {
i := 0
for i < 25 {
_ , cerr := io . CopyN ( writer , r , 128 * 1024 )
if cerr != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Copy failed" , cerr )
return
2017-09-13 12:09:48 +00:00
}
i ++
r . Seek ( 0 , 0 )
}
writer . CloseWithError ( errors . New ( "proactively closed to be verified later" ) )
} ( )
objectName := bucketName + "-resumable"
args [ "objectName" ] = objectName
2017-12-08 19:45:59 +00:00
_ , err = c . PutObject ( bucketName , objectName , reader , - 1 , minio . PutObjectOptions { ContentType : "application/octet-stream" } )
2017-09-13 12:09:48 +00:00
if err == nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject should fail" , err )
return
2017-09-13 12:09:48 +00:00
}
if err . Error ( ) != "proactively closed to be verified later" {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Unexpected error, expected : proactively closed to be verified later" , err )
return
2017-09-13 12:09:48 +00:00
}
err = c . RemoveIncompleteUpload ( bucketName , objectName )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "RemoveIncompleteUpload failed" , 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
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
successLogger ( function , args , startTime ) . Info ( )
}
// Tests FPutObject hidden contentType setting
func testFPutObjectV2 ( ) {
// initialize logging params
startTime := time . Now ( )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio v2 client object creation failed" , err )
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.
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "TempFile creation failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Copy failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( 11 * 1024 * 1024 ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( 11 * 1024 * 1024 ) ) + " got " + string ( n ) , err )
return
2017-09-13 12:09:48 +00:00
}
// Close the file pro-actively for windows.
err = file . Close ( )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "File close failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "FPutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( 11 * 1024 * 1024 ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( 11 * 1024 * 1024 ) ) + " got " + string ( n ) , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "FPutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( 11 * 1024 * 1024 ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( 11 * 1024 * 1024 ) ) + " got " + string ( n ) , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Rename failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "FPutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( 11 * 1024 * 1024 ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( 11 * 1024 * 1024 ) ) + " got " + string ( n ) , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "StatObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if rStandard . ContentType != "application/octet-stream" {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Content-Type headers mismatched, expected: application/octet-stream , got " + rStandard . ContentType , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "StatObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if rOctet . ContentType != "application/octet-stream" {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Content-Type headers mismatched, expected: application/octet-stream , got " + rOctet . ContentType , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "StatObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if rGTar . ContentType != "application/x-gtar" {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Content-Type headers mismatched, expected: application/x-gtar , got " + rGTar . ContentType , 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
2017-09-13 12:09:48 +00:00
}
err = os . Remove ( fileName + ".gtar" )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "File remove failed" , err )
return
2017-09-13 12:09:48 +00:00
}
successLogger ( function , args , startTime ) . Info ( )
}
// Tests various bucket supported formats.
func testMakeBucketRegionsV2 ( ) {
// initialize logging params
startTime := time . Now ( )
function := "MakeBucket(bucketName, region)"
args := map [ string ] interface { } {
"bucketName" : "" ,
"region" : "eu-west-1" ,
}
if os . Getenv ( serverEndpoint ) != "s3.amazonaws.com" {
ignoredLog ( function , args , startTime , "Skipped region functional tests for non s3 runs" ) . Info ( )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio v2 client object creation failed" , err )
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.
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test" )
args [ "bucketName" ] = bucketName
// Make a new bucket in 'eu-central-1'.
if err = c . MakeBucket ( bucketName , "eu-west-1" ) ; err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
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"
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , 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 + ".withperiod" , c ) ; err != nil {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
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
successLogger ( function , args , startTime ) . Info ( )
}
// Tests get object ReaderSeeker interface methods.
func testGetObjectReadSeekFunctionalV2 ( ) {
// initialize logging params
startTime := time . Now ( )
function := "GetObject(bucketName, objectName)"
args := map [ string ] interface { } {
"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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio v2 client object creation failed" , err )
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.
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAll failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
logError ( function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( bufSize ) ) + " got " + string ( n ) , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
st , err := r . Stat ( )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Stat failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if st . Size != int64 ( bufSize ) {
logError ( function , args , startTime , "" , "Number of bytes in stat does not match, expected " + string ( int64 ( bufSize ) ) + " got " + string ( st . Size ) , err )
return
2017-09-13 12:09:48 +00:00
}
offset := int64 ( 2048 )
n , err = r . Seek ( offset , 0 )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Seek failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if n != offset {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Number of seeked bytes does not match, expected " + string ( offset ) + " got " + string ( n ) , err )
return
2017-09-13 12:09:48 +00:00
}
n , err = r . Seek ( 0 , 1 )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Seek failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if n != offset {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Number of seeked bytes does not match, expected " + string ( offset ) + " got " + string ( n ) , err )
return
2017-09-13 12:09:48 +00:00
}
_ , err = r . Seek ( offset , 2 )
if err == nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Seek on positive offset for whence '2' should error out" , err )
return
2017-09-13 12:09:48 +00:00
}
n , err = r . Seek ( - offset , 2 )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Seek failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if n != st . Size - offset {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Number of seeked bytes does not match, expected " + string ( st . Size - offset ) + " got " + string ( n ) , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Copy failed" , err )
return
2017-09-13 12:09:48 +00:00
}
}
if ! bytes . Equal ( buf [ len ( buf ) - int ( offset ) : ] , buffer1 . Bytes ( ) ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Incorrect read bytes v/s original buffer" , err )
return
2017-09-13 12:09:48 +00:00
}
// Seek again and read again.
n , err = r . Seek ( offset - 1 , 0 )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Seek failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if n != ( offset - 1 ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Number of seeked bytes does not match, expected " + string ( offset - 1 ) + " got " + string ( n ) , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Copy failed" , err )
return
2017-09-13 12:09:48 +00:00
}
}
// Verify now lesser bytes.
if ! bytes . Equal ( buf [ 2047 : ] , buffer2 . Bytes ( ) ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Incorrect read bytes v/s original buffer" , 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
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
successLogger ( function , args , startTime ) . Info ( )
}
// Tests get object ReaderAt interface methods.
func testGetObjectReadAtFunctionalV2 ( ) {
// initialize logging params
startTime := time . Now ( )
function := "GetObject(bucketName, objectName)"
args := map [ string ] interface { } {
"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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio v2 client object creation failed" , err )
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.
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAll failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
logError ( function , args , startTime , "" , "Number of bytes does not match, expected " + string ( bufSize ) + " got " + string ( n ) , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
st , err := r . Stat ( )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Stat failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if st . Size != int64 ( bufSize ) {
logError ( function , args , startTime , "" , "Number of bytes does not match, expected " + string ( bufSize ) + " got " + string ( st . Size ) , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAt failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if m != len ( buf2 ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAt read shorter bytes before reaching EOF, expected " + string ( len ( buf2 ) ) + " got " + string ( m ) , err )
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( buf2 , buf [ offset : offset + 512 ] ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Incorrect read between two ReadAt from same offset" , err )
return
2017-09-13 12:09:48 +00:00
}
offset += 512
m , err = r . ReadAt ( buf3 , offset )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAt failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if m != len ( buf3 ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAt read shorter bytes before reaching EOF, expected " + string ( len ( buf3 ) ) + " got " + string ( m ) , err )
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( buf3 , buf [ offset : offset + 512 ] ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Incorrect read between two ReadAt from same offset" , err )
return
2017-09-13 12:09:48 +00:00
}
offset += 512
m , err = r . ReadAt ( buf4 , offset )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAt failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if m != len ( buf4 ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAt read shorter bytes before reaching EOF, expected " + string ( len ( buf4 ) ) + " got " + string ( m ) , err )
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( buf4 , buf [ offset : offset + 512 ] ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Incorrect read between two ReadAt from same offset" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAt failed" , err )
return
2017-09-13 12:09:48 +00:00
}
}
if m != len ( buf5 ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAt read shorter bytes before reaching EOF, expected " + string ( len ( buf5 ) ) + " got " + string ( m ) , err )
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( buf , buf5 ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Incorrect data read in GetObject, than what was previously uploaded" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAt failed" , 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
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
successLogger ( function , args , startTime ) . Info ( )
}
// Tests copy object
func testCopyObjectV2 ( ) {
// initialize logging params
startTime := time . Now ( )
function := "CopyObject(destination, source)"
args := map [ string ] interface { } {
"destination" : "" ,
"source" : "" ,
}
// 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio v2 client object creation failed" , err )
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.
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket 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 ( )
// 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
logError ( function , args , startTime , "" , "Number of bytes does not match, expected " + string ( int64 ( bufSize ) ) + " got " + string ( n ) , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetObject failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Stat failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// Copy Source
src := minio . NewSourceInfo ( bucketName , objectName , nil )
// 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetModifiedSinceCond did not fail for invalid conditions" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetUnmodifiedSinceCond did not fail for invalid conditions" , err )
return
2017-09-13 12:09:48 +00:00
}
err = src . SetMatchETagCond ( "" )
if err == nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetMatchETagCond did not fail for invalid conditions" , err )
return
2017-09-13 12:09:48 +00:00
}
err = src . SetMatchETagExceptCond ( "" )
if err == nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetMatchETagExceptCond did not fail for invalid conditions" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetModifiedSinceCond failed" , err )
return
2017-09-13 12:09:48 +00:00
}
err = src . SetMatchETagCond ( objInfo . ETag )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetMatchETagCond failed" , err )
return
2017-09-13 12:09:48 +00:00
}
args [ "source" ] = src
dst , err := minio . NewDestinationInfo ( bucketName + "-copy" , objectName + "-copy" , nil , nil )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "NewDestinationInfo failed" , err )
return
2017-09-13 12:09:48 +00:00
}
args [ "destination" ] = dst
// Perform the Copy
err = c . CopyObject ( dst , src )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "CopyObject failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetObject failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetObject failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Stat failed" , err )
return
2017-09-13 12:09:48 +00:00
}
objInfoCopy , err := readerCopy . Stat ( )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Stat failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if objInfo . Size != objInfoCopy . Size {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Number of bytes does not match, expected " + string ( objInfoCopy . Size ) + " got " + string ( objInfo . Size ) , err )
return
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetUnmodifiedSinceCond failed" , err )
return
2017-09-13 12:09:48 +00:00
}
err = src . SetMatchETagExceptCond ( objInfo . ETag )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetMatchETagExceptCond failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// Perform the Copy which should fail
err = c . CopyObject ( dst , src )
if err == nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "CopyObject did not fail for invalid conditions" , 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
2017-09-13 12:09:48 +00:00
}
successLogger ( function , args , startTime ) . Info ( )
}
func testComposeObjectErrorCasesWrapper ( c * minio . Client ) {
// initialize logging params
startTime := time . Now ( )
function := "testComposeObjectErrorCasesWrapper(minioClient)"
args := map [ string ] interface { } { }
// 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "NewDestinationInfo failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if err := c . ComposeObject ( dst , srcSlice ) ; err == nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Expected error in ComposeObject" , err )
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." {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Got unexpected error" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Setting NewSourceInfo failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// 3. ComposeObject call should fail.
if err := c . ComposeObject ( dst , [ ] minio . SourceInfo { badSrc } ) ; err == nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ComposeObject expected to fail" , err )
return
2017-09-13 12:09:48 +00:00
} else if ! strings . Contains ( err . Error ( ) , "has invalid segment-to-copy" ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Got invalid error" , err )
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
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
successLogger ( function , args , startTime ) . Info ( )
}
// Test expected error cases
func testComposeObjectErrorCasesV2 ( ) {
// initialize logging params
startTime := time . Now ( )
function := "testComposeObjectErrorCasesV2()"
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio v2 client object creation failed" , err )
return
2017-09-13 12:09:48 +00:00
}
testComposeObjectErrorCasesWrapper ( c )
}
func testComposeMultipleSources ( c * minio . Client ) {
// initialize logging params
startTime := time . Now ( )
function := "ComposeObject(destination, sources)"
args := map [ string ] interface { } {
"destination" : "" ,
"sources" : "" ,
}
// 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetRange failed" , err )
return
2017-09-13 12:09:48 +00:00
}
args [ "sources" ] = srcs
dst , err := minio . NewDestinationInfo ( bucketName , "dstObject" , nil , nil )
args [ "destination" ] = dst
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "NewDestinationInfo failed" , err )
return
2017-09-13 12:09:48 +00:00
}
err = c . ComposeObject ( dst , srcs )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ComposeObject failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "StatObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if objProps . Size != 9 * srcSize + 1 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Size mismatched! Expected " + string ( 10000 * srcSize ) + " got " + string ( objProps . Size ) , err )
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
2017-09-13 12:09:48 +00:00
}
successLogger ( function , args , startTime ) . Info ( )
}
// Test concatenating multiple objects objects
func testCompose10KSourcesV2 ( ) {
// initialize logging params
startTime := time . Now ( )
function := "testCompose10KSourcesV2(minioClient)"
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio v2 client object creation failed" , err )
return
2017-09-13 12:09:48 +00:00
}
testComposeMultipleSources ( c )
}
func testEncryptedCopyObjectWrapper ( c * minio . Client ) {
// initialize logging params
startTime := time . Now ( )
function := "testEncryptedCopyObjectWrapper(minioClient)"
args := map [ string ] interface { } { }
// 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
return
2017-09-13 12:09:48 +00:00
}
key1 := minio . NewSSEInfo ( [ ] byte ( "32byteslongsecretkeymustbegiven1" ) , "AES256" )
key2 := minio . NewSSEInfo ( [ ] byte ( "32byteslongsecretkeymustbegiven2" ) , "AES256" )
// 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
2017-12-08 19:45:59 +00:00
metadata := make ( map [ string ] string )
2017-09-13 12:09:48 +00:00
for k , v := range key1 . GetSSEHeaders ( ) {
2017-12-08 19:45:59 +00:00
metadata [ k ] = v
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
_ , err = c . PutObject ( bucketName , "srcObject" , bytes . NewReader ( buf ) , int64 ( len ( buf ) ) , minio . PutObjectOptions { UserMetadata : metadata , Progress : nil } )
2017-09-13 12:09:48 +00:00
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject call failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// 2. copy object and change encryption key
src := minio . NewSourceInfo ( bucketName , "srcObject" , & key1 )
dst , err := minio . NewDestinationInfo ( bucketName , "dstObject" , & key2 , nil )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "NewDestinationInfo failed" , err )
return
2017-09-13 12:09:48 +00:00
}
err = c . CopyObject ( dst , src )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "CopyObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// 3. get copied object and check if content is equal
2017-12-08 19:45:59 +00:00
opts := minio . GetObjectOptions { }
2017-09-13 12:09:48 +00:00
for k , v := range key2 . GetSSEHeaders ( ) {
2017-12-08 19:45:59 +00:00
opts . Set ( k , v )
2017-09-13 12:09:48 +00:00
}
coreClient := minio . Core { c }
2017-12-08 19:45:59 +00:00
reader , _ , err := coreClient . GetObject ( bucketName , "dstObject" , opts )
2017-09-13 12:09:48 +00:00
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
defer reader . Close ( )
decBytes , err := ioutil . ReadAll ( reader )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAll failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( decBytes , buf ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Downloaded object mismatched for encrypted object" , err )
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
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
successLogger ( function , args , startTime ) . Info ( )
}
// Test encrypted copy object
func testEncryptedCopyObject ( ) {
// initialize logging params
startTime := time . Now ( )
function := "testEncryptedCopyObject()"
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio v2 client object creation failed" , err )
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 ( )
function := "testEncryptedCopyObjectV2()"
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio v2 client object creation failed" , err )
return
2017-09-13 12:09:48 +00:00
}
testEncryptedCopyObjectWrapper ( c )
}
func testUserMetadataCopying ( ) {
// initialize logging params
startTime := time . Now ( )
function := "testUserMetadataCopying()"
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client object creation failed" , err )
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 ( )
function := "CopyObject(destination, source)"
args := map [ string ] interface { } {
"destination" : "" ,
"source" : "" ,
}
// 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Stat failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObjectWithMetadata failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if ! reflect . DeepEqual ( metadata , fetchMeta ( "srcObject" ) ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Metadata match failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "NewDestinationInfo failed" , err )
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.
err = c . CopyObject ( dst1 , src )
args [ "destination" ] = dst1
args [ "source" ] = src
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "CopyObject failed" , err )
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" ) ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Metadata match failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "NewDestinationInfo failed" , err )
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.
err = c . CopyObject ( dst2 , src )
args [ "destination" ] = dst2
args [ "source" ] = src
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "CopyObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
expectedHeaders = metadata
if ! reflect . DeepEqual ( expectedHeaders , fetchMeta ( "dstObject-2" ) ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Metadata match failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "NewDestinationInfo failed" , err )
return
2017-09-13 12:09:48 +00:00
}
err = c . ComposeObject ( dst3 , srcs )
function = "ComposeObject(destination, sources)"
args [ "destination" ] = dst3
args [ "source" ] = srcs
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ComposeObject failed" , err )
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" ) ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Metadata match failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "NewDestinationInfo failed" , err )
return
2017-09-13 12:09:48 +00:00
}
err = c . ComposeObject ( dst4 , srcs )
function = "ComposeObject(destination, sources)"
args [ "destination" ] = dst4
args [ "source" ] = srcs
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ComposeObject failed" , err )
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" ) ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Metadata match failed" , 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
}
2017-09-13 12:09:48 +00:00
successLogger ( function , args , startTime ) . Info ( )
}
func testUserMetadataCopyingV2 ( ) {
// initialize logging params
startTime := time . Now ( )
function := "testUserMetadataCopyingV2()"
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client v2 object creation failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// c.TraceOn(os.Stderr)
testUserMetadataCopyingWrapper ( c )
}
// Test put object with size -1 byte object.
func testPutObjectNoLengthV2 ( ) {
// initialize logging params
startTime := time . Now ( )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client v2 object creation failed" , err )
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.
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
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 ( )
// 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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObjectWithSize failed" , err )
return
2017-09-13 12:09:48 +00:00
}
2017-12-08 19:45:59 +00:00
if n != int64 ( bufSize ) {
logError ( function , args , startTime , "" , "Expected upload object size " + string ( bufSize ) + " got " + string ( n ) , 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
2017-09-13 12:09:48 +00:00
}
successLogger ( function , args , startTime ) . Info ( )
}
// Test put objects of unknown size.
func testPutObjectsUnknownV2 ( ) {
// initialize logging params
startTime := time . Now ( )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client v2 object creation failed" , err )
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.
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObjectStreaming failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( 4 ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Expected upload object size " + string ( 4 ) + " got " + string ( n ) , 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
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
successLogger ( function , args , startTime ) . Info ( )
}
// Test put object with 0 byte object.
func testPutObject0ByteV2 ( ) {
// initialize logging params
startTime := time . Now ( )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client v2 object creation failed" , err )
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.
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObjectWithSize failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if n != 0 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Expected upload object size 0 but got " + string ( n ) , 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
2017-09-13 12:09:48 +00:00
}
successLogger ( function , args , startTime ) . Info ( )
}
// Test expected error cases
func testComposeObjectErrorCases ( ) {
// initialize logging params
startTime := time . Now ( )
function := "testComposeObjectErrorCases()"
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client object creation failed" , err )
return
2017-09-13 12:09:48 +00:00
}
testComposeObjectErrorCasesWrapper ( c )
}
// Test concatenating 10K objects
func testCompose10KSources ( ) {
// initialize logging params
startTime := time . Now ( )
function := "testCompose10KSources()"
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client object creation failed" , err )
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 ( )
function := "testFunctionalV2()"
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client v2 object creation failed" , err )
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.
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test" )
// Make a new bucket.
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "file create failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "file write failed" , err )
return
2017-09-13 12:09:48 +00:00
}
}
file . Close ( )
// Verify if bucket exits and you have access.
var exists bool
exists , err = c . BucketExists ( bucketName )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "BucketExists failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if ! exists {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Could not find existing bucket " + bucketName , err )
return
2017-09-13 12:09:48 +00:00
}
// Make the bucket 'public read/write'.
err = c . SetBucketPolicy ( bucketName , "" , policy . BucketPolicyReadWrite )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "SetBucketPolicy failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// List all buckets.
buckets , err := c . ListBuckets ( )
if len ( buckets ) == 0 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "List buckets cannot be empty" , err )
return
2017-09-13 12:09:48 +00:00
}
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ListBuckets failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Bucket " + bucketName + "not found" , err )
return
2017-09-13 12:09:48 +00:00
}
objectName := bucketName + "unique"
// Generate data
buf := bytes . Repeat ( [ ] byte ( "n" ) , rand . Intn ( 1 << 19 ) )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( len ( buf ) ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Expected uploaded object length " + string ( len ( buf ) ) + " got " + string ( n ) , err )
return
2017-09-13 12:09:48 +00:00
}
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PutObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if n != int64 ( len ( buf ) ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Expected uploaded object length " + string ( len ( buf ) ) + " got " + string ( n ) , err )
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.
for obj := range c . ListObjects ( bucketName , objectName , isRecursive , doneCh ) {
if obj . Key == objectName {
objFound = true
break
}
}
if ! objFound {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Could not find existing object " + objectName , err )
return
2017-09-13 12:09:48 +00:00
}
objFound = false
isRecursive = true // Recursive is true.
for obj := range c . ListObjects ( bucketName , objectName , isRecursive , doneCh ) {
if obj . Key == objectName {
objFound = true
break
}
}
if ! objFound {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Could not find existing object " + objectName , err )
return
2017-09-13 12:09:48 +00:00
}
incompObjNotFound := true
for objIncompl := range c . ListIncompleteUploads ( bucketName , objectName , isRecursive , doneCh ) {
if objIncompl . Key != "" {
incompObjNotFound = false
break
}
}
if ! incompObjNotFound {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Unexpected dangling incomplete upload found" , err )
return
2017-09-13 12:09:48 +00:00
}
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
newReadBytes , err := ioutil . ReadAll ( newReader )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAll failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( newReadBytes , buf ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Bytes mismatch" , err )
return
2017-09-13 12:09:48 +00:00
}
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "FgetObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// Generate presigned HEAD object url.
presignedHeadURL , err := c . PresignedHeadObject ( bucketName , objectName , 3600 * time . Second , nil )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedHeadObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// Verify if presigned url works.
resp , err := http . Head ( presignedHeadURL . String ( ) )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedHeadObject URL head request failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if resp . StatusCode != http . StatusOK {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedHeadObject URL returns status " + string ( resp . StatusCode ) , err )
return
2017-09-13 12:09:48 +00:00
}
if resp . Header . Get ( "ETag" ) == "" {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Got empty ETag" , err )
return
2017-09-13 12:09:48 +00:00
}
resp . Body . Close ( )
// Generate presigned GET object url.
presignedGetURL , err := c . PresignedGetObject ( bucketName , objectName , 3600 * time . Second , nil )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedGetObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// Verify if presigned url works.
resp , err = http . Get ( presignedGetURL . String ( ) )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedGetObject URL GET request failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if resp . StatusCode != http . StatusOK {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedGetObject URL returns status " + string ( resp . StatusCode ) , err )
return
2017-09-13 12:09:48 +00:00
}
newPresignedBytes , err := ioutil . ReadAll ( resp . Body )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAll failed" , err )
return
2017-09-13 12:09:48 +00:00
}
resp . Body . Close ( )
if ! bytes . Equal ( newPresignedBytes , buf ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Bytes mismatch" , err )
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.
presignedGetURL , err = c . PresignedGetObject ( bucketName , objectName , 3600 * time . Second , reqParams )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedGetObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
// Verify if presigned url works.
resp , err = http . Get ( presignedGetURL . String ( ) )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedGetObject URL GET request failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if resp . StatusCode != http . StatusOK {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedGetObject URL returns status " + string ( resp . StatusCode ) , err )
return
2017-09-13 12:09:48 +00:00
}
newPresignedBytes , err = ioutil . ReadAll ( resp . Body )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAll failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( newPresignedBytes , buf ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Bytes mismatch" , err )
return
2017-09-13 12:09:48 +00:00
}
// Verify content disposition.
if resp . Header . Get ( "Content-Disposition" ) != "attachment; filename=\"test.txt\"" {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "wrong Content-Disposition received " , err )
return
2017-09-13 12:09:48 +00:00
}
presignedPutURL , err := c . PresignedPutObject ( bucketName , objectName + "-presigned" , 3600 * time . Second )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "PresignedPutObject failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "HTTP request to PresignedPutObject URL failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "HTTP request to PresignedPutObject URL failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "GetObject failed" , err )
return
2017-09-13 12:09:48 +00:00
}
newReadBytes , err = ioutil . ReadAll ( newReader )
if err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "ReadAll failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if ! bytes . Equal ( newReadBytes , buf ) {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Bytes mismatch" , 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 {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "File remove failed" , err )
return
2017-09-13 12:09:48 +00:00
}
if err = os . Remove ( fileName + "-f" ) ; err != nil {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "File removes failed" , err )
return
2017-09-13 12:09:48 +00:00
}
successLogger ( function , args , startTime ) . Info ( )
}
2017-12-08 19:45:59 +00:00
// Test get object with GetObjectWithContext
func testGetObjectWithContext ( ) {
// initialize logging params
startTime := time . Now ( )
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 {
2017-12-08 19:45:59 +00:00
logError ( function , args , startTime , "" , "Minio client v4 object creation failed" , err )
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.
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 ( function , args , startTime , "" , "MakeBucket failed" , err )
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 {
logError ( function , args , startTime , "" , "PutObject failed" , err )
return
}
ctx , cancel := context . WithTimeout ( context . Background ( ) , 50 * time . Millisecond )
args [ "ctx" ] = ctx
defer cancel ( )
// Read the data back
r , err := c . GetObjectWithContext ( ctx , bucketName , objectName , minio . GetObjectOptions { } )
if err != nil {
logError ( function , args , startTime , "" , "GetObjectWithContext failed - request timeout not honored" , err )
return
}
ctx , cancel = context . WithTimeout ( context . Background ( ) , 3 * time . Minute )
args [ "ctx" ] = ctx
defer cancel ( )
// Read the data back
r , err = c . GetObjectWithContext ( ctx , bucketName , objectName , minio . GetObjectOptions { } )
if err != nil {
logError ( function , args , startTime , "" , "GetObjectWithContext failed" , err )
return
}
st , err := r . Stat ( )
if err != nil {
logError ( function , args , startTime , "" , "object Stat call failed" , err )
return
}
if st . Size != int64 ( bufSize ) {
logError ( function , args , startTime , "" , "Number of bytes in stat does not match: want " + string ( bufSize ) + ", got" + string ( st . Size ) , err )
return
}
if err := r . Close ( ) ; err != nil {
logError ( function , args , startTime , "" , "object Close() call failed" , err )
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
}
successLogger ( function , args , startTime ) . Info ( )
}
// Test get object with FGetObjectWithContext
func testFGetObjectWithContext ( ) {
// initialize logging params
startTime := time . Now ( )
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 {
logError ( 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 ( 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
_ , err = c . PutObject ( bucketName , objectName , reader , int64 ( bufSize ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
if err != nil {
logError ( function , args , startTime , "" , "PutObject failed" , err )
return
}
ctx , cancel := context . WithTimeout ( context . Background ( ) , 2 * time . Millisecond )
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 {
logError ( function , args , startTime , "" , "FGetObjectWithContext with short timeout failed" , err )
return
}
ctx , cancel = context . WithTimeout ( context . Background ( ) , 5 * time . Minute )
defer cancel ( )
// Read the data back
err = c . FGetObjectWithContext ( ctx , bucketName , objectName , fileName + "-fcontext" , minio . GetObjectOptions { } )
if err != nil {
logError ( function , args , startTime , "" , "FGetObjectWithContext with long timeout failed" , err )
return
}
if err = os . Remove ( fileName + "-fcontext" ) ; err != nil {
logError ( function , args , startTime , "" , "Remove file failed" , err )
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
}
successLogger ( function , args , startTime ) . Info ( )
}
// Test validates putObject with context to see if request cancellation is honored for V2.
func testPutObjectWithContextV2 ( ) {
// initialize logging params
startTime := time . Now ( )
function := "PutObjectWithContext(ctx, bucketName, objectName, reader, size, opts)"
args := map [ string ] interface { } {
"ctx" : "" ,
"bucketName" : "" ,
"objectName" : "" ,
"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 {
logError ( function , args , startTime , "" , "Minio client v2 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" )
// Make a new bucket.
bucketName := randString ( 60 , rand . NewSource ( time . Now ( ) . UnixNano ( ) ) , "minio-go-test" )
args [ "bucketName" ] = bucketName
err = c . MakeBucket ( bucketName , "us-east-1" )
if err != nil {
logError ( function , args , startTime , "" , "MakeBucket failed" , err )
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
defer cancel ( )
_ , err = c . PutObjectWithContext ( ctx , bucketName , objectName , reader , int64 ( bufSize ) , minio . PutObjectOptions { ContentType : "binary/octet-stream" } )
if err != nil {
logError ( function , args , startTime , "" , "PutObjectWithContext with short timeout failed" , err )
return
}
ctx , cancel = context . WithTimeout ( context . Background ( ) , 3 * time . Minute )
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 {
logError ( function , args , startTime , "" , "PutObjectWithContext with long timeout failed" , err )
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
}
successLogger ( function , args , startTime ) . Info ( )
}
// Test get object with GetObjectWithContext
func testGetObjectWithContextV2 ( ) {
// initialize logging params
startTime := time . Now ( )
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 {
logError ( function , args , startTime , "" , "Minio client v2 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 ( function , args , startTime , "" , "MakeBucket failed" , err )
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 {
logError ( function , args , startTime , "" , "PutObject call failed" , err )
return
}
ctx , cancel := context . WithTimeout ( context . Background ( ) , 50 * time . Millisecond )
args [ "ctx" ] = ctx
defer cancel ( )
// Read the data back
r , err := c . GetObjectWithContext ( ctx , bucketName , objectName , minio . GetObjectOptions { } )
if err != nil {
logError ( function , args , startTime , "" , "GetObjectWithContext failed due to non-cancellation upon short timeout" , err )
return
}
ctx , cancel = context . WithTimeout ( context . Background ( ) , 3 * time . Minute )
defer cancel ( )
// Read the data back
r , err = c . GetObjectWithContext ( ctx , bucketName , objectName , minio . GetObjectOptions { } )
if err != nil {
logError ( function , args , startTime , "" , "GetObjectWithContext failed due to non-cancellation upon long timeout" , err )
return
}
st , err := r . Stat ( )
if err != nil {
logError ( function , args , startTime , "" , "object Stat call failed" , err )
return
}
if st . Size != int64 ( bufSize ) {
logError ( function , args , startTime , "" , "Number of bytes in stat does not match, expected " + string ( bufSize ) + " got " + string ( st . Size ) , err )
return
}
if err := r . Close ( ) ; err != nil {
logError ( function , args , startTime , "" , " object Close() call failed" , err )
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
}
successLogger ( function , args , startTime ) . Info ( )
}
// Test get object with FGetObjectWithContext
func testFGetObjectWithContextV2 ( ) {
// initialize logging params
startTime := time . Now ( )
function := "FGetObjectWithContext(ctx, bucketName, objectName,fileName)"
args := map [ string ] interface { } {
"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 {
logError ( function , args , startTime , "" , "Minio client v2 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 ( function , args , startTime , "" , "MakeBucket call failed" , err )
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 {
logError ( function , args , startTime , "" , "PutObject call failed" , err )
return
}
ctx , cancel := context . WithTimeout ( context . Background ( ) , 1 * time . Millisecond )
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 {
logError ( function , args , startTime , "" , "FGetObjectWithContext call with short request timeout failed" , err )
return
}
ctx , cancel = context . WithTimeout ( context . Background ( ) , 5 * time . Minute )
defer cancel ( )
// Read the data back
err = c . FGetObjectWithContext ( ctx , bucketName , objectName , fileName + "-fcontext" , minio . GetObjectOptions { } )
if err != nil {
logError ( function , args , startTime , "" , "FGetObjectWithContext call with long request timeout failed" , err )
return
}
if err = os . Remove ( fileName + "-fcontext" ) ; err != nil {
logError ( function , args , startTime , "" , "Remove file failed" , err )
return
}
// Delete all objects and buckets
if err = cleanupBucket ( bucketName , c ) ; err != nil {
logError ( function , args , startTime , "" , "Cleanup failed" , err )
return
}
successLogger ( function , args , startTime ) . Info ( )
}
// 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
if ! isQuickMode ( ) {
testMakeBucketErrorV2 ( )
testGetObjectClosedTwiceV2 ( )
testRemovePartiallyUploadedV2 ( )
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 ( )
testListPartiallyUploaded ( )
testGetObjectSeekEnd ( )
testGetObjectClosedTwice ( )
testRemoveMultipleObjects ( )
testRemovePartiallyUploaded ( )
testFPutObjectMultipart ( )
testFPutObject ( )
testGetObjectReadSeekFunctional ( )
testGetObjectReadAtFunctional ( )
testPresignedPostPolicy ( )
testCopyObject ( )
testEncryptionPutGet ( )
2017-12-08 19:45:59 +00:00
testEncryptionFPut ( )
2017-09-13 12:09:48 +00:00
testComposeObjectErrorCases ( )
testCompose10KSources ( )
testUserMetadataCopying ( )
testBucketNotification ( )
testFunctional ( )
testGetObjectObjectModified ( )
testPutObjectUploadSeekedObject ( )
2017-12-08 19:45:59 +00:00
testGetObjectWithContext ( )
testFPutObjectWithContext ( )
testFGetObjectWithContext ( )
testPutObjectWithContext ( )
// SSE-C tests will only work over TLS connection.
if tls {
testEncryptedCopyObjectV2 ( )
testEncryptedCopyObject ( )
}
2017-09-13 12:09:48 +00:00
} else {
testFunctional ( )
testFunctionalV2 ( )
}
}