vendor: add qingstor-sdk-go for QingStor

This commit is contained in:
wuyu
2017-08-04 17:09:28 +01:00
committed by Nick Craig-Wood
parent f682002b84
commit 466dd22b44
136 changed files with 15952 additions and 1 deletions
@@ -0,0 +1,3 @@
# Ignore local config
config.yaml
test_config.yaml
+269
View File
@@ -0,0 +1,269 @@
// +-------------------------------------------------------------------------
// | 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
View File
@@ -0,0 +1,79 @@
// +-------------------------------------------------------------------------
// | 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
View File
@@ -0,0 +1,95 @@
// +-------------------------------------------------------------------------
// | 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)
}
@@ -0,0 +1,88 @@
// +-------------------------------------------------------------------------
// | 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
View File
@@ -0,0 +1,105 @@
// +-------------------------------------------------------------------------
// | 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
View File
@@ -0,0 +1,15 @@
# 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
View File
@@ -0,0 +1,9 @@
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
View File
@@ -0,0 +1,4 @@
package: github.com/yunify/qingstor-sdk-go/test
import:
- package: github.com/DATA-DOG/godog
version: v0.6.0
+138
View File
@@ -0,0 +1,138 @@
// +-------------------------------------------------------------------------
// | 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)
}
options := godog.Options{
Format: "pretty",
Paths: []string{"./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"`
}
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)
}
}
+263
View File
@@ -0,0 +1,263 @@
// +-------------------------------------------------------------------------
// | 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"
"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 putObjectOutput *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")
file, err := os.Open("/tmp/sdk_bin")
if err != nil {
return err
}
defer file.Close()
hash := md5.New()
_, err = io.Copy(hash, file)
hashInBytes := hash.Sum(nil)[:16]
md5String := hex.EncodeToString(hashInBytes)
//file.Seek(0, io.SeekStart)
file.Seek(0, 0)
putObjectOutput, err = bucket.PutObject(objectKey, &qs.PutObjectInput{
ContentType: qs.String("text/plain"),
ContentMD5: qs.String(md5String),
Body: file,
})
return err
}
func putObjectStatusCodeIs(statusCode int) error {
return checkEqual(qs.IntValue(putObjectOutput.StatusCode), statusCode)
}
// --------------------------------------------------------------------------
var copyObjectOutput *qs.PutObjectOutput
func copyObjectWithKey(objectKey string) error {
copyObjectKey := fmt.Sprintf(`%s_copy`, objectKey)
copyObjectOutput, err = bucket.PutObject(copyObjectKey, &qs.PutObjectInput{
XQSCopySource: qs.String(fmt.Sprintf(`/%s/%s`, tc.BucketName, objectKey)),
})
return err
}
func copyObjectStatusCodeIs(statusCode int) error {
return checkEqual(qs.IntValue(copyObjectOutput.StatusCode), statusCode)
}
// --------------------------------------------------------------------------
var moveObjectOutput *qs.PutObjectOutput
func moveObjectWithKey(objectKey string) error {
copyObjectKey := fmt.Sprintf(`%s_copy`, objectKey)
moveObjectKey := fmt.Sprintf(`%s_move`, objectKey)
moveObjectOutput, err = bucket.PutObject(moveObjectKey, &qs.PutObjectInput{
XQSMoveSource: qs.String(fmt.Sprintf(`/%s/%s`, tc.BucketName, copyObjectKey)),
})
return err
}
func moveObjectStatusCodeIs(statusCode int) error {
return checkEqual(qs.IntValue(moveObjectOutput.StatusCode), statusCode)
}
// --------------------------------------------------------------------------
var getObjectOutput *qs.GetObjectOutput
func getObjectWithKey(objectKey string) error {
getObjectOutput, err = bucket.GetObject(objectKey, nil)
return err
}
func getObjectStatusCodeIs(statusCode int) error {
return checkEqual(qs.IntValue(getObjectOutput.StatusCode), statusCode)
}
func getObjectContentLengthIs(length int) error {
buffer := &bytes.Buffer{}
buffer.ReadFrom(getObjectOutput.Body)
getObjectOutput.Body.Close()
return checkEqual(len(buffer.Bytes())*1024, length)
}
// --------------------------------------------------------------------------
var getObjectWithContentTypeRequest *request.Request
func getObjectWithContentType(objectKey, contentType string) error {
getObjectWithContentTypeRequest, _, err = bucket.GetObjectRequest(
objectKey,
&qs.GetObjectInput{
ResponseContentType: qs.String(contentType),
},
)
if err != nil {
return err
}
err = getObjectWithContentTypeRequest.Send()
if err != nil {
return err
}
return nil
}
func getObjectContentTypeIs(contentType string) error {
return checkEqual(getObjectWithContentTypeRequest.HTTPResponse.Header.Get("Content-Type"), contentType)
}
// --------------------------------------------------------------------------
var getObjectWithQuerySignatureURL string
func getObjectWithQuerySignature(objectKey string) error {
r, _, err := bucket.GetObjectRequest(objectKey, nil)
if err != nil {
return err
}
err = r.SignQuery(10)
if err != nil {
return err
}
getObjectWithQuerySignatureURL = r.HTTPRequest.URL.String()
return nil
}
func getObjectWithQuerySignatureContentLengthIs(length int) error {
out, err := http.Get(getObjectWithQuerySignatureURL)
if err != nil {
return err
}
buffer := &bytes.Buffer{}
buffer.ReadFrom(out.Body)
out.Body.Close()
return checkEqual(len(buffer.Bytes())*1024, length)
}
// --------------------------------------------------------------------------
var headObjectOutput *qs.HeadObjectOutput
func headObjectWithKey(objectKey string) error {
headObjectOutput, err = bucket.HeadObject(objectKey, nil)
return err
}
func headObjectStatusCodeIs(statusCode int) error {
return checkEqual(qs.IntValue(headObjectOutput.StatusCode), statusCode)
}
// --------------------------------------------------------------------------
var optionsObjectOutput *qs.OptionsObjectOutput
func optionsObjectWithMethodAndOrigin(objectKey, method, origin string) error {
optionsObjectOutput, err = bucket.OptionsObject(
objectKey,
&qs.OptionsObjectInput{
AccessControlRequestMethod: qs.String(method),
Origin: qs.String(origin),
},
)
return err
}
func optionsObjectStatusCodeIs(statusCode int) error {
return checkEqual(qs.IntValue(optionsObjectOutput.StatusCode), statusCode)
}
// --------------------------------------------------------------------------
var deleteObjectOutput *qs.DeleteObjectOutput
var deleteTheMoveObjectOutput *qs.DeleteObjectOutput
func deleteObjectWithKey(objectKey string) error {
deleteObjectOutput, err = bucket.DeleteObject(objectKey)
return err
}
func deleteObjectStatusCodeIs(statusCode int) error {
return checkEqual(qs.IntValue(deleteObjectOutput.StatusCode), statusCode)
}
func deleteTheMoveObjectWithKey(objectKey string) error {
deleteTheMoveObjectOutput, err = bucket.DeleteObject(fmt.Sprintf(`%s_move`, objectKey))
return err
}
func deleteTheMoveObjectStatusCodeIs(statusCode int) error {
return checkEqual(qs.IntValue(deleteTheMoveObjectOutput.StatusCode), statusCode)
}
+238
View File
@@ -0,0 +1,238 @@
// +-------------------------------------------------------------------------
// | 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
View File
@@ -0,0 +1,60 @@
// +-------------------------------------------------------------------------
// | 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)
}
@@ -0,0 +1,7 @@
# Test configurations
zone: pek3a
bucket_name: access-key-id
retry_wait_time: 3 # seconds
max_retries: 60
+54
View File
@@ -0,0 +1,54 @@
// +-------------------------------------------------------------------------
// | 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)
}