vendor: add qingstor-sdk-go for QingStor
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
# Ignore local config
|
||||
config.yaml
|
||||
test_config.yaml
|
||||
+269
@@ -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
@@ -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
@@ -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)
|
||||
}
|
||||
+88
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,4 @@
|
||||
package: github.com/yunify/qingstor-sdk-go/test
|
||||
import:
|
||||
- package: github.com/DATA-DOG/godog
|
||||
version: v0.6.0
|
||||
+138
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
# Test configurations
|
||||
|
||||
zone: pek3a
|
||||
bucket_name: access-key-id
|
||||
|
||||
retry_wait_time: 3 # seconds
|
||||
max_retries: 60
|
||||
+54
@@ -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)
|
||||
}
|
||||
Reference in New Issue
Block a user