You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

545 lines
20 KiB

package coscrypto_test
import (
"bytes"
"context"
"crypto/aes"
"crypto/cipher"
"crypto/md5"
"crypto/rand"
"encoding/base64"
"fmt"
"io"
"io/ioutil"
math_rand "math/rand"
"net/http"
"net/url"
"os"
"testing"
"time"
"git.ouxuan.net/tommy/cos-go-sdk-v5"
coscrypto "git.ouxuan.net/tommy/cos-go-sdk-v5/crypto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
)
const (
kAppid = 1259654469
kBucket = "cosgosdktest-1259654469"
kRegion = "ap-guangzhou"
)
type CosTestSuite struct {
suite.Suite
Client *cos.Client
CClient *coscrypto.CryptoClient
Master coscrypto.MasterCipher
}
func (s *CosTestSuite) SetupSuite() {
u, _ := url.Parse("https://" + kBucket + ".cos." + kRegion + ".myqcloud.com")
b := &cos.BaseURL{BucketURL: u}
s.Client = cos.NewClient(b, &http.Client{
Transport: &cos.AuthorizationTransport{
SecretID: os.Getenv("COS_SECRETID"),
SecretKey: os.Getenv("COS_SECRETKEY"),
},
})
material := make(map[string]string)
material["desc"] = "cos crypto suite test"
kmsclient, _ := coscrypto.NewKMSClient(s.Client.GetCredential(), kRegion)
s.Master, _ = coscrypto.CreateMasterKMS(kmsclient, os.Getenv("KMSID"), material)
s.CClient = coscrypto.NewCryptoClient(s.Client, s.Master)
opt := &cos.BucketPutOptions{
XCosACL: "public-read",
}
r, err := s.Client.Bucket.Put(context.Background(), opt)
if err != nil && r != nil && r.StatusCode == 409 {
fmt.Println("BucketAlreadyOwnedByYou")
} else if err != nil {
assert.Nil(s.T(), err, "PutBucket Failed")
}
}
func (s *CosTestSuite) TestPutGetDeleteObject_DecryptWithKey_10MB() {
name := "test/objectPut" + time.Now().Format(time.RFC3339)
originData := make([]byte, 1024*1024*10+1)
_, err := rand.Read(originData)
f := bytes.NewReader(originData)
// 加密存储
_, err = s.CClient.Object.Put(context.Background(), name, f, nil)
assert.Nil(s.T(), err, "PutObject Failed")
// 获取解密信息
resp, err := s.CClient.Object.Head(context.Background(), name, nil)
assert.Nil(s.T(), err, "HeadObject Failed")
cipherKey := resp.Header.Get(coscrypto.COSClientSideEncryptionKey)
cipherKeybs, err := base64.StdEncoding.DecodeString(cipherKey)
assert.Nil(s.T(), err, "base64 Decode Failed")
cipherIV := resp.Header.Get(coscrypto.COSClientSideEncryptionStart)
cipherIVbs, err := base64.StdEncoding.DecodeString(cipherIV)
assert.Nil(s.T(), err, "base64 Decode Failed")
key, err := s.Master.Decrypt(cipherKeybs)
assert.Nil(s.T(), err, "Master Decrypt Failed")
iv, err := s.Master.Decrypt(cipherIVbs)
assert.Nil(s.T(), err, "Master Decrypt Failed")
// 正常读取
resp, err = s.Client.Object.Get(context.Background(), name, nil)
assert.Nil(s.T(), err, "GetObject Failed")
defer resp.Body.Close()
encryptedData, _ := ioutil.ReadAll(resp.Body)
assert.NotEqual(s.T(), bytes.Compare(encryptedData, originData), 0, "encryptedData == originData")
// 手动解密
block, err := aes.NewCipher(key)
assert.Nil(s.T(), err, "NewCipher Failed")
decrypter := cipher.NewCTR(block, iv)
decryptedData := make([]byte, len(originData))
decrypter.XORKeyStream(decryptedData, encryptedData)
assert.Equal(s.T(), bytes.Compare(originData, decryptedData), 0, "decryptData != originData")
_, err = s.CClient.Object.Delete(context.Background(), name)
assert.Nil(s.T(), err, "DeleteObject Failed")
}
func (s *CosTestSuite) TestPutGetDeleteObject_Normal_10MB() {
name := "test/objectPut" + time.Now().Format(time.RFC3339)
originData := make([]byte, 1024*1024*10+1)
_, err := rand.Read(originData)
f := bytes.NewReader(originData)
// 加密存储
_, err = s.CClient.Object.Put(context.Background(), name, f, nil)
assert.Nil(s.T(), err, "PutObject Failed")
// 解密读取
resp, err := s.CClient.Object.Get(context.Background(), name, nil)
assert.Nil(s.T(), err, "GetObject Failed")
defer resp.Body.Close()
decryptedData, _ := ioutil.ReadAll(resp.Body)
assert.Equal(s.T(), bytes.Compare(originData, decryptedData), 0, "decryptData != originData")
_, err = s.CClient.Object.Delete(context.Background(), name)
assert.Nil(s.T(), err, "DeleteObject Failed")
}
func (s *CosTestSuite) TestPutGetDeleteObject_VersionID() {
name := "test/objectPut" + time.Now().Format(time.RFC3339)
originData := make([]byte, 1024*1024*10+1)
_, err := rand.Read(originData)
f := bytes.NewReader(originData)
opt := &cos.BucketPutVersionOptions{
Status: "Enabled",
}
_, err = s.CClient.Bucket.PutVersioning(context.Background(), opt)
assert.Nil(s.T(), err, "PutVersioning Failed")
time.Sleep(3 * time.Second)
// 加密存储
resp, err := s.CClient.Object.Put(context.Background(), name, f, nil)
assert.Nil(s.T(), err, "PutObject Failed")
versionId := resp.Header.Get("x-cos-version-id")
_, err = s.CClient.Object.Delete(context.Background(), name)
assert.Nil(s.T(), err, "DeleteObject Failed")
// 解密读取
resp, err = s.CClient.Object.Get(context.Background(), name, nil, versionId)
assert.Nil(s.T(), err, "GetObject Failed")
defer resp.Body.Close()
decryptedData, _ := ioutil.ReadAll(resp.Body)
assert.Equal(s.T(), bytes.Compare(originData, decryptedData), 0, "decryptData != originData")
delopt := &cos.ObjectDeleteOptions{
VersionId: versionId,
}
_, err = s.CClient.Object.Delete(context.Background(), name, delopt)
assert.Nil(s.T(), err, "DeleteObject Failed")
opt.Status = "Suspended"
_, err = s.CClient.Bucket.PutVersioning(context.Background(), opt)
assert.Nil(s.T(), err, "PutVersioning Failed")
}
func (s *CosTestSuite) TestPutGetDeleteObject_ZeroFile() {
name := "test/objectPut" + time.Now().Format(time.RFC3339)
// 加密存储
_, err := s.CClient.Object.Put(context.Background(), name, bytes.NewReader([]byte("")), nil)
assert.Nil(s.T(), err, "PutObject Failed")
// 解密读取
resp, err := s.CClient.Object.Get(context.Background(), name, nil)
assert.Nil(s.T(), err, "GetObject Failed")
defer resp.Body.Close()
decryptedData, _ := ioutil.ReadAll(resp.Body)
assert.Equal(s.T(), bytes.Compare([]byte(""), decryptedData), 0, "decryptData != originData")
_, err = s.CClient.Object.Delete(context.Background(), name)
assert.Nil(s.T(), err, "DeleteObject Failed")
}
func (s *CosTestSuite) TestPutGetDeleteObject_WithMetaData() {
name := "test/objectPut" + time.Now().Format(time.RFC3339)
originData := make([]byte, 1024*1024*10+1)
_, err := rand.Read(originData)
f := bytes.NewReader(originData)
m := md5.New()
m.Write(originData)
contentMD5 := m.Sum(nil)
opt := &cos.ObjectPutOptions{
&cos.ACLHeaderOptions{
XCosACL: "private",
},
&cos.ObjectPutHeaderOptions{
ContentLength: 1024*1024*10 + 1,
ContentMD5: base64.StdEncoding.EncodeToString(contentMD5),
XCosMetaXXX: &http.Header{},
},
}
opt.XCosMetaXXX.Add("x-cos-meta-isEncrypted", "true")
// 加密存储
_, err = s.CClient.Object.Put(context.Background(), name, f, opt)
assert.Nil(s.T(), err, "PutObject Failed")
// 解密读取
resp, err := s.CClient.Object.Get(context.Background(), name, nil)
assert.Nil(s.T(), err, "GetObject Failed")
defer resp.Body.Close()
decryptedData, _ := ioutil.ReadAll(resp.Body)
assert.Equal(s.T(), bytes.Compare(originData, decryptedData), 0, "decryptData != originData")
assert.Equal(s.T(), resp.Header.Get("x-cos-meta-isEncrypted"), "true", "meta data isn't consistent")
assert.Equal(s.T(), resp.Header.Get(coscrypto.COSClientSideEncryptionCekAlg), coscrypto.AesCtrAlgorithm, "meta data isn't consistent")
assert.Equal(s.T(), resp.Header.Get(coscrypto.COSClientSideEncryptionWrapAlg), coscrypto.CosKmsCryptoWrap, "meta data isn't consistent")
assert.Equal(s.T(), resp.Header.Get(coscrypto.COSClientSideEncryptionUnencryptedContentMD5), base64.StdEncoding.EncodeToString(contentMD5), "meta data isn't consistent")
_, err = s.CClient.Object.Delete(context.Background(), name)
assert.Nil(s.T(), err, "DeleteObject Failed")
}
func (s *CosTestSuite) TestPutGetDeleteObject_ByFile() {
name := "test/objectPut" + time.Now().Format(time.RFC3339)
filepath := "tmpfile" + time.Now().Format(time.RFC3339)
newfile, err := os.Create(filepath)
assert.Nil(s.T(), err, "Create File Failed")
defer os.Remove(filepath)
originData := make([]byte, 1024*1024*10+1)
_, err = rand.Read(originData)
newfile.Write(originData)
newfile.Close()
m := md5.New()
m.Write(originData)
contentMD5 := m.Sum(nil)
opt := &cos.ObjectPutOptions{
&cos.ACLHeaderOptions{
XCosACL: "private",
},
&cos.ObjectPutHeaderOptions{
ContentLength: 1024*1024*10 + 1,
ContentMD5: base64.StdEncoding.EncodeToString(contentMD5),
XCosMetaXXX: &http.Header{},
},
}
opt.XCosMetaXXX.Add("x-cos-meta-isEncrypted", "true")
// 加密存储
_, err = s.CClient.Object.PutFromFile(context.Background(), name, filepath, opt)
assert.Nil(s.T(), err, "PutFromFile Failed")
// 解密读取
downfile := "downfile" + time.Now().Format(time.RFC3339)
resp, err := s.CClient.Object.GetToFile(context.Background(), name, downfile, nil)
assert.Nil(s.T(), err, "GetToFile Failed")
assert.Equal(s.T(), resp.Header.Get("x-cos-meta-isEncrypted"), "true", "meta data isn't consistent")
assert.Equal(s.T(), resp.Header.Get(coscrypto.COSClientSideEncryptionCekAlg), coscrypto.AesCtrAlgorithm, "meta data isn't consistent")
assert.Equal(s.T(), resp.Header.Get(coscrypto.COSClientSideEncryptionWrapAlg), coscrypto.CosKmsCryptoWrap, "meta data isn't consistent")
assert.Equal(s.T(), resp.Header.Get(coscrypto.COSClientSideEncryptionUnencryptedContentMD5), base64.StdEncoding.EncodeToString(contentMD5), "meta data isn't consistent")
fd, err := os.Open(downfile)
assert.Nil(s.T(), err, "Open File Failed")
defer os.Remove(downfile)
defer fd.Close()
m = md5.New()
io.Copy(m, fd)
downContentMD5 := m.Sum(nil)
assert.Equal(s.T(), bytes.Compare(contentMD5, downContentMD5), 0, "decryptData != originData")
_, err = s.CClient.Object.Delete(context.Background(), name)
assert.Nil(s.T(), err, "DeleteObject Failed")
}
func (s *CosTestSuite) TestPutGetDeleteObject_DecryptWithNewClient_10MB() {
name := "test/objectPut" + time.Now().Format(time.RFC3339)
originData := make([]byte, 1024*1024*10+1)
_, err := rand.Read(originData)
f := bytes.NewReader(originData)
// 加密存储
_, err = s.CClient.Object.Put(context.Background(), name, f, nil)
assert.Nil(s.T(), err, "PutObject Failed")
u, _ := url.Parse("https://" + kBucket + ".cos." + kRegion + ".myqcloud.com")
b := &cos.BaseURL{BucketURL: u}
c := cos.NewClient(b, &http.Client{
Transport: &cos.AuthorizationTransport{
SecretID: os.Getenv("COS_SECRETID"),
SecretKey: os.Getenv("COS_SECRETKEY"),
},
})
{
// 使用不同的MatDesc客户端读取, 期待错误
material := make(map[string]string)
material["desc"] = "cos crypto suite test 2"
kmsclient, _ := coscrypto.NewKMSClient(c.GetCredential(), kRegion)
master, _ := coscrypto.CreateMasterKMS(kmsclient, os.Getenv("KMSID"), material)
client := coscrypto.NewCryptoClient(c, master)
resp, err := client.Object.Get(context.Background(), name, nil)
assert.Nil(s.T(), resp, "Get Object Failed")
assert.NotNil(s.T(), err, "Get Object Failed")
}
{
// 使用相同的MatDesc客户端读取, 但KMSID不一样,期待正确,kms解密是不需要KMSID
material := make(map[string]string)
material["desc"] = "cos crypto suite test"
kmsclient, _ := coscrypto.NewKMSClient(s.Client.GetCredential(), kRegion)
master, _ := coscrypto.CreateMasterKMS(kmsclient, "KMSID", material)
client := coscrypto.NewCryptoClient(c, master)
resp, err := client.Object.Get(context.Background(), name, nil)
assert.Nil(s.T(), err, "Get Object Failed")
defer resp.Body.Close()
decryptedData, _ := ioutil.ReadAll(resp.Body)
assert.Equal(s.T(), bytes.Compare(originData, decryptedData), 0, "decryptData != originData")
}
{
// 使用相同的MatDesc和KMSID客户端读取, 期待正确
material := make(map[string]string)
material["desc"] = "cos crypto suite test"
kmsclient, _ := coscrypto.NewKMSClient(s.Client.GetCredential(), kRegion)
master, _ := coscrypto.CreateMasterKMS(kmsclient, os.Getenv("KMSID"), material)
client := coscrypto.NewCryptoClient(c, master)
resp, err := client.Object.Get(context.Background(), name, nil)
assert.Nil(s.T(), err, "Get Object Failed")
defer resp.Body.Close()
decryptedData, _ := ioutil.ReadAll(resp.Body)
assert.Equal(s.T(), bytes.Compare(originData, decryptedData), 0, "decryptData != originData")
}
_, err = s.CClient.Object.Delete(context.Background(), name)
assert.Nil(s.T(), err, "DeleteObject Failed")
}
func (s *CosTestSuite) TestPutGetDeleteObject_RangeGet() {
name := "test/objectPut" + time.Now().Format(time.RFC3339)
contentLength := 1024*1024*10 + 1
originData := make([]byte, contentLength)
_, err := rand.Read(originData)
f := bytes.NewReader(originData)
// 加密存储
_, err = s.CClient.Object.Put(context.Background(), name, f, nil)
assert.Nil(s.T(), err, "PutObject Failed")
// Range解密读取
for i := 0; i < 10; i++ {
math_rand.Seed(time.Now().UnixNano())
rangeStart := math_rand.Intn(contentLength)
rangeEnd := rangeStart + math_rand.Intn(contentLength-rangeStart)
if rangeEnd == rangeStart || rangeStart >= contentLength-1 {
continue
}
opt := &cos.ObjectGetOptions{
Range: fmt.Sprintf("bytes=%v-%v", rangeStart, rangeEnd),
}
resp, err := s.CClient.Object.Get(context.Background(), name, opt)
assert.Nil(s.T(), err, "GetObject Failed")
defer resp.Body.Close()
decryptedData, _ := ioutil.ReadAll(resp.Body)
assert.Equal(s.T(), bytes.Compare(originData[rangeStart:rangeEnd+1], decryptedData), 0, "decryptData != originData")
}
// 解密读取
resp, err := s.CClient.Object.Get(context.Background(), name, nil)
assert.Nil(s.T(), err, "GetObject Failed")
defer resp.Body.Close()
decryptedData, _ := ioutil.ReadAll(resp.Body)
assert.Equal(s.T(), bytes.Compare(originData, decryptedData), 0, "decryptData != originData")
_, err = s.CClient.Object.Delete(context.Background(), name)
assert.Nil(s.T(), err, "DeleteObject Failed")
}
func (s *CosTestSuite) TestPutGetDeleteObject_WithListenerAndRange() {
name := "test/objectPut" + time.Now().Format(time.RFC3339)
contentLength := 1024*1024*10 + 1
originData := make([]byte, contentLength)
_, err := rand.Read(originData)
f := bytes.NewReader(originData)
// 加密存储
popt := &cos.ObjectPutOptions{
nil,
&cos.ObjectPutHeaderOptions{
Listener: &cos.DefaultProgressListener{},
},
}
_, err = s.CClient.Object.Put(context.Background(), name, f, popt)
assert.Nil(s.T(), err, "PutObject Failed")
// Range解密读取
for i := 0; i < 10; i++ {
math_rand.Seed(time.Now().UnixNano())
rangeStart := math_rand.Intn(contentLength)
rangeEnd := rangeStart + math_rand.Intn(contentLength-rangeStart)
if rangeEnd == rangeStart || rangeStart >= contentLength-1 {
continue
}
opt := &cos.ObjectGetOptions{
Range: fmt.Sprintf("bytes=%v-%v", rangeStart, rangeEnd),
Listener: &cos.DefaultProgressListener{},
}
resp, err := s.CClient.Object.Get(context.Background(), name, opt)
assert.Nil(s.T(), err, "GetObject Failed")
defer resp.Body.Close()
decryptedData, _ := ioutil.ReadAll(resp.Body)
assert.Equal(s.T(), bytes.Compare(originData[rangeStart:rangeEnd+1], decryptedData), 0, "decryptData != originData")
}
// 解密读取
opt := &cos.ObjectGetOptions{
Listener: &cos.DefaultProgressListener{},
}
resp, err := s.CClient.Object.Get(context.Background(), name, opt)
assert.Nil(s.T(), err, "GetObject Failed")
defer resp.Body.Close()
decryptedData, _ := ioutil.ReadAll(resp.Body)
assert.Equal(s.T(), bytes.Compare(originData, decryptedData), 0, "decryptData != originData")
_, err = s.CClient.Object.Delete(context.Background(), name)
assert.Nil(s.T(), err, "DeleteObject Failed")
}
func (s *CosTestSuite) TestPutGetDeleteObject_Copy() {
name := "test/objectPut" + time.Now().Format(time.RFC3339)
contentLength := 1024*1024*10 + 1
originData := make([]byte, contentLength)
_, err := rand.Read(originData)
f := bytes.NewReader(originData)
// 加密存储
popt := &cos.ObjectPutOptions{
nil,
&cos.ObjectPutHeaderOptions{
Listener: &cos.DefaultProgressListener{},
},
}
resp, err := s.CClient.Object.Put(context.Background(), name, f, popt)
assert.Nil(s.T(), err, "PutObject Failed")
encryptedDataCRC := resp.Header.Get("x-cos-hash-crc64ecma")
time.Sleep(3 * time.Second)
sourceURL := fmt.Sprintf("%s/%s", s.CClient.BaseURL.BucketURL.Host, name)
{
// x-cos-metadata-directive必须为Copy,否则丢失加密信息,无法解密
dest := "test/ObjectCopy1" + time.Now().Format(time.RFC3339)
res, _, err := s.CClient.Object.Copy(context.Background(), dest, sourceURL, nil)
assert.Nil(s.T(), err, "ObjectCopy Failed")
assert.Equal(s.T(), encryptedDataCRC, res.CRC64, "CRC isn't consistent, return:%v, want:%v", res.CRC64, encryptedDataCRC)
// Range解密读取
for i := 0; i < 3; i++ {
math_rand.Seed(time.Now().UnixNano())
rangeStart := math_rand.Intn(contentLength)
rangeEnd := rangeStart + math_rand.Intn(contentLength-rangeStart)
if rangeEnd == rangeStart || rangeStart >= contentLength-1 {
continue
}
opt := &cos.ObjectGetOptions{
Range: fmt.Sprintf("bytes=%v-%v", rangeStart, rangeEnd),
Listener: &cos.DefaultProgressListener{},
}
resp, err := s.CClient.Object.Get(context.Background(), dest, opt)
assert.Nil(s.T(), err, "GetObject Failed")
defer resp.Body.Close()
decryptedData, _ := ioutil.ReadAll(resp.Body)
assert.Equal(s.T(), bytes.Compare(originData[rangeStart:rangeEnd+1], decryptedData), 0, "decryptData != originData")
}
// 解密读取
resp, err := s.CClient.Object.Get(context.Background(), dest, nil)
assert.Nil(s.T(), err, "GetObject Failed")
defer resp.Body.Close()
decryptedData, _ := ioutil.ReadAll(resp.Body)
assert.Equal(s.T(), bytes.Compare(originData, decryptedData), 0, "decryptData != originData")
_, err = s.CClient.Object.Delete(context.Background(), dest)
assert.Nil(s.T(), err, "DeleteObject Failed")
}
{
// x-cos-metadata-directive必须为Copy,否则丢失加密信息,无法解密
opt := &cos.ObjectCopyOptions{
&cos.ObjectCopyHeaderOptions{
XCosMetadataDirective: "Replaced",
},
nil,
}
dest := "test/ObjectCopy2" + time.Now().Format(time.RFC3339)
res, _, err := s.CClient.Object.Copy(context.Background(), dest, sourceURL, opt)
assert.Nil(s.T(), err, "ObjectCopy Failed")
assert.Equal(s.T(), encryptedDataCRC, res.CRC64, "CRC isn't consistent, return:%v, want:%v", res.CRC64, encryptedDataCRC)
// 解密读取
resp, err := s.CClient.Object.Get(context.Background(), dest, nil)
assert.Nil(s.T(), err, "GetObject Failed")
defer resp.Body.Close()
decryptedData, _ := ioutil.ReadAll(resp.Body)
assert.NotEqual(s.T(), bytes.Compare(originData, decryptedData), 0, "decryptData != originData")
_, err = s.CClient.Object.Delete(context.Background(), dest)
assert.Nil(s.T(), err, "DeleteObject Failed")
}
{
// MultiCopy若是分块拷贝,则无法拷贝元数据
dest := "test/ObjectCopy3" + time.Now().Format(time.RFC3339)
res, _, err := s.CClient.Object.MultiCopy(context.Background(), dest, sourceURL, nil)
assert.Nil(s.T(), err, "ObjectMultiCopy Failed")
assert.Equal(s.T(), encryptedDataCRC, res.CRC64, "CRC isn't consistent, return:%v, want:%v", res.CRC64, encryptedDataCRC)
// Range解密读取
for i := 0; i < 3; i++ {
math_rand.Seed(time.Now().UnixNano())
rangeStart := math_rand.Intn(contentLength)
rangeEnd := rangeStart + math_rand.Intn(contentLength-rangeStart)
if rangeEnd == rangeStart || rangeStart >= contentLength-1 {
continue
}
opt := &cos.ObjectGetOptions{
Range: fmt.Sprintf("bytes=%v-%v", rangeStart, rangeEnd),
Listener: &cos.DefaultProgressListener{},
}
resp, err := s.CClient.Object.Get(context.Background(), dest, opt)
assert.Nil(s.T(), err, "GetObject Failed")
defer resp.Body.Close()
decryptedData, _ := ioutil.ReadAll(resp.Body)
assert.Equal(s.T(), bytes.Compare(originData[rangeStart:rangeEnd+1], decryptedData), 0, "decryptData != originData")
}
// 解密读取
resp, err := s.CClient.Object.Get(context.Background(), dest, nil)
assert.Nil(s.T(), err, "GetObject Failed")
defer resp.Body.Close()
decryptedData, _ := ioutil.ReadAll(resp.Body)
assert.Equal(s.T(), bytes.Compare(originData, decryptedData), 0, "decryptData != originData")
_, err = s.CClient.Object.Delete(context.Background(), dest)
assert.Nil(s.T(), err, "DeleteObject Failed")
}
_, err = s.CClient.Object.Delete(context.Background(), name)
assert.Nil(s.T(), err, "DeleteObject Failed")
}
func TestCosTestSuite(t *testing.T) {
suite.Run(t, new(CosTestSuite))
}
func (s *CosTestSuite) TearDownSuite() {
}