mirror of
https://github.com/rclone/rclone.git
synced 2025-12-20 10:13:20 +00:00
vendor: switch to using go1.11 modules
This commit is contained in:
259
vendor/github.com/yunify/qingstor-sdk-go/client/image/image.go
generated
vendored
259
vendor/github.com/yunify/qingstor-sdk-go/client/image/image.go
generated
vendored
@@ -1,259 +0,0 @@
|
||||
package image
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/yunify/qingstor-sdk-go/service"
|
||||
)
|
||||
|
||||
const (
|
||||
// ActionSep is separator of action.
|
||||
ActionSep = ":"
|
||||
|
||||
// OPSep is separator of operation.
|
||||
OPSep = "|"
|
||||
|
||||
// KVSep is separator of Key-Value.
|
||||
KVSep = "_"
|
||||
|
||||
//KVPairSep is separator of args.
|
||||
KVPairSep = ","
|
||||
)
|
||||
|
||||
const (
|
||||
// InfoOperation is string of info operation.
|
||||
InfoOperation string = "info"
|
||||
|
||||
// CropOperation is string of crop operation.
|
||||
CropOperation string = "crop"
|
||||
|
||||
// FormatOperation is string of format operation.
|
||||
FormatOperation string = "format"
|
||||
|
||||
// ResizeOperation is string of resize operation.
|
||||
ResizeOperation string = "resize"
|
||||
|
||||
// RotateOperation is string of rotate operation.
|
||||
RotateOperation string = "rotate"
|
||||
|
||||
// WaterMarkOperation is string of watermark operation.
|
||||
WaterMarkOperation string = "watermark"
|
||||
|
||||
// WaterMarkImageOperation is string of watermark image operation.
|
||||
WaterMarkImageOperation string = "watermark_image"
|
||||
)
|
||||
|
||||
// ResizeMode is the type of resize mode.
|
||||
type ResizeMode int
|
||||
|
||||
const (
|
||||
// ResizeFixed resizes image to fix width and height.
|
||||
ResizeFixed ResizeMode = iota
|
||||
|
||||
// ResizeForce resizes image to force witdth and height.
|
||||
ResizeForce
|
||||
|
||||
// ResizeThumbnail resizes image to thumbnail width and height.
|
||||
ResizeThumbnail
|
||||
)
|
||||
|
||||
// CropGravity is the type of crop gravity.
|
||||
type CropGravity int
|
||||
|
||||
const (
|
||||
|
||||
// CropCenter crops image to center width and height.
|
||||
CropCenter CropGravity = iota
|
||||
|
||||
// CropNorth crops image to north width and height.
|
||||
CropNorth
|
||||
|
||||
// CropEast crops image to east width and height.
|
||||
CropEast
|
||||
|
||||
// CropSouth crops image to south width and height.
|
||||
CropSouth
|
||||
|
||||
// CropWest crops image to west width and height.
|
||||
CropWest
|
||||
|
||||
// CropNorthWest crops image to north west width and height.
|
||||
CropNorthWest
|
||||
|
||||
// CropNorthEast crops image to north east width and height.
|
||||
CropNorthEast
|
||||
|
||||
// CropSouthWest crops image to south west width and height.
|
||||
CropSouthWest
|
||||
|
||||
// CropSouthEast crops image to south east width and height.
|
||||
CropSouthEast
|
||||
|
||||
// CropAuto crops image to auto width and height.
|
||||
CropAuto
|
||||
)
|
||||
|
||||
// Image is struct of Image process.
|
||||
type Image struct {
|
||||
key *string
|
||||
bucket *service.Bucket
|
||||
input *service.ImageProcessInput
|
||||
}
|
||||
|
||||
// Init initializes an image to process.
|
||||
func Init(bucket *service.Bucket, objectKey string) *Image {
|
||||
return &Image{
|
||||
key: &objectKey,
|
||||
bucket: bucket,
|
||||
input: &service.ImageProcessInput{},
|
||||
}
|
||||
}
|
||||
|
||||
// Info gets the information of the image.
|
||||
func (image *Image) Info() *Image {
|
||||
return image.setActionParam(InfoOperation, nil)
|
||||
}
|
||||
|
||||
// RotateParam is param of the rotate operation.
|
||||
type RotateParam struct {
|
||||
Angle int `schema:"a"`
|
||||
}
|
||||
|
||||
// Rotate image.
|
||||
func (image *Image) Rotate(param *RotateParam) *Image {
|
||||
return image.setActionParam(RotateOperation, param)
|
||||
}
|
||||
|
||||
// ResizeParam is param of the resize operation.
|
||||
type ResizeParam struct {
|
||||
Width int `schema:"w,omitempty"`
|
||||
Height int `schema:"h,omitempty"`
|
||||
Mode ResizeMode `schema:"m"`
|
||||
}
|
||||
|
||||
// Resize image.
|
||||
func (image *Image) Resize(param *ResizeParam) *Image {
|
||||
return image.setActionParam(ResizeOperation, param)
|
||||
}
|
||||
|
||||
// CropParam is param of the crop operation.
|
||||
type CropParam struct {
|
||||
Width int `schema:"w,omitempty"`
|
||||
Height int `schema:"h,omitempty"`
|
||||
Gravity CropGravity `schema:"g"`
|
||||
}
|
||||
|
||||
// Crop image.
|
||||
func (image *Image) Crop(param *CropParam) *Image {
|
||||
return image.setActionParam(CropOperation, param)
|
||||
}
|
||||
|
||||
// FormatParam is param of the format operation.
|
||||
type FormatParam struct {
|
||||
Type string `schema:"t"`
|
||||
}
|
||||
|
||||
// Format image.
|
||||
func (image *Image) Format(param *FormatParam) *Image {
|
||||
return image.setActionParam(FormatOperation, param)
|
||||
}
|
||||
|
||||
// WaterMarkParam is param of the wartermark operation.
|
||||
type WaterMarkParam struct {
|
||||
Dpi int `schema:"d,omitempty"`
|
||||
Opacity float64 `schema:"p,omitempty"`
|
||||
Text string `schema:"t"`
|
||||
Color string `schema:"c"`
|
||||
}
|
||||
|
||||
// WaterMark is operation of watermark text content.
|
||||
func (image *Image) WaterMark(param *WaterMarkParam) *Image {
|
||||
return image.setActionParam(WaterMarkOperation, param)
|
||||
}
|
||||
|
||||
// WaterMarkImageParam is param of the waterMark image operation
|
||||
type WaterMarkImageParam struct {
|
||||
Left int `schema:"l"`
|
||||
Top int `schema:"t"`
|
||||
Opacity float64 `schema:"p,omitempty"`
|
||||
URL string `schema:"u"`
|
||||
}
|
||||
|
||||
// WaterMarkImage is operation of watermark image.
|
||||
func (image *Image) WaterMarkImage(param *WaterMarkImageParam) *Image {
|
||||
return image.setActionParam(WaterMarkImageOperation, param)
|
||||
}
|
||||
|
||||
// Process does Image process.
|
||||
func (image *Image) Process() (*service.ImageProcessOutput, error) {
|
||||
defer func(input *service.ImageProcessInput) {
|
||||
input.Action = nil
|
||||
}(image.input)
|
||||
return image.bucket.ImageProcess(*image.key, image.input)
|
||||
}
|
||||
|
||||
func (image *Image) setActionParam(operation string, param interface{}) *Image {
|
||||
uri := operation
|
||||
if param != nil {
|
||||
uri = fmt.Sprintf("%s%s%s", uri, ActionSep, buildOptParamStr(param))
|
||||
}
|
||||
if image.input.Action != nil {
|
||||
uri = fmt.Sprintf("%s%s%s", *image.input.Action, OPSep, uri)
|
||||
}
|
||||
image.input.Action = &uri
|
||||
return image
|
||||
}
|
||||
|
||||
func buildOptParamStr(param interface{}) string {
|
||||
v := reflect.ValueOf(param).Elem()
|
||||
var kvPairs []string
|
||||
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
vf := v.Field(i)
|
||||
tf := v.Type().Field(i)
|
||||
key := tf.Tag.Get("schema")
|
||||
value := vf.Interface()
|
||||
tagValues := strings.Split(key, ",")
|
||||
if isEmptyValue(vf) &&
|
||||
len(tagValues) == 2 &&
|
||||
tagValues[1] == "omitempty" {
|
||||
continue
|
||||
}
|
||||
key = tagValues[0]
|
||||
kvPairs = append(kvPairs, fmt.Sprintf("%v%s%v", key, KVSep, value))
|
||||
}
|
||||
return strings.Join(kvPairs, KVPairSep)
|
||||
}
|
||||
|
||||
func isEmptyValue(v reflect.Value) bool {
|
||||
switch v.Kind() {
|
||||
case reflect.Array,
|
||||
reflect.Map,
|
||||
reflect.Slice,
|
||||
reflect.String:
|
||||
return v.Len() == 0
|
||||
case reflect.Bool:
|
||||
return !v.Bool()
|
||||
case reflect.Int,
|
||||
reflect.Int8,
|
||||
reflect.Int16,
|
||||
reflect.Int32,
|
||||
reflect.Int64:
|
||||
return v.Int() == 0
|
||||
case reflect.Uint,
|
||||
reflect.Uint8,
|
||||
reflect.Uint16,
|
||||
reflect.Uint32,
|
||||
reflect.Uint64,
|
||||
reflect.Uintptr:
|
||||
return v.Uint() == 0
|
||||
case reflect.Float32,
|
||||
reflect.Float64:
|
||||
return v.Float() == 0
|
||||
case reflect.Ptr:
|
||||
return v.IsNil()
|
||||
}
|
||||
return false
|
||||
}
|
||||
63
vendor/github.com/yunify/qingstor-sdk-go/client/image/image_test.go
generated
vendored
63
vendor/github.com/yunify/qingstor-sdk-go/client/image/image_test.go
generated
vendored
@@ -1,63 +0,0 @@
|
||||
package image
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
qs "github.com/yunify/qingstor-sdk-go/service"
|
||||
)
|
||||
|
||||
var image *Image
|
||||
|
||||
func init() {
|
||||
bucket := &qs.Bucket{}
|
||||
|
||||
// test.jpg is only a string
|
||||
image = Init(bucket, "test.jpg")
|
||||
}
|
||||
|
||||
func TestQueryString(t *testing.T) {
|
||||
var param interface{}
|
||||
param = &RotateParam{
|
||||
Angle: 90,
|
||||
}
|
||||
image.setActionParam(RotateOperation, param)
|
||||
assert.Equal(t, *image.input.Action, "rotate:a_90")
|
||||
|
||||
param = &CropParam{
|
||||
Width: 300,
|
||||
Height: 400,
|
||||
Gravity: 0,
|
||||
}
|
||||
image.setActionParam(CropOperation, param)
|
||||
assert.Equal(t, *image.input.Action, "rotate:a_90|crop:w_300,h_400,g_0")
|
||||
|
||||
param = &ResizeParam{
|
||||
Width: 500,
|
||||
Height: 500,
|
||||
Mode: ResizeForce,
|
||||
}
|
||||
image.setActionParam(ResizeOperation, param)
|
||||
assert.Equal(t, *image.input.Action, "rotate:a_90|crop:w_300,h_400,g_0|resize:w_500,h_500,m_1")
|
||||
|
||||
param = &FormatParam{
|
||||
Type: "png",
|
||||
}
|
||||
image.setActionParam(FormatOperation, param)
|
||||
assert.Equal(t, *image.input.Action, "rotate:a_90|crop:w_300,h_400,g_0|resize:w_500,h_500,m_1|format:t_png")
|
||||
|
||||
param = &WaterMarkParam{
|
||||
Text: "5rC05Y2w5paH5a2X",
|
||||
}
|
||||
image.setActionParam(WaterMarkOperation, param)
|
||||
assert.Equal(t, *image.input.Action, "rotate:a_90|crop:w_300,h_400,g_0|resize:w_500,h_500,m_1|format:t_png|watermark:t_5rC05Y2w5paH5a2X,c_")
|
||||
|
||||
param = &WaterMarkImageParam{
|
||||
URL: "aHR0cHM6Ly9wZWszYS5xaW5nc3Rvci5jb20vaW1nLWRvYy1lZy9xaW5jbG91ZC5wbmc",
|
||||
}
|
||||
image.setActionParam(WaterMarkImageOperation, param)
|
||||
assert.Equal(t, *image.input.Action, "rotate:a_90|crop:w_300,h_400,g_0|resize:w_500,h_500,m_1|format:t_png|watermark:t_5rC05Y2w5paH5a2X,c_|watermark_image:l_0,t_0,u_aHR0cHM6Ly9wZWszYS5xaW5nc3Rvci5jb20vaW1nLWRvYy1lZy9xaW5jbG91ZC5wbmc")
|
||||
|
||||
image.setActionParam(InfoOperation, nil)
|
||||
assert.Equal(t, *image.input.Action, "rotate:a_90|crop:w_300,h_400,g_0|resize:w_500,h_500,m_1|format:t_png|watermark:t_5rC05Y2w5paH5a2X,c_|watermark_image:l_0,t_0,u_aHR0cHM6Ly9wZWszYS5xaW5nc3Rvci5jb20vaW1nLWRvYy1lZy9xaW5jbG91ZC5wbmc|info")
|
||||
}
|
||||
106
vendor/github.com/yunify/qingstor-sdk-go/client/upload/chunk.go
generated
vendored
106
vendor/github.com/yunify/qingstor-sdk-go/client/upload/chunk.go
generated
vendored
@@ -1,106 +0,0 @@
|
||||
package upload
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
const (
|
||||
// QingStor has a max upload parts limit to 10000.
|
||||
maxUploadParts = 10000
|
||||
// We read from stream for read 1024B.
|
||||
segmentSize = 1024
|
||||
)
|
||||
|
||||
// chunk provides a struct to read file
|
||||
type chunk struct {
|
||||
fd io.Reader
|
||||
cur int64
|
||||
size int64
|
||||
partSize int
|
||||
}
|
||||
|
||||
// newChunk creates a FileChunk struct
|
||||
func newChunk(fd io.Reader, partSize int) *chunk {
|
||||
f := &chunk{
|
||||
fd: fd,
|
||||
partSize: partSize,
|
||||
}
|
||||
f.initSize()
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
// nextPart reads the next part of the file
|
||||
func (f *chunk) nextPart() (io.ReadSeeker, error) {
|
||||
type readerAtSeeker interface {
|
||||
io.ReaderAt
|
||||
io.ReadSeeker
|
||||
}
|
||||
switch r := f.fd.(type) {
|
||||
case readerAtSeeker:
|
||||
var sectionSize int64
|
||||
var err error
|
||||
leftSize := f.size - f.cur
|
||||
if leftSize >= int64(f.partSize) {
|
||||
sectionSize = int64(f.partSize)
|
||||
} else if leftSize > 0 {
|
||||
sectionSize = f.size - f.cur
|
||||
} else {
|
||||
err = io.EOF
|
||||
}
|
||||
seekReader := io.NewSectionReader(r, f.cur, sectionSize)
|
||||
f.cur += sectionSize
|
||||
return seekReader, err
|
||||
case io.Reader:
|
||||
buf := make([]byte, segmentSize)
|
||||
var n, lenBuf int
|
||||
var err error
|
||||
var chunk []byte
|
||||
for {
|
||||
n, _ = r.Read(buf)
|
||||
if n == 0 {
|
||||
if lenBuf == 0 {
|
||||
err = io.EOF
|
||||
}
|
||||
break
|
||||
}
|
||||
lenBuf = lenBuf + n
|
||||
chunk = append(chunk, buf...)
|
||||
if lenBuf == f.partSize {
|
||||
break
|
||||
}
|
||||
}
|
||||
partBody := bytes.NewReader(chunk[:lenBuf])
|
||||
return partBody, err
|
||||
default:
|
||||
return nil, errors.New("file does not support read")
|
||||
}
|
||||
}
|
||||
|
||||
// initSize tries to detect the total stream size, setting u.size. If
|
||||
// the size is not known, size is set to -1.
|
||||
func (f *chunk) initSize() {
|
||||
f.size = -1
|
||||
|
||||
switch r := f.fd.(type) {
|
||||
case io.Seeker:
|
||||
pos, _ := r.Seek(0, 1)
|
||||
defer r.Seek(pos, 0)
|
||||
|
||||
n, err := r.Seek(0, 2)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
f.size = n
|
||||
|
||||
// Try to adjust partSize if it is too small and account for
|
||||
// integer division truncation.
|
||||
if f.size/int64(f.partSize) >= int64(maxUploadParts) {
|
||||
// Add one to the part size to account for remainders
|
||||
// during the size calculation. e.g odd number of bytes.
|
||||
f.partSize = int(f.size/int64(maxUploadParts)) + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
52
vendor/github.com/yunify/qingstor-sdk-go/client/upload/chunk_test.go
generated
vendored
52
vendor/github.com/yunify/qingstor-sdk-go/client/upload/chunk_test.go
generated
vendored
@@ -1,52 +0,0 @@
|
||||
package upload
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var partSize = 5 * 1024
|
||||
|
||||
//Test_newFileChunk is the test function for New
|
||||
func Test_newFileChunk(t *testing.T) {
|
||||
setup()
|
||||
|
||||
fd, _ := os.Open("test_file")
|
||||
defer fd.Close()
|
||||
fr := newChunk(fd, partSize)
|
||||
if fr.size != 512000 {
|
||||
t.Fatalf("expected 512000, got %d", fr.size)
|
||||
}
|
||||
|
||||
tearDown()
|
||||
}
|
||||
|
||||
// Test_nextPart is the test function for nextSeekablePart
|
||||
func Test_nextPart(t *testing.T) {
|
||||
setup()
|
||||
|
||||
fd, _ := os.Open("test_file")
|
||||
defer fd.Close()
|
||||
fr := newChunk(fd, partSize)
|
||||
partBody, err := fr.nextPart()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
temp := make([]byte, 6000)
|
||||
n, _ := partBody.Read(temp)
|
||||
if n != partSize {
|
||||
t.Fatalf("expected 5120, got %d", len(temp))
|
||||
}
|
||||
|
||||
tearDown()
|
||||
}
|
||||
|
||||
func setup() {
|
||||
exec.Command("dd", "if=/dev/zero", "of=test_file", "bs=1024", "count=500").Output()
|
||||
}
|
||||
|
||||
func tearDown() {
|
||||
exec.Command("rm", "", "test_file").Output()
|
||||
}
|
||||
110
vendor/github.com/yunify/qingstor-sdk-go/client/upload/upload_client.go
generated
vendored
110
vendor/github.com/yunify/qingstor-sdk-go/client/upload/upload_client.go
generated
vendored
@@ -1,110 +0,0 @@
|
||||
package upload
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/yunify/qingstor-sdk-go/logger"
|
||||
"github.com/yunify/qingstor-sdk-go/service"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Uploader struct provides a struct to upload
|
||||
type Uploader struct {
|
||||
bucket *service.Bucket
|
||||
partSize int
|
||||
}
|
||||
|
||||
const smallestPartSize int = 1024 * 1024 * 4
|
||||
|
||||
//Init creates a uploader struct
|
||||
func Init(bucket *service.Bucket, partSize int) *Uploader {
|
||||
return &Uploader{
|
||||
bucket: bucket,
|
||||
partSize: partSize,
|
||||
}
|
||||
}
|
||||
|
||||
// Upload uploads multi parts of large object
|
||||
func (u *Uploader) Upload(fd io.Reader, objectKey string) error {
|
||||
if u.partSize < smallestPartSize {
|
||||
logger.Errorf(nil, "Part size error")
|
||||
return errors.New("the part size is too small")
|
||||
}
|
||||
|
||||
uploadID, err := u.init(objectKey)
|
||||
if err != nil {
|
||||
logger.Errorf(nil, "Init multipart upload error, %v.", err)
|
||||
return err
|
||||
}
|
||||
|
||||
partNumbers, err := u.upload(fd, uploadID, objectKey)
|
||||
if err != nil {
|
||||
logger.Errorf(nil, "Upload multipart error, %v.", err)
|
||||
return err
|
||||
}
|
||||
|
||||
err = u.complete(objectKey, uploadID, partNumbers)
|
||||
if err != nil {
|
||||
logger.Errorf(nil, "Complete upload error, %v.", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *Uploader) init(objectKey string) (*string, error) {
|
||||
output, err := u.bucket.InitiateMultipartUpload(
|
||||
objectKey,
|
||||
&service.InitiateMultipartUploadInput{},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return output.UploadID, nil
|
||||
}
|
||||
|
||||
func (u *Uploader) upload(fd io.Reader, uploadID *string, objectKey string) ([]*service.ObjectPartType, error) {
|
||||
var partCnt int
|
||||
partNumbers := []*service.ObjectPartType{}
|
||||
fileReader := newChunk(fd, u.partSize)
|
||||
for {
|
||||
partBody, err := fileReader.nextPart()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
logger.Errorf(nil, "Get next part failed, %v", err)
|
||||
return nil, err
|
||||
}
|
||||
_, err = u.bucket.UploadMultipart(
|
||||
objectKey,
|
||||
&service.UploadMultipartInput{
|
||||
UploadID: uploadID,
|
||||
PartNumber: &partCnt,
|
||||
Body: partBody,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
logger.Errorf(nil, "Upload multipart failed, %v", err)
|
||||
return nil, err
|
||||
}
|
||||
partNumbers = append(partNumbers, &service.ObjectPartType{
|
||||
PartNumber: service.Int(partCnt - 0),
|
||||
})
|
||||
partCnt++
|
||||
}
|
||||
return partNumbers, nil
|
||||
}
|
||||
|
||||
func (u *Uploader) complete(objectKey string, uploadID *string, partNumbers []*service.ObjectPartType) error {
|
||||
_, err := u.bucket.CompleteMultipartUpload(
|
||||
objectKey,
|
||||
&service.CompleteMultipartUploadInput{
|
||||
UploadID: uploadID,
|
||||
ObjectParts: partNumbers,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
108
vendor/github.com/yunify/qingstor-sdk-go/config/config_test.go
generated
vendored
108
vendor/github.com/yunify/qingstor-sdk-go/config/config_test.go
generated
vendored
@@ -1,108 +0,0 @@
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Copyright (C) 2016 Yunify, Inc.
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// | you may not use this work except in compliance with the License.
|
||||
// | You may obtain a copy of the License in the LICENSE file, or 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 config
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yunify/qingstor-sdk-go/logger"
|
||||
)
|
||||
|
||||
func TestConfig(t *testing.T) {
|
||||
c := Config{
|
||||
AccessKeyID: "AccessKeyID",
|
||||
SecretAccessKey: "SecretAccessKey",
|
||||
Host: "qingstor.dev",
|
||||
Port: 443,
|
||||
Protocol: "https",
|
||||
ConnectionRetries: 10,
|
||||
LogLevel: "warn",
|
||||
}
|
||||
|
||||
assert.Equal(t, "AccessKeyID", c.AccessKeyID)
|
||||
assert.Equal(t, "SecretAccessKey", c.SecretAccessKey)
|
||||
assert.Equal(t, "qingstor.dev", c.Host)
|
||||
assert.Equal(t, 10, c.ConnectionRetries)
|
||||
assert.Equal(t, "warn", c.LogLevel)
|
||||
|
||||
c.AdditionalUserAgent = `"`
|
||||
assert.Error(t, c.Check())
|
||||
|
||||
c.AdditionalUserAgent = `test/user`
|
||||
assert.NoError(t, c.Check())
|
||||
}
|
||||
|
||||
func TestLoadDefaultConfig(t *testing.T) {
|
||||
config := Config{}
|
||||
config.LoadDefaultConfig()
|
||||
|
||||
assert.Equal(t, "", config.AccessKeyID)
|
||||
assert.Equal(t, "", config.SecretAccessKey)
|
||||
assert.Equal(t, "https", config.Protocol)
|
||||
assert.Equal(t, "qingstor.com", config.Host)
|
||||
assert.Equal(t, "", config.AdditionalUserAgent)
|
||||
assert.Equal(t, "WARN", logger.GetLevel())
|
||||
}
|
||||
|
||||
func TestLoadUserConfig(t *testing.T) {
|
||||
config := Config{}
|
||||
config.LoadUserConfig()
|
||||
|
||||
assert.NotNil(t, config.Host)
|
||||
assert.NotNil(t, config.Protocol)
|
||||
}
|
||||
|
||||
func TestLoadConfigFromContent(t *testing.T) {
|
||||
fileContent := `
|
||||
access_key_id: 'access_key_id'
|
||||
secret_access_key: 'secret_access_key'
|
||||
|
||||
log_level: 'debug'
|
||||
|
||||
`
|
||||
|
||||
config := Config{}
|
||||
config.LoadConfigFromContent([]byte(fileContent))
|
||||
|
||||
assert.Equal(t, "access_key_id", config.AccessKeyID)
|
||||
assert.Equal(t, "secret_access_key", config.SecretAccessKey)
|
||||
assert.Equal(t, "https", config.Protocol)
|
||||
assert.Equal(t, "qingstor.com", config.Host)
|
||||
assert.Equal(t, "DEBUG", logger.GetLevel())
|
||||
}
|
||||
|
||||
func TestNewDefault(t *testing.T) {
|
||||
config, err := NewDefault()
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, "", config.AccessKeyID)
|
||||
assert.Equal(t, "", config.SecretAccessKey)
|
||||
assert.Equal(t, "https", config.Protocol)
|
||||
assert.Equal(t, "qingstor.com", config.Host)
|
||||
assert.Equal(t, 3, config.ConnectionRetries)
|
||||
}
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
config, err := New("AccessKeyID", "SecretAccessKey")
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, "AccessKeyID", config.AccessKeyID)
|
||||
assert.Equal(t, "SecretAccessKey", config.SecretAccessKey)
|
||||
assert.Equal(t, "https", config.Protocol)
|
||||
assert.Equal(t, "qingstor.com", config.Host)
|
||||
}
|
||||
82
vendor/github.com/yunify/qingstor-sdk-go/docs/configuration.md
generated
vendored
82
vendor/github.com/yunify/qingstor-sdk-go/docs/configuration.md
generated
vendored
@@ -1,82 +0,0 @@
|
||||
# Configuration Guide
|
||||
|
||||
## Summary
|
||||
|
||||
This SDK uses a structure called "Config" to store and manage configuration, read comments of public functions in ["config/config.go"](https://github.com/yunify/qingstor-sdk-go/blob/master/config/config.go) for details.
|
||||
|
||||
Except for Access Key, you can also configure the API endpoint for private cloud usage scenario. All available configurable items are listed in the default configuration file.
|
||||
|
||||
___Default Configuration File:___
|
||||
|
||||
``` yaml
|
||||
# QingStor services configuration
|
||||
|
||||
access_key_id: 'ACCESS_KEY_ID'
|
||||
secret_access_key: 'SECRET_ACCESS_KEY'
|
||||
|
||||
host: 'qingstor.com'
|
||||
port: 443
|
||||
protocol: 'https'
|
||||
connection_retries: 3
|
||||
|
||||
# Valid log levels are "debug", "info", "warn", "error", and "fatal".
|
||||
log_level: 'warn'
|
||||
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Just create a config structure instance with your API Access Key, and initialize services you need with Init() function of the target service.
|
||||
|
||||
### Code Snippet
|
||||
|
||||
Create default configuration
|
||||
|
||||
``` go
|
||||
defaultConfig, _ := config.NewDefault()
|
||||
```
|
||||
|
||||
Create configuration from Access Key
|
||||
|
||||
``` go
|
||||
configuration, _ := config.New("ACCESS_KEY_ID", "SECRET_ACCESS_KEY")
|
||||
|
||||
anotherConfiguration := config.NewDefault()
|
||||
anotherConfiguration.AccessKeyID = "ACCESS_KEY_ID"
|
||||
anotherConfiguration.SecretAccessKey = "SECRET_ACCESS_KEY"
|
||||
```
|
||||
|
||||
Load user configuration
|
||||
|
||||
``` go
|
||||
userConfig, _ := config.NewDefault().LoadUserConfig()
|
||||
```
|
||||
|
||||
Load configuration from config file
|
||||
|
||||
``` go
|
||||
configFromFile, _ := config.NewDefault().LoadConfigFromFilepath("PATH/TO/FILE")
|
||||
```
|
||||
|
||||
Change API endpoint
|
||||
|
||||
``` go
|
||||
moreConfiguration, _ := config.NewDefault()
|
||||
|
||||
moreConfiguration.Protocol = "http"
|
||||
moreConfiguration.Host = "api.private.com"
|
||||
moreConfiguration.Port = 80
|
||||
```
|
||||
|
||||
Change http timeout
|
||||
|
||||
``` go
|
||||
customConfiguration, _ := config.NewDefault().LoadUserConfig()
|
||||
// For the default value refers to DefaultHTTPClientSettings in config package
|
||||
// ReadTimeout affect each call to HTTPResponse.Body.Read()
|
||||
customConfiguration.HTTPSettings.ReadTimeout = 2 * time.Minute
|
||||
// WriteTimeout affect each write in io.Copy while sending HTTPRequest
|
||||
customConfiguration.HTTPSettings.WriteTimeout = 2 * time.Minute
|
||||
// Re-initialize the client to take effect
|
||||
customConfiguration.InitHTTPClient()
|
||||
```
|
||||
273
vendor/github.com/yunify/qingstor-sdk-go/docs/image_process_usage.md
generated
vendored
273
vendor/github.com/yunify/qingstor-sdk-go/docs/image_process_usage.md
generated
vendored
@@ -1,273 +0,0 @@
|
||||
# QingStor Image Processing Usage Guide
|
||||
|
||||
For processing the image stored in QingStor by a variety of basic operations, such as format, crop, watermark and so on.
|
||||
Please see [QingStor Image API](https://docs.qingcloud.com/qingstor/data_process/image_process/index.html).
|
||||
|
||||
## Usage
|
||||
Before using the image service, you need to initialize the [Configuration](https://github.com/yunify/qingstor-sdk-go/blob/master/docs/configuration.md) and [QingStor Service](https://github.com/yunify/qingstor-sdk-go/blob/master/docs/qingstor_service_usage.md).
|
||||
|
||||
``` go
|
||||
//Import the latest version API
|
||||
import (
|
||||
"github.com/yunify/qingstor-sdk-go/config"
|
||||
"github.com/yunify/qingstor-sdk-go/client/image"
|
||||
qs "github.com/yunify/qingstor-sdk-go/service"
|
||||
)
|
||||
```
|
||||
|
||||
## Code Snippet
|
||||
|
||||
Create configuration from Access Key and Initialize the QingStor service with a configuration.
|
||||
``` go
|
||||
// Initialize the QingStor service with a configuration
|
||||
config, _ := config.New("ACCESS_KEY_ID", "SECRET_ACCESS_KEY")
|
||||
service, _ := qs.Init(config)
|
||||
```
|
||||
Initialize a QingStor bucket.
|
||||
``` go
|
||||
bucket, _ := service.Bucket("bucketName", "zoneID")
|
||||
```
|
||||
Initialize a image.
|
||||
``` go
|
||||
img := image.Init(bucket, "imageName")
|
||||
```
|
||||
|
||||
Now you can use the the high level APIs or basic image process API to do the image operation.
|
||||
|
||||
Get the information of the image
|
||||
``` go
|
||||
imageProcessOutput, _ := img.Info().Process()
|
||||
```
|
||||
|
||||
Crop the image.
|
||||
``` go
|
||||
imageProcessOutput, _ := img.Crop(&image.CropParam{
|
||||
...operation_param...
|
||||
}).Process()
|
||||
```
|
||||
|
||||
Rotate the image.
|
||||
``` go
|
||||
imageProcessOutput, _ := img.Rotate(&image.RotateParam{
|
||||
...operation_param...
|
||||
}).Process()
|
||||
```
|
||||
Resize the image.
|
||||
``` go
|
||||
imageProcessOutput, _ := img.Resize(&image.ResizeParam{
|
||||
...operation_param...
|
||||
}).Process()
|
||||
```
|
||||
Watermark the image.
|
||||
``` go
|
||||
imageProcessOutput, _ := img.WaterMark(&image.WaterMarkParam{
|
||||
...operation_param...
|
||||
}).Process()
|
||||
```
|
||||
WaterMarkImage the image.
|
||||
``` go
|
||||
imageProcessOutput, _ : = img.WaterMarkImage(&image.WaterMarkImageParam{
|
||||
...operation_param...
|
||||
}).Process()
|
||||
```
|
||||
Format the image.
|
||||
``` go
|
||||
imageProcessOutput, _ := img.Format(&image.Format{
|
||||
...operation_param...
|
||||
}).Process()
|
||||
```
|
||||
Operation pipline, the image will be processed by order. The maximum number of operations in the pipeline is 10.
|
||||
``` go
|
||||
// Rotate and then resize the image
|
||||
imageProcessOutput, _ := img.Rotate(&image.RotateParam{
|
||||
... operation_param...
|
||||
}).Resize(&image.ResizeParam{
|
||||
... operation_param...
|
||||
}).Process()
|
||||
```
|
||||
Use the original basic API to rotate the image 90 angles.
|
||||
``` go
|
||||
operation := "rotate:a_90"
|
||||
imageProcessOutput, err := bucket.ImageProcess("imageName", &qs.ImageProcessInput{
|
||||
Action: &operation})
|
||||
```
|
||||
|
||||
`operation_param` is the image operation param, which definined in `qingstor-sdk-go/client/image/image.go`.
|
||||
``` go
|
||||
import "github.com/yunify/qingstor-sdk-go/service"
|
||||
// client/image/image.go
|
||||
type Image struct {
|
||||
key *string
|
||||
bucket *service.Bucket
|
||||
input *service.ImageProcessInput
|
||||
}
|
||||
|
||||
// About cropping image definition
|
||||
type CropGravity int
|
||||
const (
|
||||
CropCenter CropGravity = iota
|
||||
CropNorth
|
||||
CropEast
|
||||
CropSouth
|
||||
CropWest
|
||||
CropNorthWest
|
||||
CropNorthEast
|
||||
CropSouthWest
|
||||
CropSouthEast
|
||||
CropAuto
|
||||
)
|
||||
type CropParam struct {
|
||||
Width int `schema:"w,omitempty"`
|
||||
Height int `schema:"h,omitempty"`
|
||||
Gravity CropGravity `schema:"g"`
|
||||
}
|
||||
|
||||
// About rotating image definitions
|
||||
type RotateParam struct {
|
||||
Angle int `schema:"a"`
|
||||
}
|
||||
|
||||
// About resizing image definitions
|
||||
type ResizeMode int
|
||||
type ResizeParam struct {
|
||||
Width int `schema:"w,omitempty"`
|
||||
Height int `schema:"h,omitempty"`
|
||||
Mode ResizeMode `schema:"m"`
|
||||
}
|
||||
|
||||
// On the definition of text watermarking
|
||||
type WaterMarkParam struct {
|
||||
Dpi int `schema:"d,omitempty"`
|
||||
Opacity float64 `schema:"p,omitempty"`
|
||||
Text string `schema:"t"`
|
||||
Color string `schema:"c"`
|
||||
}
|
||||
|
||||
// On the definition of image watermarking
|
||||
type WaterMarkImageParam struct {
|
||||
Left int `schema:"l"`
|
||||
Top int `schema:"t"`
|
||||
Opacity float64 `schema:"p,omitempty"`
|
||||
URL string `schema:"u"`
|
||||
}
|
||||
|
||||
// About image format conversion definitions
|
||||
type FormatParam struct {
|
||||
Type string `schema:"t"`
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
__Quick Start Code Example:__
|
||||
|
||||
Include a complete example, but the code needs to fill in your own information
|
||||
|
||||
``` go
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/yunify/qingstor-sdk-go/client/image"
|
||||
"github.com/yunify/qingstor-sdk-go/config"
|
||||
qs "github.com/yunify/qingstor-sdk-go/service"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Load your configuration
|
||||
// Replace here with your key pair
|
||||
config, err := config.New("ACCESS_KEY_ID", "SECRET_ACCESS_KEY")
|
||||
checkErr(err)
|
||||
|
||||
// Initialize QingStror Service
|
||||
service, err := qs.Init(config)
|
||||
checkErr(err)
|
||||
|
||||
// Initialize Bucket
|
||||
// Replace here with your bucketName and zoneID
|
||||
bucket, err := service.Bucket("bucketName", "zoneID")
|
||||
checkErr(err)
|
||||
|
||||
// Initialize Image
|
||||
// Replace here with your your ImageName
|
||||
img := image.Init(bucket, "imageName")
|
||||
checkErr(err)
|
||||
|
||||
// Because 0 is an invalid parameter, default not modify
|
||||
imageProcessOutput, err := img.Crop(&image.CropParam{Width: 0}).Process()
|
||||
checkErr(err)
|
||||
testOutput(imageProcessOutput)
|
||||
|
||||
// Rotate the image 90 angles
|
||||
imageProcessOutput, err = img.Rotate(&image.RotateParam{Angle: 90}).Process()
|
||||
checkErr(err)
|
||||
testOutput(imageProcessOutput)
|
||||
|
||||
// Text watermark, Watermark text content, encoded by base64.
|
||||
imageProcessOutput, err = img.WaterMark(&image.WaterMarkParam{
|
||||
Text: "5rC05Y2w5paH5a2X",
|
||||
}).Process()
|
||||
checkErr(err)
|
||||
testOutput(imageProcessOutput)
|
||||
|
||||
// Image watermark, Watermark image url encoded by base64.
|
||||
imageProcessOutput, err = img.WaterMarkImage(&image.WaterMarkImageParam{
|
||||
URL: "aHR0cHM6Ly9wZWszYS5xaW5nc3Rvci5jb20vaW1nLWRvYy1lZy9xaW5jbG91ZC5wbmc",
|
||||
}).Process()
|
||||
checkErr(err)
|
||||
testOutput(imageProcessOutput)
|
||||
|
||||
// Reszie the image with width 300px and height 400 px
|
||||
imageProcessOutput, err = img.Resize(&image.ResizeParam{
|
||||
Width: 300,
|
||||
Height: 400,
|
||||
}).Process()
|
||||
checkErr(err)
|
||||
testOutput(imageProcessOutput)
|
||||
|
||||
// Swap format to jpeg
|
||||
imageProcessOutput, err = img.Format(&image.FormatParam{
|
||||
Type: "jpeg",
|
||||
}).Process()
|
||||
checkErr(err)
|
||||
testOutput(imageProcessOutput)
|
||||
|
||||
// Pipline model
|
||||
// The maximum number of operations in the pipeline is 10
|
||||
imageProcessOutput, err = img.Rotate(&image.RotateParam{
|
||||
Angle: 270,
|
||||
}).Resize(&image.ResizeParam{
|
||||
Width: 300,
|
||||
Height: 300,
|
||||
}).Process()
|
||||
checkErr(err)
|
||||
testOutput(imageProcessOutput)
|
||||
|
||||
// Get the information of the image
|
||||
imageProcessOutput, err = img.Info().Process()
|
||||
checkErr(err)
|
||||
testOutput(imageProcessOutput)
|
||||
|
||||
// Use the original api to rotate the image 90 angles
|
||||
operation := "rotate:a_90"
|
||||
imageProcessOutput, err = bucket.ImageProcess("imageName", &qs.ImageProcessInput{
|
||||
Action: &operation})
|
||||
checkErr(err)
|
||||
defer imageProcessOutput.Close() // Don't forget to close the output otherwise will be leaking http connections
|
||||
testOutput(imageProcessOutput)
|
||||
}
|
||||
|
||||
// *qs.ImageProcessOutput: github.com/yunify/qingstor-sdk-go/service/object.go
|
||||
func testOutput(out *qs.ImageProcessOutput) {
|
||||
log.Println(*out.StatusCode)
|
||||
log.Println(*out.RequestID)
|
||||
log.Println(out.Body)
|
||||
log.Println(*out.ContentLength)
|
||||
}
|
||||
|
||||
func checkErr(err error) {
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
39
vendor/github.com/yunify/qingstor-sdk-go/docs/installation.md
generated
vendored
39
vendor/github.com/yunify/qingstor-sdk-go/docs/installation.md
generated
vendored
@@ -1,39 +0,0 @@
|
||||
# Installation Guide
|
||||
|
||||
## Requirement
|
||||
|
||||
This SDK requires Go 1.6 and higher vendor feature, the dependencies this project uses are included in the `vendor` directory. We use [glide](https://glide.sh) to manage project dependences.
|
||||
|
||||
___Notice:___ _You can also use Go 1.5 with the `GO15VENDOREXPERIMENT=1`._
|
||||
|
||||
## Install from source code
|
||||
|
||||
Use `go get` to download this SDK from GitHub:
|
||||
|
||||
``` bash
|
||||
$ go get -u github.com/yunify/qingstor-sdk-go
|
||||
```
|
||||
|
||||
You can also download a specified version of zipped source code in the repository [releases page](https://github.com/yunify/qingstor-sdk-go/releases). The zipped source code only contains golang source code without unit test files.
|
||||
|
||||
___Examples:___
|
||||
|
||||
- *[qingstor-sdk-go-source-v0.7.1.zip](https://github.com/yunify/qingstor-sdk-go/releases/download/v0.7.1/qingstor-sdk-go-source-v0.7.1.zip)*
|
||||
- *[qingstor-sdk-go-source-with-vendor-v0.7.1.zip](https://github.com/yunify/qingstor-sdk-go/releases/download/v0.7.1/qingstor-sdk-go-source-with-vendor-v0.7.1.zip)*
|
||||
|
||||
## Install from binary release (deprecated)
|
||||
|
||||
After Go 1.7, there's a new feature called Binary-Only Package. It allows distributing packages in binary form without including the source code used for compiling the package. For more information about Binary-Only Package, please read [_GoLang Package Build_](https://golang.org/pkg/go/build/) to know how to use that.
|
||||
|
||||
We provide Linux, macOS and Windows binary packages along with a header files. A header file only contains three lines of content, "//go:binary-only-package" is the first line, the second line is blank, and the second is the package name. There's one header file named "binary.go" for each golang package.
|
||||
|
||||
You can download a specified version of zipped binary release in the repository [releases page](https://github.com/yunify/qingstor-sdk-go/releases).
|
||||
|
||||
___Notice:___ _We didn't provide 386 version binary packages, since there's almost no one using a 386 machine._
|
||||
|
||||
___Examples:___
|
||||
|
||||
- *[qingstor-sdk-go-header-v0.7.1-go-1.7.zip](https://github.com/yunify/qingstor-sdk-go/releases/download/v0.7.1/qingstor-sdk-go-header-v0.7.1-go-1.7.zip)*
|
||||
- *[qingstor-sdk-go-binary-v0.7.1-linux_amd64-go-1.7.zip](https://github.com/yunify/qingstor-sdk-go/releases/download/v0.7.1/qingstor-sdk-go-binary-v0.7.1-linux_amd64-go-1.7.zip)*
|
||||
- *[qingstor-sdk-go-binary-v0.7.1-darwin_amd64-go-1.7.zip](https://github.com/yunify/qingstor-sdk-go/releases/download/v0.7.1/qingstor-sdk-go-binary-v0.7.1-darwin_amd64-go-1.7.zip)*
|
||||
- *[qingstor-sdk-go-binary-v0.7.1-windows_amd64-go-1.7.zip](https://github.com/yunify/qingstor-sdk-go/releases/download/v0.7.1/qingstor-sdk-go-binary-v0.7.1-windows_amd64-go-1.7.zip)*
|
||||
256
vendor/github.com/yunify/qingstor-sdk-go/docs/qingstor_service_usage.md
generated
vendored
256
vendor/github.com/yunify/qingstor-sdk-go/docs/qingstor_service_usage.md
generated
vendored
@@ -1,256 +0,0 @@
|
||||
# QingStor Service Usage Guide
|
||||
|
||||
Import the QingStor and initialize service with a config, and you are ready to use the initialized service. Service only contains one API, and it is "ListBuckets".
|
||||
To use bucket related APIs, you need to initialize a bucket from service using "Bucket" function.
|
||||
|
||||
Each API function take a Input struct and return an Output struct. The Input struct consists of request params, request headers, request elements and request body, and the Output holds the HTTP status code, QingStor request ID, response headers, response elements, response body and error (if error occurred).
|
||||
|
||||
You can use a specified version of a service by import a service package with a date suffix.
|
||||
|
||||
``` go
|
||||
import (
|
||||
// Import the latest version API
|
||||
"github.com/yunify/qingstor-sdk-go/config"
|
||||
qs "github.com/yunify/qingstor-sdk-go/service"
|
||||
qsErrors "github.com/yunify/qingstor-sdk-go/request/errors"
|
||||
)
|
||||
```
|
||||
|
||||
### Code Snippet
|
||||
|
||||
Initialize the QingStor service with a configuration
|
||||
|
||||
``` go
|
||||
userConfig, err := config.NewDefault().LoadUserConfig()
|
||||
if err != nil { panic(err) }
|
||||
qsService, _ := qs.Init(userConfig)
|
||||
```
|
||||
|
||||
List buckets
|
||||
|
||||
``` go
|
||||
qsOutput, err := qsService.ListBuckets(nil)
|
||||
|
||||
// Print the HTTP status code.
|
||||
// Example: 200
|
||||
fmt.Println(qs.IntValue(qsOutput.StatusCode))
|
||||
|
||||
// Print the bucket count.
|
||||
// Example: 5
|
||||
fmt.Println(qs.IntValue(qsOutput.Count))
|
||||
|
||||
// Print the name of first bucket.
|
||||
// Example: "test-bucket"
|
||||
fmt.Println(qs.String(qsOutput.Buckets[0].Name))
|
||||
```
|
||||
|
||||
Initialize a QingStor bucket
|
||||
|
||||
``` go
|
||||
bucket, err := qsService.Bucket("test-bucket", "pek3a")
|
||||
```
|
||||
|
||||
List objects in the bucket
|
||||
|
||||
``` go
|
||||
bOutput, err := bucket.ListObjects(nil)
|
||||
|
||||
// Print the HTTP status code.
|
||||
// Example: 200
|
||||
fmt.Println(qs.IntValue(bOutput.StatusCode))
|
||||
|
||||
// Print the key count.
|
||||
// Example: 7
|
||||
fmt.Println(len(bOutput.Keys))
|
||||
```
|
||||
|
||||
Set ACL of the bucket
|
||||
|
||||
``` go
|
||||
bACLOutput, err := bucket.PutACL(&qs.PutBucketACLInput{
|
||||
ACL: []*service.ACLType{{
|
||||
Grantee: &service.GranteeType{
|
||||
Type: qs.String("user"),
|
||||
ID: qs.String("usr-xxxxxxxx"),
|
||||
},
|
||||
Permission: qs.String("FULL_CONTROL"),
|
||||
}},
|
||||
})
|
||||
|
||||
// Print the HTTP status code.
|
||||
// Example: 200
|
||||
fmt.Println(qs.IntValue(bACLOutput.StatusCode))
|
||||
```
|
||||
|
||||
Put object
|
||||
|
||||
``` go
|
||||
// Open file
|
||||
file, err := os.Open("/tmp/Screenshot.jpg")
|
||||
defer file.Close()
|
||||
|
||||
// Calculate MD5
|
||||
hash := md5.New()
|
||||
io.Copy(hash, file)
|
||||
hashInBytes := hash.Sum(nil)[:16]
|
||||
md5String := hex.EncodeToString(hashInBytes)
|
||||
|
||||
// Put object
|
||||
putOutput, err := bucket.PutObject(
|
||||
"Screenshot.jpg",
|
||||
&service.PutObjectInput{
|
||||
ContentLength: qs.Int(102475), // Obtain automatically if empty
|
||||
ContentType: qs.String("image/jpeg"), // Detect automatically if empty
|
||||
ContentMD5: qs.String(md5String),
|
||||
Body: file,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
// Example: QingStor Error: StatusCode 403, Code "permission_denied"...
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
// Print the HTTP status code.
|
||||
// Example: 201
|
||||
fmt.Println(qs.IntValue(putOutput.StatusCode))
|
||||
}
|
||||
```
|
||||
|
||||
Get object
|
||||
|
||||
``` go
|
||||
getOutput, err := bucket.GetObject(
|
||||
"Screenshot.jpg",
|
||||
&GetObjectInput{},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
// Example: QingStor Error: StatusCode 404, Code "object_not_exists"...
|
||||
fmt.Println(err)
|
||||
if qsErr, ok := err.(*qsErrors.QingStorError); ok {
|
||||
println(qsErr.StatusCode, qsErr.Code)
|
||||
}
|
||||
} else {
|
||||
defer getOutput.Close() // Don't forget to close, otherwise will be leaking connections
|
||||
f, err := os.OpenFile("download_screenshot.jpg", os.O_CREATE|os.O_WRONLY, 0600)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer f.Close()
|
||||
if _, err = io.Copy(f, getOutput.Body); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Delete object
|
||||
|
||||
``` go
|
||||
delOutput, err := bucket.DeleteObject("Screenshot.jpg")
|
||||
|
||||
// Print the HTTP status code.
|
||||
// Example: 204
|
||||
fmt.Println(qs.IntValue(delOutput.StatusCode))
|
||||
```
|
||||
|
||||
Initialize Multipart Upload
|
||||
|
||||
``` go
|
||||
initOutput, err := bucket.InitiateMultipartUpload(
|
||||
"QingCloudInsight.mov",
|
||||
&service.InitiateMultipartUploadInput{
|
||||
ContentType: qs.String("video/quicktime"),
|
||||
},
|
||||
)
|
||||
|
||||
// Print the HTTP status code.
|
||||
// Example: 200
|
||||
fmt.Println(qs.IntValue(initOutput.StatusCode))
|
||||
|
||||
// Print the upload ID.
|
||||
// Example: "9d37dd6ccee643075ca4e597ad65655c"
|
||||
fmt.Println(qs.StringValue(initOutput.UploadID))
|
||||
```
|
||||
|
||||
Upload Multipart
|
||||
|
||||
``` go
|
||||
uploadOutput, err := bucket.UploadMultipart(
|
||||
"QingCloudInsight.mov",
|
||||
&service.UploadMultipartInput{
|
||||
UploadID: qs.String("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"),
|
||||
PartNumber: qs.Int(0),
|
||||
ContentMD5: qs.String(md5String0),
|
||||
Body: file0,
|
||||
},
|
||||
)
|
||||
|
||||
// Print the HTTP status code.
|
||||
// Example: 201
|
||||
fmt.Println(qs.IntValue(uploadOutput.StatusCode))
|
||||
|
||||
uploadOutput, err = bucket.UploadMultipart(
|
||||
"QingCloudInsight.mov",
|
||||
&service.UploadMultipartInput{
|
||||
UploadID: qs.String("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"),
|
||||
PartNumber: qs.Int(1),
|
||||
ContentMD5: qs.String(md5String1),
|
||||
Body: file1,
|
||||
},
|
||||
)
|
||||
|
||||
// Print the HTTP status code.
|
||||
// Example: 201
|
||||
fmt.Println(qs.IntValue(uploadOutput.StatusCode))
|
||||
|
||||
uploadOutput, err = bucket.UploadMultipart(
|
||||
"QingCloudInsight.mov"
|
||||
&service.UploadMultipartInput{
|
||||
UploadID: qs.String("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"),
|
||||
PartNumber: qs.Int(2),
|
||||
ContentMD5: qs.String(md5String2),
|
||||
Body: file2,
|
||||
},
|
||||
)
|
||||
|
||||
// Print the HTTP status code.
|
||||
// Example: 201
|
||||
fmt.Println(qs.IntValue(uploadOutput.StatusCode))
|
||||
```
|
||||
|
||||
Complete Multipart Upload
|
||||
|
||||
``` go
|
||||
completeOutput, err := bucket.CompleteMultipartUpload(
|
||||
"QingCloudInsight.mov",
|
||||
&service.CompleteMultipartUploadInput{
|
||||
UploadID: qs.String("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"),
|
||||
ObjectParts: []*service.ObjectPart{{
|
||||
PartNumber: qs.Int(0),
|
||||
}, {
|
||||
PartNumber: qs.Int(1),
|
||||
}, {
|
||||
PartNumber: qs.Int(2),
|
||||
}},
|
||||
},
|
||||
)
|
||||
|
||||
// Print the HTTP status code.
|
||||
// Example: 200
|
||||
fmt.Println(qs.IntValue(completeOutput.StatusCode))
|
||||
```
|
||||
|
||||
Abort Multipart Upload
|
||||
|
||||
``` go
|
||||
abrtOutput, err := bucket.AbortMultipartUpload(
|
||||
"QingCloudInsight.mov"
|
||||
&service.AbortMultipartUploadInput{
|
||||
UploadID: qs.String("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"),
|
||||
},
|
||||
)
|
||||
|
||||
// Print the error message.
|
||||
// Example: QingStor Error: StatusCode 400, Code...
|
||||
fmt.Println(err)
|
||||
```
|
||||
125
vendor/github.com/yunify/qingstor-sdk-go/request/builder/base_test.go
generated
vendored
125
vendor/github.com/yunify/qingstor-sdk-go/request/builder/base_test.go
generated
vendored
@@ -1,125 +0,0 @@
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Copyright (C) 2016 Yunify, Inc.
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// | you may not use this work except in compliance with the License.
|
||||
// | You may obtain a copy of the License in the LICENSE file, or 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 builder
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yunify/qingstor-sdk-go/config"
|
||||
"github.com/yunify/qingstor-sdk-go/request/data"
|
||||
)
|
||||
|
||||
type FakeProperties struct {
|
||||
A *string `name:"a"`
|
||||
B *string `name:"b"`
|
||||
CD *int `name:"c-d"`
|
||||
}
|
||||
type FakeInput struct {
|
||||
ParamA *string `location:"query" name:"a"`
|
||||
ParamB *string `location:"query" name:"b"`
|
||||
ParamCD *int `location:"query" name:"c_d" default:"1024"`
|
||||
HeaderA *string `location:"headers" name:"A"`
|
||||
HeaderB *time.Time `location:"headers" name:"B" format:"RFC 822"`
|
||||
HeaderCD *int `location:"headers" name:"C-D"`
|
||||
ElementA *string `location:"elements" name:"a"`
|
||||
ElementB *string `location:"elements" name:"b"`
|
||||
ElementCD *int64 `location:"elements" name:"cd"`
|
||||
Body *string `localtion:"body"`
|
||||
}
|
||||
|
||||
func (i *FakeInput) Validate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func String(v string) *string {
|
||||
return &v
|
||||
}
|
||||
|
||||
func Int(v int) *int {
|
||||
return &v
|
||||
}
|
||||
|
||||
func Int64(v int64) *int64 {
|
||||
return &v
|
||||
}
|
||||
|
||||
func Time(v time.Time) *time.Time {
|
||||
return &v
|
||||
}
|
||||
|
||||
func TestBaseBuilder_BuildHTTPRequest(t *testing.T) {
|
||||
conf, err := config.NewDefault()
|
||||
assert.Nil(t, err)
|
||||
|
||||
tz, err := time.LoadLocation("Asia/Shanghai")
|
||||
assert.Nil(t, err)
|
||||
|
||||
builder := BaseBuilder{}
|
||||
operation := &data.Operation{
|
||||
Config: conf,
|
||||
APIName: "This is API name",
|
||||
ServiceName: "Base",
|
||||
Properties: &FakeProperties{
|
||||
A: String("property_a"),
|
||||
B: String("property_b"),
|
||||
CD: Int(0),
|
||||
},
|
||||
RequestMethod: "GET",
|
||||
RequestURI: "/hello/<a>/<c-d>/<b>/world",
|
||||
StatusCodes: []int{
|
||||
200,
|
||||
201,
|
||||
},
|
||||
}
|
||||
inputValue := reflect.ValueOf(&FakeInput{
|
||||
ParamA: String("param_a"),
|
||||
ParamCD: Int(1024),
|
||||
HeaderA: String("header_a"),
|
||||
HeaderB: Time(time.Date(2016, 9, 1, 15, 30, 0, 0, tz)),
|
||||
ElementA: String("element_a"),
|
||||
ElementB: String("element_b"),
|
||||
ElementCD: Int64(0),
|
||||
Body: String("This is body string"),
|
||||
})
|
||||
httpRequest, err := builder.BuildHTTPRequest(operation, &inputValue)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, &map[string]string{
|
||||
"a": "property_a",
|
||||
"b": "property_b",
|
||||
"c-d": "0",
|
||||
}, builder.parsedProperties)
|
||||
assert.Equal(t, &map[string]string{
|
||||
"a": "param_a",
|
||||
"c_d": "1024",
|
||||
}, builder.parsedQuery)
|
||||
assert.Equal(t, &map[string]string{
|
||||
"A": "header_a",
|
||||
"B": "Thu, 01 Sep 2016 07:30:00 GMT",
|
||||
"Content-Type": "application/json",
|
||||
}, builder.parsedHeaders)
|
||||
assert.NotNil(t, httpRequest.Header.Get("Date"))
|
||||
assert.Equal(t, "40", httpRequest.Header.Get("Content-Length"))
|
||||
|
||||
buffer := &bytes.Buffer{}
|
||||
buffer.ReadFrom(httpRequest.Body)
|
||||
httpRequest.Body.Close()
|
||||
assert.Equal(t, "{\"a\":\"element_a\",\"b\":\"element_b\",\"cd\":0}", buffer.String())
|
||||
}
|
||||
83
vendor/github.com/yunify/qingstor-sdk-go/request/builder/qingstor_test.go
generated
vendored
83
vendor/github.com/yunify/qingstor-sdk-go/request/builder/qingstor_test.go
generated
vendored
@@ -1,83 +0,0 @@
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Copyright (C) 2016 Yunify, Inc.
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// | you may not use this work except in compliance with the License.
|
||||
// | You may obtain a copy of the License in the LICENSE file, or 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 builder
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yunify/qingstor-sdk-go/config"
|
||||
"github.com/yunify/qingstor-sdk-go/request/data"
|
||||
)
|
||||
|
||||
type ObjectSubServiceProperties struct {
|
||||
BucketName *string `json:"bucket-name" name:"bucket-name"`
|
||||
ObjectKey *string `json:"object-key" name:"object-key"`
|
||||
Zone *string `json:"zone" name:"zone"`
|
||||
}
|
||||
type GetObjectInput struct {
|
||||
IfMatch *string `json:"If-Match" name:"If-Match" location:"headers"`
|
||||
IfModifiedSince *time.Time `json:"If-Modified-Since" name:"If-Modified-Since" format:"RFC 822" location:"headers"`
|
||||
IfNoneMatch *string `json:"If-None-Match" name:"If-None-Match" location:"headers"`
|
||||
IfUnmodifiedSince time.Time `json:"If-Unmodified-Since" name:"If-Unmodified-Since" format:"RFC 822" location:"headers"`
|
||||
// Specified range of the Object
|
||||
Range *string `json:"Range" name:"Range" location:"headers"`
|
||||
}
|
||||
|
||||
func (i *GetObjectInput) Validate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestQingStorBuilder_BuildHTTPRequest(t *testing.T) {
|
||||
conf, err := config.NewDefault()
|
||||
assert.Nil(t, err)
|
||||
conf.Host = "qingstor.dev"
|
||||
|
||||
tz, err := time.LoadLocation("Asia/Shanghai")
|
||||
assert.Nil(t, err)
|
||||
|
||||
qsBuilder := &QingStorBuilder{}
|
||||
operation := &data.Operation{
|
||||
Config: conf,
|
||||
APIName: "GET Object",
|
||||
ServiceName: "QingStor",
|
||||
Properties: &ObjectSubServiceProperties{
|
||||
BucketName: String("test"),
|
||||
ObjectKey: String("path/to/key.txt"),
|
||||
Zone: String("beta"),
|
||||
},
|
||||
RequestMethod: "GET",
|
||||
RequestURI: "/<bucket-name>/<object-key>",
|
||||
StatusCodes: []int{
|
||||
201,
|
||||
},
|
||||
}
|
||||
inputValue := reflect.ValueOf(&GetObjectInput{
|
||||
IfModifiedSince: Time(time.Date(2016, 9, 1, 15, 30, 0, 0, tz)),
|
||||
Range: String("100-"),
|
||||
})
|
||||
httpRequest, err := qsBuilder.BuildHTTPRequest(operation, &inputValue)
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, httpRequest.Header.Get("Date"))
|
||||
assert.Equal(t, "0", httpRequest.Header.Get("Content-Length"))
|
||||
assert.Equal(t, "", httpRequest.Header.Get("If-Match"))
|
||||
assert.Equal(t, "Thu, 01 Sep 2016 07:30:00 GMT", httpRequest.Header.Get("If-Modified-Since"))
|
||||
assert.Equal(t, "100-", httpRequest.Header.Get("Range"))
|
||||
assert.Equal(t, "https://beta.qingstor.dev:443/test/path/to/key.txt", httpRequest.URL.String())
|
||||
}
|
||||
136
vendor/github.com/yunify/qingstor-sdk-go/request/request_test.go
generated
vendored
136
vendor/github.com/yunify/qingstor-sdk-go/request/request_test.go
generated
vendored
@@ -1,136 +0,0 @@
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Copyright (C) 2016 Yunify, Inc.
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// | you may not use this work except in compliance with the License.
|
||||
// | You may obtain a copy of the License in the LICENSE file, or 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 request
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/yunify/qingstor-sdk-go/config"
|
||||
"github.com/yunify/qingstor-sdk-go/logger"
|
||||
"github.com/yunify/qingstor-sdk-go/request/data"
|
||||
"github.com/yunify/qingstor-sdk-go/request/errors"
|
||||
)
|
||||
|
||||
type SomeActionProperties struct {
|
||||
A *string `json:"a" name:"a"`
|
||||
B *string `json:"b" name:"b"`
|
||||
CD *string `json:"c-d" name:"c-d"`
|
||||
}
|
||||
|
||||
type SomeActionInput struct {
|
||||
Date *time.Time `json:"Date" name:"Date" format:"RFC 822" location:"headers"`
|
||||
IfModifiedSince *time.Time `json:"If-Modified-Since" name:"If-Modified-Since" format:"RFC 822" location:"headers"`
|
||||
Range *string `json:"Range" name:"Range" location:"headers"`
|
||||
UploadID *string `json:"upload_id" name:"upload_id" location:"query"`
|
||||
Count *int `json:"count" name:"count" location:"elements"`
|
||||
}
|
||||
|
||||
func (s *SomeActionInput) Validate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type SomeActionOutput struct {
|
||||
StatusCode *int `location:"statusCode"`
|
||||
Error *errors.QingStorError
|
||||
RequestID *string `location:"requestID"`
|
||||
}
|
||||
|
||||
func String(v string) *string {
|
||||
return &v
|
||||
}
|
||||
|
||||
func Int(v int) *int {
|
||||
return &v
|
||||
}
|
||||
|
||||
func Time(v time.Time) *time.Time {
|
||||
return &v
|
||||
}
|
||||
|
||||
func TestRequestSend(t *testing.T) {
|
||||
conf, err := config.New("ACCESS_KEY_ID", "SECRET_ACCESS_KEY")
|
||||
assert.Nil(t, err)
|
||||
logger.SetLevel("warn")
|
||||
|
||||
operation := &data.Operation{
|
||||
Config: conf,
|
||||
Properties: &SomeActionProperties{
|
||||
A: String("aaa"),
|
||||
B: String("bbb"),
|
||||
CD: String("ccc-ddd"),
|
||||
},
|
||||
APIName: "Some Action",
|
||||
RequestMethod: "GET",
|
||||
RequestURI: "/<a>/<b>/<c-d>",
|
||||
StatusCodes: []int{
|
||||
200, // OK
|
||||
206, // Partial content
|
||||
304, // Not modified
|
||||
412, // Precondition failed
|
||||
},
|
||||
}
|
||||
|
||||
output := &SomeActionOutput{}
|
||||
r, err := New(operation, &SomeActionInput{
|
||||
Date: Time(time.Date(2016, 9, 1, 15, 30, 0, 0, time.UTC)),
|
||||
IfModifiedSince: Time(time.Date(2016, 9, 1, 15, 30, 0, 0, time.UTC)),
|
||||
Range: String("100-"),
|
||||
UploadID: String("0"),
|
||||
Count: Int(23),
|
||||
}, output)
|
||||
assert.Nil(t, err)
|
||||
|
||||
err = r.build()
|
||||
assert.Nil(t, err)
|
||||
|
||||
err = r.sign()
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, r.HTTPRequest.URL.String(), "https://qingstor.com:443/aaa/bbb/ccc-ddd?upload_id=0")
|
||||
assert.Equal(t, r.HTTPRequest.Header.Get("Range"), "100-")
|
||||
assert.Equal(t, r.HTTPRequest.Header.Get("If-Modified-Since"), "Thu, 01 Sep 2016 15:30:00 GMT")
|
||||
assert.Equal(t, r.HTTPRequest.Header.Get("Content-Length"), "12")
|
||||
assert.Equal(t, r.HTTPRequest.Header.Get("Authorization"), "QS ACCESS_KEY_ID:pA7G9qo4iQ6YHu7p4fX9Wcg4V9S6Mcgvz7p/0wEdz78=")
|
||||
|
||||
httpResponse := &http.Response{Header: http.Header{}}
|
||||
httpResponse.StatusCode = 400
|
||||
httpResponse.Header.Set("Content-Type", "application/json")
|
||||
responseString := `{
|
||||
"code": "bad_request",
|
||||
"message": "Invalid argument(s) or invalid argument value(s)",
|
||||
"request_id": "1e588695254aa08cf7a43f612e6ce14b",
|
||||
"url": "http://docs.qingcloud.com/object_storage/api/object/get.html"
|
||||
}`
|
||||
httpResponse.Body = ioutil.NopCloser(bytes.NewReader([]byte(responseString)))
|
||||
assert.Nil(t, err)
|
||||
r.HTTPResponse = httpResponse
|
||||
|
||||
err = r.unpack()
|
||||
assert.NotNil(t, err)
|
||||
|
||||
switch e := err.(type) {
|
||||
case *errors.QingStorError:
|
||||
assert.Equal(t, "bad_request", e.Code)
|
||||
assert.Equal(t, "1e588695254aa08cf7a43f612e6ce14b", e.RequestID)
|
||||
}
|
||||
}
|
||||
127
vendor/github.com/yunify/qingstor-sdk-go/request/signer/qingstor_test.go
generated
vendored
127
vendor/github.com/yunify/qingstor-sdk-go/request/signer/qingstor_test.go
generated
vendored
@@ -1,127 +0,0 @@
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Copyright (C) 2016 Yunify, Inc.
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// | you may not use this work except in compliance with the License.
|
||||
// | You may obtain a copy of the License in the LICENSE file, or 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 signer
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/pengsrc/go-shared/convert"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestQingStorSignerWriteSignature(t *testing.T) {
|
||||
url := "https://qingstor.com/?acl&upload_id=fde133b5f6d932cd9c79bac3c7318da1&part_number=0&other=abc"
|
||||
httpRequest, err := http.NewRequest("GET", url, nil)
|
||||
httpRequest.Header.Set("Date", convert.TimeToString(time.Time{}, convert.RFC822))
|
||||
httpRequest.Header.Set("X-QS-Test-2", "Test 2")
|
||||
httpRequest.Header.Set("X-QS-Test-1", "Test 1")
|
||||
assert.Nil(t, err)
|
||||
|
||||
s := QingStorSigner{
|
||||
AccessKeyID: "ENV_ACCESS_KEY_ID",
|
||||
SecretAccessKey: "ENV_SECRET_ACCESS_KEY",
|
||||
}
|
||||
|
||||
err = s.WriteSignature(httpRequest)
|
||||
assert.Nil(t, err)
|
||||
|
||||
signature := "QS ENV_ACCESS_KEY_ID:bvglZF9iMOv1RaCTxPYWxexmt1UN2m5WKngYnhDEp2c="
|
||||
assert.Equal(t, signature, httpRequest.Header.Get("Authorization"))
|
||||
}
|
||||
|
||||
func TestQingStorSignerWriteSignatureWithXQSDate(t *testing.T) {
|
||||
url := "https://qingstor.com/?acl&upload_id=fde133b5f6d932cd9c79bac3c7318da1&part_number=0&other=abc"
|
||||
httpRequest, err := http.NewRequest("GET", url, nil)
|
||||
httpRequest.Header.Set("Date", convert.TimeToString(time.Time{}, convert.RFC822))
|
||||
httpRequest.Header.Set("X-QS-Date", convert.TimeToString(time.Time{}, convert.RFC822))
|
||||
httpRequest.Header.Set("X-QS-Test-2", "Test 2")
|
||||
httpRequest.Header.Set("X-QS-Test-1", "Test 1")
|
||||
assert.Nil(t, err)
|
||||
|
||||
s := QingStorSigner{
|
||||
AccessKeyID: "ENV_ACCESS_KEY_ID",
|
||||
SecretAccessKey: "ENV_SECRET_ACCESS_KEY",
|
||||
}
|
||||
|
||||
err = s.WriteSignature(httpRequest)
|
||||
assert.Nil(t, err)
|
||||
|
||||
signature := "QS ENV_ACCESS_KEY_ID:qkY+tOMdqfDAVv+ZBtlWeEBxlbyIKaQmj5lQlylENzo="
|
||||
assert.Equal(t, signature, httpRequest.Header.Get("Authorization"))
|
||||
}
|
||||
|
||||
func TestQingStorSignerWriteSignatureChinese(t *testing.T) {
|
||||
url := "https://zone.qingstor.com/bucket-name/中文"
|
||||
httpRequest, err := http.NewRequest("GET", url, nil)
|
||||
httpRequest.Header.Set("Date", convert.TimeToString(time.Time{}, convert.RFC822))
|
||||
assert.Nil(t, err)
|
||||
|
||||
s := QingStorSigner{
|
||||
AccessKeyID: "ENV_ACCESS_KEY_ID",
|
||||
SecretAccessKey: "ENV_SECRET_ACCESS_KEY",
|
||||
}
|
||||
|
||||
err = s.WriteSignature(httpRequest)
|
||||
assert.Nil(t, err)
|
||||
|
||||
signature := "QS ENV_ACCESS_KEY_ID:XsTXX50kzqBf92zLG1aIUIJmZ0hqIHoaHgkumwnV3fs="
|
||||
assert.Equal(t, signature, httpRequest.Header.Get("Authorization"))
|
||||
}
|
||||
|
||||
func TestQingStorSignerWriteQuerySignature(t *testing.T) {
|
||||
url := "https://qingstor.com/?acl&upload_id=fde133b5f6d932cd9c79bac3c7318da1&part_number=0"
|
||||
httpRequest, err := http.NewRequest("GET", url, nil)
|
||||
httpRequest.Header.Set("Date", convert.TimeToString(time.Time{}, convert.RFC822))
|
||||
httpRequest.Header.Set("X-QS-Test-2", "Test 2")
|
||||
httpRequest.Header.Set("X-QS-Test-1", "Test 1")
|
||||
assert.Nil(t, err)
|
||||
|
||||
s := QingStorSigner{
|
||||
AccessKeyID: "ENV_ACCESS_KEY_ID",
|
||||
SecretAccessKey: "ENV_SECRET_ACCESS_KEY",
|
||||
}
|
||||
|
||||
err = s.WriteQuerySignature(httpRequest, 3600)
|
||||
assert.Nil(t, err)
|
||||
|
||||
targetURL := "https://qingstor.com/?acl&upload_id=fde133b5f6d932cd9c79bac3c7318da1&part_number=0&access_key_id=ENV_ACCESS_KEY_ID&expires=3600&signature=GRL3p3NOgHR9CQygASvyo344vdnO1hFke6ZvQ5mDVHM="
|
||||
assert.Equal(t, httpRequest.URL.String(), targetURL)
|
||||
}
|
||||
|
||||
func TestQingStorSignerWriteQuerySignatureWithXQSDate(t *testing.T) {
|
||||
url := "https://qingstor.com/?acl&upload_id=fde133b5f6d932cd9c79bac3c7318da1&part_number=0"
|
||||
httpRequest, err := http.NewRequest("GET", url, nil)
|
||||
httpRequest.Header.Set("Date", convert.TimeToString(time.Time{}, convert.RFC822))
|
||||
httpRequest.Header.Set("X-QS-Date", convert.TimeToString(time.Time{}, convert.RFC822))
|
||||
httpRequest.Header.Set("X-QS-Test-2", "Test 2")
|
||||
httpRequest.Header.Set("X-QS-Test-1", "Test 1")
|
||||
assert.Nil(t, err)
|
||||
|
||||
s := QingStorSigner{
|
||||
AccessKeyID: "ENV_ACCESS_KEY_ID",
|
||||
SecretAccessKey: "ENV_SECRET_ACCESS_KEY",
|
||||
}
|
||||
|
||||
err = s.WriteQuerySignature(httpRequest, 3600)
|
||||
assert.Nil(t, err)
|
||||
|
||||
targetURL := "https://qingstor.com/?acl&upload_id=fde133b5f6d932cd9c79bac3c7318da1&part_number=0&access_key_id=ENV_ACCESS_KEY_ID&expires=3600&signature=plFxMFP1EzKVtdF%2BbApT8rhW9AUAIWfmZcOGH3m27t0="
|
||||
assert.Equal(t, httpRequest.URL.String(), targetURL)
|
||||
}
|
||||
85
vendor/github.com/yunify/qingstor-sdk-go/request/unpacker/base_test.go
generated
vendored
85
vendor/github.com/yunify/qingstor-sdk-go/request/unpacker/base_test.go
generated
vendored
@@ -1,85 +0,0 @@
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Copyright (C) 2016 Yunify, Inc.
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// | you may not use this work except in compliance with the License.
|
||||
// | You may obtain a copy of the License in the LICENSE file, or 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 unpacker
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yunify/qingstor-sdk-go/request/data"
|
||||
)
|
||||
|
||||
func StringValue(v *string) string {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func IntValue(v *int) int {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func Int64Value(v *int64) int64 {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func TimeValue(v *time.Time) time.Time {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
func TestBaseUnpacker_UnpackHTTPRequest(t *testing.T) {
|
||||
type FakeOutput struct {
|
||||
StatusCode *int
|
||||
|
||||
A *string `location:"elements" json:"a" name:"a"`
|
||||
B *string `location:"elements" json:"b" name:"b"`
|
||||
CD *int `location:"elements" json:"cd" name:"cd"`
|
||||
EF *int64 `location:"elements" json:"ef" name:"ef"`
|
||||
}
|
||||
|
||||
httpResponse := &http.Response{Header: http.Header{}}
|
||||
httpResponse.StatusCode = 200
|
||||
httpResponse.Header.Set("Content-Type", "application/json")
|
||||
responseString := `{"a": "el_a", "b": "el_b", "cd": 1024, "ef": 2048}`
|
||||
httpResponse.Body = ioutil.NopCloser(bytes.NewReader([]byte(responseString)))
|
||||
|
||||
output := &FakeOutput{}
|
||||
outputValue := reflect.ValueOf(output)
|
||||
unpacker := BaseUnpacker{}
|
||||
err := unpacker.UnpackHTTPRequest(&data.Operation{}, httpResponse, &outputValue)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 200, IntValue(output.StatusCode))
|
||||
assert.Equal(t, "el_a", StringValue(output.A))
|
||||
assert.Equal(t, "el_b", StringValue(output.B))
|
||||
assert.Equal(t, 1024, IntValue(output.CD))
|
||||
assert.Equal(t, int64(2048), Int64Value(output.EF))
|
||||
}
|
||||
150
vendor/github.com/yunify/qingstor-sdk-go/request/unpacker/qingstor_test.go
generated
vendored
150
vendor/github.com/yunify/qingstor-sdk-go/request/unpacker/qingstor_test.go
generated
vendored
@@ -1,150 +0,0 @@
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Copyright (C) 2016 Yunify, Inc.
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// | you may not use this work except in compliance with the License.
|
||||
// | You may obtain a copy of the License in the LICENSE file, or 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 unpacker
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/yunify/qingstor-sdk-go/request/data"
|
||||
"github.com/yunify/qingstor-sdk-go/request/errors"
|
||||
)
|
||||
|
||||
func TestQingStorUnpacker_UnpackHTTPRequest(t *testing.T) {
|
||||
type Bucket struct {
|
||||
// Created time of the Bucket
|
||||
Created *time.Time `json:"created" name:"created" format:"RFC 822"`
|
||||
// QingCloud Zone ID
|
||||
Location *string `json:"location" name:"location"`
|
||||
// Bucket name
|
||||
Name *string `json:"name" name:"name"`
|
||||
// URL to access the Bucket
|
||||
URL *string `json:"url" name:"url"`
|
||||
}
|
||||
|
||||
type ListBucketsOutput struct {
|
||||
StatusCode *int `location:"statusCode"`
|
||||
Error *errors.QingStorError
|
||||
RequestID *string `location:"requestID"`
|
||||
|
||||
XTestHeader *string `json:"X-Test-Header" name:"X-Test-Header" location:"headers"`
|
||||
XTestTime *time.Time `json:"X-Test-Time" name:"X-Test-Time" format:"RFC 822" location:"headers"`
|
||||
|
||||
// Buckets information
|
||||
Buckets []*Bucket `json:"buckets" name:"buckets"`
|
||||
// Bucket count
|
||||
Count *int `json:"count" name:"count"`
|
||||
}
|
||||
|
||||
httpResponse := &http.Response{Header: http.Header{
|
||||
"X-Test-Header": []string{"test-header"},
|
||||
"X-Test-Time": []string{"Thu, 01 Sep 2016 07:30:00 GMT"},
|
||||
}}
|
||||
httpResponse.StatusCode = 200
|
||||
httpResponse.Header.Set("Content-Type", "application/json")
|
||||
responseString := `{
|
||||
"count": 2,
|
||||
"buckets": [
|
||||
{
|
||||
"name": "test-bucket",
|
||||
"location": "pek3a",
|
||||
"url": "https://test-bucket.pek3a.qingstor.com",
|
||||
"created": "2015-07-11T04:45:57Z"
|
||||
},
|
||||
{
|
||||
"name": "test-photos",
|
||||
"location": "pek3a",
|
||||
"url": "https://test-photos.pek3a.qingstor.com",
|
||||
"created": "2015-07-12T09:40:32Z"
|
||||
}
|
||||
]
|
||||
}`
|
||||
httpResponse.Body = ioutil.NopCloser(bytes.NewReader([]byte(responseString)))
|
||||
|
||||
output := &ListBucketsOutput{}
|
||||
outputValue := reflect.ValueOf(output)
|
||||
unpacker := QingStorUnpacker{}
|
||||
err := unpacker.UnpackHTTPRequest(&data.Operation{}, httpResponse, &outputValue)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "test-header", StringValue(output.XTestHeader))
|
||||
assert.Equal(t, time.Date(2016, 9, 1, 7, 30, 0, 0, time.UTC), TimeValue(output.XTestTime))
|
||||
assert.Equal(t, 2, IntValue(output.Count))
|
||||
assert.Equal(t, "test-bucket", StringValue(output.Buckets[0].Name))
|
||||
assert.Equal(t, "pek3a", StringValue(output.Buckets[0].Location))
|
||||
assert.Equal(t, time.Date(2015, 7, 12, 9, 40, 32, 0, time.UTC), TimeValue(output.Buckets[1].Created))
|
||||
}
|
||||
|
||||
func TestQingStorUnpacker_UnpackHTTPRequestWithError(t *testing.T) {
|
||||
type ListBucketsOutput struct {
|
||||
StatusCode *int `location:"statusCode"`
|
||||
Error *errors.QingStorError
|
||||
RequestID *string `location:"requestID"`
|
||||
}
|
||||
|
||||
httpResponse := &http.Response{Header: http.Header{}}
|
||||
httpResponse.StatusCode = 400
|
||||
httpResponse.Header.Set("Content-Type", "application/json")
|
||||
responseString := `{
|
||||
"code": "bad_request",
|
||||
"message": "Invalid argument(s) or invalid argument value(s)",
|
||||
"request_id": "aa08cf7a43f611e5886952542e6ce14b",
|
||||
"url": "http://docs.qingcloud.com/object_storage/api/bucket/get.html"
|
||||
}`
|
||||
httpResponse.Body = ioutil.NopCloser(bytes.NewReader([]byte(responseString)))
|
||||
|
||||
output := &ListBucketsOutput{}
|
||||
outputValue := reflect.ValueOf(output)
|
||||
unpacker := QingStorUnpacker{}
|
||||
err := unpacker.UnpackHTTPRequest(&data.Operation{}, httpResponse, &outputValue)
|
||||
assert.NotNil(t, err)
|
||||
switch e := err.(type) {
|
||||
case *errors.QingStorError:
|
||||
assert.Equal(t, "bad_request", e.Code)
|
||||
assert.Equal(t, "aa08cf7a43f611e5886952542e6ce14b", e.RequestID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestQingStorUnpacker_UnpackHeadHTTPRequestWithError(t *testing.T) {
|
||||
type HeadBucketsOutput struct {
|
||||
StatusCode *int `location:"statusCode"`
|
||||
Error *errors.QingStorError
|
||||
RequestID *string `location:"requestID"`
|
||||
}
|
||||
|
||||
httpResponse := &http.Response{Header: http.Header{}}
|
||||
httpResponse.StatusCode = 404
|
||||
httpResponse.Header.Set("Content-Type", "application/json")
|
||||
httpResponse.Header.Set("X-QS-Request-ID", "aa08cf7a43f611e5886952542e6ce14b")
|
||||
httpResponse.Body = ioutil.NopCloser(strings.NewReader(""))
|
||||
|
||||
output := &HeadBucketsOutput{}
|
||||
outputValue := reflect.ValueOf(output)
|
||||
unpacker := QingStorUnpacker{}
|
||||
err := unpacker.UnpackHTTPRequest(&data.Operation{}, httpResponse, &outputValue)
|
||||
assert.NotNil(t, err)
|
||||
switch e := err.(type) {
|
||||
case *errors.QingStorError:
|
||||
assert.Equal(t, "aa08cf7a43f611e5886952542e6ce14b", e.RequestID)
|
||||
}
|
||||
}
|
||||
311
vendor/github.com/yunify/qingstor-sdk-go/service/convert_types_test.go
generated
vendored
311
vendor/github.com/yunify/qingstor-sdk-go/service/convert_types_test.go
generated
vendored
@@ -1,311 +0,0 @@
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Copyright (C) 2016 Yunify, Inc.
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// | you may not use this work except in compliance with the License.
|
||||
// | You may obtain a copy of the License in the LICENSE file, or 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 service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var testCasesStringSlice = [][]string{
|
||||
{"a", "b", "c", "d", "e"},
|
||||
{"a", "b", "", "", "e"},
|
||||
}
|
||||
|
||||
func TestStringSlice(t *testing.T) {
|
||||
for idx, in := range testCasesStringSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := StringSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := StringValueSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesStringValueSlice = [][]*string{
|
||||
{String("a"), String("b"), nil, String("c")},
|
||||
}
|
||||
|
||||
func TestStringValueSlice(t *testing.T) {
|
||||
for idx, in := range testCasesStringValueSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := StringValueSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, out[i], "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
out2 := StringSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out2 {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesStringMap = []map[string]string{
|
||||
{"a": "1", "b": "2", "c": "3"},
|
||||
}
|
||||
|
||||
func TestStringMap(t *testing.T) {
|
||||
for idx, in := range testCasesStringMap {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := StringMap(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := StringValueMap(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesBoolSlice = [][]bool{
|
||||
{true, true, false, false},
|
||||
}
|
||||
|
||||
func TestBoolSlice(t *testing.T) {
|
||||
for idx, in := range testCasesBoolSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := BoolSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := BoolValueSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesBoolValueSlice = [][]*bool{}
|
||||
|
||||
func TestBoolValueSlice(t *testing.T) {
|
||||
for idx, in := range testCasesBoolValueSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := BoolValueSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, out[i], "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
out2 := BoolSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out2 {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesBoolMap = []map[string]bool{
|
||||
{"a": true, "b": false, "c": true},
|
||||
}
|
||||
|
||||
func TestBoolMap(t *testing.T) {
|
||||
for idx, in := range testCasesBoolMap {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := BoolMap(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := BoolValueMap(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesIntSlice = [][]int{
|
||||
{1, 2, 3, 4},
|
||||
}
|
||||
|
||||
func TestIntSlice(t *testing.T) {
|
||||
for idx, in := range testCasesIntSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := IntSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := IntValueSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesIntValueSlice = [][]*int{}
|
||||
|
||||
func TestIntValueSlice(t *testing.T) {
|
||||
for idx, in := range testCasesIntValueSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := IntValueSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, out[i], "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
out2 := IntSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out2 {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesIntMap = []map[string]int{
|
||||
{"a": 3, "b": 2, "c": 1},
|
||||
}
|
||||
|
||||
func TestIntMap(t *testing.T) {
|
||||
for idx, in := range testCasesIntMap {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := IntMap(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := IntValueMap(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesTimeSlice = [][]time.Time{
|
||||
{time.Now(), time.Now().AddDate(100, 0, 0)},
|
||||
}
|
||||
|
||||
func TestTimeSlice(t *testing.T) {
|
||||
for idx, in := range testCasesTimeSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := TimeSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := TimeValueSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesTimeValueSlice = [][]*time.Time{}
|
||||
|
||||
func TestTimeValueSlice(t *testing.T) {
|
||||
for idx, in := range testCasesTimeValueSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := TimeValueSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, out[i], "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
out2 := TimeSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out2 {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesTimeMap = []map[string]time.Time{
|
||||
{"a": time.Now().AddDate(-100, 0, 0), "b": time.Now()},
|
||||
}
|
||||
|
||||
func TestTimeMap(t *testing.T) {
|
||||
for idx, in := range testCasesTimeMap {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := TimeMap(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := TimeValueMap(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
8
vendor/github.com/yunify/qingstor-sdk-go/template/manifest.json
generated
vendored
8
vendor/github.com/yunify/qingstor-sdk-go/template/manifest.json
generated
vendored
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"output": {
|
||||
"file_naming": {
|
||||
"style": "snake_case",
|
||||
"extension": ".go"
|
||||
}
|
||||
}
|
||||
}
|
||||
44
vendor/github.com/yunify/qingstor-sdk-go/template/service.tmpl
generated
vendored
44
vendor/github.com/yunify/qingstor-sdk-go/template/service.tmpl
generated
vendored
@@ -1,44 +0,0 @@
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Copyright (C) 2016 Yunify, Inc.
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// | you may not use this work except in compliance with the License.
|
||||
// | You may obtain a copy of the License in the LICENSE file, or 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.
|
||||
// +-------------------------------------------------------------------------
|
||||
|
||||
{{$service := .Data.Service}}
|
||||
|
||||
// Package service provides {{$service.Name}} Service API (API Version {{$service.APIVersion}})
|
||||
package service
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/yunify/qingstor-sdk-go/config"
|
||||
"github.com/yunify/qingstor-sdk-go/request"
|
||||
"github.com/yunify/qingstor-sdk-go/request/data"
|
||||
)
|
||||
|
||||
var _ http.Header
|
||||
|
||||
{{if $service.Description}}// Service {{$service.Description}}{{end}}
|
||||
type Service struct {
|
||||
Config *config.Config
|
||||
}
|
||||
|
||||
// Init initializes a new service.
|
||||
func Init(c *config.Config) (*Service, error) {
|
||||
return &Service{Config: c}, nil
|
||||
}
|
||||
|
||||
{{range $_, $operation := $service.Operations}}
|
||||
{{template "RenderOperation" passThrough $service $operation}}
|
||||
{{end}}
|
||||
402
vendor/github.com/yunify/qingstor-sdk-go/template/shared.tmpl
generated
vendored
402
vendor/github.com/yunify/qingstor-sdk-go/template/shared.tmpl
generated
vendored
@@ -1,402 +0,0 @@
|
||||
{{define "Type"}}
|
||||
{{- $typeName := index . 0 -}}
|
||||
{{- $disablePointer := index . 1 -}}
|
||||
|
||||
{{- if eq $typeName "string" -}}
|
||||
{{- if not $disablePointer -}}*{{- end -}}string
|
||||
{{- else if eq $typeName "boolean" -}}
|
||||
{{- if not $disablePointer -}}*{{- end -}}bool
|
||||
{{- else if eq $typeName "integer" -}}
|
||||
{{- if not $disablePointer -}}*{{- end -}}int
|
||||
{{- else if eq $typeName "long" -}}
|
||||
{{- if not $disablePointer -}}*{{- end -}}int64
|
||||
{{- else if eq $typeName "timestamp" -}}
|
||||
{{- if not $disablePointer -}}*{{- end -}}time.Time
|
||||
{{- else if eq $typeName "binary" -}}
|
||||
io.Reader
|
||||
{{- else if eq $typeName "array" -}}
|
||||
interface{}
|
||||
{{- else if eq $typeName "object" -}}
|
||||
interface{}
|
||||
{{- else if eq $typeName "map" -}}
|
||||
interface{}
|
||||
{{- else if eq $typeName "any" -}}
|
||||
interface{}
|
||||
{{- else -}}
|
||||
*{{$typeName | camelCase}}Type
|
||||
{{- end -}}
|
||||
{{end}}
|
||||
|
||||
{{define "PropertyType"}}
|
||||
{{- $property := index . 0 -}}
|
||||
{{- $disablePointer := index . 1 -}}
|
||||
|
||||
{{- if eq $property.Type "object" -}}
|
||||
{{template "Type" passThrough $property.ExtraType $disablePointer}}
|
||||
{{- else if eq $property.Type "array" -}}
|
||||
[]{{template "Type" passThrough $property.ExtraType $disablePointer}}
|
||||
{{- else if eq $property.Type "map" -}}
|
||||
map[string]{{template "Type" passThrough $property.ExtraType $disablePointer}}
|
||||
{{- else if eq $property.Type "any" -}}
|
||||
{{template "Type" passThrough $property.Type $disablePointer}}
|
||||
{{- else -}}
|
||||
{{template "Type" passThrough $property.Type $disablePointer}}
|
||||
{{- end -}}
|
||||
{{end}}
|
||||
|
||||
{{define "PropertyTags"}}
|
||||
{{- $property := . -}}
|
||||
{{- if $property.IsRequired -}}
|
||||
{{- printf `json:"%s"` ($property.Name | normalized) -}}
|
||||
{{- else -}}
|
||||
{{- printf `json:"%s,omitempty"` ($property.Name | normalized) -}}
|
||||
{{- end -}}
|
||||
{{- printf ` name:"%s"` ($property.Name | normalized) -}}
|
||||
{{- if $property.Format}}
|
||||
{{- printf ` format:"%s"` $property.Format -}}
|
||||
{{- end -}}
|
||||
{{- if $property.Default -}}
|
||||
{{- printf ` default:"%s"` $property.Default -}}
|
||||
{{- end -}}
|
||||
{{end}}
|
||||
|
||||
{{define "PropertyTagsDashConnected"}}
|
||||
{{- $property := . -}}
|
||||
{{- printf `json:"%s"` ($property.Name | dashConnected) -}}
|
||||
{{- printf ` name:"%s"` ($property.Name | dashConnected) -}}
|
||||
{{end}}
|
||||
|
||||
{{define "PropertyExtraTags"}}
|
||||
{{- $propertyExtraTags := . -}}
|
||||
{{- if $propertyExtraTags -}}
|
||||
{{- printf " %s" $propertyExtraTags -}}
|
||||
{{- end -}}
|
||||
{{end}}
|
||||
|
||||
{{define "RenderProperties"}}
|
||||
{{- $customizedType := index . 0 -}}
|
||||
{{- $propertyExtraTags := index . 1 -}}
|
||||
{{- $operationName := index . 2 -}}
|
||||
|
||||
{{range $_, $property := $customizedType.Properties -}}
|
||||
{{if or (ne $operationName "Delete Multiple Objects") (ne $property.ID "Content-MD5") -}}
|
||||
{{if $property.Description -}}
|
||||
// {{$property.Description}}
|
||||
{{end -}}
|
||||
{{if $property.Enum -}}
|
||||
// {{$property.ID | camelCase}}'s available values: {{$property.Enum | commaConnected}}
|
||||
{{end -}}
|
||||
{{$property.ID | camelCase | upperFirst}}{{" " -}}
|
||||
{{template "PropertyType" passThrough $property false}}{{" " -}}
|
||||
`{{template "PropertyTags" $property}}{{template "PropertyExtraTags" $propertyExtraTags}}`{{" " -}}
|
||||
{{if $property.IsRequired -}}
|
||||
// Required
|
||||
{{- end}}
|
||||
{{- end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{define "RenderOperation"}}
|
||||
{{$service := index . 0}}
|
||||
{{$operation := index . 1}}
|
||||
|
||||
{{$belongs := replace $service.Name "QingStor" "Service" -1}}
|
||||
{{$belongs := replace $belongs "Object" "Bucket" -1}}
|
||||
{{$opID := $operation.ID | camelCase}}
|
||||
|
||||
{{$isBucket := eq $service.Name "Bucket"}}
|
||||
{{$isObject := eq $service.Name "Object"}}
|
||||
|
||||
{{$hasQuery := gt (len $operation.Request.Query.Properties) 0}}
|
||||
{{$hasHeaders := gt (len $operation.Request.Headers.Properties) 0}}
|
||||
{{$hasElements := gt (len $operation.Request.Elements.Properties) 0}}
|
||||
{{$hasStringBody := eq $operation.Request.Body.Type "string"}}
|
||||
{{$hasBinaryBody := eq $operation.Request.Body.Type "binary"}}
|
||||
{{$hasInput := or $hasQuery $hasHeaders $hasElements $hasStringBody $hasBinaryBody}}
|
||||
|
||||
{{if $operation.Description -}}
|
||||
{{if eq $belongs "Bucket" -}}
|
||||
// {{replace $opID "Bucket" "" -1}} does {{$operation.Description}}
|
||||
{{else -}}
|
||||
// {{$opID}} does {{$operation.Description}}
|
||||
{{end -}}
|
||||
{{end -}}
|
||||
{{if $operation.DocumentationURL -}}
|
||||
// Documentation URL: {{$operation.DocumentationURL}}
|
||||
{{- end}}
|
||||
{{if eq $belongs "Bucket" -}}
|
||||
func (s *{{$belongs}}) {{replace $opID "Bucket" "" -1 -}}(
|
||||
{{- if $isObject}}objectKey string,{{end -}}
|
||||
{{- if $hasInput}}input *{{$opID}}Input{{end -}}
|
||||
) (*{{$opID}}Output, error) {
|
||||
{{else -}}
|
||||
func (s *{{$belongs}}) {{$opID}}(
|
||||
{{- if $hasInput}}input *{{$opID}}Input{{end -}}
|
||||
) (*{{$opID}}Output, error) {
|
||||
{{end -}}
|
||||
{{if eq $belongs "Bucket" -}}
|
||||
r, x, err := s.{{replace $opID "Bucket" "" -1}}Request(
|
||||
{{- if $isObject}}objectKey,{{end -}}
|
||||
{{- if $hasInput}}input{{end -}}
|
||||
)
|
||||
{{else -}}
|
||||
r, x, err := s.{{$opID}}Request(
|
||||
{{- if $hasInput}}input{{end -}}
|
||||
)
|
||||
{{end}}
|
||||
if err != nil {
|
||||
return x, err
|
||||
}
|
||||
|
||||
err = r.Send()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
requestID := r.HTTPResponse.Header.Get(http.CanonicalHeaderKey("X-QS-Request-ID"))
|
||||
x.RequestID = &requestID
|
||||
|
||||
return x, err
|
||||
}
|
||||
|
||||
{{if $operation.Description -}}
|
||||
{{if eq $belongs "Bucket" -}}
|
||||
// {{replace $opID "Bucket" "" -1}}Request creates request and output object of {{$opID}}.
|
||||
{{else -}}
|
||||
// {{$opID}}Request creates request and output object of {{$opID}}.
|
||||
{{end -}}
|
||||
{{end -}}
|
||||
{{if eq $belongs "Bucket" -}}
|
||||
func (s *{{$belongs}}) {{replace $opID "Bucket" "" -1 -}}Request(
|
||||
{{- if $isObject}}objectKey string,{{end -}}
|
||||
{{- if $hasInput}}input *{{$opID}}Input{{end -}}
|
||||
) (*request.Request, *{{$opID}}Output, error) {
|
||||
{{else -}}
|
||||
func (s *{{$belongs}}) {{$opID}}Request(
|
||||
{{- if $hasInput}}input *{{$opID}}Input{{end -}}
|
||||
) (*request.Request, *{{$opID}}Output, error) {
|
||||
{{end -}}
|
||||
{{if $hasInput}}
|
||||
if input == nil {
|
||||
input = &{{$opID}}Input{}
|
||||
}
|
||||
{{end}}
|
||||
{{$path := $operation.Request.Path}}
|
||||
{{$path := replace $path "{" "<" -1}}
|
||||
{{$path := replace $path "}" ">" -1}}
|
||||
{{$path := dashConnected $path}}
|
||||
|
||||
{{- if ne $belongs "Service"}}
|
||||
properties := *s.Properties
|
||||
{{- end}}
|
||||
{{if eq $service.Name "Object"}}
|
||||
properties.ObjectKey = &objectKey
|
||||
{{end}}
|
||||
|
||||
o := &data.Operation{
|
||||
Config: s.Config,
|
||||
{{- if ne $belongs "Service"}}
|
||||
Properties: &properties,
|
||||
{{- end}}
|
||||
APIName: "{{$operation.Name}}",
|
||||
RequestMethod: "{{$operation.Request.Method}}",
|
||||
RequestURI: "{{$path}}",
|
||||
StatusCodes: []int{
|
||||
{{range $keyStatus, $valueStatus := $operation.Responses -}}
|
||||
{{- if $valueStatus.StatusCode -}}
|
||||
{{$valueStatus.StatusCode.Code}}, // {{$valueStatus.StatusCode.Description}}
|
||||
{{else}}
|
||||
200, // OK
|
||||
{{end -}}
|
||||
{{else}}
|
||||
200, // OK
|
||||
{{end -}}
|
||||
},
|
||||
}
|
||||
|
||||
x := &{{$opID}}Output{}
|
||||
r, err := request.New(o, {{if $hasInput}}input{{else}}nil{{end}}, x)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return r, x, nil
|
||||
}
|
||||
|
||||
{{if $hasInput}}
|
||||
// {{$opID}}Input presents input for {{$opID}}.
|
||||
type {{$opID}}Input struct {
|
||||
{{- if $operation.Request.Query.Properties | len}}
|
||||
{{$data := $operation.Request.Query -}}
|
||||
{{template "RenderProperties" passThrough $data `location:"query"` $operation.Name}}
|
||||
{{end}}
|
||||
|
||||
{{- if $operation.Request.Headers.Properties | len}}
|
||||
{{$data := $operation.Request.Headers -}}
|
||||
{{template "RenderProperties" passThrough $data `location:"headers"` $operation.Name}}
|
||||
{{end}}
|
||||
|
||||
{{- if $operation.Request.Elements.Properties | len}}
|
||||
{{$data := $operation.Request.Elements -}}
|
||||
{{template "RenderProperties" passThrough $data `location:"elements"` $operation.Name}}
|
||||
{{end}}
|
||||
|
||||
{{- if eq $operation.Request.Body.Type "string"}}
|
||||
{{if $operation.Request.Body.Description -}}
|
||||
// {{$operation.Request.Body.Description}}
|
||||
{{- end}}
|
||||
Body string `location:"body"`
|
||||
{{else if eq $operation.Request.Body.Type "binary"}}
|
||||
{{if $operation.Request.Body.Description -}}
|
||||
// {{$operation.Request.Body.Description}}
|
||||
{{- end}}
|
||||
Body io.Reader `location:"body"`
|
||||
{{end}}
|
||||
}
|
||||
|
||||
// Validate validates the input for {{$opID}}.
|
||||
func (v *{{$opID}}Input) Validate() error {
|
||||
{{template "ValidateCustomizedType" passThrough $operation.Request.Query $operation.Name}}
|
||||
{{template "ValidateCustomizedType" passThrough $operation.Request.Headers $operation.Name}}
|
||||
{{template "ValidateCustomizedType" passThrough $operation.Request.Elements $operation.Name}}
|
||||
|
||||
return nil
|
||||
}
|
||||
{{end}}
|
||||
|
||||
// {{$opID}}Output presents output for {{$opID}}.
|
||||
type {{$opID}}Output struct {
|
||||
StatusCode *int `location:"statusCode"`
|
||||
|
||||
RequestID *string `location:"requestID"`
|
||||
{{range $keyStatus, $valueStatus := $operation.Responses -}}
|
||||
{{if eq $valueStatus.Body.Type "string"}}
|
||||
{{if $valueStatus.Body.Description -}}
|
||||
// {{$valueStatus.Body.Description}}
|
||||
{{- end}}
|
||||
Body string `location:"body"`
|
||||
{{else if eq $valueStatus.Body.Type "binary"}}
|
||||
{{if $valueStatus.Body.Description -}}
|
||||
// {{$valueStatus.Body.Description}}
|
||||
{{- end}}
|
||||
Body io.ReadCloser `location:"body"`
|
||||
{{end}}
|
||||
|
||||
{{if $valueStatus.Elements.Properties | len}}
|
||||
{{$data := $valueStatus.Elements}}
|
||||
{{template "RenderProperties" passThrough $data `location:"elements"` $operation.Name}}
|
||||
{{end}}
|
||||
|
||||
{{if $valueStatus.Headers.Properties | len}}
|
||||
{{$data := $valueStatus.Headers}}
|
||||
{{template "RenderProperties" passThrough $data `location:"headers"` $operation.Name}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
}
|
||||
{{range $keyStatus, $valueStatus := $operation.Responses -}}
|
||||
{{if eq $valueStatus.Body.Type "binary"}}
|
||||
// Close will close the underlay body.
|
||||
func (o *{{$opID}}Output) Close() (err error) {
|
||||
if o.Body != nil {
|
||||
return o.Body.Close()
|
||||
}
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{define "SubServiceInitParams"}}
|
||||
{{- $customizedType := index . 0 -}}
|
||||
{{- $disablePointer := index . 1 -}}
|
||||
|
||||
{{- range $_, $property := $customizedType.Properties -}}
|
||||
{{$property.ID | camelCase | lowerFirstWord}}{{" " -}}
|
||||
{{template "PropertyType" passThrough $property $disablePointer}},
|
||||
{{- end -}}
|
||||
{{end}}
|
||||
|
||||
{{define "ValidateCustomizedType"}}
|
||||
{{$customizedType := index . 0}}
|
||||
{{$operationName := index . 1}}
|
||||
|
||||
{{range $_, $property := $customizedType.Properties}}
|
||||
{{if or (ne $operationName "Delete Multiple Objects") (ne $property.ID "Content-MD5") -}}
|
||||
{{$isNormalType := or (eq $property.Type "string") (eq $property.Type "integer")}}
|
||||
{{$isContentLength := eq $property.ID "Content-Length"}}
|
||||
{{if and $isNormalType (not $isContentLength) }}
|
||||
{{if $property.IsRequired }}
|
||||
if v.{{$property.ID | camelCase}} == nil {
|
||||
return errors.ParameterRequiredError{
|
||||
ParameterName: "{{$property.ID | camelCase}}",
|
||||
ParentName: "{{$customizedType.ID | camelCase}}",
|
||||
}
|
||||
}
|
||||
{{end}}
|
||||
{{$parameterName := $property.ID | camelCase | lowerFirstWord}}
|
||||
{{if gt ($property.Enum | len) 0}}
|
||||
if v.{{$property.ID | camelCase}} != nil {
|
||||
{{$parameterName}}ValidValues := []string{
|
||||
{{- $property.Enum | commaConnectedWithQuote -}}
|
||||
}
|
||||
{{$parameterName}}ParameterValue := fmt.Sprint(*v.{{$property.ID | camelCase}})
|
||||
|
||||
{{$parameterName}}IsValid := false
|
||||
for _, value := range {{$parameterName}}ValidValues {
|
||||
if value == {{$parameterName}}ParameterValue {
|
||||
{{$parameterName}}IsValid = true
|
||||
}
|
||||
}
|
||||
|
||||
if !{{$parameterName}}IsValid {
|
||||
return errors.ParameterValueNotAllowedError{
|
||||
ParameterName: "{{$property.ID | camelCase}}",
|
||||
ParameterValue: {{$parameterName}}ParameterValue,
|
||||
AllowedValues: {{$parameterName}}ValidValues,
|
||||
}
|
||||
}
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{if eq $property.Type "object"}}
|
||||
if v.{{$property.ID | camelCase}} != nil {
|
||||
if err := v.{{$property.ID | camelCase}}.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
{{if $property.IsRequired }}
|
||||
if v.{{$property.ID | camelCase}} == nil {
|
||||
return errors.ParameterRequiredError{
|
||||
ParameterName: "{{$property.ID | camelCase}}",
|
||||
ParentName: "{{$customizedType.ID | camelCase}}",
|
||||
}
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{if eq $property.Type "array"}}
|
||||
{{if $property.IsRequired}}
|
||||
if len(v.{{$property.ID | camelCase}}) == 0 {
|
||||
return errors.ParameterRequiredError{
|
||||
ParameterName: "{{$property.ID | camelCase}}",
|
||||
ParentName: "{{$customizedType.ID | camelCase}}",
|
||||
}
|
||||
}
|
||||
{{end}}
|
||||
{{$isNotString := ne $property.ExtraType "string"}}
|
||||
{{$isNotInteger := ne $property.ExtraType "integer"}}
|
||||
{{$isNotTimestamp := ne $property.ExtraType "timestamp"}}
|
||||
{{if and $isNotString $isNotInteger $isNotTimestamp}}
|
||||
if len(v.{{$property.ID | camelCase}}) > 0 {
|
||||
for _, property := range v.{{$property.ID | camelCase}} {
|
||||
if err := property.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
70
vendor/github.com/yunify/qingstor-sdk-go/template/sub_service.tmpl
generated
vendored
70
vendor/github.com/yunify/qingstor-sdk-go/template/sub_service.tmpl
generated
vendored
@@ -1,70 +0,0 @@
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Copyright (C) 2016 Yunify, Inc.
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// | you may not use this work except in compliance with the License.
|
||||
// | You may obtain a copy of the License in the LICENSE file, or 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.
|
||||
// +-------------------------------------------------------------------------
|
||||
|
||||
{{$service := .Data.Service}}
|
||||
{{$subService := index .Data.SubServices .CurrentSubServiceID}}
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/yunify/qingstor-sdk-go/config"
|
||||
"github.com/yunify/qingstor-sdk-go/request"
|
||||
"github.com/yunify/qingstor-sdk-go/request/data"
|
||||
"github.com/yunify/qingstor-sdk-go/request/errors"
|
||||
)
|
||||
|
||||
var _ fmt.State
|
||||
var _ io.Reader
|
||||
var _ http.Header
|
||||
var _ strings.Reader
|
||||
var _ time.Time
|
||||
var _ config.Config
|
||||
|
||||
{{if ne $subService.Name "Object"}}
|
||||
// {{$subService.ID | camelCase}} presents {{$subService.ID | snakeCase}}.
|
||||
type {{$subService.ID | camelCase}} struct {
|
||||
Config *config.Config
|
||||
Properties *Properties
|
||||
}
|
||||
|
||||
// {{$subService.ID | camelCase}} initializes a new {{$subService.ID | snakeCase}}.
|
||||
func (s *Service) {{$subService.ID | camelCase}}(
|
||||
{{- template "SubServiceInitParams" passThrough $subService.Properties true -}}
|
||||
) (*{{$subService.ID | camelCase}}, error) {
|
||||
{{- range $_, $property := $subService.Properties.Properties -}}
|
||||
{{if eq $property.ID "zone"}}
|
||||
{{$property.ID}} = strings.ToLower({{$property.ID}})
|
||||
{{end}}
|
||||
{{- end -}}
|
||||
properties := &Properties{
|
||||
{{range $_, $property := $subService.Properties.Properties -}}
|
||||
{{$property.ID | upperFirst}}: &{{$property.ID}},
|
||||
{{end -}}
|
||||
}
|
||||
|
||||
return &{{$subService.ID | camelCase}}{Config: s.Config, Properties: properties}, nil
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{range $_, $operation := $subService.Operations}}
|
||||
{{template "RenderOperation" passThrough $subService $operation}}
|
||||
{{end}}
|
||||
63
vendor/github.com/yunify/qingstor-sdk-go/template/types.tmpl
generated
vendored
63
vendor/github.com/yunify/qingstor-sdk-go/template/types.tmpl
generated
vendored
@@ -1,63 +0,0 @@
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Copyright (C) 2016 Yunify, Inc.
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// | you may not use this work except in compliance with the License.
|
||||
// | You may obtain a copy of the License in the LICENSE file, or 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.
|
||||
// +-------------------------------------------------------------------------
|
||||
|
||||
{{$service := .Data.Service}}
|
||||
{{$objectSubService := index .Data.SubServices "Object"}}
|
||||
{{$customizedTypes := .Data.CustomizedTypes}}
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/yunify/qingstor-sdk-go/request/errors"
|
||||
)
|
||||
|
||||
// Properties presents the service properties.
|
||||
type Properties struct {
|
||||
{{- template "RenderProperties" passThrough $service.Properties "" "" -}}
|
||||
{{if $objectSubService -}}
|
||||
{{range $_, $p := $objectSubService.Properties.Properties -}}
|
||||
{{- if $p.Description -}}
|
||||
// {{$p.Description}}
|
||||
{{end -}}
|
||||
{{if $p.Enum -}}
|
||||
// {{camelCase $p.ID}}'s available values: {{commaConnected $p.Enum}}
|
||||
{{end -}}
|
||||
{{$p.ID | camelCase | upperFirst}}{{" " -}}
|
||||
{{template "PropertyType" passThrough $p false}}{{" " -}}
|
||||
`{{template "PropertyTagsDashConnected" $p}}`{{" " -}}
|
||||
{{if $p.IsRequired -}}
|
||||
// Required
|
||||
{{- end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
}
|
||||
|
||||
{{range $_, $customizedType := $customizedTypes}}
|
||||
// {{$customizedType.ID | camelCase}}Type presents {{$customizedType.ID | camelCase}}.
|
||||
type {{$customizedType.ID | camelCase}}Type struct {
|
||||
{{template "RenderProperties" passThrough $customizedType "" ""}}
|
||||
}
|
||||
|
||||
// Validate validates the {{$customizedType.ID | camelCase}}.
|
||||
func (v *{{$customizedType.ID | camelCase}}Type) Validate() error {
|
||||
{{template "ValidateCustomizedType" passThrough $customizedType ""}}
|
||||
|
||||
return nil
|
||||
}
|
||||
{{end}}
|
||||
3
vendor/github.com/yunify/qingstor-sdk-go/test/.gitignore
generated
vendored
3
vendor/github.com/yunify/qingstor-sdk-go/test/.gitignore
generated
vendored
@@ -1,3 +0,0 @@
|
||||
# Ignore local config
|
||||
config.yaml
|
||||
test_config.yaml
|
||||
269
vendor/github.com/yunify/qingstor-sdk-go/test/bucket.go
generated
vendored
269
vendor/github.com/yunify/qingstor-sdk-go/test/bucket.go
generated
vendored
@@ -1,269 +0,0 @@
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Copyright (C) 2016 Yunify, Inc.
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// | you may not use this work except in compliance with the License.
|
||||
// | You may obtain a copy of the License in the LICENSE file, or 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 (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/DATA-DOG/godog"
|
||||
"github.com/DATA-DOG/godog/gherkin"
|
||||
|
||||
qsErrors "github.com/yunify/qingstor-sdk-go/request/errors"
|
||||
qs "github.com/yunify/qingstor-sdk-go/service"
|
||||
)
|
||||
|
||||
// BucketFeatureContext provides feature context for bucket.
|
||||
func BucketFeatureContext(s *godog.Suite) {
|
||||
s.Step(`^initialize the bucket$`, initializeTheBucket)
|
||||
s.Step(`^the bucket is initialized$`, theBucketIsInitialized)
|
||||
|
||||
s.Step(`^put bucket$`, putBucketFake)
|
||||
s.Step(`^put bucket status code is (\d+)$`, putBucketStatusCodeIsFake)
|
||||
s.Step(`^put same bucket again$`, putSameBucketAgain)
|
||||
s.Step(`^put same bucket again status code is (\d+)$$`, putSameBucketAgainStatusCodeIs)
|
||||
|
||||
s.Step(`^list objects$`, listObjects)
|
||||
s.Step(`^list objects status code is (\d+)$`, listObjectsStatusCodeIs)
|
||||
s.Step(`^list objects keys count is (\d+)$`, listObjectsKeysCountIs)
|
||||
|
||||
s.Step(`^head bucket$`, headBucket)
|
||||
s.Step(`^head bucket status code is (\d+)$`, headBucketStatusCodeIs)
|
||||
|
||||
s.Step(`^delete bucket$`, deleteBucketFake)
|
||||
s.Step(`^delete bucket status code is (\d+)$`, deleteBucketStatusCodeIsFake)
|
||||
|
||||
s.Step(`^delete multiple objects:$`, deleteMultipleObjects)
|
||||
s.Step(`^delete multiple objects code is (\d+)$`, deleteMultipleObjectsCodeIs)
|
||||
|
||||
s.Step(`^get bucket statistics$`, getBucketStatistics)
|
||||
s.Step(`^get bucket statistics status code is (\d+)$`, getBucketStatisticsStatusCodeIs)
|
||||
s.Step(`^get bucket statistics status is "([^"]*)"$`, getBucketStatisticsStatusIs)
|
||||
|
||||
s.Step(`^an object created by initiate multipart upload$`, anObjectCreatedByInitiateMultipartUpload)
|
||||
s.Step(`^list multipart uploads$`, listMultipartUploads)
|
||||
s.Step(`^list multipart uploads count is (\d+)$`, listMultipartUploadsCountIs)
|
||||
s.Step(`^list multipart uploads with prefix$`, listMultipartUploadsWithPrefix)
|
||||
s.Step(`^list multipart uploads with prefix count is (\d+)$`, listMultipartUploadsWithPrefixCountIs)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var bucket *qs.Bucket
|
||||
|
||||
func initializeTheBucket() error {
|
||||
bucket, err = qsService.Bucket(tc.BucketName, tc.Zone)
|
||||
return err
|
||||
}
|
||||
|
||||
func theBucketIsInitialized() error {
|
||||
if bucket == nil {
|
||||
return errors.New("Bucket is not initialized")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var putBucketOutput *qs.PutBucketOutput
|
||||
|
||||
func putBucket() error {
|
||||
putBucketOutput, err = bucket.Put()
|
||||
return err
|
||||
}
|
||||
|
||||
func putBucketFake() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func putBucketStatusCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(putBucketOutput.StatusCode), statusCode)
|
||||
}
|
||||
|
||||
func putBucketStatusCodeIsFake(_ int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
func putSameBucketAgain() error {
|
||||
_, err = bucket.Put()
|
||||
return nil
|
||||
}
|
||||
|
||||
func putSameBucketAgainStatusCodeIs(statusCode int) error {
|
||||
switch e := err.(type) {
|
||||
case *qsErrors.QingStorError:
|
||||
return checkEqual(e.StatusCode, statusCode)
|
||||
}
|
||||
|
||||
return fmt.Errorf("put same bucket again should get \"%d\"", statusCode)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var listObjectsOutput *qs.ListObjectsOutput
|
||||
|
||||
func listObjects() error {
|
||||
listObjectsOutput, err = bucket.ListObjects(&qs.ListObjectsInput{
|
||||
Delimiter: qs.String("/"),
|
||||
Limit: qs.Int(1000),
|
||||
Prefix: qs.String("Test/"),
|
||||
Marker: qs.String("Next"),
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func listObjectsStatusCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(listObjectsOutput.StatusCode), statusCode)
|
||||
}
|
||||
|
||||
func listObjectsKeysCountIs(count int) error {
|
||||
return checkEqual(len(listObjectsOutput.Keys), count)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var headBucketOutput *qs.HeadBucketOutput
|
||||
|
||||
func headBucket() error {
|
||||
headBucketOutput, err = bucket.Head()
|
||||
return err
|
||||
}
|
||||
|
||||
func headBucketStatusCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(headBucketOutput.StatusCode), statusCode)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var deleteBucketOutput *qs.DeleteBucketOutput
|
||||
|
||||
func deleteBucket() error {
|
||||
deleteBucketOutput, err = bucket.Delete()
|
||||
return err
|
||||
}
|
||||
|
||||
func deleteBucketFake() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteBucketStatusCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(deleteBucketOutput.StatusCode), statusCode)
|
||||
}
|
||||
|
||||
func deleteBucketStatusCodeIsFake(_ int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var deleteMultipleObjectsOutput *qs.DeleteMultipleObjectsOutput
|
||||
|
||||
func deleteMultipleObjects(requestJSON *gherkin.DocString) error {
|
||||
_, err := bucket.PutObject("object_0", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = bucket.PutObject("object_1", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = bucket.PutObject("object_2", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
deleteMultipleObjectsInput := &qs.DeleteMultipleObjectsInput{}
|
||||
err = json.Unmarshal([]byte(requestJSON.Content), deleteMultipleObjectsInput)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
deleteMultipleObjectsOutput, err = bucket.DeleteMultipleObjects(
|
||||
&qs.DeleteMultipleObjectsInput{
|
||||
Objects: deleteMultipleObjectsInput.Objects,
|
||||
Quiet: deleteMultipleObjectsInput.Quiet,
|
||||
},
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func deleteMultipleObjectsCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(deleteMultipleObjectsOutput.StatusCode), statusCode)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var getBucketStatisticsOutput *qs.GetBucketStatisticsOutput
|
||||
|
||||
func getBucketStatistics() error {
|
||||
getBucketStatisticsOutput, err = bucket.GetStatistics()
|
||||
return err
|
||||
}
|
||||
|
||||
func getBucketStatisticsStatusCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(getBucketStatisticsOutput.StatusCode), statusCode)
|
||||
}
|
||||
|
||||
func getBucketStatisticsStatusIs(status string) error {
|
||||
return checkEqual(qs.StringValue(getBucketStatisticsOutput.Status), status)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
var listMultipartUploadsOutputObjectKey = "list_multipart_uploads_object_key"
|
||||
var listMultipartUploadsInitiateOutput *qs.InitiateMultipartUploadOutput
|
||||
var listMultipartUploadsOutput *qs.ListMultipartUploadsOutput
|
||||
|
||||
func anObjectCreatedByInitiateMultipartUpload() error {
|
||||
listMultipartUploadsInitiateOutput, err = bucket.InitiateMultipartUpload(
|
||||
listMultipartUploadsOutputObjectKey, nil,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func listMultipartUploads() error {
|
||||
listMultipartUploadsOutput, err = bucket.ListMultipartUploads(nil)
|
||||
return err
|
||||
}
|
||||
|
||||
func listMultipartUploadsCountIs(count int) error {
|
||||
return checkEqual(len(listMultipartUploadsOutput.Uploads), count)
|
||||
}
|
||||
|
||||
func listMultipartUploadsWithPrefix() error {
|
||||
listMultipartUploadsOutput, err = bucket.ListMultipartUploads(
|
||||
&qs.ListMultipartUploadsInput{
|
||||
Prefix: qs.String(listMultipartUploadsOutputObjectKey),
|
||||
},
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func listMultipartUploadsWithPrefixCountIs(count int) error {
|
||||
_, err = bucket.AbortMultipartUpload(
|
||||
listMultipartUploadsOutputObjectKey, &qs.AbortMultipartUploadInput{
|
||||
UploadID: listMultipartUploadsInitiateOutput.UploadID,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return checkEqual(len(listMultipartUploadsOutput.Uploads), count)
|
||||
}
|
||||
79
vendor/github.com/yunify/qingstor-sdk-go/test/bucket_acl.go
generated
vendored
79
vendor/github.com/yunify/qingstor-sdk-go/test/bucket_acl.go
generated
vendored
@@ -1,79 +0,0 @@
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Copyright (C) 2016 Yunify, Inc.
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// | you may not use this work except in compliance with the License.
|
||||
// | You may obtain a copy of the License in the LICENSE file, or 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 (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/DATA-DOG/godog"
|
||||
"github.com/DATA-DOG/godog/gherkin"
|
||||
|
||||
qs "github.com/yunify/qingstor-sdk-go/service"
|
||||
)
|
||||
|
||||
// BucketACLFeatureContext provides feature context for bucket ACL.
|
||||
func BucketACLFeatureContext(s *godog.Suite) {
|
||||
s.Step(`^put bucket ACL:$`, putBucketACL)
|
||||
s.Step(`^put bucket ACL status code is (\d+)$`, putBucketACLStatusCodeIs)
|
||||
|
||||
s.Step(`^get bucket ACL$`, getBucketACL)
|
||||
s.Step(`^get bucket ACL status code is (\d+)$`, getBucketACLStatusCodeIs)
|
||||
s.Step(`^get bucket ACL should have grantee name "([^"]*)"$`, getBucketACLShouldHaveGranteeName)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var putBucketACLOutput *qs.PutBucketACLOutput
|
||||
|
||||
func putBucketACL(ACLJSONText *gherkin.DocString) error {
|
||||
putBucketACLInput := &qs.PutBucketACLInput{}
|
||||
err = json.Unmarshal([]byte(ACLJSONText.Content), putBucketACLInput)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
putBucketACLOutput, err = bucket.PutACL(putBucketACLInput)
|
||||
return err
|
||||
}
|
||||
|
||||
func putBucketACLStatusCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(putBucketACLOutput.StatusCode), statusCode)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var getBucketACLOutput *qs.GetBucketACLOutput
|
||||
|
||||
func getBucketACL() error {
|
||||
getBucketACLOutput, err = bucket.GetACL()
|
||||
return err
|
||||
}
|
||||
|
||||
func getBucketACLStatusCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(getBucketACLOutput.StatusCode), statusCode)
|
||||
}
|
||||
|
||||
func getBucketACLShouldHaveGranteeName(name string) error {
|
||||
for _, ACL := range getBucketACLOutput.ACL {
|
||||
if qs.StringValue(ACL.Grantee.Name) == name {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("Grantee name \"%s\" not found in bucket ACLs", name)
|
||||
}
|
||||
95
vendor/github.com/yunify/qingstor-sdk-go/test/bucket_cors.go
generated
vendored
95
vendor/github.com/yunify/qingstor-sdk-go/test/bucket_cors.go
generated
vendored
@@ -1,95 +0,0 @@
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Copyright (C) 2016 Yunify, Inc.
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// | you may not use this work except in compliance with the License.
|
||||
// | You may obtain a copy of the License in the LICENSE file, or 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 (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/DATA-DOG/godog"
|
||||
"github.com/DATA-DOG/godog/gherkin"
|
||||
|
||||
qs "github.com/yunify/qingstor-sdk-go/service"
|
||||
)
|
||||
|
||||
// BucketCORSFeatureContext provides feature context for bucket CORS.
|
||||
func BucketCORSFeatureContext(s *godog.Suite) {
|
||||
s.Step(`^put bucket CORS:$`, putBucketCORS)
|
||||
s.Step(`^put bucket CORS status code is (\d+)$`, putBucketCORSStatusCodeIs)
|
||||
|
||||
s.Step(`^get bucket CORS$`, getBucketCORS)
|
||||
s.Step(`^get bucket CORS status code is (\d+)$`, getBucketCORSStatusCodeIs)
|
||||
s.Step(`^get bucket CORS should have allowed origin "([^"]*)"$`, getBucketCORSShouldHaveAllowedOrigin)
|
||||
|
||||
s.Step(`^delete bucket CORS`, deleteBucketCORS)
|
||||
s.Step(`^delete bucket CORS status code is (\d+)$`, deleteBucketCORSStatusCodeIs)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var putBucketCORSOutput *qs.PutBucketCORSOutput
|
||||
|
||||
func putBucketCORS(CORSJSONText *gherkin.DocString) error {
|
||||
putBucketCORSInput := &qs.PutBucketCORSInput{}
|
||||
err = json.Unmarshal([]byte(CORSJSONText.Content), putBucketCORSInput)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
putBucketCORSOutput, err = bucket.PutCORS(putBucketCORSInput)
|
||||
return err
|
||||
}
|
||||
|
||||
func putBucketCORSStatusCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(putBucketCORSOutput.StatusCode), statusCode)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var getBucketCORSOutput *qs.GetBucketCORSOutput
|
||||
|
||||
func getBucketCORS() error {
|
||||
getBucketCORSOutput, err = bucket.GetCORS()
|
||||
return err
|
||||
}
|
||||
|
||||
func getBucketCORSStatusCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(getBucketCORSOutput.StatusCode), statusCode)
|
||||
}
|
||||
|
||||
func getBucketCORSShouldHaveAllowedOrigin(origin string) error {
|
||||
for _, CORSRule := range getBucketCORSOutput.CORSRules {
|
||||
if qs.StringValue(CORSRule.AllowedOrigin) == origin {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("Allowed origin \"%s\" not found in bucket CORS rules", origin)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var deleteBucketCORSOutput *qs.DeleteBucketCORSOutput
|
||||
|
||||
func deleteBucketCORS() error {
|
||||
deleteBucketCORSOutput, err = bucket.DeleteCORS()
|
||||
return err
|
||||
}
|
||||
|
||||
func deleteBucketCORSStatusCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(deleteBucketCORSOutput.StatusCode), statusCode)
|
||||
}
|
||||
88
vendor/github.com/yunify/qingstor-sdk-go/test/bucket_external_mirror.go
generated
vendored
88
vendor/github.com/yunify/qingstor-sdk-go/test/bucket_external_mirror.go
generated
vendored
@@ -1,88 +0,0 @@
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Copyright (C) 2016 Yunify, Inc.
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// | you may not use this work except in compliance with the License.
|
||||
// | You may obtain a copy of the License in the LICENSE file, or 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 (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/DATA-DOG/godog"
|
||||
"github.com/DATA-DOG/godog/gherkin"
|
||||
|
||||
qs "github.com/yunify/qingstor-sdk-go/service"
|
||||
)
|
||||
|
||||
// BucketExternalMirrorFeatureContext provides feature context for bucket external mirror.
|
||||
func BucketExternalMirrorFeatureContext(s *godog.Suite) {
|
||||
s.Step(`^put bucket external mirror:$`, putBucketExternalMirror)
|
||||
s.Step(`^put bucket external mirror status code is (\d+)$`, putBucketExternalMirrorStatusCodeIs)
|
||||
|
||||
s.Step(`^get bucket external mirror$`, getBucketExternalMirror)
|
||||
s.Step(`^get bucket external mirror status code is (\d+)$`, getBucketExternalMirrorStatusCodeIs)
|
||||
s.Step(`^get bucket external mirror should have source_site "([^"]*)"$`, getBucketExternalMirrorShouldHaveSourceSite)
|
||||
|
||||
s.Step(`^delete bucket external mirror$`, deleteBucketExternalMirror)
|
||||
s.Step(`^delete bucket external mirror status code is (\d+)$`, deleteBucketExternalMirrorStatusCodeIs)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var putBucketExternalMirrorOutput *qs.PutBucketExternalMirrorOutput
|
||||
|
||||
func putBucketExternalMirror(ExternalMirrorJSONText *gherkin.DocString) error {
|
||||
putBucketExternalMirrorInput := &qs.PutBucketExternalMirrorInput{}
|
||||
err = json.Unmarshal([]byte(ExternalMirrorJSONText.Content), putBucketExternalMirrorInput)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
putBucketExternalMirrorOutput, err = bucket.PutExternalMirror(putBucketExternalMirrorInput)
|
||||
return err
|
||||
}
|
||||
|
||||
func putBucketExternalMirrorStatusCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(putBucketExternalMirrorOutput.StatusCode), statusCode)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var getBucketExternalMirrorOutput *qs.GetBucketExternalMirrorOutput
|
||||
|
||||
func getBucketExternalMirror() error {
|
||||
getBucketExternalMirrorOutput, err = bucket.GetExternalMirror()
|
||||
return err
|
||||
}
|
||||
|
||||
func getBucketExternalMirrorStatusCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(getBucketExternalMirrorOutput.StatusCode), statusCode)
|
||||
}
|
||||
|
||||
func getBucketExternalMirrorShouldHaveSourceSite(sourceSite string) error {
|
||||
return checkEqual(qs.StringValue(getBucketExternalMirrorOutput.SourceSite), sourceSite)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var deleteBucketExternalMirrorOutput *qs.DeleteBucketExternalMirrorOutput
|
||||
|
||||
func deleteBucketExternalMirror() error {
|
||||
deleteBucketExternalMirrorOutput, err = bucket.DeleteExternalMirror()
|
||||
return err
|
||||
}
|
||||
|
||||
func deleteBucketExternalMirrorStatusCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(deleteBucketExternalMirrorOutput.StatusCode), statusCode)
|
||||
}
|
||||
105
vendor/github.com/yunify/qingstor-sdk-go/test/bucket_policy.go
generated
vendored
105
vendor/github.com/yunify/qingstor-sdk-go/test/bucket_policy.go
generated
vendored
@@ -1,105 +0,0 @@
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Copyright (C) 2016 Yunify, Inc.
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// | you may not use this work except in compliance with the License.
|
||||
// | You may obtain a copy of the License in the LICENSE file, or 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 (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/DATA-DOG/godog"
|
||||
"github.com/DATA-DOG/godog/gherkin"
|
||||
|
||||
qs "github.com/yunify/qingstor-sdk-go/service"
|
||||
)
|
||||
|
||||
// BucketPolicyFeatureContext provides feature context for bucket policy.
|
||||
func BucketPolicyFeatureContext(s *godog.Suite) {
|
||||
s.Step(`^put bucket policy:$`, putBucketPolicy)
|
||||
s.Step(`^put bucket policy status code is (\d+)$`, putBucketPolicyStatusCodeIs)
|
||||
|
||||
s.Step(`^get bucket policy$`, getBucketPolicy)
|
||||
s.Step(`^get bucket policy status code is (\d+)$`, getBucketPolicyStatusCodeIs)
|
||||
s.Step(`^get bucket policy should have Referer "([^"]*)"$`, getBucketPolicyShouldHaveReferer)
|
||||
|
||||
s.Step(`^delete bucket policy$`, deleteBucketPolicy)
|
||||
s.Step(`^delete bucket policy status code is (\d+)$`, deleteBucketPolicyStatusCodeIs)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var putBucketPolicyOutput *qs.PutBucketPolicyOutput
|
||||
|
||||
func putBucketPolicy(PolicyJSONText *gherkin.DocString) error {
|
||||
putBucketPolicyInput := &qs.PutBucketPolicyInput{}
|
||||
err = json.Unmarshal([]byte(PolicyJSONText.Content), putBucketPolicyInput)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(putBucketPolicyInput.Statement) == 1 {
|
||||
putBucketPolicyInput.Statement[0].Resource = qs.StringSlice([]string{tc.BucketName + "/*"})
|
||||
}
|
||||
|
||||
putBucketPolicyOutput, err = bucket.PutPolicy(putBucketPolicyInput)
|
||||
return err
|
||||
}
|
||||
|
||||
func putBucketPolicyStatusCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(putBucketPolicyOutput.StatusCode), statusCode)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var getBucketPolicyOutput *qs.GetBucketPolicyOutput
|
||||
|
||||
func getBucketPolicy() error {
|
||||
getBucketPolicyOutput, err = bucket.GetPolicy()
|
||||
return err
|
||||
}
|
||||
|
||||
func getBucketPolicyStatusCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(getBucketPolicyOutput.StatusCode), statusCode)
|
||||
}
|
||||
|
||||
func getBucketPolicyShouldHaveReferer(compare string) error {
|
||||
for _, statement := range getBucketPolicyOutput.Statement {
|
||||
if statement.Condition != nil &&
|
||||
statement.Condition.StringLike != nil {
|
||||
|
||||
for _, referer := range statement.Condition.StringLike.Referer {
|
||||
if qs.StringValue(referer) == compare {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("Referer \"%s\" not found in bucket policy statement", compare)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var deleteBucketPolicyOutput *qs.DeleteBucketPolicyOutput
|
||||
|
||||
func deleteBucketPolicy() error {
|
||||
deleteBucketPolicyOutput, err = bucket.DeletePolicy()
|
||||
return err
|
||||
}
|
||||
|
||||
func deleteBucketPolicyStatusCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(deleteBucketPolicyOutput.StatusCode), statusCode)
|
||||
}
|
||||
15
vendor/github.com/yunify/qingstor-sdk-go/test/config.yaml.example
generated
vendored
15
vendor/github.com/yunify/qingstor-sdk-go/test/config.yaml.example
generated
vendored
@@ -1,15 +0,0 @@
|
||||
# QingStor services configuration
|
||||
|
||||
access_key_id: ACCESS_KEY_ID
|
||||
secret_access_key: SECRET_ACCESS_KEY
|
||||
|
||||
host: qingstor.com
|
||||
port: 443
|
||||
protocol: https
|
||||
connection_retries: 3
|
||||
|
||||
# Additional User-Agent
|
||||
additional_user_agent: "test/integration"
|
||||
|
||||
# Valid log levels are "debug", "info", "warn", "error", and "fatal".
|
||||
log_level: debug
|
||||
9
vendor/github.com/yunify/qingstor-sdk-go/test/glide.lock
generated
vendored
9
vendor/github.com/yunify/qingstor-sdk-go/test/glide.lock
generated
vendored
@@ -1,9 +0,0 @@
|
||||
hash: a498153ecdb880e9d2a81849ffae311e03bf11570e30d28f64d396d532a066c6
|
||||
updated: 2017-05-22T13:59:32.427609656+08:00
|
||||
imports:
|
||||
- name: github.com/DATA-DOG/godog
|
||||
version: 623ff9946e5c72834c19a019a153b8e3a338a52c
|
||||
subpackages:
|
||||
- colors
|
||||
- gherkin
|
||||
testImports: []
|
||||
4
vendor/github.com/yunify/qingstor-sdk-go/test/glide.yaml
generated
vendored
4
vendor/github.com/yunify/qingstor-sdk-go/test/glide.yaml
generated
vendored
@@ -1,4 +0,0 @@
|
||||
package: github.com/yunify/qingstor-sdk-go/test
|
||||
import:
|
||||
- package: github.com/DATA-DOG/godog
|
||||
version: v0.6.0
|
||||
68
vendor/github.com/yunify/qingstor-sdk-go/test/image.go
generated
vendored
68
vendor/github.com/yunify/qingstor-sdk-go/test/image.go
generated
vendored
@@ -1,68 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/DATA-DOG/godog"
|
||||
|
||||
qs "github.com/yunify/qingstor-sdk-go/service"
|
||||
)
|
||||
|
||||
// ImageFeatureContext provides feature context for image.
|
||||
func ImageFeatureContext(s *godog.Suite) {
|
||||
s.Step(`^image process with key "([^"]*)" and query "([^"]*)"$`, imageProcessWithKeyAndQuery)
|
||||
s.Step(`^image process status code is (\d+)$`, imageProcessStatusCodeIs)
|
||||
|
||||
}
|
||||
|
||||
var imageName string
|
||||
|
||||
func imageProcessWithKeyAndQuery(objectKey, query string) error {
|
||||
if bucket == nil {
|
||||
return errors.New("The bucket is not exist")
|
||||
}
|
||||
file, err := os.Open(path.Join("features", "fixtures", objectKey))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
imageName = objectKey
|
||||
|
||||
_, err = bucket.PutObject(imageName, &qs.PutObjectInput{Body: file})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
output, err := bucket.ImageProcess(objectKey, &qs.ImageProcessInput{
|
||||
Action: &query})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
imageProcessOutput = output
|
||||
return nil
|
||||
}
|
||||
|
||||
var imageProcessOutput *qs.ImageProcessOutput
|
||||
|
||||
func imageProcessStatusCodeIs(statusCode int) error {
|
||||
defer deleteImage(imageName)
|
||||
return checkEqual(qs.IntValue(imageProcessOutput.StatusCode), statusCode)
|
||||
}
|
||||
|
||||
var oOutput *qs.DeleteObjectOutput
|
||||
|
||||
func deleteImage(imageName string) error {
|
||||
|
||||
if bucket == nil {
|
||||
return errors.New("The bucket is not exist")
|
||||
}
|
||||
|
||||
oOutput, err = bucket.DeleteObject(imageName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return checkEqual(qs.IntValue(oOutput.StatusCode), 204)
|
||||
}
|
||||
10
vendor/github.com/yunify/qingstor-sdk-go/test/local_features/upload.feature
generated
vendored
10
vendor/github.com/yunify/qingstor-sdk-go/test/local_features/upload.feature
generated
vendored
@@ -1,10 +0,0 @@
|
||||
@upload
|
||||
Feature: the upload feature
|
||||
|
||||
Scenario: create the uploader
|
||||
When initialize uploader
|
||||
Then uploader is initialized
|
||||
|
||||
Scenario: upload large file
|
||||
When upload a large file
|
||||
Then the large file is uploaded
|
||||
142
vendor/github.com/yunify/qingstor-sdk-go/test/main.go
generated
vendored
142
vendor/github.com/yunify/qingstor-sdk-go/test/main.go
generated
vendored
@@ -1,142 +0,0 @@
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Copyright (C) 2016 Yunify, Inc.
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// | you may not use this work except in compliance with the License.
|
||||
// | You may obtain a copy of the License in the LICENSE file, or 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 (
|
||||
"gopkg.in/yaml.v2"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/DATA-DOG/godog"
|
||||
|
||||
"github.com/yunify/qingstor-sdk-go/config"
|
||||
qsErrors "github.com/yunify/qingstor-sdk-go/request/errors"
|
||||
qs "github.com/yunify/qingstor-sdk-go/service"
|
||||
)
|
||||
|
||||
func main() {
|
||||
setUp()
|
||||
|
||||
context := func(s *godog.Suite) {
|
||||
ServiceFeatureContext(s)
|
||||
BucketFeatureContext(s)
|
||||
BucketACLFeatureContext(s)
|
||||
BucketCORSFeatureContext(s)
|
||||
BucketPolicyFeatureContext(s)
|
||||
BucketExternalMirrorFeatureContext(s)
|
||||
ObjectFeatureContext(s)
|
||||
ObjectMultipartFeatureContext(s)
|
||||
ImageFeatureContext(s)
|
||||
UploadFeatureContext(s)
|
||||
}
|
||||
options := godog.Options{
|
||||
Format: "pretty",
|
||||
Paths: []string{"./features", "./local_features"},
|
||||
Tags: "",
|
||||
}
|
||||
status := godog.RunWithOptions("*", context, options)
|
||||
|
||||
//tearDown()
|
||||
|
||||
os.Exit(status)
|
||||
}
|
||||
|
||||
func setUp() {
|
||||
loadTestConfig()
|
||||
loadConfig()
|
||||
initQingStorService()
|
||||
|
||||
err := initializeTheBucket()
|
||||
checkErrorForExit(err)
|
||||
|
||||
err = theBucketIsInitialized()
|
||||
checkErrorForExit(err)
|
||||
|
||||
//err = putBucket()
|
||||
//checkError(err)
|
||||
|
||||
//err = putBucketStatusCodeIs(201)
|
||||
//checkError(err)
|
||||
}
|
||||
|
||||
func tearDown() {
|
||||
err := deleteBucket()
|
||||
checkError(err)
|
||||
|
||||
err = deleteBucketStatusCodeIs(204)
|
||||
checkError(err)
|
||||
|
||||
retries := 0
|
||||
for retries < tc.MaxRetries {
|
||||
deleteBucketOutput, err = bucket.Delete()
|
||||
checkError(err)
|
||||
if err != nil {
|
||||
switch e := err.(type) {
|
||||
case *qsErrors.QingStorError:
|
||||
if e.Code == "bucket_not_exists" {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
retries++
|
||||
time.Sleep(time.Second * time.Duration(tc.RetryWaitTime))
|
||||
}
|
||||
}
|
||||
|
||||
var err error
|
||||
var tc *testConfig
|
||||
var c *config.Config
|
||||
var qsService *qs.Service
|
||||
|
||||
type testConfig struct {
|
||||
Zone string `json:"zone" yaml:"zone"`
|
||||
BucketName string `json:"bucket_name" yaml:"bucket_name"`
|
||||
|
||||
RetryWaitTime int `json:"retry_wait_time" yaml:"retry_wait_time"`
|
||||
MaxRetries int `json:"max_retries" yaml:"max_retries"`
|
||||
|
||||
Concurrency int `json:"concurrency"`
|
||||
}
|
||||
|
||||
func loadTestConfig() {
|
||||
if tc == nil {
|
||||
configYAML, err := ioutil.ReadFile("./test_config.yaml")
|
||||
checkErrorForExit(err)
|
||||
|
||||
tc = &testConfig{}
|
||||
err = yaml.Unmarshal(configYAML, tc)
|
||||
checkErrorForExit(err)
|
||||
}
|
||||
}
|
||||
|
||||
func loadConfig() {
|
||||
if c == nil {
|
||||
c, err = config.NewDefault()
|
||||
checkErrorForExit(err)
|
||||
|
||||
err = c.LoadConfigFromFilePath("./config.yaml")
|
||||
checkErrorForExit(err)
|
||||
}
|
||||
}
|
||||
|
||||
func initQingStorService() {
|
||||
if qsService == nil {
|
||||
qsService, err = qs.Init(c)
|
||||
checkErrorForExit(err)
|
||||
}
|
||||
}
|
||||
647
vendor/github.com/yunify/qingstor-sdk-go/test/object.go
generated
vendored
647
vendor/github.com/yunify/qingstor-sdk-go/test/object.go
generated
vendored
@@ -1,647 +0,0 @@
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Copyright (C) 2016 Yunify, Inc.
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// | you may not use this work except in compliance with the License.
|
||||
// | You may obtain a copy of the License in the LICENSE file, or 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"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"sync"
|
||||
|
||||
"github.com/DATA-DOG/godog"
|
||||
|
||||
"github.com/yunify/qingstor-sdk-go/request"
|
||||
qs "github.com/yunify/qingstor-sdk-go/service"
|
||||
)
|
||||
|
||||
// ObjectFeatureContext provides feature context for object.
|
||||
func ObjectFeatureContext(s *godog.Suite) {
|
||||
s.Step(`^put object with key "(.{1,})"$`, putObjectWithKey)
|
||||
s.Step(`^put object status code is (\d+)$`, putObjectStatusCodeIs)
|
||||
|
||||
s.Step(`^copy object with key "(.{1,})"$`, copyObjectWithKey)
|
||||
s.Step(`^copy object status code is (\d+)$`, copyObjectStatusCodeIs)
|
||||
|
||||
s.Step(`^move object with key "(.{1,})"$`, moveObjectWithKey)
|
||||
s.Step(`^move object status code is (\d+)$`, moveObjectStatusCodeIs)
|
||||
|
||||
s.Step(`^get object with key "(.{1,})"$`, getObjectWithKey)
|
||||
s.Step(`^get object status code is (\d+)$`, getObjectStatusCodeIs)
|
||||
s.Step(`^get object content length is (\d+)$`, getObjectContentLengthIs)
|
||||
|
||||
s.Step(`^get object "(.{1,})" with content type "(.{1,})"$`, getObjectWithContentType)
|
||||
s.Step(`^get object content type is "(.{1,})"$`, getObjectContentTypeIs)
|
||||
|
||||
s.Step(`^get object "(.{1,})" with query signature$`, getObjectWithQuerySignature)
|
||||
s.Step(`^get object with query signature content length is (\d+)$`, getObjectWithQuerySignatureContentLengthIs)
|
||||
|
||||
s.Step(`^head object with key "(.{1,})"$`, headObjectWithKey)
|
||||
s.Step(`^head object status code is (\d+)$`, headObjectStatusCodeIs)
|
||||
|
||||
s.Step(`^options object "(.{1,})" with method "([^"]*)" and origin "([^"]*)"$`, optionsObjectWithMethodAndOrigin)
|
||||
s.Step(`^options object status code is (\d+)$`, optionsObjectStatusCodeIs)
|
||||
|
||||
s.Step(`^delete object with key "(.{1,})"$`, deleteObjectWithKey)
|
||||
s.Step(`^delete object status code is (\d+)$`, deleteObjectStatusCodeIs)
|
||||
s.Step(`^delete the move object with key "(.{1,})"$`, deleteTheMoveObjectWithKey)
|
||||
s.Step(`^delete the move object status code is (\d+)$`, deleteTheMoveObjectStatusCodeIs)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
var putObjectOutputs []*qs.PutObjectOutput
|
||||
|
||||
func putObjectWithKey(objectKey string) error {
|
||||
_, err = exec.Command("dd", "if=/dev/zero", "of=/tmp/sdk_bin", "bs=1024", "count=1").Output()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove("/tmp/sdk_bin")
|
||||
|
||||
errChan := make(chan error, tc.Concurrency)
|
||||
putObjectOutputs = make([]*qs.PutObjectOutput, tc.Concurrency)
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(tc.Concurrency)
|
||||
for i := 0; i < tc.Concurrency; i++ {
|
||||
go func(index int, errChan chan<- error) {
|
||||
wg.Done()
|
||||
|
||||
file, err := os.Open("/tmp/sdk_bin")
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
hash := md5.New()
|
||||
_, err = io.Copy(hash, file)
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
return
|
||||
}
|
||||
hashInBytes := hash.Sum(nil)[:16]
|
||||
md5String := hex.EncodeToString(hashInBytes)
|
||||
|
||||
//file.Seek(0, io.SeekStart)
|
||||
file.Seek(0, 0)
|
||||
if len(objectKey) > 1000 {
|
||||
objectKey = objectKey[:1000]
|
||||
}
|
||||
putObjectOutput, err := bucket.PutObject(
|
||||
fmt.Sprintf("%s-%d", objectKey, index),
|
||||
&qs.PutObjectInput{
|
||||
ContentType: qs.String("text/plain"),
|
||||
ContentMD5: qs.String(md5String),
|
||||
Body: file,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
return
|
||||
}
|
||||
putObjectOutputs[index] = putObjectOutput
|
||||
errChan <- nil
|
||||
return
|
||||
}(i, errChan)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
for i := 0; i < tc.Concurrency; i++ {
|
||||
err = <-errChan
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func putObjectStatusCodeIs(statusCode int) error {
|
||||
for _, output := range putObjectOutputs {
|
||||
err = checkEqual(qs.IntValue(output.StatusCode), statusCode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
var copyObjectOutputs []*qs.PutObjectOutput
|
||||
|
||||
func copyObjectWithKey(objectKey string) error {
|
||||
errChan := make(chan error, tc.Concurrency)
|
||||
copyObjectOutputs = make([]*qs.PutObjectOutput, tc.Concurrency)
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(tc.Concurrency)
|
||||
for i := 0; i < tc.Concurrency; i++ {
|
||||
go func(index int, errChan chan<- error) {
|
||||
wg.Done()
|
||||
|
||||
if len(objectKey) > 1000 {
|
||||
objectKey = objectKey[:1000]
|
||||
}
|
||||
copyObjectOutput, err := bucket.PutObject(
|
||||
fmt.Sprintf("%s-%d-copy", objectKey, index),
|
||||
&qs.PutObjectInput{
|
||||
XQSCopySource: qs.String(
|
||||
fmt.Sprintf("/%s/%s-%d", tc.BucketName, objectKey, index),
|
||||
),
|
||||
})
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
return
|
||||
}
|
||||
copyObjectOutputs[index] = copyObjectOutput
|
||||
errChan <- nil
|
||||
return
|
||||
}(i, errChan)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
for i := 0; i < tc.Concurrency; i++ {
|
||||
err = <-errChan
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func copyObjectStatusCodeIs(statusCode int) error {
|
||||
for _, output := range copyObjectOutputs {
|
||||
err = checkEqual(qs.IntValue(output.StatusCode), statusCode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
var moveObjectOutputs []*qs.PutObjectOutput
|
||||
|
||||
func moveObjectWithKey(objectKey string) error {
|
||||
errChan := make(chan error, tc.Concurrency)
|
||||
moveObjectOutputs = make([]*qs.PutObjectOutput, tc.Concurrency)
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(tc.Concurrency)
|
||||
for i := 0; i < tc.Concurrency; i++ {
|
||||
go func(index int, errChan chan<- error) {
|
||||
wg.Done()
|
||||
|
||||
if len(objectKey) > 1000 {
|
||||
objectKey = objectKey[:1000]
|
||||
}
|
||||
moveObjectOutput, err := bucket.PutObject(
|
||||
fmt.Sprintf("%s-%d-move", objectKey, index),
|
||||
&qs.PutObjectInput{
|
||||
XQSMoveSource: qs.String(
|
||||
fmt.Sprintf(`/%s/%s-%d-copy`, tc.BucketName, objectKey, index),
|
||||
),
|
||||
})
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
return
|
||||
}
|
||||
moveObjectOutputs[index] = moveObjectOutput
|
||||
errChan <- nil
|
||||
return
|
||||
}(i, errChan)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
for i := 0; i < tc.Concurrency; i++ {
|
||||
err = <-errChan
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func moveObjectStatusCodeIs(statusCode int) error {
|
||||
for _, output := range moveObjectOutputs {
|
||||
err = checkEqual(qs.IntValue(output.StatusCode), statusCode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var getObjectOutputs []*qs.GetObjectOutput
|
||||
|
||||
func getObjectWithKey(objectKey string) error {
|
||||
errChan := make(chan error, tc.Concurrency)
|
||||
getObjectOutputs = make([]*qs.GetObjectOutput, tc.Concurrency)
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(tc.Concurrency)
|
||||
for i := 0; i < tc.Concurrency; i++ {
|
||||
go func(index int, errChan chan<- error) {
|
||||
wg.Done()
|
||||
|
||||
if len(objectKey) > 1000 {
|
||||
objectKey = objectKey[:1000]
|
||||
}
|
||||
getObjectOutput, err := bucket.GetObject(
|
||||
fmt.Sprintf("%s-%d", objectKey, index), nil,
|
||||
)
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
return
|
||||
}
|
||||
getObjectOutputs[index] = getObjectOutput
|
||||
errChan <- nil
|
||||
return
|
||||
}(i, errChan)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
for i := 0; i < tc.Concurrency; i++ {
|
||||
err = <-errChan
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getObjectStatusCodeIs(statusCode int) error {
|
||||
for _, output := range getObjectOutputs {
|
||||
err = checkEqual(qs.IntValue(output.StatusCode), statusCode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getObjectContentLengthIs(length int) error {
|
||||
buffer := &bytes.Buffer{}
|
||||
for _, output := range getObjectOutputs {
|
||||
buffer.Truncate(0)
|
||||
buffer.ReadFrom(output.Body)
|
||||
err = checkEqual(len(buffer.Bytes())*1024, length)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var getObjectWithContentTypeRequests []*request.Request
|
||||
|
||||
func getObjectWithContentType(objectKey, contentType string) error {
|
||||
errChan := make(chan error, tc.Concurrency)
|
||||
getObjectWithContentTypeRequests = make([]*request.Request, tc.Concurrency)
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(tc.Concurrency)
|
||||
for i := 0; i < tc.Concurrency; i++ {
|
||||
go func(index int, errChan chan<- error) {
|
||||
wg.Done()
|
||||
|
||||
if len(objectKey) > 1000 {
|
||||
objectKey = objectKey[:1000]
|
||||
}
|
||||
getObjectWithContentTypeRequest, _, err := bucket.GetObjectRequest(
|
||||
fmt.Sprintf("%s-%d", objectKey, index),
|
||||
&qs.GetObjectInput{
|
||||
ResponseContentType: qs.String(contentType),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
return
|
||||
}
|
||||
err = getObjectWithContentTypeRequest.Send()
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
return
|
||||
}
|
||||
err = getObjectWithContentTypeRequest.Send()
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
return
|
||||
}
|
||||
getObjectWithContentTypeRequests[index] = getObjectWithContentTypeRequest
|
||||
errChan <- nil
|
||||
return
|
||||
}(i, errChan)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
for i := 0; i < tc.Concurrency; i++ {
|
||||
err = <-errChan
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getObjectContentTypeIs(contentType string) error {
|
||||
for _, r := range getObjectWithContentTypeRequests {
|
||||
err = checkEqual(r.HTTPResponse.Header.Get("Content-Type"), contentType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var getObjectWithQuerySignatureURLs []string
|
||||
|
||||
func getObjectWithQuerySignature(objectKey string) error {
|
||||
errChan := make(chan error, tc.Concurrency)
|
||||
getObjectWithQuerySignatureURLs = make([]string, tc.Concurrency)
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(tc.Concurrency)
|
||||
for i := 0; i < tc.Concurrency; i++ {
|
||||
go func(index int, errChan chan<- error) {
|
||||
wg.Done()
|
||||
|
||||
if len(objectKey) > 1000 {
|
||||
objectKey = objectKey[:1000]
|
||||
}
|
||||
r, _, err := bucket.GetObjectRequest(
|
||||
fmt.Sprintf("%s-%d", objectKey, index), nil,
|
||||
)
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
return
|
||||
}
|
||||
err = r.Build()
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
return
|
||||
}
|
||||
err = r.SignQuery(10)
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
return
|
||||
}
|
||||
|
||||
getObjectWithQuerySignatureURLs[index] = r.HTTPRequest.URL.String()
|
||||
errChan <- nil
|
||||
return
|
||||
}(i, errChan)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
for i := 0; i < tc.Concurrency; i++ {
|
||||
err = <-errChan
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getObjectWithQuerySignatureContentLengthIs(length int) error {
|
||||
buffer := &bytes.Buffer{}
|
||||
for _, url := range getObjectWithQuerySignatureURLs {
|
||||
out, err := http.Get(url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buffer.Truncate(0)
|
||||
buffer.ReadFrom(out.Body)
|
||||
out.Body.Close()
|
||||
err = checkEqual(len(buffer.Bytes())*1024, length)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var headObjectOutputs []*qs.HeadObjectOutput
|
||||
|
||||
func headObjectWithKey(objectKey string) error {
|
||||
errChan := make(chan error, tc.Concurrency)
|
||||
headObjectOutputs = make([]*qs.HeadObjectOutput, tc.Concurrency)
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(tc.Concurrency)
|
||||
for i := 0; i < tc.Concurrency; i++ {
|
||||
go func(index int, errChan chan<- error) {
|
||||
wg.Done()
|
||||
|
||||
if len(objectKey) > 1000 {
|
||||
objectKey = objectKey[:1000]
|
||||
}
|
||||
headObjectOutput, err := bucket.HeadObject(
|
||||
fmt.Sprintf("%s-%d", objectKey, index), nil,
|
||||
)
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
return
|
||||
}
|
||||
headObjectOutputs[index] = headObjectOutput
|
||||
errChan <- nil
|
||||
return
|
||||
}(i, errChan)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
for i := 0; i < tc.Concurrency; i++ {
|
||||
err = <-errChan
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func headObjectStatusCodeIs(statusCode int) error {
|
||||
for _, output := range headObjectOutputs {
|
||||
err = checkEqual(qs.IntValue(output.StatusCode), statusCode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var optionsObjectOutputs []*qs.OptionsObjectOutput
|
||||
|
||||
func optionsObjectWithMethodAndOrigin(objectKey, method, origin string) error {
|
||||
errChan := make(chan error, tc.Concurrency)
|
||||
optionsObjectOutputs = make([]*qs.OptionsObjectOutput, tc.Concurrency)
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(tc.Concurrency)
|
||||
for i := 0; i < tc.Concurrency; i++ {
|
||||
go func(index int, errChan chan<- error) {
|
||||
wg.Done()
|
||||
|
||||
if len(objectKey) > 1000 {
|
||||
objectKey = objectKey[:1000]
|
||||
}
|
||||
optionsObjectOutput, err := bucket.OptionsObject(
|
||||
fmt.Sprintf("%s-%d", objectKey, index),
|
||||
&qs.OptionsObjectInput{
|
||||
AccessControlRequestMethod: qs.String(method),
|
||||
Origin: qs.String(origin),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
return
|
||||
}
|
||||
optionsObjectOutputs[index] = optionsObjectOutput
|
||||
errChan <- nil
|
||||
return
|
||||
}(i, errChan)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
for i := 0; i < tc.Concurrency; i++ {
|
||||
err = <-errChan
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func optionsObjectStatusCodeIs(statusCode int) error {
|
||||
for _, output := range optionsObjectOutputs {
|
||||
err = checkEqual(qs.IntValue(output.StatusCode), statusCode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var deleteObjectOutputs []*qs.DeleteObjectOutput
|
||||
var deleteTheMoveObjectOutputs []*qs.DeleteObjectOutput
|
||||
|
||||
func deleteObjectWithKey(objectKey string) error {
|
||||
errChan := make(chan error, tc.Concurrency)
|
||||
deleteObjectOutputs = make([]*qs.DeleteObjectOutput, tc.Concurrency)
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(tc.Concurrency)
|
||||
for i := 0; i < tc.Concurrency; i++ {
|
||||
go func(index int, errChan chan<- error) {
|
||||
wg.Done()
|
||||
|
||||
if len(objectKey) > 1000 {
|
||||
objectKey = objectKey[:1000]
|
||||
}
|
||||
deleteObjectOutput, err := bucket.DeleteObject(
|
||||
fmt.Sprintf("%s-%d", objectKey, index),
|
||||
)
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
return
|
||||
}
|
||||
deleteObjectOutputs[index] = deleteObjectOutput
|
||||
errChan <- nil
|
||||
return
|
||||
}(i, errChan)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
for i := 0; i < tc.Concurrency; i++ {
|
||||
err = <-errChan
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteObjectStatusCodeIs(statusCode int) error {
|
||||
for _, output := range deleteObjectOutputs {
|
||||
err = checkEqual(qs.IntValue(output.StatusCode), statusCode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteTheMoveObjectWithKey(objectKey string) error {
|
||||
errChan := make(chan error, tc.Concurrency)
|
||||
deleteTheMoveObjectOutputs = make([]*qs.DeleteObjectOutput, tc.Concurrency)
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(tc.Concurrency)
|
||||
for i := 0; i < tc.Concurrency; i++ {
|
||||
go func(index int, errChan chan<- error) {
|
||||
wg.Done()
|
||||
|
||||
if len(objectKey) > 1000 {
|
||||
objectKey = objectKey[:1000]
|
||||
}
|
||||
deleteTheMoveObjectOutput, err := bucket.DeleteObject(
|
||||
fmt.Sprintf("%s-%d-move", objectKey, index),
|
||||
)
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
return
|
||||
}
|
||||
deleteTheMoveObjectOutputs[index] = deleteTheMoveObjectOutput
|
||||
errChan <- nil
|
||||
return
|
||||
}(i, errChan)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
for i := 0; i < tc.Concurrency; i++ {
|
||||
err = <-errChan
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteTheMoveObjectStatusCodeIs(statusCode int) error {
|
||||
for _, output := range deleteTheMoveObjectOutputs {
|
||||
err = checkEqual(qs.IntValue(output.StatusCode), statusCode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
238
vendor/github.com/yunify/qingstor-sdk-go/test/object_multipart.go
generated
vendored
238
vendor/github.com/yunify/qingstor-sdk-go/test/object_multipart.go
generated
vendored
@@ -1,238 +0,0 @@
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Copyright (C) 2016 Yunify, Inc.
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// | you may not use this work except in compliance with the License.
|
||||
// | You may obtain a copy of the License in the LICENSE file, or 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 (
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/DATA-DOG/godog"
|
||||
|
||||
"fmt"
|
||||
"github.com/yunify/qingstor-sdk-go/request/errors"
|
||||
qs "github.com/yunify/qingstor-sdk-go/service"
|
||||
)
|
||||
|
||||
// ObjectMultipartFeatureContext provides feature context for object multipart.
|
||||
func ObjectMultipartFeatureContext(s *godog.Suite) {
|
||||
s.Step(`^initiate multipart upload with key "(.{1,})"$`, initiateMultipartUploadWithKey)
|
||||
s.Step(`^initiate multipart upload status code is (\d+)$`, initiateMultipartUploadStatusCodeIs)
|
||||
|
||||
s.Step(`^upload the first part with key "(.{1,})"$`, uploadTheFirstPartWithKey)
|
||||
s.Step(`^upload the first part status code is (\d+)$`, uploadTheFirstPartStatusCodeIs)
|
||||
s.Step(`^upload the second part with key "(.{1,})"$`, uploadTheSecondPartWithKey)
|
||||
s.Step(`^upload the second part status code is (\d+)$`, uploadTheSecondPartStatusCodeIs)
|
||||
s.Step(`^upload the third part with key "(.{1,})"$`, uploadTheThirdPartWithKey)
|
||||
s.Step(`^upload the third part status code is (\d+)$`, uploadTheThirdPartStatusCodeIs)
|
||||
|
||||
s.Step(`^list multipart with key "(.{1,})"$`, listMultipartWithKey)
|
||||
s.Step(`^list multipart status code is (\d+)$`, listMultipartStatusCodeIs)
|
||||
s.Step(`^list multipart object parts count is (\d+)$`, listMultipartObjectPartsCountIs)
|
||||
|
||||
s.Step(`^complete multipart upload with key "(.{1,})"$`, completeMultipartUploadWithKey)
|
||||
s.Step(`^complete multipart upload status code is (\d+)$`, completeMultipartUploadStatusCodeIs)
|
||||
|
||||
s.Step(`^abort multipart upload with key "(.{1,})"$`, abortMultipartUploadWithKey)
|
||||
s.Step(`^abort multipart upload status code is (\d+)$`, abortMultipartUploadStatusCodeIs)
|
||||
|
||||
s.Step(`^delete the multipart object with key "(.{1,})"$`, deleteTheMultipartObjectWithKey)
|
||||
s.Step(`^delete the multipart object status code is (\d+)$`, deleteTheMultipartObjectStatusCodeIs)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var initiateMultipartUploadOutput *qs.InitiateMultipartUploadOutput
|
||||
|
||||
func initiateMultipartUploadWithKey(objectKey string) error {
|
||||
initiateMultipartUploadOutput, err = bucket.InitiateMultipartUpload(
|
||||
objectKey,
|
||||
&qs.InitiateMultipartUploadInput{
|
||||
ContentType: qs.String("text/plain"),
|
||||
},
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func initiateMultipartUploadStatusCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(initiateMultipartUploadOutput.StatusCode), statusCode)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var uploadTheFirstPartOutput *qs.UploadMultipartOutput
|
||||
var uploadTheSecondPartOutput *qs.UploadMultipartOutput
|
||||
var uploadTheThirdPartOutput *qs.UploadMultipartOutput
|
||||
|
||||
func uploadTheFirstPartWithKey(objectKey string) error {
|
||||
_, err = exec.Command("dd", "if=/dev/zero", "of=/tmp/sdk_bin_part_0", "bs=1048576", "count=5").Output()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove("/tmp/sdk_bin_part_0")
|
||||
|
||||
file, err := os.Open("/tmp/sdk_bin_part_0")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
uploadTheFirstPartOutput, err = bucket.UploadMultipart(
|
||||
objectKey,
|
||||
&qs.UploadMultipartInput{
|
||||
UploadID: initiateMultipartUploadOutput.UploadID,
|
||||
PartNumber: qs.Int(0),
|
||||
Body: file,
|
||||
},
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func uploadTheFirstPartStatusCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(uploadTheFirstPartOutput.StatusCode), statusCode)
|
||||
}
|
||||
|
||||
func uploadTheSecondPartWithKey(objectKey string) error {
|
||||
_, err = exec.Command("dd", "if=/dev/zero", "of=/tmp/sdk_bin_part_1", "bs=1048576", "count=4").Output()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove("/tmp/sdk_bin_part_1")
|
||||
|
||||
file, err := os.Open("/tmp/sdk_bin_part_1")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
uploadTheSecondPartOutput, err = bucket.UploadMultipart(
|
||||
objectKey,
|
||||
&qs.UploadMultipartInput{
|
||||
UploadID: initiateMultipartUploadOutput.UploadID,
|
||||
PartNumber: qs.Int(1),
|
||||
Body: file,
|
||||
},
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func uploadTheSecondPartStatusCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(uploadTheSecondPartOutput.StatusCode), statusCode)
|
||||
}
|
||||
|
||||
func uploadTheThirdPartWithKey(objectKey string) error {
|
||||
_, err = exec.Command("dd", "if=/dev/zero", "of=/tmp/sdk_bin_part_2", "bs=1048576", "count=3").Output()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove("/tmp/sdk_bin_part_2")
|
||||
|
||||
file, err := os.Open("/tmp/sdk_bin_part_2")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
uploadTheThirdPartOutput, err = bucket.UploadMultipart(
|
||||
objectKey,
|
||||
&qs.UploadMultipartInput{
|
||||
UploadID: initiateMultipartUploadOutput.UploadID,
|
||||
PartNumber: qs.Int(2),
|
||||
Body: file,
|
||||
},
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func uploadTheThirdPartStatusCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(uploadTheThirdPartOutput.StatusCode), statusCode)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var listMultipartOutput *qs.ListMultipartOutput
|
||||
|
||||
func listMultipartWithKey(objectKey string) error {
|
||||
listMultipartOutput, err = bucket.ListMultipart(
|
||||
objectKey,
|
||||
&qs.ListMultipartInput{
|
||||
UploadID: initiateMultipartUploadOutput.UploadID,
|
||||
},
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func listMultipartStatusCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(listMultipartOutput.StatusCode), statusCode)
|
||||
}
|
||||
|
||||
func listMultipartObjectPartsCountIs(count int) error {
|
||||
return checkEqual(len(listMultipartOutput.ObjectParts), count)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var completeMultipartUploadOutput *qs.CompleteMultipartUploadOutput
|
||||
|
||||
func completeMultipartUploadWithKey(objectKey string) error {
|
||||
completeMultipartUploadOutput, err = bucket.CompleteMultipartUpload(
|
||||
objectKey,
|
||||
&qs.CompleteMultipartUploadInput{
|
||||
UploadID: initiateMultipartUploadOutput.UploadID,
|
||||
ETag: qs.String(`"4072783b8efb99a9e5817067d68f61c6"`),
|
||||
ObjectParts: listMultipartOutput.ObjectParts,
|
||||
},
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func completeMultipartUploadStatusCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(completeMultipartUploadOutput.StatusCode), statusCode)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
func abortMultipartUploadWithKey(objectKey string) error {
|
||||
_, err = bucket.AbortMultipartUpload(
|
||||
objectKey,
|
||||
&qs.AbortMultipartUploadInput{
|
||||
UploadID: initiateMultipartUploadOutput.UploadID,
|
||||
},
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
func abortMultipartUploadStatusCodeIs(statusCode int) error {
|
||||
switch e := err.(type) {
|
||||
case *errors.QingStorError:
|
||||
return checkEqual(e.StatusCode, statusCode)
|
||||
}
|
||||
|
||||
return fmt.Errorf("abort multipart upload should get \"%d\"", statusCode)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var deleteTheMultipartObjectOutput *qs.DeleteObjectOutput
|
||||
|
||||
func deleteTheMultipartObjectWithKey(objectKey string) error {
|
||||
deleteTheMultipartObjectOutput, err = bucket.DeleteObject(objectKey)
|
||||
return err
|
||||
}
|
||||
|
||||
func deleteTheMultipartObjectStatusCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(deleteTheMultipartObjectOutput.StatusCode), statusCode)
|
||||
}
|
||||
60
vendor/github.com/yunify/qingstor-sdk-go/test/service.go
generated
vendored
60
vendor/github.com/yunify/qingstor-sdk-go/test/service.go
generated
vendored
@@ -1,60 +0,0 @@
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Copyright (C) 2016 Yunify, Inc.
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// | you may not use this work except in compliance with the License.
|
||||
// | You may obtain a copy of the License in the LICENSE file, or 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 (
|
||||
"errors"
|
||||
|
||||
"github.com/DATA-DOG/godog"
|
||||
|
||||
qs "github.com/yunify/qingstor-sdk-go/service"
|
||||
)
|
||||
|
||||
// ServiceFeatureContext provides feature context for service.
|
||||
func ServiceFeatureContext(s *godog.Suite) {
|
||||
s.Step(`^initialize QingStor service$`, initializeQingStorService)
|
||||
s.Step(`^the QingStor service is initialized$`, theQingStorServiceIsInitialized)
|
||||
|
||||
s.Step(`^list buckets$`, listBuckets)
|
||||
s.Step(`^list buckets status code is (\d+)$`, listBucketsStatusCodeIs)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
func initializeQingStorService() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func theQingStorServiceIsInitialized() error {
|
||||
if qsService == nil {
|
||||
return errors.New("QingStor service is not initialized")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
var listBucketsOutput *qs.ListBucketsOutput
|
||||
|
||||
func listBuckets() error {
|
||||
listBucketsOutput, err = qsService.ListBuckets(nil)
|
||||
return err
|
||||
}
|
||||
|
||||
func listBucketsStatusCodeIs(statusCode int) error {
|
||||
return checkEqual(qs.IntValue(listBucketsOutput.StatusCode), statusCode)
|
||||
}
|
||||
9
vendor/github.com/yunify/qingstor-sdk-go/test/test_config.yaml.example
generated
vendored
9
vendor/github.com/yunify/qingstor-sdk-go/test/test_config.yaml.example
generated
vendored
@@ -1,9 +0,0 @@
|
||||
# Test configurations
|
||||
|
||||
zone: pek3a
|
||||
bucket_name: access-key-id
|
||||
|
||||
retry_wait_time: 3 # seconds
|
||||
max_retries: 60
|
||||
|
||||
concurrency: 1
|
||||
67
vendor/github.com/yunify/qingstor-sdk-go/test/upload.go
generated
vendored
67
vendor/github.com/yunify/qingstor-sdk-go/test/upload.go
generated
vendored
@@ -1,67 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/DATA-DOG/godog"
|
||||
"github.com/yunify/qingstor-sdk-go/client/upload"
|
||||
)
|
||||
|
||||
var uploader *upload.Uploader
|
||||
|
||||
// UploadFeatureContext provides feature context for upload.
|
||||
func UploadFeatureContext(s *godog.Suite) {
|
||||
s.Step("initialize uploader$", initializeUploader)
|
||||
s.Step("uploader is initialized$", uploaderIsInitialized)
|
||||
|
||||
s.Step("upload a large file$", uploadLargeFile)
|
||||
s.Step("the large file is uploaded$", largeFileIsUploaded)
|
||||
}
|
||||
|
||||
var fd *os.File
|
||||
|
||||
func initializeUploader() error {
|
||||
uploadSetup()
|
||||
PartSize := 4 * 1024 * 1024
|
||||
|
||||
fd, err = os.Open("test_file")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
uploader = upload.Init(bucket, PartSize)
|
||||
return nil
|
||||
}
|
||||
|
||||
func uploaderIsInitialized() error {
|
||||
if uploader == nil {
|
||||
return errors.New("uploader not initialized")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var objectKey string
|
||||
|
||||
func uploadLargeFile() error {
|
||||
objectKey = "test_multipart_upload"
|
||||
err := uploader.Upload(fd, objectKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func largeFileIsUploaded() error {
|
||||
defer uploadTearDown()
|
||||
return nil
|
||||
}
|
||||
|
||||
func uploadSetup() {
|
||||
exec.Command("dd", "if=/dev/zero", "of=test_file", "bs=1024", "count=20480").Output()
|
||||
}
|
||||
|
||||
func uploadTearDown() {
|
||||
exec.Command("rm", "", "test_file").Output()
|
||||
}
|
||||
54
vendor/github.com/yunify/qingstor-sdk-go/test/utils.go
generated
vendored
54
vendor/github.com/yunify/qingstor-sdk-go/test/utils.go
generated
vendored
@@ -1,54 +0,0 @@
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Copyright (C) 2016 Yunify, Inc.
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// | you may not use this work except in compliance with the License.
|
||||
// | You may obtain a copy of the License in the LICENSE file, or 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 (
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func checkError(err error) {
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func checkErrorForExit(err error, code ...int) {
|
||||
if err != nil {
|
||||
exitCode := 1
|
||||
if len(code) > 0 {
|
||||
exitCode = code[0]
|
||||
}
|
||||
fmt.Println(err.Error(), exitCode)
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
}
|
||||
|
||||
func checkEqual(value, shouldBe interface{}) error {
|
||||
if value == nil || shouldBe == nil {
|
||||
if value == shouldBe {
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
if reflect.DeepEqual(value, shouldBe) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("Value \"%v\" should be \"%v\"", value, shouldBe)
|
||||
}
|
||||
30
vendor/github.com/yunify/qingstor-sdk-go/utils/escape_test.go
generated
vendored
30
vendor/github.com/yunify/qingstor-sdk-go/utils/escape_test.go
generated
vendored
@@ -1,30 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestURLQueryEscape(t *testing.T) {
|
||||
assert.Equal(t, "/", URLQueryEscape("/"))
|
||||
assert.Equal(t, "%20", URLQueryEscape(" "))
|
||||
assert.Equal(t,
|
||||
"%21%40%23%24%25%5E%26%2A%28%29_%2B%7B%7D%7C",
|
||||
URLQueryEscape("!@#$%^&*()_+{}|"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestURLQueryUnescape(t *testing.T) {
|
||||
x, err := URLQueryUnescape("/")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "/", x)
|
||||
|
||||
x, err = URLQueryUnescape("%20")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, " ", x)
|
||||
|
||||
x, err = URLQueryUnescape("%21%40%23%24%25%5E%26%2A%28%29_%2B%7B%7D%7C")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "!@#$%^&*()_+{}|", x)
|
||||
}
|
||||
28
vendor/github.com/yunify/qingstor-sdk-go/version_test.go
generated
vendored
28
vendor/github.com/yunify/qingstor-sdk-go/version_test.go
generated
vendored
@@ -1,28 +0,0 @@
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Copyright (C) 2016 Yunify, Inc.
|
||||
// +-------------------------------------------------------------------------
|
||||
// | Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// | you may not use this work except in compliance with the License.
|
||||
// | You may obtain a copy of the License in the LICENSE file, or 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 sdk
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestVersion(t *testing.T) {
|
||||
assert.Equal(t, "string", reflect.ValueOf(Version).Type().String())
|
||||
}
|
||||
Reference in New Issue
Block a user