aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/cloud.google.com/go/storage
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-06-13 20:23:21 +0200
committerDmitry Vyukov <dvyukov@google.com>2017-06-13 20:23:21 +0200
commitb41e96b421acda1761e9ba2ee17da16efad436cd (patch)
treeb6200bf1c3665161b6d76453bb56f7bd5ce32f42 /vendor/cloud.google.com/go/storage
parentf58147fb5ea43427d38c2a4437f35647138fbf9d (diff)
vendor: switch from dep to godep
dep tool vendored too much code (100MB) including tests and unused packages. godep vendored significantly less (12MB) without tests and unused packages. The main advantage is that pre-Go1.9 toolchain does not run tests of all vendor packages now.
Diffstat (limited to 'vendor/cloud.google.com/go/storage')
-rw-r--r--vendor/cloud.google.com/go/storage/bucket_test.go187
-rw-r--r--vendor/cloud.google.com/go/storage/doc.go2
-rw-r--r--vendor/cloud.google.com/go/storage/example_test.go543
-rw-r--r--vendor/cloud.google.com/go/storage/integration_test.go1421
-rw-r--r--vendor/cloud.google.com/go/storage/invoke_test.go56
-rw-r--r--vendor/cloud.google.com/go/storage/storage_test.go701
-rw-r--r--vendor/cloud.google.com/go/storage/testdata/dummy_pem39
-rw-r--r--vendor/cloud.google.com/go/storage/testdata/dummy_rsa27
-rw-r--r--vendor/cloud.google.com/go/storage/writer.go27
-rw-r--r--vendor/cloud.google.com/go/storage/writer_test.go131
10 files changed, 2 insertions, 3132 deletions
diff --git a/vendor/cloud.google.com/go/storage/bucket_test.go b/vendor/cloud.google.com/go/storage/bucket_test.go
deleted file mode 100644
index e9ef12df3..000000000
--- a/vendor/cloud.google.com/go/storage/bucket_test.go
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License 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 storage
-
-import (
- "net/http"
- "reflect"
- "testing"
- "time"
-
- "cloud.google.com/go/internal/pretty"
- raw "google.golang.org/api/storage/v1"
-)
-
-func TestBucketAttrsToRawBucket(t *testing.T) {
- t.Parallel()
- attrs := &BucketAttrs{
- Name: "name",
- ACL: []ACLRule{{Entity: "bob@example.com", Role: RoleOwner}},
- DefaultObjectACL: []ACLRule{{Entity: AllUsers, Role: RoleReader}},
- Location: "loc",
- StorageClass: "class",
- VersioningEnabled: false,
- // should be ignored:
- MetaGeneration: 39,
- Created: time.Now(),
- Labels: map[string]string{"label": "value"},
- }
- got := attrs.toRawBucket()
- want := &raw.Bucket{
- Name: "name",
- Acl: []*raw.BucketAccessControl{
- {Entity: "bob@example.com", Role: "OWNER"},
- },
- DefaultObjectAcl: []*raw.ObjectAccessControl{
- {Entity: "allUsers", Role: "READER"},
- },
- Location: "loc",
- StorageClass: "class",
- Versioning: nil, // ignore VersioningEnabled if flase
- Labels: map[string]string{"label": "value"},
- }
- msg, ok, err := pretty.Diff(want, got)
- if err != nil {
- t.Fatal(err)
- }
- if !ok {
- t.Error(msg)
- }
-
- attrs.VersioningEnabled = true
- got = attrs.toRawBucket()
- want.Versioning = &raw.BucketVersioning{Enabled: true}
- msg, ok, err = pretty.Diff(want, got)
- if err != nil {
- t.Fatal(err)
- }
- if !ok {
- t.Error(msg)
- }
-}
-
-func TestBucketAttrsToUpdateToRawBucket(t *testing.T) {
- t.Parallel()
- au := &BucketAttrsToUpdate{VersioningEnabled: false}
- au.SetLabel("a", "foo")
- au.DeleteLabel("b")
- au.SetLabel("c", "")
- got := au.toRawBucket()
- want := &raw.Bucket{
- Versioning: &raw.BucketVersioning{
- Enabled: false,
- ForceSendFields: []string{"Enabled"},
- },
- Labels: map[string]string{
- "a": "foo",
- "c": "",
- },
- NullFields: []string{"Labels.b"},
- }
- msg, ok, err := pretty.Diff(want, got)
- if err != nil {
- t.Fatal(err)
- }
- if !ok {
- t.Error(msg)
- }
-
- var au2 BucketAttrsToUpdate
- au2.DeleteLabel("b")
- got = au2.toRawBucket()
- want = &raw.Bucket{
- Labels: map[string]string{},
- ForceSendFields: []string{"Labels"},
- NullFields: []string{"Labels.b"},
- }
- msg, ok, err = pretty.Diff(want, got)
- if err != nil {
- t.Fatal(err)
- }
- if !ok {
- t.Error(msg)
- }
-
-}
-
-func TestCallBuilders(t *testing.T) {
- rc, err := raw.New(&http.Client{})
- if err != nil {
- t.Fatal(err)
- }
- c := &Client{raw: rc}
- const metagen = 17
-
- b := c.Bucket("name")
- bm := b.If(BucketConditions{MetagenerationMatch: metagen})
-
- for i, test := range []struct {
- callFunc func(*BucketHandle) (interface{}, error)
- want interface {
- Header() http.Header
- }
- metagenFunc func(interface{})
- }{
- {
- func(b *BucketHandle) (interface{}, error) { return b.newGetCall() },
- rc.Buckets.Get("name").Projection("full"),
- func(req interface{}) { req.(*raw.BucketsGetCall).IfMetagenerationMatch(metagen) },
- },
- {
- func(b *BucketHandle) (interface{}, error) { return b.newDeleteCall() },
- rc.Buckets.Delete("name"),
- func(req interface{}) { req.(*raw.BucketsDeleteCall).IfMetagenerationMatch(metagen) },
- },
- {
- func(b *BucketHandle) (interface{}, error) {
- return b.newPatchCall(&BucketAttrsToUpdate{VersioningEnabled: false})
- },
- rc.Buckets.Patch("name", &raw.Bucket{
- Versioning: &raw.BucketVersioning{Enabled: false, ForceSendFields: []string{"Enabled"}},
- }).Projection("full"),
- func(req interface{}) { req.(*raw.BucketsPatchCall).IfMetagenerationMatch(metagen) },
- },
- } {
- got, err := test.callFunc(b)
- if err != nil {
- t.Fatal(err)
- }
- setClientHeader(test.want.Header())
- if !reflect.DeepEqual(got, test.want) {
- t.Errorf("#%d: got %#v, want %#v", i, got, test.want)
- }
-
- got, err = test.callFunc(bm)
- if err != nil {
- t.Fatal(err)
- }
- test.metagenFunc(test.want)
- if !reflect.DeepEqual(got, test.want) {
- t.Errorf("#%d: got %#v, want %#v", i, got, test.want)
- }
- }
-
- // Error.
- bm = b.If(BucketConditions{MetagenerationMatch: 1, MetagenerationNotMatch: 2})
- if _, err := bm.newGetCall(); err == nil {
- t.Errorf("got nil, want error")
- }
- if _, err := bm.newDeleteCall(); err == nil {
- t.Errorf("got nil, want error")
- }
- if _, err := bm.newPatchCall(&BucketAttrsToUpdate{}); err == nil {
- t.Errorf("got nil, want error")
- }
-}
diff --git a/vendor/cloud.google.com/go/storage/doc.go b/vendor/cloud.google.com/go/storage/doc.go
index 951391f54..b932926cb 100644
--- a/vendor/cloud.google.com/go/storage/doc.go
+++ b/vendor/cloud.google.com/go/storage/doc.go
@@ -158,4 +158,4 @@ Authentication
See examples of authorization and authentication at
https://godoc.org/cloud.google.com/go#pkg-examples.
*/
-package storage // import "cloud.google.com/go/storage"
+package storage
diff --git a/vendor/cloud.google.com/go/storage/example_test.go b/vendor/cloud.google.com/go/storage/example_test.go
deleted file mode 100644
index d8ec8ff6d..000000000
--- a/vendor/cloud.google.com/go/storage/example_test.go
+++ /dev/null
@@ -1,543 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License 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 storage_test
-
-import (
- "fmt"
- "io"
- "io/ioutil"
- "log"
- "os"
- "time"
-
- "cloud.google.com/go/storage"
- "golang.org/x/net/context"
- "google.golang.org/api/iterator"
-)
-
-func ExampleNewClient() {
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- // Use the client.
-
- // Close the client when finished.
- if err := client.Close(); err != nil {
- // TODO: handle error.
- }
-}
-
-func ExampleNewClient_auth() {
- ctx := context.Background()
- // Use Google Application Default Credentials to authorize and authenticate the client.
- // More information about Application Default Credentials and how to enable is at
- // https://developers.google.com/identity/protocols/application-default-credentials.
- client, err := storage.NewClient(ctx)
- if err != nil {
- log.Fatal(err)
- }
-
- // Use the client.
-
- // Close the client when finished.
- if err := client.Close(); err != nil {
- log.Fatal(err)
- }
-}
-
-func ExampleBucketHandle_Create() {
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- if err := client.Bucket("my-bucket").Create(ctx, "my-project", nil); err != nil {
- // TODO: handle error.
- }
-}
-
-func ExampleBucketHandle_Delete() {
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- if err := client.Bucket("my-bucket").Delete(ctx); err != nil {
- // TODO: handle error.
- }
-}
-
-func ExampleBucketHandle_Attrs() {
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- attrs, err := client.Bucket("my-bucket").Attrs(ctx)
- if err != nil {
- // TODO: handle error.
- }
- fmt.Println(attrs)
-}
-
-func ExampleBucketHandle_Update() {
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- // Enable versioning in the bucket, regardless of its previous value.
- attrs, err := client.Bucket("my-bucket").Update(ctx,
- storage.BucketAttrsToUpdate{VersioningEnabled: true})
- if err != nil {
- // TODO: handle error.
- }
- fmt.Println(attrs)
-}
-
-// If your update is based on the bucket's previous attributes, match the
-// metageneration number to make sure the bucket hasn't changed since you read it.
-func ExampleBucketHandle_Update_readModifyWrite() {
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- b := client.Bucket("my-bucket")
- attrs, err := b.Attrs(ctx)
- if err != nil {
- // TODO: handle error.
- }
- var au storage.BucketAttrsToUpdate
- au.SetLabel("lab", attrs.Labels["lab"]+"-more")
- if attrs.Labels["delete-me"] == "yes" {
- au.DeleteLabel("delete-me")
- }
- attrs, err = b.
- If(storage.BucketConditions{MetagenerationMatch: attrs.MetaGeneration}).
- Update(ctx, au)
- if err != nil {
- // TODO: handle error.
- }
- fmt.Println(attrs)
-}
-
-func ExampleClient_Buckets() {
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- it := client.Bucket("my-bucket")
- _ = it // TODO: iterate using Next or iterator.Pager.
-}
-
-func ExampleBucketIterator_Next() {
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- it := client.Buckets(ctx, "my-project")
- for {
- bucketAttrs, err := it.Next()
- if err == iterator.Done {
- break
- }
- if err != nil {
- // TODO: Handle error.
- }
- fmt.Println(bucketAttrs)
- }
-}
-
-func ExampleBucketHandle_Objects() {
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- it := client.Bucket("my-bucket").Objects(ctx, nil)
- _ = it // TODO: iterate using Next or iterator.Pager.
-}
-
-func ExampleObjectIterator_Next() {
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- it := client.Bucket("my-bucket").Objects(ctx, nil)
- for {
- objAttrs, err := it.Next()
- if err == iterator.Done {
- break
- }
- if err != nil {
- // TODO: Handle error.
- }
- fmt.Println(objAttrs)
- }
-}
-
-func ExampleSignedURL() {
- pkey, err := ioutil.ReadFile("my-private-key.pem")
- if err != nil {
- // TODO: handle error.
- }
- url, err := storage.SignedURL("my-bucket", "my-object", &storage.SignedURLOptions{
- GoogleAccessID: "xxx@developer.gserviceaccount.com",
- PrivateKey: pkey,
- Method: "GET",
- Expires: time.Now().Add(48 * time.Hour),
- })
- if err != nil {
- // TODO: handle error.
- }
- fmt.Println(url)
-}
-
-func ExampleObjectHandle_Attrs() {
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- objAttrs, err := client.Bucket("my-bucket").Object("my-object").Attrs(ctx)
- if err != nil {
- // TODO: handle error.
- }
- fmt.Println(objAttrs)
-}
-
-func ExampleObjectHandle_Attrs_withConditions() {
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- obj := client.Bucket("my-bucket").Object("my-object")
- // Read the object.
- objAttrs1, err := obj.Attrs(ctx)
- if err != nil {
- // TODO: handle error.
- }
- // Do something else for a while.
- time.Sleep(5 * time.Minute)
- // Now read the same contents, even if the object has been written since the last read.
- objAttrs2, err := obj.Generation(objAttrs1.Generation).Attrs(ctx)
- if err != nil {
- // TODO: handle error.
- }
- fmt.Println(objAttrs1, objAttrs2)
-}
-
-func ExampleObjectHandle_Update() {
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- // Change only the content type of the object.
- objAttrs, err := client.Bucket("my-bucket").Object("my-object").Update(ctx, storage.ObjectAttrsToUpdate{
- ContentType: "text/html",
- ContentDisposition: "", // delete ContentDisposition
- })
- if err != nil {
- // TODO: handle error.
- }
- fmt.Println(objAttrs)
-}
-
-func ExampleObjectHandle_NewReader() {
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- rc, err := client.Bucket("my-bucket").Object("my-object").NewReader(ctx)
- if err != nil {
- // TODO: handle error.
- }
- slurp, err := ioutil.ReadAll(rc)
- rc.Close()
- if err != nil {
- // TODO: handle error.
- }
- fmt.Println("file contents:", slurp)
-}
-
-func ExampleObjectHandle_NewRangeReader() {
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- // Read only the first 64K.
- rc, err := client.Bucket("bucketname").Object("filename1").NewRangeReader(ctx, 0, 64*1024)
- if err != nil {
- // TODO: handle error.
- }
- slurp, err := ioutil.ReadAll(rc)
- rc.Close()
- if err != nil {
- // TODO: handle error.
- }
- fmt.Println("first 64K of file contents:", slurp)
-}
-
-func ExampleObjectHandle_NewWriter() {
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- wc := client.Bucket("bucketname").Object("filename1").NewWriter(ctx)
- _ = wc // TODO: Use the Writer.
-}
-
-func ExampleWriter_Write() {
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- wc := client.Bucket("bucketname").Object("filename1").NewWriter(ctx)
- wc.ContentType = "text/plain"
- wc.ACL = []storage.ACLRule{{storage.AllUsers, storage.RoleReader}}
- if _, err := wc.Write([]byte("hello world")); err != nil {
- // TODO: handle error.
- }
- if err := wc.Close(); err != nil {
- // TODO: handle error.
- }
- fmt.Println("updated object:", wc.Attrs())
-}
-
-func ExampleObjectHandle_Delete() {
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- // To delete multiple objects in a bucket, list them with an
- // ObjectIterator, then Delete them.
-
- // If you are using this package on the App Engine Flex runtime,
- // you can init a bucket client with your app's default bucket name.
- // See http://godoc.org/google.golang.org/appengine/file#DefaultBucketName.
- bucket := client.Bucket("my-bucket")
- it := bucket.Objects(ctx, nil)
- for {
- objAttrs, err := it.Next()
- if err != nil && err != iterator.Done {
- // TODO: Handle error.
- }
- if err == iterator.Done {
- break
- }
- if err := bucket.Object(objAttrs.Name).Delete(ctx); err != nil {
- // TODO: Handle error.
- }
- }
- fmt.Println("deleted all object items in the bucket specified.")
-}
-
-func ExampleACLHandle_Delete() {
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- // No longer grant access to the bucket to everyone on the Internet.
- if err := client.Bucket("my-bucket").ACL().Delete(ctx, storage.AllUsers); err != nil {
- // TODO: handle error.
- }
-}
-
-func ExampleACLHandle_Set() {
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- // Let any authenticated user read my-bucket/my-object.
- obj := client.Bucket("my-bucket").Object("my-object")
- if err := obj.ACL().Set(ctx, storage.AllAuthenticatedUsers, storage.RoleReader); err != nil {
- // TODO: handle error.
- }
-}
-
-func ExampleACLHandle_List() {
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- // List the default object ACLs for my-bucket.
- aclRules, err := client.Bucket("my-bucket").DefaultObjectACL().List(ctx)
- if err != nil {
- // TODO: handle error.
- }
- fmt.Println(aclRules)
-}
-
-func ExampleCopier_Run() {
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- src := client.Bucket("bucketname").Object("file1")
- dst := client.Bucket("another-bucketname").Object("file2")
-
- // Copy content and modify metadata.
- copier := dst.CopierFrom(src)
- copier.ContentType = "text/plain"
- attrs, err := copier.Run(ctx)
- if err != nil {
- // TODO: Handle error, possibly resuming with copier.RewriteToken.
- }
- fmt.Println(attrs)
-
- // Just copy content.
- attrs, err = dst.CopierFrom(src).Run(ctx)
- if err != nil {
- // TODO: Handle error. No way to resume.
- }
- fmt.Println(attrs)
-}
-
-func ExampleCopier_Run_progress() {
- // Display progress across multiple rewrite RPCs.
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- src := client.Bucket("bucketname").Object("file1")
- dst := client.Bucket("another-bucketname").Object("file2")
-
- copier := dst.CopierFrom(src)
- copier.ProgressFunc = func(copiedBytes, totalBytes uint64) {
- log.Printf("copy %.1f%% done", float64(copiedBytes)/float64(totalBytes)*100)
- }
- if _, err := copier.Run(ctx); err != nil {
- // TODO: handle error.
- }
-}
-
-var key1, key2 []byte
-
-func ExampleObjectHandle_CopierFrom_rotateEncryptionKeys() {
- // To rotate the encryption key on an object, copy it onto itself.
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- obj := client.Bucket("bucketname").Object("obj")
- // Assume obj is encrypted with key1, and we want to change to key2.
- _, err = obj.Key(key2).CopierFrom(obj.Key(key1)).Run(ctx)
- if err != nil {
- // TODO: handle error.
- }
-}
-
-func ExampleComposer_Run() {
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- bkt := client.Bucket("bucketname")
- src1 := bkt.Object("o1")
- src2 := bkt.Object("o2")
- dst := bkt.Object("o3")
- // Compose and modify metadata.
- c := dst.ComposerFrom(src1, src2)
- c.ContentType = "text/plain"
- attrs, err := c.Run(ctx)
- if err != nil {
- // TODO: Handle error.
- }
- fmt.Println(attrs)
- // Just compose.
- attrs, err = dst.ComposerFrom(src1, src2).Run(ctx)
- if err != nil {
- // TODO: Handle error.
- }
- fmt.Println(attrs)
-}
-
-var gen int64
-
-func ExampleObjectHandle_Generation() {
- // Read an object's contents from generation gen, regardless of the
- // current generation of the object.
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- obj := client.Bucket("my-bucket").Object("my-object")
- rc, err := obj.Generation(gen).NewReader(ctx)
- if err != nil {
- // TODO: handle error.
- }
- defer rc.Close()
- if _, err := io.Copy(os.Stdout, rc); err != nil {
- // TODO: handle error.
- }
-}
-
-func ExampleObjectHandle_If() {
- // Read from an object only if the current generation is gen.
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- obj := client.Bucket("my-bucket").Object("my-object")
- rc, err := obj.If(storage.Conditions{GenerationMatch: gen}).NewReader(ctx)
- if err != nil {
- // TODO: handle error.
- }
- defer rc.Close()
- if _, err := io.Copy(os.Stdout, rc); err != nil {
- // TODO: handle error.
- }
-}
-
-var secretKey []byte
-
-func ExampleObjectHandle_Key() {
- ctx := context.Background()
- client, err := storage.NewClient(ctx)
- if err != nil {
- // TODO: handle error.
- }
- obj := client.Bucket("my-bucket").Object("my-object")
- // Encrypt the object's contents.
- w := obj.Key(secretKey).NewWriter(ctx)
- if _, err := w.Write([]byte("top secret")); err != nil {
- // TODO: handle error.
- }
- if err := w.Close(); err != nil {
- // TODO: handle error.
- }
-}
diff --git a/vendor/cloud.google.com/go/storage/integration_test.go b/vendor/cloud.google.com/go/storage/integration_test.go
deleted file mode 100644
index 94def61ad..000000000
--- a/vendor/cloud.google.com/go/storage/integration_test.go
+++ /dev/null
@@ -1,1421 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License 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 storage
-
-import (
- "bytes"
- "compress/gzip"
- "crypto/md5"
- "crypto/sha256"
- "encoding/base64"
- "flag"
- "fmt"
- "hash/crc32"
- "io"
- "io/ioutil"
- "log"
- "math/rand"
- "net/http"
- "os"
- "reflect"
- "sort"
- "strconv"
- "strings"
- "testing"
- "time"
-
- gax "github.com/googleapis/gax-go"
-
- "golang.org/x/net/context"
-
- "cloud.google.com/go/iam"
- "cloud.google.com/go/internal"
- "cloud.google.com/go/internal/testutil"
- "google.golang.org/api/googleapi"
- "google.golang.org/api/iterator"
- itesting "google.golang.org/api/iterator/testing"
- "google.golang.org/api/option"
-)
-
-const testPrefix = "-go-cloud-storage-test"
-
-// suffix is a timestamp-based suffix which is added to all buckets created by
-// tests. This reduces flakiness when the tests are run in parallel and allows
-// automatic cleaning up of artifacts left when tests fail.
-var suffix = fmt.Sprintf("%s-%d", testPrefix, time.Now().UnixNano())
-
-func TestMain(m *testing.M) {
- integrationTest := initIntegrationTest()
- exit := m.Run()
- if integrationTest {
- if err := cleanup(); err != nil {
- // No need to be loud if cleanup() fails; we'll get
- // any undeleted buckets next time.
- log.Printf("Post-test cleanup failed: %v\n", err)
- }
- }
- os.Exit(exit)
-}
-
-// If integration tests will be run, create a unique bucket for them.
-func initIntegrationTest() bool {
- flag.Parse() // needed for testing.Short()
- ctx := context.Background()
- if testing.Short() {
- return false
- }
- client, bucket := config(ctx)
- if client == nil {
- return false
- }
- defer client.Close()
- if err := client.Bucket(bucket).Create(ctx, testutil.ProjID(), nil); err != nil {
- log.Fatalf("creating bucket %q: %v", bucket, err)
- }
- return true
-}
-
-// testConfig returns the Client used to access GCS and the default bucket
-// name to use. testConfig skips the current test if credentials are not
-// available or when being run in Short mode.
-func testConfig(ctx context.Context, t *testing.T) (*Client, string) {
- if testing.Short() {
- t.Skip("Integration tests skipped in short mode")
- }
- client, bucket := config(ctx)
- if client == nil {
- t.Skip("Integration tests skipped. See CONTRIBUTING.md for details")
- }
- return client, bucket
-}
-
-// config is like testConfig, but it doesn't need a *testing.T.
-func config(ctx context.Context) (*Client, string) {
- ts := testutil.TokenSource(ctx, ScopeFullControl)
- if ts == nil {
- return nil, ""
- }
- p := testutil.ProjID()
- if p == "" {
- log.Fatal("The project ID must be set. See CONTRIBUTING.md for details")
- }
- client, err := NewClient(ctx, option.WithTokenSource(ts))
- if err != nil {
- log.Fatalf("NewClient: %v", err)
- }
- return client, p + suffix
-}
-
-func TestBucketMethods(t *testing.T) {
- ctx := context.Background()
- client, bucket := testConfig(ctx, t)
- defer client.Close()
-
- projectID := testutil.ProjID()
- newBucket := bucket + "-new"
- b := client.Bucket(newBucket)
- // Test Create and Delete.
- if err := b.Create(ctx, projectID, nil); err != nil {
- t.Errorf("Bucket(%v).Create(%v, %v) failed: %v", newBucket, projectID, nil, err)
- }
- attrs, err := b.Attrs(ctx)
- if err != nil {
- t.Error(err)
- } else {
- if got, want := attrs.MetaGeneration, int64(1); got != want {
- t.Errorf("got metagen %d, want %d", got, want)
- }
- if got, want := attrs.StorageClass, "STANDARD"; got != want {
- t.Errorf("got storage class %q, want %q", got, want)
- }
- if attrs.VersioningEnabled {
- t.Error("got versioning enabled, wanted it disabled")
- }
- }
- if err := client.Bucket(newBucket).Delete(ctx); err != nil {
- t.Errorf("Bucket(%v).Delete failed: %v", newBucket, err)
- }
-
- // Test Create and Delete with attributes.
- labels := map[string]string{
- "l1": "v1",
- "empty": "",
- }
- attrs = &BucketAttrs{
- StorageClass: "NEARLINE",
- VersioningEnabled: true,
- Labels: labels,
- }
- if err := client.Bucket(newBucket).Create(ctx, projectID, attrs); err != nil {
- t.Errorf("Bucket(%v).Create(%v, %v) failed: %v", newBucket, projectID, attrs, err)
- }
- attrs, err = b.Attrs(ctx)
- if err != nil {
- t.Error(err)
- } else {
- if got, want := attrs.MetaGeneration, int64(1); got != want {
- t.Errorf("got metagen %d, want %d", got, want)
- }
- if got, want := attrs.StorageClass, "NEARLINE"; got != want {
- t.Errorf("got storage class %q, want %q", got, want)
- }
- if !attrs.VersioningEnabled {
- t.Error("got versioning disabled, wanted it enabled")
- }
- if got, want := attrs.Labels, labels; !reflect.DeepEqual(got, want) {
- t.Errorf("labels: got %v, want %v", got, want)
- }
- }
- if err := client.Bucket(newBucket).Delete(ctx); err != nil {
- t.Errorf("Bucket(%v).Delete failed: %v", newBucket, err)
- }
-}
-
-func TestIntegration_BucketUpdate(t *testing.T) {
- ctx := context.Background()
- client, bucket := testConfig(ctx, t)
- defer client.Close()
-
- b := client.Bucket(bucket)
- attrs, err := b.Attrs(ctx)
- if err != nil {
- t.Fatal(err)
- }
- if attrs.VersioningEnabled {
- t.Fatal("bucket should not have versioning by default")
- }
- if len(attrs.Labels) > 0 {
- t.Fatal("bucket should not have labels initially")
- }
-
- // Using empty BucketAttrsToUpdate should be a no-nop.
- attrs, err = b.Update(ctx, BucketAttrsToUpdate{})
- if err != nil {
- t.Fatal(err)
- }
- if attrs.VersioningEnabled {
- t.Fatal("should not have versioning")
- }
- if len(attrs.Labels) > 0 {
- t.Fatal("should not have labels")
- }
-
- // Turn on versioning, add some labels.
- ua := BucketAttrsToUpdate{VersioningEnabled: true}
- ua.SetLabel("l1", "v1")
- ua.SetLabel("empty", "")
- attrs, err = b.Update(ctx, ua)
- if err != nil {
- t.Fatal(err)
- }
- if !attrs.VersioningEnabled {
- t.Fatal("should have versioning now")
- }
- wantLabels := map[string]string{
- "l1": "v1",
- "empty": "",
- }
- if !reflect.DeepEqual(attrs.Labels, wantLabels) {
- t.Fatalf("got %v, want %v", attrs.Labels, wantLabels)
- }
-
- // Turn off versioning again; add and remove some more labels.
- ua = BucketAttrsToUpdate{VersioningEnabled: false}
- ua.SetLabel("l1", "v2") // update
- ua.SetLabel("new", "new") // create
- ua.DeleteLabel("empty") // delete
- ua.DeleteLabel("absent") // delete non-existent
- attrs, err = b.Update(ctx, ua)
- if err != nil {
- t.Fatal(err)
- }
- if attrs.VersioningEnabled {
- t.Fatal("should have versioning off")
- }
- wantLabels = map[string]string{
- "l1": "v2",
- "new": "new",
- }
- if !reflect.DeepEqual(attrs.Labels, wantLabels) {
- t.Fatalf("got %v, want %v", attrs.Labels, wantLabels)
- }
-}
-
-func TestIntegration_ConditionalDelete(t *testing.T) {
- ctx := context.Background()
- client, bucket := testConfig(ctx, t)
- defer client.Close()
-
- o := client.Bucket(bucket).Object("conddel")
-
- wc := o.NewWriter(ctx)
- wc.ContentType = "text/plain"
- if _, err := wc.Write([]byte("foo")); err != nil {
- t.Fatal(err)
- }
- if err := wc.Close(); err != nil {
- t.Fatal(err)
- }
-
- gen := wc.Attrs().Generation
- metaGen := wc.Attrs().Metageneration
-
- if err := o.Generation(gen - 1).Delete(ctx); err == nil {
- t.Fatalf("Unexpected successful delete with Generation")
- }
- if err := o.If(Conditions{MetagenerationMatch: metaGen + 1}).Delete(ctx); err == nil {
- t.Fatalf("Unexpected successful delete with IfMetaGenerationMatch")
- }
- if err := o.If(Conditions{MetagenerationNotMatch: metaGen}).Delete(ctx); err == nil {
- t.Fatalf("Unexpected successful delete with IfMetaGenerationNotMatch")
- }
- if err := o.Generation(gen).Delete(ctx); err != nil {
- t.Fatalf("final delete failed: %v", err)
- }
-}
-
-func TestObjects(t *testing.T) {
- // TODO(djd): there are a lot of closely-related tests here which share
- // a common setup. Once we can depend on Go 1.7 features, we should refactor
- // this test to use the sub-test feature. This will increase the readability
- // of this test, and should also reduce the time it takes to execute.
- // https://golang.org/pkg/testing/#hdr-Subtests_and_Sub_benchmarks
- ctx := context.Background()
- client, bucket := testConfig(ctx, t)
- defer client.Close()
-
- bkt := client.Bucket(bucket)
-
- const defaultType = "text/plain"
-
- // Populate object names and make a map for their contents.
- objects := []string{
- "obj1",
- "obj2",
- "obj/with/slashes",
- }
- contents := make(map[string][]byte)
-
- // Test Writer.
- for _, obj := range objects {
- c := randomContents()
- if err := writeObject(ctx, bkt.Object(obj), defaultType, c); err != nil {
- t.Errorf("Write for %v failed with %v", obj, err)
- }
- contents[obj] = c
- }
-
- testObjectIterator(t, bkt, objects)
-
- // Test Reader.
- for _, obj := range objects {
- rc, err := bkt.Object(obj).NewReader(ctx)
- if err != nil {
- t.Errorf("Can't create a reader for %v, errored with %v", obj, err)
- continue
- }
- if !rc.checkCRC {
- t.Errorf("%v: not checking CRC", obj)
- }
- slurp, err := ioutil.ReadAll(rc)
- if err != nil {
- t.Errorf("Can't ReadAll object %v, errored with %v", obj, err)
- }
- if got, want := slurp, contents[obj]; !bytes.Equal(got, want) {
- t.Errorf("Contents (%q) = %q; want %q", obj, got, want)
- }
- if got, want := rc.Size(), len(contents[obj]); got != int64(want) {
- t.Errorf("Size (%q) = %d; want %d", obj, got, want)
- }
- if got, want := rc.ContentType(), "text/plain"; got != want {
- t.Errorf("ContentType (%q) = %q; want %q", obj, got, want)
- }
- rc.Close()
-
- // Check early close.
- buf := make([]byte, 1)
- rc, err = bkt.Object(obj).NewReader(ctx)
- if err != nil {
- t.Fatalf("%v: %v", obj, err)
- }
- _, err = rc.Read(buf)
- if err != nil {
- t.Fatalf("%v: %v", obj, err)
- }
- if got, want := buf, contents[obj][:1]; !bytes.Equal(got, want) {
- t.Errorf("Contents[0] (%q) = %q; want %q", obj, got, want)
- }
- if err := rc.Close(); err != nil {
- t.Errorf("%v Close: %v", obj, err)
- }
-
- // Test SignedURL
- opts := &SignedURLOptions{
- GoogleAccessID: "xxx@clientid",
- PrivateKey: dummyKey("rsa"),
- Method: "GET",
- MD5: "ICy5YqxZB1uWSwcVLSNLcA==",
- Expires: time.Date(2020, time.October, 2, 10, 0, 0, 0, time.UTC),
- ContentType: "application/json",
- Headers: []string{"x-header1", "x-header2"},
- }
- u, err := SignedURL(bucket, obj, opts)
- if err != nil {
- t.Fatalf("SignedURL(%q, %q) errored with %v", bucket, obj, err)
- }
- res, err := client.hc.Get(u)
- if err != nil {
- t.Fatalf("Can't get URL %q: %v", u, err)
- }
- slurp, err = ioutil.ReadAll(res.Body)
- if err != nil {
- t.Fatalf("Can't ReadAll signed object %v, errored with %v", obj, err)
- }
- if got, want := slurp, contents[obj]; !bytes.Equal(got, want) {
- t.Errorf("Contents (%v) = %q; want %q", obj, got, want)
- }
- res.Body.Close()
- }
-
- obj := objects[0]
- objlen := int64(len(contents[obj]))
- // Test Range Reader.
- for i, r := range []struct {
- offset, length, want int64
- }{
- {0, objlen, objlen},
- {0, objlen / 2, objlen / 2},
- {objlen / 2, objlen, objlen / 2},
- {0, 0, 0},
- {objlen / 2, 0, 0},
- {objlen / 2, -1, objlen / 2},
- {0, objlen * 2, objlen},
- } {
- rc, err := bkt.Object(obj).NewRangeReader(ctx, r.offset, r.length)
- if err != nil {
- t.Errorf("%d: Can't create a range reader for %v, errored with %v", i, obj, err)
- continue
- }
- if rc.Size() != objlen {
- t.Errorf("%d: Reader has a content-size of %d, want %d", i, rc.Size(), objlen)
- }
- if rc.Remain() != r.want {
- t.Errorf("%d: Reader's available bytes reported as %d, want %d", i, rc.Remain(), r.want)
- }
- slurp, err := ioutil.ReadAll(rc)
- if err != nil {
- t.Errorf("%d:Can't ReadAll object %v, errored with %v", i, obj, err)
- continue
- }
- if len(slurp) != int(r.want) {
- t.Errorf("%d:RangeReader (%d, %d): Read %d bytes, wanted %d bytes", i, r.offset, r.length, len(slurp), r.want)
- continue
- }
- if got, want := slurp, contents[obj][r.offset:r.offset+r.want]; !bytes.Equal(got, want) {
- t.Errorf("RangeReader (%d, %d) = %q; want %q", r.offset, r.length, got, want)
- }
- rc.Close()
- }
-
- // Test content encoding
- const zeroCount = 20 << 20
- w := bkt.Object("gzip-test").NewWriter(ctx)
- w.ContentEncoding = "gzip"
- gw := gzip.NewWriter(w)
- if _, err := io.Copy(gw, io.LimitReader(zeros{}, zeroCount)); err != nil {
- t.Fatalf("io.Copy, upload: %v", err)
- }
- if err := gw.Close(); err != nil {
- t.Errorf("gzip.Close(): %v", err)
- }
- if err := w.Close(); err != nil {
- t.Errorf("w.Close(): %v", err)
- }
- r, err := bkt.Object("gzip-test").NewReader(ctx)
- if err != nil {
- t.Fatalf("NewReader(gzip-test): %v", err)
- }
- n, err := io.Copy(ioutil.Discard, r)
- if err != nil {
- t.Errorf("io.Copy, download: %v", err)
- }
- if n != zeroCount {
- t.Errorf("downloaded bad data: got %d bytes, want %d", n, zeroCount)
- }
-
- // Test NotFound.
- _, err = bkt.Object("obj-not-exists").NewReader(ctx)
- if err != ErrObjectNotExist {
- t.Errorf("Object should not exist, err found to be %v", err)
- }
-
- objName := objects[0]
-
- // Test NewReader googleapi.Error.
- // Since a 429 or 5xx is hard to cause, we trigger a 416.
- realLen := len(contents[objName])
- _, err = bkt.Object(objName).NewRangeReader(ctx, int64(realLen*2), 10)
- if err, ok := err.(*googleapi.Error); !ok {
- t.Error("NewRangeReader did not return a googleapi.Error")
- } else {
- if err.Code != 416 {
- t.Errorf("Code = %d; want %d", err.Code, 416)
- }
- if len(err.Header) == 0 {
- t.Error("Missing googleapi.Error.Header")
- }
- if len(err.Body) == 0 {
- t.Error("Missing googleapi.Error.Body")
- }
- }
-
- // Test StatObject.
- o, err := bkt.Object(objName).Attrs(ctx)
- if err != nil {
- t.Error(err)
- }
- if got, want := o.Name, objName; got != want {
- t.Errorf("Name (%v) = %q; want %q", objName, got, want)
- }
- if got, want := o.ContentType, defaultType; got != want {
- t.Errorf("ContentType (%v) = %q; want %q", objName, got, want)
- }
- created := o.Created
- // Check that the object is newer than its containing bucket.
- bAttrs, err := bkt.Attrs(ctx)
- if err != nil {
- t.Error(err)
- }
- if o.Created.Before(bAttrs.Created) {
- t.Errorf("Object %v is older than its containing bucket, %v", o, bAttrs)
- }
-
- // Test object copy.
- copyName := "copy-" + objName
- copyObj, err := bkt.Object(copyName).CopierFrom(bkt.Object(objName)).Run(ctx)
- if err != nil {
- t.Errorf("Copier.Run failed with %v", err)
- } else if !namesEqual(copyObj, bucket, copyName) {
- t.Errorf("Copy object bucket, name: got %q.%q, want %q.%q",
- copyObj.Bucket, copyObj.Name, bucket, copyName)
- }
-
- // Copying with attributes.
- const contentEncoding = "identity"
- copier := bkt.Object(copyName).CopierFrom(bkt.Object(objName))
- copier.ContentEncoding = contentEncoding
- copyObj, err = copier.Run(ctx)
- if err != nil {
- t.Errorf("Copier.Run failed with %v", err)
- } else {
- if !namesEqual(copyObj, bucket, copyName) {
- t.Errorf("Copy object bucket, name: got %q.%q, want %q.%q",
- copyObj.Bucket, copyObj.Name, bucket, copyName)
- }
- if copyObj.ContentEncoding != contentEncoding {
- t.Errorf("Copy ContentEncoding: got %q, want %q", copyObj.ContentEncoding, contentEncoding)
- }
- }
-
- // Test UpdateAttrs.
- metadata := map[string]string{"key": "value"}
- updated, err := bkt.Object(objName).Update(ctx, ObjectAttrsToUpdate{
- ContentType: "text/html",
- ContentLanguage: "en",
- Metadata: metadata,
- ACL: []ACLRule{{Entity: "domain-google.com", Role: RoleReader}},
- })
- if err != nil {
- t.Errorf("UpdateAttrs failed with %v", err)
- } else {
- if got, want := updated.ContentType, "text/html"; got != want {
- t.Errorf("updated.ContentType == %q; want %q", got, want)
- }
- if got, want := updated.ContentLanguage, "en"; got != want {
- t.Errorf("updated.ContentLanguage == %q; want %q", updated.ContentLanguage, want)
- }
- if got, want := updated.Metadata, metadata; !reflect.DeepEqual(got, want) {
- t.Errorf("updated.Metadata == %+v; want %+v", updated.Metadata, want)
- }
- if got, want := updated.Created, created; got != want {
- t.Errorf("updated.Created == %q; want %q", got, want)
- }
- if !updated.Created.Before(updated.Updated) {
- t.Errorf("updated.Updated should be newer than update.Created")
- }
- }
- // Delete ContentType and ContentLanguage.
- updated, err = bkt.Object(objName).Update(ctx, ObjectAttrsToUpdate{
- ContentType: "",
- ContentLanguage: "",
- Metadata: map[string]string{},
- })
- if err != nil {
- t.Errorf("UpdateAttrs failed with %v", err)
- } else {
- if got, want := updated.ContentType, ""; got != want {
- t.Errorf("updated.ContentType == %q; want %q", got, want)
- }
- if got, want := updated.ContentLanguage, ""; got != want {
- t.Errorf("updated.ContentLanguage == %q; want %q", updated.ContentLanguage, want)
- }
- if updated.Metadata != nil {
- t.Errorf("updated.Metadata == %+v; want nil", updated.Metadata)
- }
- if got, want := updated.Created, created; got != want {
- t.Errorf("updated.Created == %q; want %q", got, want)
- }
- if !updated.Created.Before(updated.Updated) {
- t.Errorf("updated.Updated should be newer than update.Created")
- }
- }
-
- // Test checksums.
- checksumCases := []struct {
- name string
- contents [][]byte
- size int64
- md5 string
- crc32c uint32
- }{
- {
- name: "checksum-object",
- contents: [][]byte{[]byte("hello"), []byte("world")},
- size: 10,
- md5: "fc5e038d38a57032085441e7fe7010b0",
- crc32c: 1456190592,
- },
- {
- name: "zero-object",
- contents: [][]byte{},
- size: 0,
- md5: "d41d8cd98f00b204e9800998ecf8427e",
- crc32c: 0,
- },
- }
- for _, c := range checksumCases {
- wc := bkt.Object(c.name).NewWriter(ctx)
- for _, data := range c.contents {
- if _, err := wc.Write(data); err != nil {
- t.Errorf("Write(%q) failed with %q", data, err)
- }
- }
- if err = wc.Close(); err != nil {
- t.Errorf("%q: close failed with %q", c.name, err)
- }
- obj := wc.Attrs()
- if got, want := obj.Size, c.size; got != want {
- t.Errorf("Object (%q) Size = %v; want %v", c.name, got, want)
- }
- if got, want := fmt.Sprintf("%x", obj.MD5), c.md5; got != want {
- t.Errorf("Object (%q) MD5 = %q; want %q", c.name, got, want)
- }
- if got, want := obj.CRC32C, c.crc32c; got != want {
- t.Errorf("Object (%q) CRC32C = %v; want %v", c.name, got, want)
- }
- }
-
- // Test public ACL.
- publicObj := objects[0]
- if err = bkt.Object(publicObj).ACL().Set(ctx, AllUsers, RoleReader); err != nil {
- t.Errorf("PutACLEntry failed with %v", err)
- }
- publicClient, err := NewClient(ctx, option.WithHTTPClient(http.DefaultClient))
- if err != nil {
- t.Fatal(err)
- }
-
- slurp, err := readObject(ctx, publicClient.Bucket(bucket).Object(publicObj))
- if err != nil {
- t.Errorf("readObject failed with %v", err)
- } else if !bytes.Equal(slurp, contents[publicObj]) {
- t.Errorf("Public object's content: got %q, want %q", slurp, contents[publicObj])
- }
-
- // Test writer error handling.
- wc := publicClient.Bucket(bucket).Object(publicObj).NewWriter(ctx)
- if _, err := wc.Write([]byte("hello")); err != nil {
- t.Errorf("Write unexpectedly failed with %v", err)
- }
- if err = wc.Close(); err == nil {
- t.Error("Close expected an error, found none")
- }
-
- // Test deleting the copy object.
- if err := bkt.Object(copyName).Delete(ctx); err != nil {
- t.Errorf("Deletion of %v failed with %v", copyName, err)
- }
- // Deleting it a second time should return ErrObjectNotExist.
- if err := bkt.Object(copyName).Delete(ctx); err != ErrObjectNotExist {
- t.Errorf("second deletion of %v = %v; want ErrObjectNotExist", copyName, err)
- }
- _, err = bkt.Object(copyName).Attrs(ctx)
- if err != ErrObjectNotExist {
- t.Errorf("Copy is expected to be deleted, stat errored with %v", err)
- }
-
- // Test object composition.
- var compSrcs []*ObjectHandle
- var wantContents []byte
- for _, obj := range objects {
- compSrcs = append(compSrcs, bkt.Object(obj))
- wantContents = append(wantContents, contents[obj]...)
- }
- checkCompose := func(obj *ObjectHandle, wantContentType string) {
- rc, err := obj.NewReader(ctx)
- if err != nil {
- t.Fatalf("NewReader: %v", err)
- }
- slurp, err = ioutil.ReadAll(rc)
- if err != nil {
- t.Fatalf("ioutil.ReadAll: %v", err)
- }
- defer rc.Close()
- if !bytes.Equal(slurp, wantContents) {
- t.Errorf("Composed object contents\ngot: %q\nwant: %q", slurp, wantContents)
- }
- if got := rc.ContentType(); got != wantContentType {
- t.Errorf("Composed object content-type = %q, want %q", got, wantContentType)
- }
- }
-
- // Compose should work even if the user sets no destination attributes.
- compDst := bkt.Object("composed1")
- c := compDst.ComposerFrom(compSrcs...)
- if _, err := c.Run(ctx); err != nil {
- t.Fatalf("ComposeFrom error: %v", err)
- }
- checkCompose(compDst, "application/octet-stream")
-
- // It should also work if we do.
- compDst = bkt.Object("composed2")
- c = compDst.ComposerFrom(compSrcs...)
- c.ContentType = "text/json"
- if _, err := c.Run(ctx); err != nil {
- t.Fatalf("ComposeFrom error: %v", err)
- }
- checkCompose(compDst, "text/json")
-}
-
-func namesEqual(obj *ObjectAttrs, bucketName, objectName string) bool {
- return obj.Bucket == bucketName && obj.Name == objectName
-}
-
-func testObjectIterator(t *testing.T, bkt *BucketHandle, objects []string) {
- ctx := context.Background()
- // Collect the list of items we expect: ObjectAttrs in lexical order by name.
- names := make([]string, len(objects))
- copy(names, objects)
- sort.Strings(names)
- var attrs []*ObjectAttrs
- for _, name := range names {
- attr, err := bkt.Object(name).Attrs(ctx)
- if err != nil {
- t.Errorf("Object(%q).Attrs: %v", name, err)
- return
- }
- attrs = append(attrs, attr)
- }
- // The following iterator test fails occasionally, probably because the
- // underlying Objects.List operation is eventually consistent. So we retry
- // it.
- tctx, cancel := context.WithTimeout(ctx, 30*time.Second)
- defer cancel()
- var msg string
- var ok bool
- err := internal.Retry(tctx, gax.Backoff{}, func() (stop bool, err error) {
- msg, ok = itesting.TestIterator(attrs,
- func() interface{} { return bkt.Objects(ctx, &Query{Prefix: "obj"}) },
- func(it interface{}) (interface{}, error) { return it.(*ObjectIterator).Next() })
- if ok {
- return true, nil
- } else {
- t.Logf("TestIterator failed, trying again: %s", msg)
- return false, nil
- }
- })
- if !ok {
- t.Errorf("ObjectIterator.Next: %s (err=%v)", msg, err)
- }
- // TODO(jba): test query.Delimiter != ""
-}
-
-func TestACL(t *testing.T) {
- ctx := context.Background()
- client, bucket := testConfig(ctx, t)
- defer client.Close()
-
- bkt := client.Bucket(bucket)
-
- entity := ACLEntity("domain-google.com")
- rule := ACLRule{Entity: entity, Role: RoleReader}
- if err := bkt.DefaultObjectACL().Set(ctx, entity, RoleReader); err != nil {
- t.Errorf("Can't put default ACL rule for the bucket, errored with %v", err)
- }
- acl, err := bkt.DefaultObjectACL().List(ctx)
- if err != nil {
- t.Errorf("DefaultObjectACL.List for bucket %q: %v", bucket, err)
- } else if !hasRule(acl, rule) {
- t.Errorf("default ACL missing %#v", rule)
- }
- aclObjects := []string{"acl1", "acl2"}
- for _, obj := range aclObjects {
- c := randomContents()
- if err := writeObject(ctx, bkt.Object(obj), "", c); err != nil {
- t.Errorf("Write for %v failed with %v", obj, err)
- }
- }
- name := aclObjects[0]
- o := bkt.Object(name)
- acl, err = o.ACL().List(ctx)
- if err != nil {
- t.Errorf("Can't retrieve ACL of %v", name)
- } else if !hasRule(acl, rule) {
- t.Errorf("object ACL missing %+v", rule)
- }
- if err := o.ACL().Delete(ctx, entity); err != nil {
- t.Errorf("object ACL: could not delete entity %s", entity)
- }
- // Delete the default ACL rule. We can't move this code earlier in the
- // test, because the test depends on the fact that the object ACL inherits
- // it.
- if err := bkt.DefaultObjectACL().Delete(ctx, entity); err != nil {
- t.Errorf("default ACL: could not delete entity %s", entity)
- }
-
- entity2 := ACLEntity("user-jbd@google.com")
- rule2 := ACLRule{Entity: entity2, Role: RoleReader}
- if err := bkt.ACL().Set(ctx, entity2, RoleReader); err != nil {
- t.Errorf("Error while putting bucket ACL rule: %v", err)
- }
- bACL, err := bkt.ACL().List(ctx)
- if err != nil {
- t.Errorf("Error while getting the ACL of the bucket: %v", err)
- } else if !hasRule(bACL, rule2) {
- t.Errorf("bucket ACL missing %+v", rule2)
- }
- if err := bkt.ACL().Delete(ctx, entity2); err != nil {
- t.Errorf("Error while deleting bucket ACL rule: %v", err)
- }
-
-}
-
-func hasRule(acl []ACLRule, rule ACLRule) bool {
- for _, r := range acl {
- if r == rule {
- return true
- }
- }
- return false
-}
-
-func TestValidObjectNames(t *testing.T) {
- ctx := context.Background()
- client, bucket := testConfig(ctx, t)
- defer client.Close()
-
- bkt := client.Bucket(bucket)
-
- validNames := []string{
- "gopher",
- "Гоферови",
- "a",
- strings.Repeat("a", 1024),
- }
- for _, name := range validNames {
- if err := writeObject(ctx, bkt.Object(name), "", []byte("data")); err != nil {
- t.Errorf("Object %q write failed: %v. Want success", name, err)
- continue
- }
- defer bkt.Object(name).Delete(ctx)
- }
-
- invalidNames := []string{
- "", // Too short.
- strings.Repeat("a", 1025), // Too long.
- "new\nlines",
- "bad\xffunicode",
- }
- for _, name := range invalidNames {
- // Invalid object names will either cause failure during Write or Close.
- if err := writeObject(ctx, bkt.Object(name), "", []byte("data")); err != nil {
- continue
- }
- defer bkt.Object(name).Delete(ctx)
- t.Errorf("%q should have failed. Didn't", name)
- }
-}
-
-func TestWriterContentType(t *testing.T) {
- ctx := context.Background()
- client, bucket := testConfig(ctx, t)
- defer client.Close()
-
- obj := client.Bucket(bucket).Object("content")
- testCases := []struct {
- content string
- setType, wantType string
- }{
- {
- content: "It was the best of times, it was the worst of times.",
- wantType: "text/plain; charset=utf-8",
- },
- {
- content: "<html><head><title>My first page</title></head></html>",
- wantType: "text/html; charset=utf-8",
- },
- {
- content: "<html><head><title>My first page</title></head></html>",
- setType: "text/html",
- wantType: "text/html",
- },
- {
- content: "<html><head><title>My first page</title></head></html>",
- setType: "image/jpeg",
- wantType: "image/jpeg",
- },
- }
- for i, tt := range testCases {
- if err := writeObject(ctx, obj, tt.setType, []byte(tt.content)); err != nil {
- t.Errorf("writing #%d: %v", i, err)
- }
- attrs, err := obj.Attrs(ctx)
- if err != nil {
- t.Errorf("obj.Attrs: %v", err)
- continue
- }
- if got := attrs.ContentType; got != tt.wantType {
- t.Errorf("Content-Type = %q; want %q\nContent: %q\nSet Content-Type: %q", got, tt.wantType, tt.content, tt.setType)
- }
- }
-}
-
-func TestZeroSizedObject(t *testing.T) {
- t.Parallel()
- ctx := context.Background()
- client, bucket := testConfig(ctx, t)
- defer client.Close()
-
- obj := client.Bucket(bucket).Object("zero")
-
- // Check writing it works as expected.
- w := obj.NewWriter(ctx)
- if err := w.Close(); err != nil {
- t.Fatalf("Writer.Close: %v", err)
- }
- defer obj.Delete(ctx)
-
- // Check we can read it too.
- body, err := readObject(ctx, obj)
- if err != nil {
- t.Fatalf("readObject: %v", err)
- }
- if len(body) != 0 {
- t.Errorf("Body is %v, want empty []byte{}", body)
- }
-}
-
-func TestIntegration_Encryption(t *testing.T) {
- // This function tests customer-supplied encryption keys for all operations
- // involving objects. Bucket and ACL operations aren't tested because they
- // aren't affected customer encryption.
- ctx := context.Background()
- client, bucket := testConfig(ctx, t)
- defer client.Close()
-
- obj := client.Bucket(bucket).Object("customer-encryption")
- key := []byte("my-secret-AES-256-encryption-key")
- keyHash := sha256.Sum256(key)
- keyHashB64 := base64.StdEncoding.EncodeToString(keyHash[:])
- key2 := []byte("My-Secret-AES-256-Encryption-Key")
- contents := "top secret."
-
- checkMetadataCall := func(msg string, f func(o *ObjectHandle) (*ObjectAttrs, error)) {
- // Performing a metadata operation without the key should succeed.
- attrs, err := f(obj)
- if err != nil {
- t.Fatalf("%s: %v", msg, err)
- }
- // The key hash should match...
- if got, want := attrs.CustomerKeySHA256, keyHashB64; got != want {
- t.Errorf("%s: key hash: got %q, want %q", msg, got, want)
- }
- // ...but CRC and MD5 should not be present.
- if attrs.CRC32C != 0 {
- t.Errorf("%s: CRC: got %v, want 0", msg, attrs.CRC32C)
- }
- if len(attrs.MD5) > 0 {
- t.Errorf("%s: MD5: got %v, want len == 0", msg, attrs.MD5)
- }
-
- // Performing a metadata operation with the key should succeed.
- attrs, err = f(obj.Key(key))
- if err != nil {
- t.Fatalf("%s: %v", msg, err)
- }
- // Check the key and content hashes.
- if got, want := attrs.CustomerKeySHA256, keyHashB64; got != want {
- t.Errorf("%s: key hash: got %q, want %q", msg, got, want)
- }
- if attrs.CRC32C == 0 {
- t.Errorf("%s: CRC: got 0, want non-zero", msg)
- }
- if len(attrs.MD5) == 0 {
- t.Errorf("%s: MD5: got len == 0, want len > 0", msg)
- }
- }
-
- checkRead := func(msg string, o *ObjectHandle, k []byte, wantContents string) {
- // Reading the object without the key should fail.
- if _, err := readObject(ctx, o); err == nil {
- t.Errorf("%s: reading without key: want error, got nil", msg)
- }
- // Reading the object with the key should succeed.
- got, err := readObject(ctx, o.Key(k))
- if err != nil {
- t.Fatalf("%s: %v", msg, err)
- }
- gotContents := string(got)
- // And the contents should match what we wrote.
- if gotContents != wantContents {
- t.Errorf("%s: contents: got %q, want %q", msg, gotContents, wantContents)
- }
- }
-
- checkReadUnencrypted := func(msg string, obj *ObjectHandle, wantContents string) {
- got, err := readObject(ctx, obj)
- if err != nil {
- t.Fatalf("%s: %v", msg, err)
- }
- gotContents := string(got)
- if gotContents != wantContents {
- t.Errorf("%s: got %q, want %q", gotContents, wantContents)
- }
- }
-
- // Write to obj using our own encryption key, which is a valid 32-byte
- // AES-256 key.
- w := obj.Key(key).NewWriter(ctx)
- w.Write([]byte(contents))
- if err := w.Close(); err != nil {
- t.Fatal(err)
- }
-
- checkMetadataCall("Attrs", func(o *ObjectHandle) (*ObjectAttrs, error) {
- return o.Attrs(ctx)
- })
-
- checkMetadataCall("Update", func(o *ObjectHandle) (*ObjectAttrs, error) {
- return o.Update(ctx, ObjectAttrsToUpdate{ContentLanguage: "en"})
- })
-
- checkRead("first object", obj, key, contents)
-
- obj2 := client.Bucket(bucket).Object("customer-encryption-2")
- // Copying an object without the key should fail.
- if _, err := obj2.CopierFrom(obj).Run(ctx); err == nil {
- t.Fatal("want error, got nil")
- }
- // Copying an object with the key should succeed.
- if _, err := obj2.CopierFrom(obj.Key(key)).Run(ctx); err != nil {
- t.Fatal(err)
- }
- // The destination object is not encrypted; we can read it without a key.
- checkReadUnencrypted("copy dest", obj2, contents)
-
- // Providing a key on the destination but not the source should fail,
- // since the source is encrypted.
- if _, err := obj2.Key(key2).CopierFrom(obj).Run(ctx); err == nil {
- t.Fatal("want error, got nil")
- }
-
- // But copying with keys for both source and destination should succeed.
- if _, err := obj2.Key(key2).CopierFrom(obj.Key(key)).Run(ctx); err != nil {
- t.Fatal(err)
- }
- // And the destination should be encrypted, meaning we can only read it
- // with a key.
- checkRead("copy destination", obj2, key2, contents)
-
- // Change obj2's key to prepare for compose, where all objects must have
- // the same key. Also illustrates key rotation: copy an object to itself
- // with a different key.
- if _, err := obj2.Key(key).CopierFrom(obj2.Key(key2)).Run(ctx); err != nil {
- t.Fatal(err)
- }
- obj3 := client.Bucket(bucket).Object("customer-encryption-3")
- // Composing without keys should fail.
- if _, err := obj3.ComposerFrom(obj, obj2).Run(ctx); err == nil {
- t.Fatal("want error, got nil")
- }
- // Keys on the source objects result in an error.
- if _, err := obj3.ComposerFrom(obj.Key(key), obj2).Run(ctx); err == nil {
- t.Fatal("want error, got nil")
- }
- // A key on the destination object both decrypts the source objects
- // and encrypts the destination.
- if _, err := obj3.Key(key).ComposerFrom(obj, obj2).Run(ctx); err != nil {
- t.Fatalf("got %v, want nil", err)
- }
- // Check that the destination in encrypted.
- checkRead("compose destination", obj3, key, contents+contents)
-
- // You can't compose one or more unencrypted source objects into an
- // encrypted destination object.
- _, err := obj2.CopierFrom(obj2.Key(key)).Run(ctx) // unencrypt obj2
- if err != nil {
- t.Fatal(err)
- }
- if _, err := obj3.Key(key).ComposerFrom(obj2).Run(ctx); err == nil {
- t.Fatal("got nil, want error")
- }
-}
-
-func TestIntegration_NonexistentBucket(t *testing.T) {
- t.Parallel()
- ctx := context.Background()
- client, bucket := testConfig(ctx, t)
- defer client.Close()
-
- bkt := client.Bucket(bucket + "-nonexistent")
- if _, err := bkt.Attrs(ctx); err != ErrBucketNotExist {
- t.Errorf("Attrs: got %v, want ErrBucketNotExist", err)
- }
- it := bkt.Objects(ctx, nil)
- if _, err := it.Next(); err != ErrBucketNotExist {
- t.Errorf("Objects: got %v, want ErrBucketNotExist", err)
- }
-}
-
-func TestIntegration_PerObjectStorageClass(t *testing.T) {
- const (
- defaultStorageClass = "STANDARD"
- newStorageClass = "MULTI_REGIONAL"
- )
- ctx := context.Background()
- client, bucket := testConfig(ctx, t)
- defer client.Close()
-
- bkt := client.Bucket(bucket)
-
- // The bucket should have the default storage class.
- battrs, err := bkt.Attrs(ctx)
- if err != nil {
- t.Fatal(err)
- }
- if battrs.StorageClass != defaultStorageClass {
- t.Fatalf("bucket storage class: got %q, want %q",
- battrs.StorageClass, defaultStorageClass)
- }
- // Write an object; it should start with the bucket's storage class.
- obj := bkt.Object("posc")
- if err := writeObject(ctx, obj, "", []byte("foo")); err != nil {
- t.Fatal(err)
- }
- oattrs, err := obj.Attrs(ctx)
- if err != nil {
- t.Fatal(err)
- }
- if oattrs.StorageClass != defaultStorageClass {
- t.Fatalf("object storage class: got %q, want %q",
- oattrs.StorageClass, defaultStorageClass)
- }
- // Now use Copy to change the storage class.
- copier := obj.CopierFrom(obj)
- copier.StorageClass = newStorageClass
- oattrs2, err := copier.Run(ctx)
- if err != nil {
- log.Fatal(err)
- }
- if oattrs2.StorageClass != newStorageClass {
- t.Fatalf("new object storage class: got %q, want %q",
- oattrs2.StorageClass, newStorageClass)
- }
-
- // We can also write a new object using a non-default storage class.
- obj2 := bkt.Object("posc2")
- w := obj2.NewWriter(ctx)
- w.StorageClass = newStorageClass
- if _, err := w.Write([]byte("xxx")); err != nil {
- t.Fatal(err)
- }
- if err := w.Close(); err != nil {
- t.Fatal(err)
- }
- if w.Attrs().StorageClass != newStorageClass {
- t.Fatalf("new object storage class: got %q, want %q",
- w.Attrs().StorageClass, newStorageClass)
- }
-}
-
-func TestIntegration_BucketInCopyAttrs(t *testing.T) {
- // Confirm that if bucket is included in the object attributes of a rewrite
- // call, but object name and content-type aren't, then we get an error. See
- // the comment in Copier.Run.
- ctx := context.Background()
- client, bucket := testConfig(ctx, t)
- defer client.Close()
-
- bkt := client.Bucket(bucket)
- obj := bkt.Object("bucketInCopyAttrs")
- if err := writeObject(ctx, obj, "", []byte("foo")); err != nil {
- t.Fatal(err)
- }
- copier := obj.CopierFrom(obj)
- rawObject := copier.ObjectAttrs.toRawObject(bucket)
- _, err := copier.callRewrite(ctx, obj, rawObject)
- if err == nil {
- t.Errorf("got nil, want error")
- }
-}
-
-func TestIntegration_NoUnicodeNormalization(t *testing.T) {
- t.Parallel()
- ctx := context.Background()
- client, _ := testConfig(ctx, t)
- defer client.Close()
- bkt := client.Bucket("storage-library-test-bucket")
-
- for _, tst := range []struct {
- nameQuoted, content string
- }{
- {`"Caf\u00e9"`, "Normalization Form C"},
- {`"Cafe\u0301"`, "Normalization Form D"},
- } {
- name, err := strconv.Unquote(tst.nameQuoted)
- if err != nil {
- t.Fatalf("invalid name: %s: %v", tst.nameQuoted, err)
- }
- got, err := readObject(ctx, bkt.Object(name))
- if err != nil {
- t.Fatal(err)
- }
- if g := string(got); g != tst.content {
- t.Errorf("content of %s is %q, want %q", tst.nameQuoted, g, tst.content)
- }
- }
-}
-
-func TestIntegration_HashesOnUpload(t *testing.T) {
- // Check that the user can provide hashes on upload, and that these are checked.
- if testing.Short() {
- t.Skip("Integration tests skipped in short mode")
- }
- ctx := context.Background()
- client, bucket := testConfig(ctx, t)
- if client == nil {
- t.Skip("Integration tests skipped. See CONTRIBUTING.md for details")
- }
- defer client.Close()
- obj := client.Bucket(bucket).Object("hashesOnUpload-1")
- data := []byte("I can't wait to be verified")
-
- write := func(w *Writer) error {
- if _, err := w.Write(data); err != nil {
- w.Close()
- return err
- }
- return w.Close()
- }
-
- crc32c := crc32.Checksum(data, crc32cTable)
- // The correct CRC should succeed.
- w := obj.NewWriter(ctx)
- w.CRC32C = crc32c
- w.SendCRC32C = true
- if err := write(w); err != nil {
- t.Fatal(err)
- }
-
- // If we change the CRC, validation should fail.
- w = obj.NewWriter(ctx)
- w.CRC32C = crc32c + 1
- w.SendCRC32C = true
- if err := write(w); err == nil {
- t.Fatal("write with bad CRC32c: want error, got nil")
- }
-
- // If we have the wrong CRC but forget to send it, we succeed.
- w = obj.NewWriter(ctx)
- w.CRC32C = crc32c + 1
- if err := write(w); err != nil {
- t.Fatal(err)
- }
-
- // MD5
- md5 := md5.Sum(data)
- // The correct MD5 should succeed.
- w = obj.NewWriter(ctx)
- w.MD5 = md5[:]
- if err := write(w); err != nil {
- t.Fatal(err)
- }
-
- // If we change the MD5, validation should fail.
- w = obj.NewWriter(ctx)
- w.MD5 = append([]byte(nil), md5[:]...)
- w.MD5[0]++
- if err := write(w); err == nil {
- t.Fatal("write with bad MD5: want error, got nil")
- }
-}
-
-func TestIntegration_BucketIAM(t *testing.T) {
- ctx := context.Background()
- client, bucket := testConfig(ctx, t)
- defer client.Close()
-
- bkt := client.Bucket(bucket)
-
- // This bucket is unique to this test run. So we don't have
- // to worry about other runs interfering with our IAM policy
- // changes.
-
- member := "projectViewer:" + testutil.ProjID()
- role := iam.RoleName("roles/storage.objectViewer")
- // Get the bucket's IAM policy.
- policy, err := bkt.IAM().Policy(ctx)
- if err != nil {
- t.Fatalf("Getting policy: %v", err)
- }
- // The member should not have the role.
- if policy.HasRole(member, role) {
- t.Errorf("member %q has role %q", member, role)
- }
- // Change the policy.
- policy.Add(member, role)
- if err := bkt.IAM().SetPolicy(ctx, policy); err != nil {
- t.Fatalf("SetPolicy: %v", err)
- }
- // Confirm that the binding was added.
- policy, err = bkt.IAM().Policy(ctx)
- if err != nil {
- t.Fatalf("Getting policy: %v", err)
- }
- if !policy.HasRole(member, role) {
- t.Errorf("member %q does not have role %q", member, role)
- }
-
- // Check TestPermissions.
- // This client should have all these permissions (and more).
- perms := []string{"storage.buckets.get", "storage.buckets.delete"}
- got, err := bkt.IAM().TestPermissions(ctx, perms)
- if err != nil {
- t.Fatalf("TestPermissions: %v", err)
- }
- sort.Strings(perms)
- sort.Strings(got)
- if !reflect.DeepEqual(got, perms) {
- t.Errorf("got %v, want %v", got, perms)
- }
-}
-
-func writeObject(ctx context.Context, obj *ObjectHandle, contentType string, contents []byte) error {
- w := obj.NewWriter(ctx)
- w.ContentType = contentType
- if contents != nil {
- if _, err := w.Write(contents); err != nil {
- _ = w.Close()
- return err
- }
- }
- return w.Close()
-}
-
-func readObject(ctx context.Context, obj *ObjectHandle) ([]byte, error) {
- r, err := obj.NewReader(ctx)
- if err != nil {
- return nil, err
- }
- defer r.Close()
- return ioutil.ReadAll(r)
-}
-
-// cleanup deletes the bucket used for testing, as well as old
-// testing buckets that weren't cleaned previously.
-func cleanup() error {
- if testing.Short() {
- return nil // Don't clean up in short mode.
- }
- ctx := context.Background()
- client, bucket := config(ctx)
- if client == nil {
- return nil // Don't cleanup if we're not configured correctly.
- }
- defer client.Close()
- if err := killBucket(ctx, client, bucket); err != nil {
- return err
- }
-
- // Delete buckets whose name begins with our test prefix, and which were
- // created a while ago. (Unfortunately GCS doesn't provide last-modified
- // time, which would be a better way to check for staleness.)
- const expireAge = 24 * time.Hour
- projectID := testutil.ProjID()
- it := client.Buckets(ctx, projectID)
- it.Prefix = projectID + testPrefix
- for {
- bktAttrs, err := it.Next()
- if err == iterator.Done {
- break
- }
- if err != nil {
- return err
- }
- if time.Since(bktAttrs.Created) > expireAge {
- log.Printf("deleting bucket %q, which is more than %s old", bktAttrs.Name, expireAge)
- if err := killBucket(ctx, client, bktAttrs.Name); err != nil {
- return err
- }
- }
- }
- return nil
-}
-
-// killBucket deletes a bucket and all its objects.
-func killBucket(ctx context.Context, client *Client, bucketName string) error {
- bkt := client.Bucket(bucketName)
- // Bucket must be empty to delete.
- it := bkt.Objects(ctx, nil)
- for {
- objAttrs, err := it.Next()
- if err == iterator.Done {
- break
- }
- if err != nil {
- return err
- }
- if err := bkt.Object(objAttrs.Name).Delete(ctx); err != nil {
- return fmt.Errorf("deleting %q: %v", bucketName+"/"+objAttrs.Name, err)
- }
- }
- // GCS is eventually consistent, so this delete may fail because the
- // replica still sees an object in the bucket. We log the error and expect
- // a later test run to delete the bucket.
- if err := bkt.Delete(ctx); err != nil {
- log.Printf("deleting %q: %v", bucketName, err)
- }
- return nil
-}
-
-func randomContents() []byte {
- h := md5.New()
- io.WriteString(h, fmt.Sprintf("hello world%d", rand.Intn(100000)))
- return h.Sum(nil)
-}
-
-type zeros struct{}
-
-func (zeros) Read(p []byte) (int, error) { return len(p), nil }
diff --git a/vendor/cloud.google.com/go/storage/invoke_test.go b/vendor/cloud.google.com/go/storage/invoke_test.go
deleted file mode 100644
index f7a58070a..000000000
--- a/vendor/cloud.google.com/go/storage/invoke_test.go
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License 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 storage
-
-import (
- "errors"
- "testing"
-
- "golang.org/x/net/context"
- "google.golang.org/api/googleapi"
-)
-
-func TestInvoke(t *testing.T) {
- t.Parallel()
- ctx := context.Background()
- // Time-based tests are flaky. We just make sure that invoke eventually
- // returns with the right error.
-
- for _, test := range []struct {
- count int // number of times to return retryable error
- retryCode int // error code for retryable error
- err error // error to return after count returns of retryCode
- }{
- {0, 0, nil},
- {0, 0, errors.New("foo")},
- {1, 429, nil},
- {1, 429, errors.New("bar")},
- {2, 518, nil},
- {2, 599, &googleapi.Error{Code: 428}},
- } {
- counter := 0
- call := func() error {
- counter++
- if counter <= test.count {
- return &googleapi.Error{Code: test.retryCode}
- }
- return test.err
- }
- got := runWithRetry(ctx, call)
- if got != test.err {
- t.Errorf("%v: got %v, want %v", test, got, test.err)
- }
- }
-}
diff --git a/vendor/cloud.google.com/go/storage/storage_test.go b/vendor/cloud.google.com/go/storage/storage_test.go
deleted file mode 100644
index 47f17e753..000000000
--- a/vendor/cloud.google.com/go/storage/storage_test.go
+++ /dev/null
@@ -1,701 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License 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 storage
-
-import (
- "crypto/tls"
- "encoding/json"
- "fmt"
- "io"
- "io/ioutil"
- "log"
- "net"
- "net/http"
- "net/http/httptest"
- "reflect"
- "strings"
- "testing"
- "time"
-
- "golang.org/x/net/context"
- "google.golang.org/api/iterator"
- "google.golang.org/api/option"
- raw "google.golang.org/api/storage/v1"
-)
-
-func TestSignedURL(t *testing.T) {
- t.Parallel()
- expires, _ := time.Parse(time.RFC3339, "2002-10-02T10:00:00-05:00")
- url, err := SignedURL("bucket-name", "object-name", &SignedURLOptions{
- GoogleAccessID: "xxx@clientid",
- PrivateKey: dummyKey("rsa"),
- Method: "GET",
- MD5: "ICy5YqxZB1uWSwcVLSNLcA==",
- Expires: expires,
- ContentType: "application/json",
- Headers: []string{"x-header1", "x-header2"},
- })
- if err != nil {
- t.Error(err)
- }
- want := "https://storage.googleapis.com/bucket-name/object-name?" +
- "Expires=1033570800&GoogleAccessId=xxx%40clientid&Signature=" +
- "ZMw18bZVhySNYAMEX87RMyuZCUMtGLVi%2B2zU2ByiQ0Rxgij%2BhFZ5LsT" +
- "5ZPIH5h3QXB%2BiSb1URJnZo3aF0exVP%2FYR1hpg2e65w9HHt7yYjIqcg" +
- "%2FfAOIyxriFtgRYk3oAv%2FFLF62fI8iF%2BCp0fWSm%2FHggz22blVnQz" +
- "EtSP%2BuRhFle4172L%2B710sfMDtyQLKTz6W4TmRjC9ymTi8mVj95dZgyF" +
- "RXbibTdtw0JzndE0Ig4c6pU4xDPPiyaziUSVDMIpzZDJH1GYOGHxbFasba4" +
- "1rRoWWkdBnsMtHm2ck%2FsFD2leL6u8q0OpVAc4ZdxseucL4OpCy%2BCLhQ" +
- "JFQT5bqSljP0g%3D%3D"
- if url != want {
- t.Fatalf("Unexpected signed URL; found %v", url)
- }
-}
-
-func TestSignedURL_PEMPrivateKey(t *testing.T) {
- t.Parallel()
- expires, _ := time.Parse(time.RFC3339, "2002-10-02T10:00:00-05:00")
- url, err := SignedURL("bucket-name", "object-name", &SignedURLOptions{
- GoogleAccessID: "xxx@clientid",
- PrivateKey: dummyKey("pem"),
- Method: "GET",
- MD5: "ICy5YqxZB1uWSwcVLSNLcA==",
- Expires: expires,
- ContentType: "application/json",
- Headers: []string{"x-header1", "x-header2"},
- })
- if err != nil {
- t.Error(err)
- }
- want := "https://storage.googleapis.com/bucket-name/object-name?" +
- "Expires=1033570800&GoogleAccessId=xxx%40clientid&Signature=" +
- "gHlh63sOxJnNj22X%2B%2F4kwOSNMeqwXWr4udEfrzJPQcq1xzxA8ovMM5SOrOc%" +
- "2FuE%2Ftc9%2Bq7a42CDBwZff1PsvuJMBDaPbluU257h%2Bvxx8lHMnb%2Bg1wD1" +
- "99FiCE014MRH9TlIg%2FdXRkErosVWTy4GqAgZemmKHo0HwDGT6IovB9mdg%3D"
- if url != want {
- t.Fatalf("Unexpected signed URL; found %v", url)
- }
-}
-
-func TestSignedURL_SignBytes(t *testing.T) {
- t.Parallel()
- expires, _ := time.Parse(time.RFC3339, "2002-10-02T10:00:00-05:00")
- url, err := SignedURL("bucket-name", "object-name", &SignedURLOptions{
- GoogleAccessID: "xxx@clientid",
- SignBytes: func(b []byte) ([]byte, error) {
- return []byte("signed"), nil
- },
- Method: "GET",
- MD5: "ICy5YqxZB1uWSwcVLSNLcA==",
- Expires: expires,
- ContentType: "application/json",
- Headers: []string{"x-header1", "x-header2"},
- })
- if err != nil {
- t.Error(err)
- }
- want := "https://storage.googleapis.com/bucket-name/object-name?" +
- "Expires=1033570800&GoogleAccessId=xxx%40clientid&Signature=" +
- "c2lnbmVk" // base64('signed') == 'c2lnbmVk'
- if url != want {
- t.Fatalf("Unexpected signed URL\ngot: %q\nwant: %q", url, want)
- }
-}
-
-func TestSignedURL_URLUnsafeObjectName(t *testing.T) {
- t.Parallel()
- expires, _ := time.Parse(time.RFC3339, "2002-10-02T10:00:00-05:00")
- url, err := SignedURL("bucket-name", "object name界", &SignedURLOptions{
- GoogleAccessID: "xxx@clientid",
- PrivateKey: dummyKey("pem"),
- Method: "GET",
- MD5: "ICy5YqxZB1uWSwcVLSNLcA==",
- Expires: expires,
- ContentType: "application/json",
- Headers: []string{"x-header1", "x-header2"},
- })
- if err != nil {
- t.Error(err)
- }
- want := "https://storage.googleapis.com/bucket-name/object%20name%E7%95%8C?" +
- "Expires=1033570800&GoogleAccessId=xxx%40clientid&Signature=" +
- "LSxs1YwXNKOa7mQv1ZAI2ao0Fuv6yXLLU7%2BQ97z2B7hYZ57OiFwQ72EdGXSiIM" +
- "JwLisEKkwoSlYCMm3uuTdgJtXXVi7SYXMfdeKaonyQwMv531KETCBTSewt8CW%2B" +
- "FaUJ5SEYG44SeJCiqeIr3GF7t90UNWs6TdFXDaKShpQzBGg%3D"
- if url != want {
- t.Fatalf("Unexpected signed URL; found %v", url)
- }
-}
-
-func TestSignedURL_MissingOptions(t *testing.T) {
- t.Parallel()
- pk := dummyKey("rsa")
- expires, _ := time.Parse(time.RFC3339, "2002-10-02T10:00:00-05:00")
- var tests = []struct {
- opts *SignedURLOptions
- errMsg string
- }{
- {
- &SignedURLOptions{},
- "missing required GoogleAccessID",
- },
- {
- &SignedURLOptions{GoogleAccessID: "access_id"},
- "exactly one of PrivateKey or SignedBytes must be set",
- },
- {
- &SignedURLOptions{
- GoogleAccessID: "access_id",
- SignBytes: func(b []byte) ([]byte, error) { return b, nil },
- PrivateKey: pk,
- },
- "exactly one of PrivateKey or SignedBytes must be set",
- },
- {
- &SignedURLOptions{
- GoogleAccessID: "access_id",
- PrivateKey: pk,
- },
- "missing required method",
- },
- {
- &SignedURLOptions{
- GoogleAccessID: "access_id",
- SignBytes: func(b []byte) ([]byte, error) { return b, nil },
- },
- "missing required method",
- },
- {
- &SignedURLOptions{
- GoogleAccessID: "access_id",
- PrivateKey: pk,
- Method: "PUT",
- },
- "missing required expires",
- },
- {
- &SignedURLOptions{
- GoogleAccessID: "access_id",
- PrivateKey: pk,
- Method: "PUT",
- Expires: expires,
- MD5: "invalid",
- },
- "invalid MD5 checksum",
- },
- }
- for _, test := range tests {
- _, err := SignedURL("bucket", "name", test.opts)
- if !strings.Contains(err.Error(), test.errMsg) {
- t.Errorf("expected err: %v, found: %v", test.errMsg, err)
- }
- }
-}
-
-func dummyKey(kind string) []byte {
- slurp, err := ioutil.ReadFile(fmt.Sprintf("./testdata/dummy_%s", kind))
- if err != nil {
- log.Fatal(err)
- }
- return slurp
-}
-
-func TestCopyToMissingFields(t *testing.T) {
- t.Parallel()
- var tests = []struct {
- srcBucket, srcName, destBucket, destName string
- errMsg string
- }{
- {
- "mybucket", "", "mybucket", "destname",
- "name is empty",
- },
- {
- "mybucket", "srcname", "mybucket", "",
- "name is empty",
- },
- {
- "", "srcfile", "mybucket", "destname",
- "name is empty",
- },
- {
- "mybucket", "srcfile", "", "destname",
- "name is empty",
- },
- }
- ctx := context.Background()
- client, err := NewClient(ctx, option.WithHTTPClient(&http.Client{Transport: &fakeTransport{}}))
- if err != nil {
- panic(err)
- }
- for i, test := range tests {
- src := client.Bucket(test.srcBucket).Object(test.srcName)
- dst := client.Bucket(test.destBucket).Object(test.destName)
- _, err := dst.CopierFrom(src).Run(ctx)
- if !strings.Contains(err.Error(), test.errMsg) {
- t.Errorf("CopyTo test #%v:\ngot err %q\nwant err %q", i, err, test.errMsg)
- }
- }
-}
-
-func TestObjectNames(t *testing.T) {
- t.Parallel()
- // Naming requirements: https://cloud.google.com/storage/docs/bucket-naming
- const maxLegalLength = 1024
-
- type testT struct {
- name, want string
- }
- tests := []testT{
- // Embedded characters important in URLs.
- {"foo % bar", "foo%20%25%20bar"},
- {"foo ? bar", "foo%20%3F%20bar"},
- {"foo / bar", "foo%20/%20bar"},
- {"foo %?/ bar", "foo%20%25%3F/%20bar"},
-
- // Non-Roman scripts
- {"타코", "%ED%83%80%EC%BD%94"},
- {"世界", "%E4%B8%96%E7%95%8C"},
-
- // Longest legal name
- {strings.Repeat("a", maxLegalLength), strings.Repeat("a", maxLegalLength)},
-
- // Line terminators besides CR and LF: https://en.wikipedia.org/wiki/Newline#Unicode
- {"foo \u000b bar", "foo%20%0B%20bar"},
- {"foo \u000c bar", "foo%20%0C%20bar"},
- {"foo \u0085 bar", "foo%20%C2%85%20bar"},
- {"foo \u2028 bar", "foo%20%E2%80%A8%20bar"},
- {"foo \u2029 bar", "foo%20%E2%80%A9%20bar"},
-
- // Null byte.
- {"foo \u0000 bar", "foo%20%00%20bar"},
-
- // Non-control characters that are discouraged, but not forbidden, according to the documentation.
- {"foo # bar", "foo%20%23%20bar"},
- {"foo []*? bar", "foo%20%5B%5D%2A%3F%20bar"},
-
- // Angstrom symbol singleton and normalized forms: http://unicode.org/reports/tr15/
- {"foo \u212b bar", "foo%20%E2%84%AB%20bar"},
- {"foo \u0041\u030a bar", "foo%20A%CC%8A%20bar"},
- {"foo \u00c5 bar", "foo%20%C3%85%20bar"},
-
- // Hangul separating jamo: http://www.unicode.org/versions/Unicode7.0.0/ch18.pdf (Table 18-10)
- {"foo \u3131\u314f bar", "foo%20%E3%84%B1%E3%85%8F%20bar"},
- {"foo \u1100\u1161 bar", "foo%20%E1%84%80%E1%85%A1%20bar"},
- {"foo \uac00 bar", "foo%20%EA%B0%80%20bar"},
- }
-
- // C0 control characters not forbidden by the docs.
- var runes []rune
- for r := rune(0x01); r <= rune(0x1f); r++ {
- if r != '\u000a' && r != '\u000d' {
- runes = append(runes, r)
- }
- }
- tests = append(tests, testT{fmt.Sprintf("foo %s bar", string(runes)), "foo%20%01%02%03%04%05%06%07%08%09%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20bar"})
-
- // C1 control characters, plus DEL.
- runes = nil
- for r := rune(0x7f); r <= rune(0x9f); r++ {
- runes = append(runes, r)
- }
- tests = append(tests, testT{fmt.Sprintf("foo %s bar", string(runes)), "foo%20%7F%C2%80%C2%81%C2%82%C2%83%C2%84%C2%85%C2%86%C2%87%C2%88%C2%89%C2%8A%C2%8B%C2%8C%C2%8D%C2%8E%C2%8F%C2%90%C2%91%C2%92%C2%93%C2%94%C2%95%C2%96%C2%97%C2%98%C2%99%C2%9A%C2%9B%C2%9C%C2%9D%C2%9E%C2%9F%20bar"})
-
- opts := &SignedURLOptions{
- GoogleAccessID: "xxx@clientid",
- PrivateKey: dummyKey("rsa"),
- Method: "GET",
- MD5: "ICy5YqxZB1uWSwcVLSNLcA==",
- Expires: time.Date(2002, time.October, 2, 10, 0, 0, 0, time.UTC),
- ContentType: "application/json",
- Headers: []string{"x-header1", "x-header2"},
- }
-
- for _, test := range tests {
- g, err := SignedURL("bucket-name", test.name, opts)
- if err != nil {
- t.Errorf("SignedURL(%q) err=%v, want nil", test.name, err)
- }
- if w := "/bucket-name/" + test.want; !strings.Contains(g, w) {
- t.Errorf("SignedURL(%q)=%q, want substring %q", test.name, g, w)
- }
- }
-}
-
-func TestCondition(t *testing.T) {
- t.Parallel()
- gotReq := make(chan *http.Request, 1)
- hc, close := newTestServer(func(w http.ResponseWriter, r *http.Request) {
- io.Copy(ioutil.Discard, r.Body)
- gotReq <- r
- w.WriteHeader(200)
- })
- defer close()
- ctx := context.Background()
- c, err := NewClient(ctx, option.WithHTTPClient(hc))
- if err != nil {
- t.Fatal(err)
- }
-
- obj := c.Bucket("buck").Object("obj")
- dst := c.Bucket("dstbuck").Object("dst")
- tests := []struct {
- fn func()
- want string
- }{
- {
- func() { obj.Generation(1234).NewReader(ctx) },
- "GET /buck/obj?generation=1234",
- },
- {
- func() { obj.If(Conditions{GenerationMatch: 1234}).NewReader(ctx) },
- "GET /buck/obj?ifGenerationMatch=1234",
- },
- {
- func() { obj.If(Conditions{GenerationNotMatch: 1234}).NewReader(ctx) },
- "GET /buck/obj?ifGenerationNotMatch=1234",
- },
- {
- func() { obj.If(Conditions{MetagenerationMatch: 1234}).NewReader(ctx) },
- "GET /buck/obj?ifMetagenerationMatch=1234",
- },
- {
- func() { obj.If(Conditions{MetagenerationNotMatch: 1234}).NewReader(ctx) },
- "GET /buck/obj?ifMetagenerationNotMatch=1234",
- },
- {
- func() { obj.If(Conditions{MetagenerationNotMatch: 1234}).Attrs(ctx) },
- "GET /storage/v1/b/buck/o/obj?alt=json&ifMetagenerationNotMatch=1234&projection=full",
- },
-
- {
- func() { obj.If(Conditions{MetagenerationMatch: 1234}).Update(ctx, ObjectAttrsToUpdate{}) },
- "PATCH /storage/v1/b/buck/o/obj?alt=json&ifMetagenerationMatch=1234&projection=full",
- },
- {
- func() { obj.Generation(1234).Delete(ctx) },
- "DELETE /storage/v1/b/buck/o/obj?alt=json&generation=1234",
- },
- {
- func() {
- w := obj.If(Conditions{GenerationMatch: 1234}).NewWriter(ctx)
- w.ContentType = "text/plain"
- w.Close()
- },
- "POST /upload/storage/v1/b/buck/o?alt=json&ifGenerationMatch=1234&projection=full&uploadType=multipart",
- },
- {
- func() {
- w := obj.If(Conditions{DoesNotExist: true}).NewWriter(ctx)
- w.ContentType = "text/plain"
- w.Close()
- },
- "POST /upload/storage/v1/b/buck/o?alt=json&ifGenerationMatch=0&projection=full&uploadType=multipart",
- },
- {
- func() {
- dst.If(Conditions{MetagenerationMatch: 5678}).CopierFrom(obj.If(Conditions{GenerationMatch: 1234})).Run(ctx)
- },
- "POST /storage/v1/b/buck/o/obj/rewriteTo/b/dstbuck/o/dst?alt=json&ifMetagenerationMatch=5678&ifSourceGenerationMatch=1234&projection=full",
- },
- }
-
- for i, tt := range tests {
- tt.fn()
- select {
- case r := <-gotReq:
- got := r.Method + " " + r.RequestURI
- if got != tt.want {
- t.Errorf("%d. RequestURI = %q; want %q", i, got, tt.want)
- }
- case <-time.After(5 * time.Second):
- t.Fatalf("%d. timeout", i)
- }
- if err != nil {
- t.Fatal(err)
- }
- }
-
- // Test an error, too:
- err = obj.Generation(1234).NewWriter(ctx).Close()
- if err == nil || !strings.Contains(err.Error(), "NewWriter: generation not supported") {
- t.Errorf("want error about unsupported generation; got %v", err)
- }
-}
-
-func TestConditionErrors(t *testing.T) {
- t.Parallel()
- for _, conds := range []Conditions{
- {GenerationMatch: 0},
- {DoesNotExist: false}, // same as above, actually
- {GenerationMatch: 1, GenerationNotMatch: 2},
- {GenerationNotMatch: 2, DoesNotExist: true},
- {MetagenerationMatch: 1, MetagenerationNotMatch: 2},
- } {
- if err := conds.validate(""); err == nil {
- t.Errorf("%+v: got nil, want error", conds)
- }
- }
-}
-
-// Test object compose.
-func TestObjectCompose(t *testing.T) {
- t.Parallel()
- gotURL := make(chan string, 1)
- gotBody := make(chan []byte, 1)
- hc, close := newTestServer(func(w http.ResponseWriter, r *http.Request) {
- body, _ := ioutil.ReadAll(r.Body)
- gotURL <- r.URL.String()
- gotBody <- body
- w.Write([]byte("{}"))
- })
- defer close()
- ctx := context.Background()
- c, err := NewClient(ctx, option.WithHTTPClient(hc))
- if err != nil {
- t.Fatal(err)
- }
-
- testCases := []struct {
- desc string
- dst *ObjectHandle
- srcs []*ObjectHandle
- attrs *ObjectAttrs
- wantReq raw.ComposeRequest
- wantURL string
- wantErr bool
- }{
- {
- desc: "basic case",
- dst: c.Bucket("foo").Object("bar"),
- srcs: []*ObjectHandle{
- c.Bucket("foo").Object("baz"),
- c.Bucket("foo").Object("quux"),
- },
- wantURL: "/storage/v1/b/foo/o/bar/compose?alt=json",
- wantReq: raw.ComposeRequest{
- Destination: &raw.Object{Bucket: "foo"},
- SourceObjects: []*raw.ComposeRequestSourceObjects{
- {Name: "baz"},
- {Name: "quux"},
- },
- },
- },
- {
- desc: "with object attrs",
- dst: c.Bucket("foo").Object("bar"),
- srcs: []*ObjectHandle{
- c.Bucket("foo").Object("baz"),
- c.Bucket("foo").Object("quux"),
- },
- attrs: &ObjectAttrs{
- Name: "not-bar",
- ContentType: "application/json",
- },
- wantURL: "/storage/v1/b/foo/o/bar/compose?alt=json",
- wantReq: raw.ComposeRequest{
- Destination: &raw.Object{
- Bucket: "foo",
- Name: "not-bar",
- ContentType: "application/json",
- },
- SourceObjects: []*raw.ComposeRequestSourceObjects{
- {Name: "baz"},
- {Name: "quux"},
- },
- },
- },
- {
- desc: "with conditions",
- dst: c.Bucket("foo").Object("bar").If(Conditions{
- GenerationMatch: 12,
- MetagenerationMatch: 34,
- }),
- srcs: []*ObjectHandle{
- c.Bucket("foo").Object("baz").Generation(56),
- c.Bucket("foo").Object("quux").If(Conditions{GenerationMatch: 78}),
- },
- wantURL: "/storage/v1/b/foo/o/bar/compose?alt=json&ifGenerationMatch=12&ifMetagenerationMatch=34",
- wantReq: raw.ComposeRequest{
- Destination: &raw.Object{Bucket: "foo"},
- SourceObjects: []*raw.ComposeRequestSourceObjects{
- {
- Name: "baz",
- Generation: 56,
- },
- {
- Name: "quux",
- ObjectPreconditions: &raw.ComposeRequestSourceObjectsObjectPreconditions{
- IfGenerationMatch: 78,
- },
- },
- },
- },
- },
- {
- desc: "no sources",
- dst: c.Bucket("foo").Object("bar"),
- wantErr: true,
- },
- {
- desc: "destination, no bucket",
- dst: c.Bucket("").Object("bar"),
- srcs: []*ObjectHandle{
- c.Bucket("foo").Object("baz"),
- },
- wantErr: true,
- },
- {
- desc: "destination, no object",
- dst: c.Bucket("foo").Object(""),
- srcs: []*ObjectHandle{
- c.Bucket("foo").Object("baz"),
- },
- wantErr: true,
- },
- {
- desc: "source, different bucket",
- dst: c.Bucket("foo").Object("bar"),
- srcs: []*ObjectHandle{
- c.Bucket("otherbucket").Object("baz"),
- },
- wantErr: true,
- },
- {
- desc: "source, no object",
- dst: c.Bucket("foo").Object("bar"),
- srcs: []*ObjectHandle{
- c.Bucket("foo").Object(""),
- },
- wantErr: true,
- },
- {
- desc: "destination, bad condition",
- dst: c.Bucket("foo").Object("bar").Generation(12),
- srcs: []*ObjectHandle{
- c.Bucket("foo").Object("baz"),
- },
- wantErr: true,
- },
- {
- desc: "source, bad condition",
- dst: c.Bucket("foo").Object("bar"),
- srcs: []*ObjectHandle{
- c.Bucket("foo").Object("baz").If(Conditions{MetagenerationMatch: 12}),
- },
- wantErr: true,
- },
- }
-
- for _, tt := range testCases {
- composer := tt.dst.ComposerFrom(tt.srcs...)
- if tt.attrs != nil {
- composer.ObjectAttrs = *tt.attrs
- }
- _, err := composer.Run(ctx)
- if gotErr := err != nil; gotErr != tt.wantErr {
- t.Errorf("%s: got error %v; want err %t", tt.desc, err, tt.wantErr)
- continue
- }
- if tt.wantErr {
- continue
- }
- url, body := <-gotURL, <-gotBody
- if url != tt.wantURL {
- t.Errorf("%s: request URL\ngot %q\nwant %q", tt.desc, url, tt.wantURL)
- }
- var req raw.ComposeRequest
- if err := json.Unmarshal(body, &req); err != nil {
- t.Errorf("%s: json.Unmarshal %v (body %s)", tt.desc, err, body)
- }
- if !reflect.DeepEqual(req, tt.wantReq) {
- // Print to JSON.
- wantReq, _ := json.Marshal(tt.wantReq)
- t.Errorf("%s: request body\ngot %s\nwant %s", tt.desc, body, wantReq)
- }
- }
-}
-
-// Test that ObjectIterator's Next and NextPage methods correctly terminate
-// if there is nothing to iterate over.
-func TestEmptyObjectIterator(t *testing.T) {
- t.Parallel()
- hClient, close := newTestServer(func(w http.ResponseWriter, r *http.Request) {
- io.Copy(ioutil.Discard, r.Body)
- fmt.Fprintf(w, "{}")
- })
- defer close()
- ctx := context.Background()
- client, err := NewClient(ctx, option.WithHTTPClient(hClient))
- if err != nil {
- t.Fatal(err)
- }
- it := client.Bucket("b").Objects(ctx, nil)
- _, err = it.Next()
- if err != iterator.Done {
- t.Errorf("got %v, want Done", err)
- }
-}
-
-// Test that BucketIterator's Next method correctly terminates if there is
-// nothing to iterate over.
-func TestEmptyBucketIterator(t *testing.T) {
- t.Parallel()
- hClient, close := newTestServer(func(w http.ResponseWriter, r *http.Request) {
- io.Copy(ioutil.Discard, r.Body)
- fmt.Fprintf(w, "{}")
- })
- defer close()
- ctx := context.Background()
- client, err := NewClient(ctx, option.WithHTTPClient(hClient))
- if err != nil {
- t.Fatal(err)
- }
- it := client.Buckets(ctx, "project")
- _, err = it.Next()
- if err != iterator.Done {
- t.Errorf("got %v, want Done", err)
- }
-
-}
-
-func TestCodecUint32(t *testing.T) {
- t.Parallel()
- for _, u := range []uint32{0, 1, 256, 0xFFFFFFFF} {
- s := encodeUint32(u)
- d, err := decodeUint32(s)
- if err != nil {
- t.Fatal(err)
- }
- if d != u {
- t.Errorf("got %d, want input %d", d, u)
- }
- }
-}
-
-func newTestServer(handler func(w http.ResponseWriter, r *http.Request)) (*http.Client, func()) {
- ts := httptest.NewTLSServer(http.HandlerFunc(handler))
- tlsConf := &tls.Config{InsecureSkipVerify: true}
- tr := &http.Transport{
- TLSClientConfig: tlsConf,
- DialTLS: func(netw, addr string) (net.Conn, error) {
- return tls.Dial("tcp", ts.Listener.Addr().String(), tlsConf)
- },
- }
- return &http.Client{Transport: tr}, func() {
- tr.CloseIdleConnections()
- ts.Close()
- }
-}
diff --git a/vendor/cloud.google.com/go/storage/testdata/dummy_pem b/vendor/cloud.google.com/go/storage/testdata/dummy_pem
deleted file mode 100644
index 3428d4497..000000000
--- a/vendor/cloud.google.com/go/storage/testdata/dummy_pem
+++ /dev/null
@@ -1,39 +0,0 @@
-Bag Attributes
- friendlyName: privatekey
- localKeyID: 54 69 6D 65 20 31 34 31 36 38 35 32 30 30 34 37 37 32
-Key Attributes: <No Attributes>
------BEGIN RSA PRIVATE KEY-----
-MIICXQIBAAKBgQCtCWMoJ2Bok2QoGFyU7A6IlGprO9QfUTT0jNrLkIbM5OWNIuDx
-64+PEaTS5g5m+2Hz/lmd5jJKanAH4dY9LZzsaYAPq1K17Gcmg1hEisYeKsgOcjYY
-kwRkV+natCTsC+tfWmS0voRh0jA1rI1J4MikceoHtgWdEuoHrrptRVpWKwIDAQAB
-AoGAKp3uQvx3vSnX+BwP6Um+RpsvHpwMoW3xue1bEdnVqW8SrlERz+NxZw40ZxDs
-KSbuuBZD4iTI7BUM5JQVnNm4FQY1YrPlWZLyI73Bj8RKTXrPdJheM/0r7xjiIXbQ
-7w4cUSM9rVugnI/rxF2kPIQTGYI+EG/6+P+k6VvgPmC0T/ECQQDUPskiS18WaY+i
-Koalbrb3GakaBoHrC1b4ln4CAv7fq7H4WvFvqi/2rxLhHYq31iwxYy8s7J7Sba1+
-5vwJ2TxZAkEA0LVfs3Q2VWZ+cM3bv0aYTalMXg6wT+LoNvk9HnOb0zQYajF3qm4G
-ZFdfEqvOkje0zQ4fcihARKyda/VY84UGIwJBAIZa0FvjNmgrnn7bSKzEbxHwrnkJ
-EYjGfuGR8mY3mzvfpiM+/oLfSslvfhX+62cALq18yco4ZzlxsFgaxAU//NECQDcS
-NN94YcHlGqYPW9W7/gI4EwOaoqFhwV6II71+SfbP/0U+KlJZV+xwNZEKrqZcdqPI
-/zkzL8ovNha/laokRrsCQQCyoPHGcBWj+VFbNoyQnX4tghc6rOY7n4pmpgQvU825
-TAM9vnYtSkKK/V56kEDNBO5LwiRsir95IUNclqqMKR1C
------END RSA PRIVATE KEY-----
-Bag Attributes
- friendlyName: privatekey
- localKeyID: 54 69 6D 65 20 31 34 31 36 38 35 32 30 30 34 37 37 32
-subject=/CN=1079432350659-nvog0vmn9s6pqr3kr4v2avbc7nkhoa11.apps.googleusercontent.com
-issuer=/CN=1079432350659-nvog0vmn9s6pqr3kr4v2avbc7nkhoa11.apps.googleusercontent.com
------BEGIN CERTIFICATE-----
-MIICXTCCAcagAwIBAgIIHxTMQUVJRZ0wDQYJKoZIhvcNAQEFBQAwVDFSMFAGA1UE
-AxNJMTA3OTQzMjM1MDY1OS1udm9nMHZtbjlzNnBxcjNrcjR2MmF2YmM3bmtob2Ex
-MS5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbTAeFw0xNDExMjQxODAwMDRaFw0y
-NDExMjExODAwMDRaMFQxUjBQBgNVBAMTSTEwNzk0MzIzNTA2NTktbnZvZzB2bW45
-czZwcXIza3I0djJhdmJjN25raG9hMTEuYXBwcy5nb29nbGV1c2VyY29udGVudC5j
-b20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAK0JYygnYGiTZCgYXJTsDoiU
-ams71B9RNPSM2suQhszk5Y0i4PHrj48RpNLmDmb7YfP+WZ3mMkpqcAfh1j0tnOxp
-gA+rUrXsZyaDWESKxh4qyA5yNhiTBGRX6dq0JOwL619aZLS+hGHSMDWsjUngyKRx
-6ge2BZ0S6geuum1FWlYrAgMBAAGjODA2MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/
-BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEBBQUAA4GB
-ACVvKkZkomHq3uffOQwdZ4VJYuxrvDGnZu/ExW9WngO2teEsjxABL41TNnRYHN5T
-lMC19poFA2tR/DySDLJ2XNs/hSvyQUL6HHCncVdR4Srpie88j48peY1MZSMP51Jv
-qagbbP5K5DSEu02/zZaV0kaCvLEN0KAtj/noDuOOnQU2
------END CERTIFICATE-----
diff --git a/vendor/cloud.google.com/go/storage/testdata/dummy_rsa b/vendor/cloud.google.com/go/storage/testdata/dummy_rsa
deleted file mode 100644
index 4ce6678db..000000000
--- a/vendor/cloud.google.com/go/storage/testdata/dummy_rsa
+++ /dev/null
@@ -1,27 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEAx4fm7dngEmOULNmAs1IGZ9Apfzh+BkaQ1dzkmbUgpcoghucE
-DZRnAGd2aPyB6skGMXUytWQvNYav0WTR00wFtX1ohWTfv68HGXJ8QXCpyoSKSSFY
-fuP9X36wBSkSX9J5DVgiuzD5VBdzUISSmapjKm+DcbRALjz6OUIPEWi1Tjl6p5RK
-1w41qdbmt7E5/kGhKLDuT7+M83g4VWhgIvaAXtnhklDAggilPPa8ZJ1IFe31lNlr
-k4DRk38nc6sEutdf3RL7QoH7FBusI7uXV03DC6dwN1kP4GE7bjJhcRb/7jYt7CQ9
-/E9Exz3c0yAp0yrTg0Fwh+qxfH9dKwN52S7SBwIDAQABAoIBAQCaCs26K07WY5Jt
-3a2Cw3y2gPrIgTCqX6hJs7O5ByEhXZ8nBwsWANBUe4vrGaajQHdLj5OKfsIDrOvn
-2NI1MqflqeAbu/kR32q3tq8/Rl+PPiwUsW3E6Pcf1orGMSNCXxeducF2iySySzh3
-nSIhCG5uwJDWI7a4+9KiieFgK1pt/Iv30q1SQS8IEntTfXYwANQrfKUVMmVF9aIK
-6/WZE2yd5+q3wVVIJ6jsmTzoDCX6QQkkJICIYwCkglmVy5AeTckOVwcXL0jqw5Kf
-5/soZJQwLEyBoQq7Kbpa26QHq+CJONetPP8Ssy8MJJXBT+u/bSseMb3Zsr5cr43e
-DJOhwsThAoGBAPY6rPKl2NT/K7XfRCGm1sbWjUQyDShscwuWJ5+kD0yudnT/ZEJ1
-M3+KS/iOOAoHDdEDi9crRvMl0UfNa8MAcDKHflzxg2jg/QI+fTBjPP5GOX0lkZ9g
-z6VePoVoQw2gpPFVNPPTxKfk27tEzbaffvOLGBEih0Kb7HTINkW8rIlzAoGBAM9y
-1yr+jvfS1cGFtNU+Gotoihw2eMKtIqR03Yn3n0PK1nVCDKqwdUqCypz4+ml6cxRK
-J8+Pfdh7D+ZJd4LEG6Y4QRDLuv5OA700tUoSHxMSNn3q9As4+T3MUyYxWKvTeu3U
-f2NWP9ePU0lV8ttk7YlpVRaPQmc1qwooBA/z/8AdAoGAW9x0HWqmRICWTBnpjyxx
-QGlW9rQ9mHEtUotIaRSJ6K/F3cxSGUEkX1a3FRnp6kPLcckC6NlqdNgNBd6rb2rA
-cPl/uSkZP42Als+9YMoFPU/xrrDPbUhu72EDrj3Bllnyb168jKLa4VBOccUvggxr
-Dm08I1hgYgdN5huzs7y6GeUCgYEAj+AZJSOJ6o1aXS6rfV3mMRve9bQ9yt8jcKXw
-5HhOCEmMtaSKfnOF1Ziih34Sxsb7O2428DiX0mV/YHtBnPsAJidL0SdLWIapBzeg
-KHArByIRkwE6IvJvwpGMdaex1PIGhx5i/3VZL9qiq/ElT05PhIb+UXgoWMabCp84
-OgxDK20CgYAeaFo8BdQ7FmVX2+EEejF+8xSge6WVLtkaon8bqcn6P0O8lLypoOhd
-mJAYH8WU+UAy9pecUnDZj14LAGNVmYcse8HFX71MoshnvCTFEPVo4rZxIAGwMpeJ
-5jgQ3slYLpqrGlcbLgUXBUgzEO684Wk/UV9DFPlHALVqCfXQ9dpJPg==
------END RSA PRIVATE KEY-----
diff --git a/vendor/cloud.google.com/go/storage/writer.go b/vendor/cloud.google.com/go/storage/writer.go
index 809dfb1bd..21ffdb91c 100644
--- a/vendor/cloud.google.com/go/storage/writer.go
+++ b/vendor/cloud.google.com/go/storage/writer.go
@@ -49,16 +49,6 @@ type Writer struct {
// must be done before the first Write call.
ChunkSize int
- // ProgressFunc can be used to monitor the progress of a large write.
- // operation. If ProgressFunc is not nil and writing requires multiple
- // calls to the underlying service (see
- // https://cloud.google.com/storage/docs/json_api/v1/how-tos/resumable-upload),
- // then ProgressFunc will be invoked after each call with the number of bytes of
- // content copied so far.
- //
- // ProgressFunc should return quickly without blocking.
- ProgressFunc func(int64)
-
ctx context.Context
o *ObjectHandle
@@ -108,9 +98,6 @@ func (w *Writer) open() error {
Media(pr, mediaOpts...).
Projection("full").
Context(w.ctx)
- if w.ProgressFunc != nil {
- call.ProgressUpdater(func(n, _ int64) { w.ProgressFunc(n) })
- }
if err := setEncryptionHeaders(call.Header(), w.o.encryptionKey, false); err != nil {
w.err = err
pr.CloseWithError(w.err)
@@ -120,14 +107,7 @@ func (w *Writer) open() error {
err := applyConds("NewWriter", w.o.gen, w.o.conds, call)
if err == nil {
setClientHeader(call.Header())
- // We will only retry here if the initial POST, which obtains a URI for
- // the resumable upload, fails with a retryable error. The upload itself
- // has its own retry logic.
- err = runWithRetry(w.ctx, func() error {
- var err2 error
- resp, err2 = call.Do()
- return err2
- })
+ resp, err = call.Do()
}
if err != nil {
w.err = err
@@ -140,11 +120,6 @@ func (w *Writer) open() error {
}
// Write appends to w. It implements the io.Writer interface.
-//
-// Since writes happen asynchronously, Write may return a nil
-// error even though the write failed (or will fail). Always
-// use the error returned from Writer.Close to determine if
-// the upload was successful.
func (w *Writer) Write(p []byte) (n int, err error) {
if w.err != nil {
return 0, w.err
diff --git a/vendor/cloud.google.com/go/storage/writer_test.go b/vendor/cloud.google.com/go/storage/writer_test.go
deleted file mode 100644
index 87b6adaf8..000000000
--- a/vendor/cloud.google.com/go/storage/writer_test.go
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License 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 storage
-
-import (
- "bytes"
- "crypto/sha256"
- "encoding/base64"
- "fmt"
- "io/ioutil"
- "net/http"
- "reflect"
- "strings"
- "testing"
-
- "golang.org/x/net/context"
-
- "google.golang.org/api/option"
-)
-
-type fakeTransport struct {
- gotReq *http.Request
- results []transportResult
-}
-
-type transportResult struct {
- res *http.Response
- err error
-}
-
-func (t *fakeTransport) addResult(res *http.Response, err error) {
- t.results = append(t.results, transportResult{res, err})
-}
-
-func (t *fakeTransport) RoundTrip(req *http.Request) (*http.Response, error) {
- t.gotReq = req
- if len(t.results) == 0 {
- return nil, fmt.Errorf("error handling request")
- }
- result := t.results[0]
- t.results = t.results[1:]
- return result.res, result.err
-}
-
-func TestErrorOnObjectsInsertCall(t *testing.T) {
- t.Parallel()
- ctx := context.Background()
-
- doWrite := func(hc *http.Client) *Writer {
- client, err := NewClient(ctx, option.WithHTTPClient(hc))
- if err != nil {
- t.Fatalf("error when creating client: %v", err)
- }
- wc := client.Bucket("bucketname").Object("filename1").NewWriter(ctx)
- wc.ContentType = "text/plain"
-
- // We can't check that the Write fails, since it depends on the write to the
- // underling fakeTransport failing which is racy.
- wc.Write([]byte("hello world"))
- return wc
- }
-
- wc := doWrite(&http.Client{Transport: &fakeTransport{}})
- // Close must always return an error though since it waits for the transport to
- // have closed.
- if err := wc.Close(); err == nil {
- t.Errorf("expected error on close, got nil")
- }
-
- // Retry on 5xx
- ft := &fakeTransport{}
- ft.addResult(&http.Response{
- StatusCode: 503,
- Body: ioutil.NopCloser(&bytes.Buffer{}),
- }, nil)
- ft.addResult(&http.Response{
- StatusCode: 200,
- Body: ioutil.NopCloser(strings.NewReader("{}")),
- }, nil)
- wc = doWrite(&http.Client{Transport: ft})
- if err := wc.Close(); err != nil {
- t.Errorf("got %v, want nil", err)
- }
-}
-
-func TestEncryption(t *testing.T) {
- t.Parallel()
- ctx := context.Background()
- ft := &fakeTransport{}
- hc := &http.Client{Transport: ft}
- client, err := NewClient(ctx, option.WithHTTPClient(hc))
- if err != nil {
- t.Fatalf("error when creating client: %v", err)
- }
- obj := client.Bucket("bucketname").Object("filename1")
- key := []byte("secret-key-that-is-32-bytes-long")
- wc := obj.Key(key).NewWriter(ctx)
- // TODO(jba): use something other than fakeTransport, which always returns error.
- wc.Write([]byte("hello world"))
- wc.Close()
- if got, want := ft.gotReq.Header.Get("x-goog-encryption-algorithm"), "AES256"; got != want {
- t.Errorf("algorithm: got %q, want %q", got, want)
- }
- gotKey, err := base64.StdEncoding.DecodeString(ft.gotReq.Header.Get("x-goog-encryption-key"))
- if err != nil {
- t.Fatalf("decoding key: %v", err)
- }
- if !reflect.DeepEqual(gotKey, key) {
- t.Errorf("key: got %v, want %v", gotKey, key)
- }
- wantHash := sha256.Sum256(key)
- gotHash, err := base64.StdEncoding.DecodeString(ft.gotReq.Header.Get("x-goog-encryption-key-sha256"))
- if err != nil {
- t.Fatalf("decoding hash: %v", err)
- }
- if !reflect.DeepEqual(gotHash, wantHash[:]) { // wantHash is an array
- t.Errorf("hash: got\n%v, want\n%v", gotHash, wantHash)
- }
-}