Add ci test with the testify and travis, test the working
This commit is contained in:
40
.travis.yml
40
.travis.yml
@@ -1,27 +1,29 @@
|
|||||||
language: go
|
language: go
|
||||||
go:
|
go:
|
||||||
- 1.6
|
- '1.6'
|
||||||
- 1.7
|
- '1.7'
|
||||||
- 1.8
|
- '1.8'
|
||||||
- 1.9
|
- '1.9'
|
||||||
- master
|
- 1.10.x
|
||||||
|
- master
|
||||||
sudo: false
|
sudo: false
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- go get github.com/mattn/goveralls
|
- go get github.com/mattn/goveralls
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- go get
|
- go get
|
||||||
- go build
|
- go build
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- make test
|
- make test
|
||||||
- go test -coverprofile=cover.out github.com/tencentyun/cos-go-sdk-v5
|
- make ci-test
|
||||||
- $HOME/gopath/bin/goveralls -service=travis-ci -coverprofile=cover.out
|
- go test -coverprofile=cover.out github.com/tencentyun/cos-go-sdk-v5
|
||||||
|
- "$HOME/gopath/bin/goveralls -service=travis-ci -coverprofile=cover.out"
|
||||||
matrix:
|
matrix:
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- go: 1.6
|
- go: 1.6
|
||||||
- go: 1.7
|
- go: 1.7
|
||||||
- go: master
|
- go: master
|
||||||
|
env:
|
||||||
|
global:
|
||||||
|
- secure: XXB/cFVnJcAzhOZ2/zplwjhhhireQQGGRbNscPgQ0kpUQCyPZ6oIHvJMafuP4TVTJHEdMiaDxm0HNvgARuopXVaQNmK2UZj6xw40Ud7OT7ZUnw88xkQkXOI5GwG8oz9LqxIXUSItHegKXRLW0e1PoBdjZNv6lxGFAtuOcl9ekAg/q2lGIIQFefz6NK7gCmGYULKe+4J15VFldoYNM0JesxxxArTvtv8+k+U53oUwy9dex6z5oIA1zGIeKLcOD2xXgbjid/Ett3t0B2w3GfJWoM9rGV0eHgveOAUGe5tQkMKvl5LK1hj+93ZmU0MAG7x7t9jYKrFPqU/eDNJRMb4Ro6L7lIXVEKaBUkLx28PnwFQ5D043GBVtQGqYNcldZXIfbyYEHQZlD/BWFOt5YqTpGg+7Wm4NC3Yffqsurzk54juT7FftzVy0A8MFkqO+c5RHrOSUlm01pWXkGLHgZhUP5gEZEuUaoluSQTZksmAUJZ7F8DxwpE4SYBqfN27PZ87rWDNyOqNv1w1trzwx2IfdHHA+vfCZ7UM5e85gxFWUO2tJCUai2q21v3gBrcAgBOb6BwVzbWAorM2zY20f0l21XxOWMakA+r4JJA3s3EmcczcQeeL6pkFIAh+qKdFEPuyQTjH1mGpPzYFNbWtvPXijQo5PqyGrKL8W1t3ovwXMXoE=
|
||||||
|
- secure: bep0PPD/oYW5zY0QpeeC+WgFIya5DNRVmR92MO+e5BdFlSJPhstoG8bRh91EeftzC/Hyd3PUEIglPqTgZPxwysqW/81plsU95wV3qJi9gPi7+ZtYXH4xZTnaqgZsTr7jsKSVoKHSu7XqCtbSytW8YMN9wRWzG19/9hX2Z79Q6yNy5l9856Oyj1E2IXDjdZLPsWDhnZ8Vvk1wAVy2fc2esqKzHAZwm8n9vee2yR8vz7GXUszzpKvn4R43eNzdlFEHCmN0ANmxLJZmnYDpZHHfNf4slts+0S6I7awFXppuXUDaJPBRCia4XoFeSw+01IW1Vi0kAwvGLhxjJCWc4M/4ZU0byXDT11tDFvWa19NmnbYiizWiXNVecn1oNWYJqIKe7TTAMAtHSXAPmLX0rXuXKzwM09W6yrLFufCxyix9IOnenEbe9WwSdBbhmeLF3Wu/uVGkDog/FsXJM75sk956vV9UKh9zF4B9/NR8szJMF7shEs0Fbru5UUWheqg4AadPl3dhAWuj2+6NANa1LpH3JVD3II9dlXeMmMvsSwDvrYUaX/S8tf6JwZG0zCJK0TYp05rjxH+NIzWaMUTY7+HwYqqK3pOW3San0SlZiMq8N7GSnKUZ7WRQXYSB4gXHrg+mWyeVC7XnqiRtCwVi+LtPMu+YUbg7dwVi0vtKjYZYIUY=
|
||||||
|
- secure: Ob28vrOuHMKNKEtChkWbsaVv2SwLhcxXMnvGe4XN+y3mFvdhYnwpt6NdgThF8OCZ0761tvTRmvALfiZnO0uORjTtoHKkVPrnVIxlCcode0NVJZNHGn2fqjemdLKCnSeX7hm+9zeLpCnIvC+Sp3iZ3t2AH4AzgFx6nirWO3HwT5l9rNL9Q1CfwlOpNJJ36r9JTHwQnXmOfOmszUNoZ3rtiFXJ8dCi+BgY0lsiIRSiDkAH7KAPf86REM+ww81AaXG4/RuYx1Vj5zQCtZN7XEOViSXEbqqb8SrIFOccDu5FV12djg+4QS7FSjLVGrdIUcn4oI6pS24Et3oXf8xFx6JLYyGGhgZ2BsyJEx5vLQvkTWnMTrwZVRtCQ+g6lMUQpJhL2rBrmVBUqBFb5IH69O7corQm53n5qLM8IiosAQLfbOtML/1PyEpKCG2aOx1377Fx2yzxXW3ucP1PBqCzli0oCM2T52LfiNvZTzkIU6XJebBnzkZXepzOIFSur86kxgvQFElw9ro2X6XXPKU5S25xVaUSvaN1kmqLSkToJ9S1rmDYXnJR4aH0R2GcLw+EkMHFJJoAjnRHxrB4/1vOJbzmfS+qy6ShRhUMSD8gk4YJ6Y7o9h7oekuWOEn+XGhl29U9T5OApzHfoPEGZwLnpHxAiKJtQtv/TNhBIOFCjigsF7U=
|
||||||
|
|||||||
4
Makefile
4
Makefile
@@ -17,4 +17,6 @@ lint:
|
|||||||
|
|
||||||
.PHONY: example
|
.PHONY: example
|
||||||
example:
|
example:
|
||||||
cd examples && sh test.sh
|
cd example && sh test.sh
|
||||||
|
ci-test:
|
||||||
|
cd costesting && go test -v
|
||||||
|
|||||||
1
cos.go
1
cos.go
@@ -326,6 +326,7 @@ type ACLHeaderOptions struct {
|
|||||||
type ACLGrantee struct {
|
type ACLGrantee struct {
|
||||||
Type string `xml:"type,attr"`
|
Type string `xml:"type,attr"`
|
||||||
UIN string `xml:"uin,omitempty"`
|
UIN string `xml:"uin,omitempty"`
|
||||||
|
URI string `xml:"URI,omitempty"`
|
||||||
ID string `xml:",omitempty"`
|
ID string `xml:",omitempty"`
|
||||||
DisplayName string `xml:",omitempty"`
|
DisplayName string `xml:",omitempty"`
|
||||||
SubAccount string `xml:"Subaccount,omitempty"`
|
SubAccount string `xml:"Subaccount,omitempty"`
|
||||||
|
|||||||
449
costesting/ci_test.go
Normal file
449
costesting/ci_test.go
Normal file
@@ -0,0 +1,449 @@
|
|||||||
|
package cos
|
||||||
|
|
||||||
|
// Basic imports
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
"github.com/tencentyun/cos-go-sdk-v5"
|
||||||
|
"github.com/tencentyun/cos-go-sdk-v5/debug"
|
||||||
|
"io/ioutil"
|
||||||
|
"math/rand"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Define the suite, and absorb the built-in basic suite
|
||||||
|
// functionality from testify - including a T() method which
|
||||||
|
// returns the current testing context
|
||||||
|
type CosTestSuite struct {
|
||||||
|
suite.Suite
|
||||||
|
VariableThatShouldStartAtFive int
|
||||||
|
|
||||||
|
// CI client
|
||||||
|
Client *cos.Client
|
||||||
|
|
||||||
|
// Copy source client
|
||||||
|
CClient *cos.Client
|
||||||
|
|
||||||
|
Region string
|
||||||
|
|
||||||
|
Bucket string
|
||||||
|
|
||||||
|
Appid string
|
||||||
|
|
||||||
|
// test_object
|
||||||
|
TestObject string
|
||||||
|
|
||||||
|
// special_file_name
|
||||||
|
SepFileName string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CosTestSuite) SetupSuite() {
|
||||||
|
fmt.Println("Set up test")
|
||||||
|
// init
|
||||||
|
s.TestObject = "test.txt"
|
||||||
|
s.SepFileName = "中文" + "→↓←→↖↗↙↘! \"#$%&'()*+,-./0123456789:;<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
|
||||||
|
|
||||||
|
// CI client for test interface
|
||||||
|
// URL like this http://test-1253846586.cos.ap-guangzhou.myqcloud.com
|
||||||
|
u := os.Getenv("COS_BUCKET_URL")
|
||||||
|
|
||||||
|
// Get the region
|
||||||
|
iu, _ := url.Parse(u)
|
||||||
|
p := strings.Split(iu.Host, ".")
|
||||||
|
assert.Equal(s.T(), 5, len(p), "Bucket host is not right")
|
||||||
|
s.Region = p[2]
|
||||||
|
|
||||||
|
// Bucket name
|
||||||
|
pp := strings.Split(p[0], "-")
|
||||||
|
s.Bucket = pp[0]
|
||||||
|
s.Appid = pp[1]
|
||||||
|
|
||||||
|
ib := &cos.BaseURL{BucketURL: iu}
|
||||||
|
s.Client = cos.NewClient(ib, &http.Client{
|
||||||
|
Transport: &cos.AuthorizationTransport{
|
||||||
|
SecretID: os.Getenv("COS_SECRETID"),
|
||||||
|
SecretKey: os.Getenv("COS_SECRETKEY"),
|
||||||
|
Transport: &debug.DebugRequestTransport{
|
||||||
|
// RequestHeader: true,
|
||||||
|
// RequestBody: true,
|
||||||
|
// ResponseHeader: true,
|
||||||
|
// ResponseBody: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
opt := &cos.BucketPutOptions{
|
||||||
|
XCosACL: "public-read",
|
||||||
|
}
|
||||||
|
r, err := s.Client.Bucket.Put(context.Background(), opt)
|
||||||
|
if err != nil && r.StatusCode == 409 {
|
||||||
|
fmt.Println("BucketAlreadyOwnedByYou")
|
||||||
|
} else if err != nil {
|
||||||
|
assert.Nil(s.T(), err, "PutBucket Failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin of api test
|
||||||
|
|
||||||
|
// Service API
|
||||||
|
func (s *CosTestSuite) TestGetService() {
|
||||||
|
_, _, err := s.Client.Service.Get(context.Background())
|
||||||
|
assert.Nil(s.T(), err, "GetService Failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bucket API
|
||||||
|
func (s *CosTestSuite) TestPutHeadDeleteBucket() {
|
||||||
|
u := "http://gosdkbuckettest-" + s.Appid + ".cos.ap-beijing-1.myqcloud.com"
|
||||||
|
iu, _ := url.Parse(u)
|
||||||
|
ib := &cos.BaseURL{BucketURL: iu}
|
||||||
|
client := cos.NewClient(ib, &http.Client{
|
||||||
|
Transport: &cos.AuthorizationTransport{
|
||||||
|
SecretID: os.Getenv("COS_SECRETID"),
|
||||||
|
SecretKey: os.Getenv("COS_SECRETKEY"),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
r, err := client.Bucket.Put(context.Background(), nil)
|
||||||
|
if err != nil && r.StatusCode == 409 {
|
||||||
|
fmt.Println("BucketAlreadyOwnedByYou")
|
||||||
|
} else if err != nil {
|
||||||
|
assert.Nil(s.T(), err, "PutBucket Failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
_, err = client.Bucket.Head(context.Background())
|
||||||
|
assert.Nil(s.T(), err, "HeadBucket Failed")
|
||||||
|
|
||||||
|
_, err = client.Bucket.Delete(context.Background())
|
||||||
|
assert.Nil(s.T(), err, "DeleteBucket Failed")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CosTestSuite) TestPutBucketACLIllegal() {
|
||||||
|
opt := &cos.BucketPutACLOptions{
|
||||||
|
Header: &cos.ACLHeaderOptions{
|
||||||
|
XCosACL: "public-read-writ",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err := s.Client.Bucket.PutACL(context.Background(), opt)
|
||||||
|
assert.NotNil(s.T(), err, "PutBucketACL illegal Failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CosTestSuite) TestPutGetBucketACLNormal() {
|
||||||
|
// with header
|
||||||
|
opt := &cos.BucketPutACLOptions{
|
||||||
|
Header: &cos.ACLHeaderOptions{
|
||||||
|
XCosACL: "private",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err := s.Client.Bucket.PutACL(context.Background(), opt)
|
||||||
|
assert.Nil(s.T(), err, "PutBucketACL normal Failed")
|
||||||
|
|
||||||
|
v, _, err := s.Client.Bucket.GetACL(context.Background())
|
||||||
|
assert.Nil(s.T(), err, "GetBucketACL normal Failed")
|
||||||
|
assert.Equal(s.T(), 1, len(v.AccessControlList), "GetBucketACL normal Failed, must be private")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CosTestSuite) TestGetBucket() {
|
||||||
|
opt := &cos.BucketGetOptions{
|
||||||
|
Prefix: "中文",
|
||||||
|
MaxKeys: 3,
|
||||||
|
}
|
||||||
|
_, _, err := s.Client.Bucket.Get(context.Background(), opt)
|
||||||
|
assert.Nil(s.T(), err, "GetBucket Failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CosTestSuite) TestGetBucketLocation() {
|
||||||
|
v, _, err := s.Client.Bucket.GetLocation(context.Background())
|
||||||
|
assert.Nil(s.T(), err, "GetLocation Failed")
|
||||||
|
assert.Equal(s.T(), s.Region, v.Location, "GetLocation wrong region")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CosTestSuite) TestPutGetDeleteCORS() {
|
||||||
|
opt := &cos.BucketPutCORSOptions{
|
||||||
|
Rules: []cos.BucketCORSRule{
|
||||||
|
{
|
||||||
|
AllowedOrigins: []string{"http://www.qq.com"},
|
||||||
|
AllowedMethods: []string{"PUT", "GET"},
|
||||||
|
AllowedHeaders: []string{"x-cos-meta-test", "x-cos-xx"},
|
||||||
|
MaxAgeSeconds: 500,
|
||||||
|
ExposeHeaders: []string{"x-cos-meta-test1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err := s.Client.Bucket.PutCORS(context.Background(), opt)
|
||||||
|
assert.Nil(s.T(), err, "PutBucketCORS Failed")
|
||||||
|
|
||||||
|
v, _, err := s.Client.Bucket.GetCORS(context.Background())
|
||||||
|
assert.Nil(s.T(), err, "GetBucketCORS Failed")
|
||||||
|
assert.Equal(s.T(), 1, len(v.Rules), "GetBucketCORS wrong number rules")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CosTestSuite) TestPutGetDeleteLifeCycle() {
|
||||||
|
lc := &cos.BucketPutLifecycleOptions{
|
||||||
|
Rules: []cos.BucketLifecycleRule{
|
||||||
|
{
|
||||||
|
ID: "1234",
|
||||||
|
Filter: &cos.BucketLifecycleFilter{Prefix: "test"},
|
||||||
|
Status: "Enabled",
|
||||||
|
Transition: &cos.BucketLifecycleTransition{
|
||||||
|
Days: 10,
|
||||||
|
StorageClass: "Standard",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err := s.Client.Bucket.PutLifecycle(context.Background(), lc)
|
||||||
|
assert.Nil(s.T(), err, "PutBucketLifecycle Failed")
|
||||||
|
_, _, err = s.Client.Bucket.GetLifecycle(context.Background())
|
||||||
|
assert.Nil(s.T(), err, "GetBucketLifecycle Failed")
|
||||||
|
_, err = s.Client.Bucket.DeleteLifecycle(context.Background())
|
||||||
|
assert.Nil(s.T(), err, "DeleteBucketLifecycle Failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CosTestSuite) TestListMultipartUploads() {
|
||||||
|
// Create new upload
|
||||||
|
name := "test_multipart.txt"
|
||||||
|
v, _, err := s.Client.Object.InitiateMultipartUpload(context.Background(), name, nil)
|
||||||
|
assert.Nil(s.T(), err, "InitiateMultipartUpload Failed")
|
||||||
|
id := v.UploadID
|
||||||
|
|
||||||
|
// List
|
||||||
|
r, _, err := s.Client.Bucket.ListMultipartUploads(context.Background(), nil)
|
||||||
|
assert.Nil(s.T(), err, "ListMultipartUploads Failed")
|
||||||
|
assert.Equal(s.T(), 1, len(r.Uploads), "ListMultipartUploads wrong number uploads")
|
||||||
|
for _, p := range r.Uploads {
|
||||||
|
assert.Equal(s.T(), name, p.Key, "ListMultipartUploads wrong key")
|
||||||
|
assert.Equal(s.T(), id, p.UploadID, "ListMultipartUploads wrong uploadid")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Abort
|
||||||
|
_, err = s.Client.Object.AbortMultipartUpload(context.Background(), name, id)
|
||||||
|
assert.Nil(s.T(), err, "AbortMultipartUpload Failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Object API
|
||||||
|
func (s *CosTestSuite) TestPutHeadGetDeleteObject_10MB() {
|
||||||
|
name := "test/objectPut.go"
|
||||||
|
b := make([]byte, 1024*1024*10)
|
||||||
|
_, err := rand.Read(b)
|
||||||
|
content := fmt.Sprintf("%X", b)
|
||||||
|
f := strings.NewReader(content)
|
||||||
|
|
||||||
|
_, err = s.Client.Object.Put(context.Background(), name, f, nil)
|
||||||
|
assert.Nil(s.T(), err, "PutObject Failed")
|
||||||
|
|
||||||
|
_, err = s.Client.Object.Head(context.Background(), name, nil)
|
||||||
|
assert.Nil(s.T(), err, "HeadObject Failed")
|
||||||
|
|
||||||
|
_, err = s.Client.Object.Delete(context.Background(), name)
|
||||||
|
assert.Nil(s.T(), err, "DeleteObject Failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CosTestSuite) TestPutGetDeleteObjectByFile_10MB() {
|
||||||
|
// Create tmp file
|
||||||
|
filePath := "tmpfile"
|
||||||
|
newfile, err := os.Create(filePath)
|
||||||
|
assert.Nil(s.T(), err, "create tmp file Failed")
|
||||||
|
defer newfile.Close()
|
||||||
|
|
||||||
|
name := "test/objectPutByFile.go"
|
||||||
|
b := make([]byte, 1024*1024*10)
|
||||||
|
_, err = rand.Read(b)
|
||||||
|
|
||||||
|
newfile.Write(b)
|
||||||
|
_, err = s.Client.Object.PutFromFile(context.Background(), name, filePath, nil)
|
||||||
|
assert.Nil(s.T(), err, "PutObject Failed")
|
||||||
|
|
||||||
|
// Over write tmp file
|
||||||
|
_, err = s.Client.Object.GetToFile(context.Background(), name, filePath, nil)
|
||||||
|
assert.Nil(s.T(), err, "HeadObject Failed")
|
||||||
|
|
||||||
|
_, err = s.Client.Object.Delete(context.Background(), name)
|
||||||
|
assert.Nil(s.T(), err, "DeleteObject Failed")
|
||||||
|
|
||||||
|
// remove the local tmp file
|
||||||
|
err = os.Remove(filePath)
|
||||||
|
assert.Nil(s.T(), err, "remove local file Failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CosTestSuite) TestPutGetDeleteObjectSpecialName() {
|
||||||
|
f := strings.NewReader("test")
|
||||||
|
_, err := s.Client.Object.Put(context.Background(), s.SepFileName, f, nil)
|
||||||
|
assert.Nil(s.T(), err, "PutObject Failed")
|
||||||
|
|
||||||
|
resp, err := s.Client.Object.Get(context.Background(), s.SepFileName, nil)
|
||||||
|
assert.Nil(s.T(), err, "GetObject Failed")
|
||||||
|
defer resp.Body.Close()
|
||||||
|
bs, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
assert.Equal(s.T(), "test", string(bs), "GetObject failed content wrong")
|
||||||
|
|
||||||
|
_, err = s.Client.Object.Delete(context.Background(), s.SepFileName)
|
||||||
|
assert.Nil(s.T(), err, "DeleteObject Failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CosTestSuite) TestPutObjectToNonExistBucket() {
|
||||||
|
u := "http://gosdknonexistbucket-" + s.Appid + ".cos." + s.Region + ".myqcloud.com"
|
||||||
|
iu, _ := url.Parse(u)
|
||||||
|
ib := &cos.BaseURL{BucketURL: iu}
|
||||||
|
client := cos.NewClient(ib, &http.Client{
|
||||||
|
Transport: &cos.AuthorizationTransport{
|
||||||
|
SecretID: os.Getenv("COS_SECRETID"),
|
||||||
|
SecretKey: os.Getenv("COS_SECRETKEY"),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
name := "test/objectPut.go"
|
||||||
|
f := strings.NewReader("test")
|
||||||
|
r, err := client.Object.Put(context.Background(), name, f, nil)
|
||||||
|
assert.NotNil(s.T(), err, "PutObject ToNonExistBucket Failed")
|
||||||
|
assert.Equal(s.T(), 404, r.StatusCode, "PutObject ToNonExistBucket, not 404")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CosTestSuite) TestPutGetObjectACL() {
|
||||||
|
name := "test/objectACL.go"
|
||||||
|
f := strings.NewReader("test")
|
||||||
|
_, err := s.Client.Object.Put(context.Background(), name, f, nil)
|
||||||
|
assert.Nil(s.T(), err, "PutObject Failed")
|
||||||
|
|
||||||
|
// Put acl
|
||||||
|
opt := &cos.ObjectPutACLOptions{
|
||||||
|
Header: &cos.ACLHeaderOptions{
|
||||||
|
XCosACL: "public-read",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err = s.Client.Object.PutACL(context.Background(), name, opt)
|
||||||
|
assert.Nil(s.T(), err, "PutObjectACL Failed")
|
||||||
|
v, _, err := s.Client.Object.GetACL(context.Background(), name)
|
||||||
|
assert.Nil(s.T(), err, "GetObjectACL Failed")
|
||||||
|
assert.Equal(s.T(), 2, len(v.AccessControlList), "GetLifecycle wrong number rules")
|
||||||
|
|
||||||
|
_, err = s.Client.Object.Delete(context.Background(), name)
|
||||||
|
assert.Nil(s.T(), err, "DeleteObject Failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CosTestSuite) TestCopyObject() {
|
||||||
|
u := "http://gosdkcopytest-" + s.Appid + ".cos.ap-beijing-1.myqcloud.com"
|
||||||
|
iu, _ := url.Parse(u)
|
||||||
|
ib := &cos.BaseURL{BucketURL: iu}
|
||||||
|
c := cos.NewClient(ib, &http.Client{
|
||||||
|
Transport: &cos.AuthorizationTransport{
|
||||||
|
SecretID: os.Getenv("COS_SECRETID"),
|
||||||
|
SecretKey: os.Getenv("COS_SECRETKEY"),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
opt := &cos.BucketPutOptions{
|
||||||
|
XCosACL: "public-read",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notice in intranet the bucket host sometimes has i/o timeout problem
|
||||||
|
r, err := c.Bucket.Put(context.Background(), opt)
|
||||||
|
if err != nil && r.StatusCode == 409 {
|
||||||
|
fmt.Println("BucketAlreadyOwnedByYou")
|
||||||
|
} else if err != nil {
|
||||||
|
assert.Nil(s.T(), err, "PutBucket Failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
source := "test/objectMove1.go"
|
||||||
|
expected := "test"
|
||||||
|
f := strings.NewReader(expected)
|
||||||
|
|
||||||
|
_, err = c.Object.Put(context.Background(), source, f, nil)
|
||||||
|
assert.Nil(s.T(), err, "PutObject Failed")
|
||||||
|
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
// Copy file
|
||||||
|
soruceURL := fmt.Sprintf("%s/%s", iu.Host, source)
|
||||||
|
dest := source
|
||||||
|
//opt := &cos.ObjectCopyOptions{}
|
||||||
|
_, _, err = s.Client.Object.Copy(context.Background(), dest, soruceURL, nil)
|
||||||
|
assert.Nil(s.T(), err, "PutObjectCopy Failed")
|
||||||
|
|
||||||
|
// Check content
|
||||||
|
resp, err := s.Client.Object.Get(context.Background(), dest, nil)
|
||||||
|
assert.Nil(s.T(), err, "GetObject Failed")
|
||||||
|
bs, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
resp.Body.Close()
|
||||||
|
result := string(bs)
|
||||||
|
assert.Equal(s.T(), expected, result, "PutObjectCopy Failed, wrong content")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CosTestSuite) TestCreateAbortMultipartUpload() {
|
||||||
|
name := "test_multipart.txt"
|
||||||
|
v, _, err := s.Client.Object.InitiateMultipartUpload(context.Background(), name, nil)
|
||||||
|
assert.Nil(s.T(), err, "InitiateMultipartUpload Failed")
|
||||||
|
|
||||||
|
_, err = s.Client.Object.AbortMultipartUpload(context.Background(), name, v.UploadID)
|
||||||
|
assert.Nil(s.T(), err, "AbortMultipartUpload Failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CosTestSuite) TestCreateCompleteMultipartUpload() {
|
||||||
|
name := "test/test_complete_upload.go"
|
||||||
|
v, _, err := s.Client.Object.InitiateMultipartUpload(context.Background(), name, nil)
|
||||||
|
uploadID := v.UploadID
|
||||||
|
blockSize := 1024 * 1024 * 3
|
||||||
|
|
||||||
|
opt := &cos.CompleteMultipartUploadOptions{}
|
||||||
|
for i := 1; i < 5; i++ {
|
||||||
|
b := make([]byte, blockSize)
|
||||||
|
_, err := rand.Read(b)
|
||||||
|
content := fmt.Sprintf("%X", b)
|
||||||
|
f := strings.NewReader(content)
|
||||||
|
|
||||||
|
resp, err := s.Client.Object.UploadPart(
|
||||||
|
context.Background(), name, uploadID, i, f, nil,
|
||||||
|
)
|
||||||
|
assert.Nil(s.T(), err, "UploadPart Failed")
|
||||||
|
etag := resp.Header.Get("Etag")
|
||||||
|
opt.Parts = append(opt.Parts, cos.Object{
|
||||||
|
PartNumber: i, ETag: etag},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = s.Client.Object.CompleteMultipartUpload(
|
||||||
|
context.Background(), name, uploadID, opt,
|
||||||
|
)
|
||||||
|
assert.Nil(s.T(), err, "CompleteMultipartUpload Failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of api test
|
||||||
|
|
||||||
|
// All methods that begin with "Test" are run as tests within a
|
||||||
|
// suite.
|
||||||
|
// In order for 'go test' to run this suite, we need to create
|
||||||
|
// a normal test function and pass our suite to suite.Run
|
||||||
|
func TestCosTestSuite(t *testing.T) {
|
||||||
|
suite.Run(t, new(CosTestSuite))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CosTestSuite) TearDownSuite() {
|
||||||
|
// Clean the file in bucket
|
||||||
|
r, _, err := s.Client.Bucket.ListMultipartUploads(context.Background(), nil)
|
||||||
|
assert.Nil(s.T(), err, "ListMultipartUploads Failed")
|
||||||
|
for _, p := range r.Uploads {
|
||||||
|
// Abort
|
||||||
|
_, err = s.Client.Object.AbortMultipartUpload(context.Background(), p.Key, p.UploadID)
|
||||||
|
assert.Nil(s.T(), err, "AbortMultipartUpload Failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete objects
|
||||||
|
opt := &cos.BucketGetOptions{
|
||||||
|
MaxKeys: 500,
|
||||||
|
}
|
||||||
|
v, _, err := s.Client.Bucket.Get(context.Background(), opt)
|
||||||
|
assert.Nil(s.T(), err, "GetBucket Failed")
|
||||||
|
for _, c := range v.Contents {
|
||||||
|
_, err := s.Client.Object.Delete(context.Background(), c.Key)
|
||||||
|
assert.Nil(s.T(), err, "DeleteObject Failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("tear down~")
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -21,6 +22,8 @@ func main() {
|
|||||||
Transport: &cos.AuthorizationTransport{
|
Transport: &cos.AuthorizationTransport{
|
||||||
SecretID: os.Getenv("COS_SECRETID"),
|
SecretID: os.Getenv("COS_SECRETID"),
|
||||||
SecretKey: os.Getenv("COS_SECRETKEY"),
|
SecretKey: os.Getenv("COS_SECRETKEY"),
|
||||||
|
SecretID: ak,
|
||||||
|
SecretKey: sk,
|
||||||
Transport: &debug.DebugRequestTransport{
|
Transport: &debug.DebugRequestTransport{
|
||||||
RequestHeader: true,
|
RequestHeader: true,
|
||||||
RequestBody: true,
|
RequestBody: true,
|
||||||
@@ -30,6 +33,7 @@ func main() {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Case1 Download object into ReadCloser(). the body needs to be closed
|
||||||
name := "test/hello.txt"
|
name := "test/hello.txt"
|
||||||
resp, err := c.Object.Get(context.Background(), name, nil)
|
resp, err := c.Object.Get(context.Background(), name, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -39,7 +43,26 @@ func main() {
|
|||||||
resp.Body.Close()
|
resp.Body.Close()
|
||||||
fmt.Printf("%s\n", string(bs))
|
fmt.Printf("%s\n", string(bs))
|
||||||
|
|
||||||
// range
|
// Case2 Download object to local file. the body needs to be closed
|
||||||
|
fd, err := os.OpenFile("hello.txt", os.O_WRONLY|os.O_CREATE, 0660)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer fd.Close()
|
||||||
|
resp, err = c.Object.Get(context.Background(), name, nil)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
io.Copy(fd, resp.Body)
|
||||||
|
resp.Body.Close()
|
||||||
|
|
||||||
|
// Case3 Download object to local file path
|
||||||
|
err = c.Object.GetToFile(context.Background(), name, "hello_1.txt", nil)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Case4 Download object with range header, can used to concurrent download
|
||||||
opt := &cos.ObjectGetOptions{
|
opt := &cos.ObjectGetOptions{
|
||||||
ResponseContentType: "text/html",
|
ResponseContentType: "text/html",
|
||||||
Range: "bytes=0-3",
|
Range: "bytes=0-3",
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ func main() {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Case1 normal put object
|
||||||
name := "test/objectPut.go"
|
name := "test/objectPut.go"
|
||||||
f := strings.NewReader("test")
|
f := strings.NewReader("test")
|
||||||
|
|
||||||
@@ -36,6 +37,7 @@ func main() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Case2 put object with the options
|
||||||
name = "test/put_option.go"
|
name = "test/put_option.go"
|
||||||
f = strings.NewReader("test xxx")
|
f = strings.NewReader("test xxx")
|
||||||
opt := &cos.ObjectPutOptions{
|
opt := &cos.ObjectPutOptions{
|
||||||
@@ -51,4 +53,11 @@ func main() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Case3 put object by local file
|
||||||
|
_, err = c.Object.PutFromFile(context.Background(), name, "./test10M", nil)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
function run() {
|
run() {
|
||||||
go run "$@"
|
go run "$@"
|
||||||
|
|
||||||
if [ $? -ne 0 ]
|
if [ $? -ne 0 ]
|
||||||
|
|||||||
35
object.go
35
object.go
@@ -6,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -41,6 +42,29 @@ func (s *ObjectService) Get(ctx context.Context, name string, opt *ObjectGetOpti
|
|||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetToFile download the object to local file
|
||||||
|
func (s *ObjectService) GetToFile(ctx context.Context, name, localpath string, opt *ObjectGetOptions) (*Response, error) {
|
||||||
|
resp, err := s.Get(context.Background(), name, opt)
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// If file exist, overwrite it
|
||||||
|
fd, err := os.OpenFile(localpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0660)
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = io.Copy(fd, resp.Body)
|
||||||
|
fd.Close()
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ObjectPutHeaderOptions the options of header of the put object
|
// ObjectPutHeaderOptions the options of header of the put object
|
||||||
type ObjectPutHeaderOptions struct {
|
type ObjectPutHeaderOptions struct {
|
||||||
CacheControl string `header:"Cache-Control,omitempty" url:"-"`
|
CacheControl string `header:"Cache-Control,omitempty" url:"-"`
|
||||||
@@ -81,6 +105,17 @@ func (s *ObjectService) Put(ctx context.Context, name string, r io.Reader, opt *
|
|||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PutFromFile put object from local file
|
||||||
|
func (s *ObjectService) PutFromFile(ctx context.Context, name string, filePath string, opt *ObjectPutOptions) (*Response, error) {
|
||||||
|
fd, err := os.Open(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer fd.Close()
|
||||||
|
|
||||||
|
return s.Put(ctx, name, fd, opt)
|
||||||
|
}
|
||||||
|
|
||||||
// ObjectCopyHeaderOptions is the head option of the Copy
|
// ObjectCopyHeaderOptions is the head option of the Copy
|
||||||
type ObjectCopyHeaderOptions struct {
|
type ObjectCopyHeaderOptions struct {
|
||||||
XCosMetadataDirective string `header:"x-cos-metadata-directive,omitempty" url:"-" xml:"-"`
|
XCosMetadataDirective string `header:"x-cos-metadata-directive,omitempty" url:"-" xml:"-"`
|
||||||
|
|||||||
@@ -121,6 +121,22 @@ type CompleteMultipartUploadResult struct {
|
|||||||
ETag string
|
ETag string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ObjectList can used for sort the parts which needs in complete upload part
|
||||||
|
// sort.Sort(cos.ObjectList(opt.Parts))
|
||||||
|
type ObjectList []Object
|
||||||
|
|
||||||
|
func (o ObjectList) Len() int {
|
||||||
|
return len(o)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o ObjectList) Swap(i, j int) {
|
||||||
|
o[i], o[j] = o[j], o[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o ObjectList) Less(i, j int) bool { // rewrite the Less method from small to big
|
||||||
|
return o[i].PartNumber < o[j].PartNumber
|
||||||
|
}
|
||||||
|
|
||||||
// CompleteMultipartUpload 用来实现完成整个分块上传。当您已经使用Upload Parts上传所有块以后,你可以用该API完成上传。
|
// CompleteMultipartUpload 用来实现完成整个分块上传。当您已经使用Upload Parts上传所有块以后,你可以用该API完成上传。
|
||||||
// 在使用该API时,您必须在Body中给出每一个块的PartNumber和ETag,用来校验块的准确性。
|
// 在使用该API时,您必须在Body中给出每一个块的PartNumber和ETag,用来校验块的准确性。
|
||||||
//
|
//
|
||||||
|
|||||||
1
vendor/github.com/google/go-querystring
generated
vendored
Submodule
1
vendor/github.com/google/go-querystring
generated
vendored
Submodule
Submodule vendor/github.com/google/go-querystring added at 44c6ddd0a2
1
vendor/github.com/mozillazg/go-httpheader
generated
vendored
Submodule
1
vendor/github.com/mozillazg/go-httpheader
generated
vendored
Submodule
Submodule vendor/github.com/mozillazg/go-httpheader added at 61f2392c33
1
vendor/github.com/stretchr/testify
generated
vendored
Submodule
1
vendor/github.com/stretchr/testify
generated
vendored
Submodule
Submodule vendor/github.com/stretchr/testify added at 363ebb24d0
Reference in New Issue
Block a user