Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 

2354 rindas
69 KiB

  1. // Copyright 2014 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package storage
  15. import (
  16. "bytes"
  17. "compress/gzip"
  18. "crypto/md5"
  19. "crypto/sha256"
  20. "encoding/base64"
  21. "encoding/json"
  22. "flag"
  23. "fmt"
  24. "hash/crc32"
  25. "io"
  26. "io/ioutil"
  27. "log"
  28. "math/rand"
  29. "net/http"
  30. "os"
  31. "path/filepath"
  32. "runtime"
  33. "sort"
  34. "strconv"
  35. "strings"
  36. "testing"
  37. "time"
  38. "github.com/google/go-cmp/cmp/cmpopts"
  39. "golang.org/x/net/context"
  40. "cloud.google.com/go/iam"
  41. "cloud.google.com/go/internal/testutil"
  42. "cloud.google.com/go/internal/uid"
  43. "google.golang.org/api/googleapi"
  44. "google.golang.org/api/iterator"
  45. itesting "google.golang.org/api/iterator/testing"
  46. "google.golang.org/api/option"
  47. )
  48. const testPrefix = "go-integration-test"
  49. var (
  50. uidSpace = uid.NewSpace(testPrefix, nil)
  51. bucketName = uidSpace.New()
  52. )
  53. func TestMain(m *testing.M) {
  54. integrationTest := initIntegrationTest()
  55. exit := m.Run()
  56. if integrationTest {
  57. if err := cleanup(); err != nil {
  58. // No need to be loud if cleanup() fails; we'll get
  59. // any undeleted buckets next time.
  60. log.Printf("Post-test cleanup failed: %v\n", err)
  61. }
  62. }
  63. os.Exit(exit)
  64. }
  65. // If integration tests will be run, create a unique bucket for them.
  66. func initIntegrationTest() bool {
  67. flag.Parse() // needed for testing.Short()
  68. ctx := context.Background()
  69. if testing.Short() {
  70. return false
  71. }
  72. client := config(ctx)
  73. if client == nil {
  74. return false
  75. }
  76. defer client.Close()
  77. if err := client.Bucket(bucketName).Create(ctx, testutil.ProjID(), nil); err != nil {
  78. log.Fatalf("creating bucket %q: %v", bucketName, err)
  79. }
  80. return true
  81. }
  82. // testConfig returns the Client used to access GCS. testConfig skips
  83. // the current test if credentials are not available or when being run
  84. // in Short mode.
  85. func testConfig(ctx context.Context, t *testing.T) *Client {
  86. if testing.Short() {
  87. t.Skip("Integration tests skipped in short mode")
  88. }
  89. client := config(ctx)
  90. if client == nil {
  91. t.Skip("Integration tests skipped. See CONTRIBUTING.md for details")
  92. }
  93. return client
  94. }
  95. // config is like testConfig, but it doesn't need a *testing.T.
  96. func config(ctx context.Context) *Client {
  97. ts := testutil.TokenSource(ctx, ScopeFullControl)
  98. if ts == nil {
  99. return nil
  100. }
  101. p := testutil.ProjID()
  102. if p == "" {
  103. log.Fatal("The project ID must be set. See CONTRIBUTING.md for details")
  104. }
  105. client, err := NewClient(ctx, option.WithTokenSource(ts))
  106. if err != nil {
  107. log.Fatalf("NewClient: %v", err)
  108. }
  109. return client
  110. }
  111. func TestIntegration_BucketMethods(t *testing.T) {
  112. ctx := context.Background()
  113. client := testConfig(ctx, t)
  114. defer client.Close()
  115. h := testHelper{t}
  116. projectID := testutil.ProjID()
  117. newBucketName := uidSpace.New()
  118. b := client.Bucket(newBucketName)
  119. // Test Create and Delete.
  120. h.mustCreate(b, projectID, nil)
  121. attrs := h.mustBucketAttrs(b)
  122. if got, want := attrs.MetaGeneration, int64(1); got != want {
  123. t.Errorf("got metagen %d, want %d", got, want)
  124. }
  125. if got, want := attrs.StorageClass, "STANDARD"; got != want {
  126. t.Errorf("got storage class %q, want %q", got, want)
  127. }
  128. if attrs.VersioningEnabled {
  129. t.Error("got versioning enabled, wanted it disabled")
  130. }
  131. h.mustDeleteBucket(b)
  132. // Test Create and Delete with attributes.
  133. labels := map[string]string{
  134. "l1": "v1",
  135. "empty": "",
  136. }
  137. attrs = &BucketAttrs{
  138. StorageClass: "NEARLINE",
  139. VersioningEnabled: true,
  140. Labels: labels,
  141. Lifecycle: Lifecycle{
  142. Rules: []LifecycleRule{{
  143. Action: LifecycleAction{
  144. Type: SetStorageClassAction,
  145. StorageClass: "NEARLINE",
  146. },
  147. Condition: LifecycleCondition{
  148. AgeInDays: 10,
  149. Liveness: Archived,
  150. CreatedBefore: time.Date(2017, 1, 1, 0, 0, 0, 0, time.UTC),
  151. MatchesStorageClasses: []string{"MULTI_REGIONAL", "STANDARD"},
  152. NumNewerVersions: 3,
  153. },
  154. }, {
  155. Action: LifecycleAction{
  156. Type: DeleteAction,
  157. },
  158. Condition: LifecycleCondition{
  159. AgeInDays: 30,
  160. Liveness: Live,
  161. CreatedBefore: time.Date(2017, 1, 1, 0, 0, 0, 0, time.UTC),
  162. MatchesStorageClasses: []string{"NEARLINE"},
  163. NumNewerVersions: 10,
  164. },
  165. }},
  166. },
  167. }
  168. h.mustCreate(b, projectID, attrs)
  169. attrs = h.mustBucketAttrs(b)
  170. if got, want := attrs.MetaGeneration, int64(1); got != want {
  171. t.Errorf("got metagen %d, want %d", got, want)
  172. }
  173. if got, want := attrs.StorageClass, "NEARLINE"; got != want {
  174. t.Errorf("got storage class %q, want %q", got, want)
  175. }
  176. if !attrs.VersioningEnabled {
  177. t.Error("got versioning disabled, wanted it enabled")
  178. }
  179. if got, want := attrs.Labels, labels; !testutil.Equal(got, want) {
  180. t.Errorf("labels: got %v, want %v", got, want)
  181. }
  182. h.mustDeleteBucket(b)
  183. }
  184. func TestIntegration_BucketUpdate(t *testing.T) {
  185. ctx := context.Background()
  186. client := testConfig(ctx, t)
  187. defer client.Close()
  188. h := testHelper{t}
  189. b := client.Bucket(bucketName)
  190. attrs := h.mustBucketAttrs(b)
  191. if attrs.VersioningEnabled {
  192. t.Fatal("bucket should not have versioning by default")
  193. }
  194. if len(attrs.Labels) > 0 {
  195. t.Fatal("bucket should not have labels initially")
  196. }
  197. // Using empty BucketAttrsToUpdate should be a no-nop.
  198. attrs = h.mustUpdateBucket(b, BucketAttrsToUpdate{})
  199. if attrs.VersioningEnabled {
  200. t.Fatal("should not have versioning")
  201. }
  202. if len(attrs.Labels) > 0 {
  203. t.Fatal("should not have labels")
  204. }
  205. // Turn on versioning, add some labels.
  206. ua := BucketAttrsToUpdate{VersioningEnabled: true}
  207. ua.SetLabel("l1", "v1")
  208. ua.SetLabel("empty", "")
  209. attrs = h.mustUpdateBucket(b, ua)
  210. if !attrs.VersioningEnabled {
  211. t.Fatal("should have versioning now")
  212. }
  213. wantLabels := map[string]string{
  214. "l1": "v1",
  215. "empty": "",
  216. }
  217. if !testutil.Equal(attrs.Labels, wantLabels) {
  218. t.Fatalf("got %v, want %v", attrs.Labels, wantLabels)
  219. }
  220. // Turn off versioning again; add and remove some more labels.
  221. ua = BucketAttrsToUpdate{VersioningEnabled: false}
  222. ua.SetLabel("l1", "v2") // update
  223. ua.SetLabel("new", "new") // create
  224. ua.DeleteLabel("empty") // delete
  225. ua.DeleteLabel("absent") // delete non-existent
  226. attrs = h.mustUpdateBucket(b, ua)
  227. if attrs.VersioningEnabled {
  228. t.Fatal("should have versioning off")
  229. }
  230. wantLabels = map[string]string{
  231. "l1": "v2",
  232. "new": "new",
  233. }
  234. if !testutil.Equal(attrs.Labels, wantLabels) {
  235. t.Fatalf("got %v, want %v", attrs.Labels, wantLabels)
  236. }
  237. // Configure a lifecycle
  238. wantLifecycle := Lifecycle{
  239. Rules: []LifecycleRule{
  240. {
  241. Action: LifecycleAction{Type: "Delete"},
  242. Condition: LifecycleCondition{AgeInDays: 30},
  243. },
  244. },
  245. }
  246. ua = BucketAttrsToUpdate{Lifecycle: &wantLifecycle}
  247. attrs = h.mustUpdateBucket(b, ua)
  248. if !testutil.Equal(attrs.Lifecycle, wantLifecycle) {
  249. t.Fatalf("got %v, want %v", attrs.Lifecycle, wantLifecycle)
  250. }
  251. }
  252. func TestIntegration_ConditionalDelete(t *testing.T) {
  253. ctx := context.Background()
  254. client := testConfig(ctx, t)
  255. defer client.Close()
  256. h := testHelper{t}
  257. o := client.Bucket(bucketName).Object("conddel")
  258. wc := o.NewWriter(ctx)
  259. wc.ContentType = "text/plain"
  260. h.mustWrite(wc, []byte("foo"))
  261. gen := wc.Attrs().Generation
  262. metaGen := wc.Attrs().Metageneration
  263. if err := o.Generation(gen - 1).Delete(ctx); err == nil {
  264. t.Fatalf("Unexpected successful delete with Generation")
  265. }
  266. if err := o.If(Conditions{MetagenerationMatch: metaGen + 1}).Delete(ctx); err == nil {
  267. t.Fatalf("Unexpected successful delete with IfMetaGenerationMatch")
  268. }
  269. if err := o.If(Conditions{MetagenerationNotMatch: metaGen}).Delete(ctx); err == nil {
  270. t.Fatalf("Unexpected successful delete with IfMetaGenerationNotMatch")
  271. }
  272. if err := o.Generation(gen).Delete(ctx); err != nil {
  273. t.Fatalf("final delete failed: %v", err)
  274. }
  275. }
  276. func TestIntegration_Objects(t *testing.T) {
  277. // TODO(jba): Use subtests (Go 1.7).
  278. ctx := context.Background()
  279. client := testConfig(ctx, t)
  280. defer client.Close()
  281. h := testHelper{t}
  282. bkt := client.Bucket(bucketName)
  283. const defaultType = "text/plain"
  284. // Populate object names and make a map for their contents.
  285. objects := []string{
  286. "obj1",
  287. "obj2",
  288. "obj/with/slashes",
  289. }
  290. contents := make(map[string][]byte)
  291. // Test Writer.
  292. for _, obj := range objects {
  293. c := randomContents()
  294. if err := writeObject(ctx, bkt.Object(obj), defaultType, c); err != nil {
  295. t.Errorf("Write for %v failed with %v", obj, err)
  296. }
  297. contents[obj] = c
  298. }
  299. testObjectIterator(t, bkt, objects)
  300. // Test Reader.
  301. for _, obj := range objects {
  302. rc, err := bkt.Object(obj).NewReader(ctx)
  303. if err != nil {
  304. t.Errorf("Can't create a reader for %v, errored with %v", obj, err)
  305. continue
  306. }
  307. if !rc.checkCRC {
  308. t.Errorf("%v: not checking CRC", obj)
  309. }
  310. slurp, err := ioutil.ReadAll(rc)
  311. if err != nil {
  312. t.Errorf("Can't ReadAll object %v, errored with %v", obj, err)
  313. }
  314. if got, want := slurp, contents[obj]; !bytes.Equal(got, want) {
  315. t.Errorf("Contents (%q) = %q; want %q", obj, got, want)
  316. }
  317. if got, want := rc.Size(), len(contents[obj]); got != int64(want) {
  318. t.Errorf("Size (%q) = %d; want %d", obj, got, want)
  319. }
  320. if got, want := rc.ContentType(), "text/plain"; got != want {
  321. t.Errorf("ContentType (%q) = %q; want %q", obj, got, want)
  322. }
  323. if got, want := rc.CacheControl(), "public, max-age=60"; got != want {
  324. t.Errorf("CacheControl (%q) = %q; want %q", obj, got, want)
  325. }
  326. rc.Close()
  327. // Check early close.
  328. buf := make([]byte, 1)
  329. rc, err = bkt.Object(obj).NewReader(ctx)
  330. if err != nil {
  331. t.Fatalf("%v: %v", obj, err)
  332. }
  333. _, err = rc.Read(buf)
  334. if err != nil {
  335. t.Fatalf("%v: %v", obj, err)
  336. }
  337. if got, want := buf, contents[obj][:1]; !bytes.Equal(got, want) {
  338. t.Errorf("Contents[0] (%q) = %q; want %q", obj, got, want)
  339. }
  340. if err := rc.Close(); err != nil {
  341. t.Errorf("%v Close: %v", obj, err)
  342. }
  343. }
  344. obj := objects[0]
  345. objlen := int64(len(contents[obj]))
  346. // Test Range Reader.
  347. for i, r := range []struct {
  348. offset, length, want int64
  349. }{
  350. {0, objlen, objlen},
  351. {0, objlen / 2, objlen / 2},
  352. {objlen / 2, objlen, objlen / 2},
  353. {0, 0, 0},
  354. {objlen / 2, 0, 0},
  355. {objlen / 2, -1, objlen / 2},
  356. {0, objlen * 2, objlen},
  357. } {
  358. rc, err := bkt.Object(obj).NewRangeReader(ctx, r.offset, r.length)
  359. if err != nil {
  360. t.Errorf("%d: Can't create a range reader for %v, errored with %v", i, obj, err)
  361. continue
  362. }
  363. if rc.Size() != objlen {
  364. t.Errorf("%d: Reader has a content-size of %d, want %d", i, rc.Size(), objlen)
  365. }
  366. if rc.Remain() != r.want {
  367. t.Errorf("%d: Reader's available bytes reported as %d, want %d", i, rc.Remain(), r.want)
  368. }
  369. slurp, err := ioutil.ReadAll(rc)
  370. if err != nil {
  371. t.Errorf("%d:Can't ReadAll object %v, errored with %v", i, obj, err)
  372. continue
  373. }
  374. if len(slurp) != int(r.want) {
  375. t.Errorf("%d:RangeReader (%d, %d): Read %d bytes, wanted %d bytes", i, r.offset, r.length, len(slurp), r.want)
  376. continue
  377. }
  378. if got, want := slurp, contents[obj][r.offset:r.offset+r.want]; !bytes.Equal(got, want) {
  379. t.Errorf("RangeReader (%d, %d) = %q; want %q", r.offset, r.length, got, want)
  380. }
  381. rc.Close()
  382. }
  383. // Test content encoding
  384. const zeroCount = 20 << 20
  385. w := bkt.Object("gzip-test").NewWriter(ctx)
  386. w.ContentEncoding = "gzip"
  387. gw := gzip.NewWriter(w)
  388. if _, err := io.Copy(gw, io.LimitReader(zeros{}, zeroCount)); err != nil {
  389. t.Fatalf("io.Copy, upload: %v", err)
  390. }
  391. if err := gw.Close(); err != nil {
  392. t.Errorf("gzip.Close(): %v", err)
  393. }
  394. if err := w.Close(); err != nil {
  395. t.Errorf("w.Close(): %v", err)
  396. }
  397. r, err := bkt.Object("gzip-test").NewReader(ctx)
  398. if err != nil {
  399. t.Fatalf("NewReader(gzip-test): %v", err)
  400. }
  401. n, err := io.Copy(ioutil.Discard, r)
  402. if err != nil {
  403. t.Errorf("io.Copy, download: %v", err)
  404. }
  405. if n != zeroCount {
  406. t.Errorf("downloaded bad data: got %d bytes, want %d", n, zeroCount)
  407. }
  408. // Test NotFound.
  409. _, err = bkt.Object("obj-not-exists").NewReader(ctx)
  410. if err != ErrObjectNotExist {
  411. t.Errorf("Object should not exist, err found to be %v", err)
  412. }
  413. objName := objects[0]
  414. // Test NewReader googleapi.Error.
  415. // Since a 429 or 5xx is hard to cause, we trigger a 416.
  416. realLen := len(contents[objName])
  417. _, err = bkt.Object(objName).NewRangeReader(ctx, int64(realLen*2), 10)
  418. if err, ok := err.(*googleapi.Error); !ok {
  419. t.Error("NewRangeReader did not return a googleapi.Error")
  420. } else {
  421. if err.Code != 416 {
  422. t.Errorf("Code = %d; want %d", err.Code, 416)
  423. }
  424. if len(err.Header) == 0 {
  425. t.Error("Missing googleapi.Error.Header")
  426. }
  427. if len(err.Body) == 0 {
  428. t.Error("Missing googleapi.Error.Body")
  429. }
  430. }
  431. // Test StatObject.
  432. o := h.mustObjectAttrs(bkt.Object(objName))
  433. if got, want := o.Name, objName; got != want {
  434. t.Errorf("Name (%v) = %q; want %q", objName, got, want)
  435. }
  436. if got, want := o.ContentType, defaultType; got != want {
  437. t.Errorf("ContentType (%v) = %q; want %q", objName, got, want)
  438. }
  439. created := o.Created
  440. // Check that the object is newer than its containing bucket.
  441. bAttrs := h.mustBucketAttrs(bkt)
  442. if o.Created.Before(bAttrs.Created) {
  443. t.Errorf("Object %v is older than its containing bucket, %v", o, bAttrs)
  444. }
  445. // Test object copy.
  446. copyName := "copy-" + objName
  447. copyObj, err := bkt.Object(copyName).CopierFrom(bkt.Object(objName)).Run(ctx)
  448. if err != nil {
  449. t.Errorf("Copier.Run failed with %v", err)
  450. } else if !namesEqual(copyObj, bucketName, copyName) {
  451. t.Errorf("Copy object bucket, name: got %q.%q, want %q.%q",
  452. copyObj.Bucket, copyObj.Name, bucketName, copyName)
  453. }
  454. // Copying with attributes.
  455. const contentEncoding = "identity"
  456. copier := bkt.Object(copyName).CopierFrom(bkt.Object(objName))
  457. copier.ContentEncoding = contentEncoding
  458. copyObj, err = copier.Run(ctx)
  459. if err != nil {
  460. t.Errorf("Copier.Run failed with %v", err)
  461. } else {
  462. if !namesEqual(copyObj, bucketName, copyName) {
  463. t.Errorf("Copy object bucket, name: got %q.%q, want %q.%q",
  464. copyObj.Bucket, copyObj.Name, bucketName, copyName)
  465. }
  466. if copyObj.ContentEncoding != contentEncoding {
  467. t.Errorf("Copy ContentEncoding: got %q, want %q", copyObj.ContentEncoding, contentEncoding)
  468. }
  469. }
  470. // Test UpdateAttrs.
  471. metadata := map[string]string{"key": "value"}
  472. updated, err := bkt.Object(objName).Update(ctx, ObjectAttrsToUpdate{
  473. ContentType: "text/html",
  474. ContentLanguage: "en",
  475. Metadata: metadata,
  476. ACL: []ACLRule{{Entity: "domain-google.com", Role: RoleReader}},
  477. })
  478. if err != nil {
  479. t.Errorf("UpdateAttrs failed with %v", err)
  480. } else {
  481. if got, want := updated.ContentType, "text/html"; got != want {
  482. t.Errorf("updated.ContentType == %q; want %q", got, want)
  483. }
  484. if got, want := updated.ContentLanguage, "en"; got != want {
  485. t.Errorf("updated.ContentLanguage == %q; want %q", updated.ContentLanguage, want)
  486. }
  487. if got, want := updated.Metadata, metadata; !testutil.Equal(got, want) {
  488. t.Errorf("updated.Metadata == %+v; want %+v", updated.Metadata, want)
  489. }
  490. if got, want := updated.Created, created; got != want {
  491. t.Errorf("updated.Created == %q; want %q", got, want)
  492. }
  493. if !updated.Created.Before(updated.Updated) {
  494. t.Errorf("updated.Updated should be newer than update.Created")
  495. }
  496. }
  497. // Delete ContentType and ContentLanguage.
  498. updated, err = bkt.Object(objName).Update(ctx, ObjectAttrsToUpdate{
  499. ContentType: "",
  500. ContentLanguage: "",
  501. Metadata: map[string]string{},
  502. })
  503. if err != nil {
  504. t.Errorf("UpdateAttrs failed with %v", err)
  505. } else {
  506. if got, want := updated.ContentType, ""; got != want {
  507. t.Errorf("updated.ContentType == %q; want %q", got, want)
  508. }
  509. if got, want := updated.ContentLanguage, ""; got != want {
  510. t.Errorf("updated.ContentLanguage == %q; want %q", updated.ContentLanguage, want)
  511. }
  512. if updated.Metadata != nil {
  513. t.Errorf("updated.Metadata == %+v; want nil", updated.Metadata)
  514. }
  515. if got, want := updated.Created, created; got != want {
  516. t.Errorf("updated.Created == %q; want %q", got, want)
  517. }
  518. if !updated.Created.Before(updated.Updated) {
  519. t.Errorf("updated.Updated should be newer than update.Created")
  520. }
  521. }
  522. // Test checksums.
  523. checksumCases := []struct {
  524. name string
  525. contents [][]byte
  526. size int64
  527. md5 string
  528. crc32c uint32
  529. }{
  530. {
  531. name: "checksum-object",
  532. contents: [][]byte{[]byte("hello"), []byte("world")},
  533. size: 10,
  534. md5: "fc5e038d38a57032085441e7fe7010b0",
  535. crc32c: 1456190592,
  536. },
  537. {
  538. name: "zero-object",
  539. contents: [][]byte{},
  540. size: 0,
  541. md5: "d41d8cd98f00b204e9800998ecf8427e",
  542. crc32c: 0,
  543. },
  544. }
  545. for _, c := range checksumCases {
  546. wc := bkt.Object(c.name).NewWriter(ctx)
  547. for _, data := range c.contents {
  548. if _, err := wc.Write(data); err != nil {
  549. t.Errorf("Write(%q) failed with %q", data, err)
  550. }
  551. }
  552. if err = wc.Close(); err != nil {
  553. t.Errorf("%q: close failed with %q", c.name, err)
  554. }
  555. obj := wc.Attrs()
  556. if got, want := obj.Size, c.size; got != want {
  557. t.Errorf("Object (%q) Size = %v; want %v", c.name, got, want)
  558. }
  559. if got, want := fmt.Sprintf("%x", obj.MD5), c.md5; got != want {
  560. t.Errorf("Object (%q) MD5 = %q; want %q", c.name, got, want)
  561. }
  562. if got, want := obj.CRC32C, c.crc32c; got != want {
  563. t.Errorf("Object (%q) CRC32C = %v; want %v", c.name, got, want)
  564. }
  565. }
  566. // Test public ACL.
  567. publicObj := objects[0]
  568. if err = bkt.Object(publicObj).ACL().Set(ctx, AllUsers, RoleReader); err != nil {
  569. t.Errorf("PutACLEntry failed with %v", err)
  570. }
  571. publicClient, err := NewClient(ctx, option.WithHTTPClient(http.DefaultClient))
  572. if err != nil {
  573. t.Fatal(err)
  574. }
  575. slurp := h.mustRead(publicClient.Bucket(bucketName).Object(publicObj))
  576. if !bytes.Equal(slurp, contents[publicObj]) {
  577. t.Errorf("Public object's content: got %q, want %q", slurp, contents[publicObj])
  578. }
  579. // Test writer error handling.
  580. wc := publicClient.Bucket(bucketName).Object(publicObj).NewWriter(ctx)
  581. if _, err := wc.Write([]byte("hello")); err != nil {
  582. t.Errorf("Write unexpectedly failed with %v", err)
  583. }
  584. if err = wc.Close(); err == nil {
  585. t.Error("Close expected an error, found none")
  586. }
  587. // Test deleting the copy object.
  588. h.mustDeleteObject(bkt.Object(copyName))
  589. // Deleting it a second time should return ErrObjectNotExist.
  590. if err := bkt.Object(copyName).Delete(ctx); err != ErrObjectNotExist {
  591. t.Errorf("second deletion of %v = %v; want ErrObjectNotExist", copyName, err)
  592. }
  593. _, err = bkt.Object(copyName).Attrs(ctx)
  594. if err != ErrObjectNotExist {
  595. t.Errorf("Copy is expected to be deleted, stat errored with %v", err)
  596. }
  597. // Test object composition.
  598. var compSrcs []*ObjectHandle
  599. var wantContents []byte
  600. for _, obj := range objects {
  601. compSrcs = append(compSrcs, bkt.Object(obj))
  602. wantContents = append(wantContents, contents[obj]...)
  603. }
  604. checkCompose := func(obj *ObjectHandle, wantContentType string) {
  605. rc := h.mustNewReader(obj)
  606. slurp, err = ioutil.ReadAll(rc)
  607. if err != nil {
  608. t.Fatalf("ioutil.ReadAll: %v", err)
  609. }
  610. defer rc.Close()
  611. if !bytes.Equal(slurp, wantContents) {
  612. t.Errorf("Composed object contents\ngot: %q\nwant: %q", slurp, wantContents)
  613. }
  614. if got := rc.ContentType(); got != wantContentType {
  615. t.Errorf("Composed object content-type = %q, want %q", got, wantContentType)
  616. }
  617. }
  618. // Compose should work even if the user sets no destination attributes.
  619. compDst := bkt.Object("composed1")
  620. c := compDst.ComposerFrom(compSrcs...)
  621. if _, err := c.Run(ctx); err != nil {
  622. t.Fatalf("ComposeFrom error: %v", err)
  623. }
  624. checkCompose(compDst, "application/octet-stream")
  625. // It should also work if we do.
  626. compDst = bkt.Object("composed2")
  627. c = compDst.ComposerFrom(compSrcs...)
  628. c.ContentType = "text/json"
  629. if _, err := c.Run(ctx); err != nil {
  630. t.Fatalf("ComposeFrom error: %v", err)
  631. }
  632. checkCompose(compDst, "text/json")
  633. }
  634. func namesEqual(obj *ObjectAttrs, bucketName, objectName string) bool {
  635. return obj.Bucket == bucketName && obj.Name == objectName
  636. }
  637. func testObjectIterator(t *testing.T, bkt *BucketHandle, objects []string) {
  638. ctx := context.Background()
  639. h := testHelper{t}
  640. // Collect the list of items we expect: ObjectAttrs in lexical order by name.
  641. names := make([]string, len(objects))
  642. copy(names, objects)
  643. sort.Strings(names)
  644. var attrs []*ObjectAttrs
  645. for _, name := range names {
  646. attrs = append(attrs, h.mustObjectAttrs(bkt.Object(name)))
  647. }
  648. msg, ok := itesting.TestIterator(attrs,
  649. func() interface{} { return bkt.Objects(ctx, &Query{Prefix: "obj"}) },
  650. func(it interface{}) (interface{}, error) { return it.(*ObjectIterator).Next() })
  651. if !ok {
  652. t.Errorf("ObjectIterator.Next: %s", msg)
  653. }
  654. // TODO(jba): test query.Delimiter != ""
  655. }
  656. func TestIntegration_SignedURL(t *testing.T) {
  657. // To test SignedURL, we need a real user email and private key. Extract them
  658. // from the JSON key file.
  659. jwtConf, err := testutil.JWTConfig()
  660. if err != nil {
  661. t.Fatal(err)
  662. }
  663. if jwtConf == nil {
  664. t.Skip("JSON key file is not present")
  665. }
  666. ctx := context.Background()
  667. client := testConfig(ctx, t)
  668. defer client.Close()
  669. bkt := client.Bucket(bucketName)
  670. obj := "signedURL"
  671. contents := []byte("This is a test of SignedURL.\n")
  672. md5 := "Jyxvgwm9n2MsrGTMPbMeYA==" // base64-encoded MD5 of contents
  673. if err := writeObject(ctx, bkt.Object(obj), "text/plain", contents); err != nil {
  674. t.Fatalf("writing: %v", err)
  675. }
  676. for _, test := range []struct {
  677. desc string
  678. opts SignedURLOptions
  679. headers map[string][]string
  680. fail bool
  681. }{
  682. {
  683. desc: "basic",
  684. },
  685. {
  686. desc: "MD5 sent and matches",
  687. opts: SignedURLOptions{MD5: md5},
  688. headers: map[string][]string{"Content-MD5": {md5}},
  689. },
  690. {
  691. desc: "MD5 not sent",
  692. opts: SignedURLOptions{MD5: md5},
  693. fail: true,
  694. },
  695. {
  696. desc: "Content-Type sent and matches",
  697. opts: SignedURLOptions{ContentType: "text/plain"},
  698. headers: map[string][]string{"Content-Type": {"text/plain"}},
  699. },
  700. {
  701. desc: "Content-Type sent but does not match",
  702. opts: SignedURLOptions{ContentType: "text/plain"},
  703. headers: map[string][]string{"Content-Type": {"application/json"}},
  704. fail: true,
  705. },
  706. {
  707. desc: "Canonical headers sent and match",
  708. opts: SignedURLOptions{Headers: []string{
  709. " X-Goog-Foo: Bar baz ",
  710. "X-Goog-Novalue", // ignored: no value
  711. "X-Google-Foo", // ignored: wrong prefix
  712. }},
  713. headers: map[string][]string{"X-Goog-foo": {"Bar baz "}},
  714. },
  715. {
  716. desc: "Canonical headers sent but don't match",
  717. opts: SignedURLOptions{Headers: []string{" X-Goog-Foo: Bar baz"}},
  718. headers: map[string][]string{"X-Goog-Foo": {"bar baz"}},
  719. fail: true,
  720. },
  721. } {
  722. opts := test.opts
  723. opts.GoogleAccessID = jwtConf.Email
  724. opts.PrivateKey = jwtConf.PrivateKey
  725. opts.Method = "GET"
  726. opts.Expires = time.Now().Add(time.Hour)
  727. u, err := SignedURL(bucketName, obj, &opts)
  728. if err != nil {
  729. t.Errorf("%s: SignedURL: %v", test.desc, err)
  730. continue
  731. }
  732. got, err := getURL(u, test.headers)
  733. if err != nil && !test.fail {
  734. t.Errorf("%s: getURL %q: %v", test.desc, u, err)
  735. } else if err == nil && !bytes.Equal(got, contents) {
  736. t.Errorf("%s: got %q, want %q", test.desc, got, contents)
  737. }
  738. }
  739. }
  740. // Make a GET request to a URL using an unauthenticated client, and return its contents.
  741. func getURL(url string, headers map[string][]string) ([]byte, error) {
  742. req, err := http.NewRequest("GET", url, nil)
  743. if err != nil {
  744. return nil, err
  745. }
  746. req.Header = headers
  747. res, err := http.DefaultClient.Do(req)
  748. if err != nil {
  749. return nil, err
  750. }
  751. defer res.Body.Close()
  752. bytes, err := ioutil.ReadAll(res.Body)
  753. if err != nil {
  754. return nil, err
  755. }
  756. if res.StatusCode != 200 {
  757. return nil, fmt.Errorf("code=%d, body=%s", res.StatusCode, string(bytes))
  758. }
  759. return bytes, nil
  760. }
  761. func TestIntegration_ACL(t *testing.T) {
  762. ctx := context.Background()
  763. client := testConfig(ctx, t)
  764. defer client.Close()
  765. bkt := client.Bucket(bucketName)
  766. entity := ACLEntity("domain-google.com")
  767. rule := ACLRule{Entity: entity, Role: RoleReader}
  768. if err := bkt.DefaultObjectACL().Set(ctx, entity, RoleReader); err != nil {
  769. t.Errorf("Can't put default ACL rule for the bucket, errored with %v", err)
  770. }
  771. acl, err := bkt.DefaultObjectACL().List(ctx)
  772. if err != nil {
  773. t.Errorf("DefaultObjectACL.List for bucket %q: %v", bucketName, err)
  774. } else if !hasRule(acl, rule) {
  775. t.Errorf("default ACL missing %#v", rule)
  776. }
  777. aclObjects := []string{"acl1", "acl2"}
  778. for _, obj := range aclObjects {
  779. c := randomContents()
  780. if err := writeObject(ctx, bkt.Object(obj), "", c); err != nil {
  781. t.Errorf("Write for %v failed with %v", obj, err)
  782. }
  783. }
  784. name := aclObjects[0]
  785. o := bkt.Object(name)
  786. acl, err = o.ACL().List(ctx)
  787. if err != nil {
  788. t.Errorf("Can't retrieve ACL of %v", name)
  789. } else if !hasRule(acl, rule) {
  790. t.Errorf("object ACL missing %+v", rule)
  791. }
  792. if err := o.ACL().Delete(ctx, entity); err != nil {
  793. t.Errorf("object ACL: could not delete entity %s", entity)
  794. }
  795. // Delete the default ACL rule. We can't move this code earlier in the
  796. // test, because the test depends on the fact that the object ACL inherits
  797. // it.
  798. if err := bkt.DefaultObjectACL().Delete(ctx, entity); err != nil {
  799. t.Errorf("default ACL: could not delete entity %s", entity)
  800. }
  801. entity2 := ACLEntity("user-jbd@google.com")
  802. rule2 := ACLRule{Entity: entity2, Role: RoleReader}
  803. if err := bkt.ACL().Set(ctx, entity2, RoleReader); err != nil {
  804. t.Errorf("Error while putting bucket ACL rule: %v", err)
  805. }
  806. bACL, err := bkt.ACL().List(ctx)
  807. if err != nil {
  808. t.Errorf("Error while getting the ACL of the bucket: %v", err)
  809. } else if !hasRule(bACL, rule2) {
  810. t.Errorf("bucket ACL missing %+v", rule2)
  811. }
  812. if err := bkt.ACL().Delete(ctx, entity2); err != nil {
  813. t.Errorf("Error while deleting bucket ACL rule: %v", err)
  814. }
  815. }
  816. func hasRule(acl []ACLRule, rule ACLRule) bool {
  817. for _, r := range acl {
  818. if r == rule {
  819. return true
  820. }
  821. }
  822. return false
  823. }
  824. func TestIntegration_ValidObjectNames(t *testing.T) {
  825. ctx := context.Background()
  826. client := testConfig(ctx, t)
  827. defer client.Close()
  828. bkt := client.Bucket(bucketName)
  829. validNames := []string{
  830. "gopher",
  831. "Гоферови",
  832. "a",
  833. strings.Repeat("a", 1024),
  834. }
  835. for _, name := range validNames {
  836. if err := writeObject(ctx, bkt.Object(name), "", []byte("data")); err != nil {
  837. t.Errorf("Object %q write failed: %v. Want success", name, err)
  838. continue
  839. }
  840. defer bkt.Object(name).Delete(ctx)
  841. }
  842. invalidNames := []string{
  843. "", // Too short.
  844. strings.Repeat("a", 1025), // Too long.
  845. "new\nlines",
  846. "bad\xffunicode",
  847. }
  848. for _, name := range invalidNames {
  849. // Invalid object names will either cause failure during Write or Close.
  850. if err := writeObject(ctx, bkt.Object(name), "", []byte("data")); err != nil {
  851. continue
  852. }
  853. defer bkt.Object(name).Delete(ctx)
  854. t.Errorf("%q should have failed. Didn't", name)
  855. }
  856. }
  857. func TestIntegration_WriterContentType(t *testing.T) {
  858. ctx := context.Background()
  859. client := testConfig(ctx, t)
  860. defer client.Close()
  861. obj := client.Bucket(bucketName).Object("content")
  862. testCases := []struct {
  863. content string
  864. setType, wantType string
  865. }{
  866. {
  867. content: "It was the best of times, it was the worst of times.",
  868. wantType: "text/plain; charset=utf-8",
  869. },
  870. {
  871. content: "<html><head><title>My first page</title></head></html>",
  872. wantType: "text/html; charset=utf-8",
  873. },
  874. {
  875. content: "<html><head><title>My first page</title></head></html>",
  876. setType: "text/html",
  877. wantType: "text/html",
  878. },
  879. {
  880. content: "<html><head><title>My first page</title></head></html>",
  881. setType: "image/jpeg",
  882. wantType: "image/jpeg",
  883. },
  884. }
  885. for i, tt := range testCases {
  886. if err := writeObject(ctx, obj, tt.setType, []byte(tt.content)); err != nil {
  887. t.Errorf("writing #%d: %v", i, err)
  888. }
  889. attrs, err := obj.Attrs(ctx)
  890. if err != nil {
  891. t.Errorf("obj.Attrs: %v", err)
  892. continue
  893. }
  894. if got := attrs.ContentType; got != tt.wantType {
  895. t.Errorf("Content-Type = %q; want %q\nContent: %q\nSet Content-Type: %q", got, tt.wantType, tt.content, tt.setType)
  896. }
  897. }
  898. }
  899. func TestIntegration_ZeroSizedObject(t *testing.T) {
  900. t.Parallel()
  901. ctx := context.Background()
  902. client := testConfig(ctx, t)
  903. defer client.Close()
  904. h := testHelper{t}
  905. obj := client.Bucket(bucketName).Object("zero")
  906. // Check writing it works as expected.
  907. w := obj.NewWriter(ctx)
  908. if err := w.Close(); err != nil {
  909. t.Fatalf("Writer.Close: %v", err)
  910. }
  911. defer obj.Delete(ctx)
  912. // Check we can read it too.
  913. body := h.mustRead(obj)
  914. if len(body) != 0 {
  915. t.Errorf("Body is %v, want empty []byte{}", body)
  916. }
  917. }
  918. func TestIntegration_Encryption(t *testing.T) {
  919. // This function tests customer-supplied encryption keys for all operations
  920. // involving objects. Bucket and ACL operations aren't tested because they
  921. // aren't affected by customer encryption. Neither is deletion.
  922. ctx := context.Background()
  923. client := testConfig(ctx, t)
  924. defer client.Close()
  925. h := testHelper{t}
  926. obj := client.Bucket(bucketName).Object("customer-encryption")
  927. key := []byte("my-secret-AES-256-encryption-key")
  928. keyHash := sha256.Sum256(key)
  929. keyHashB64 := base64.StdEncoding.EncodeToString(keyHash[:])
  930. key2 := []byte("My-Secret-AES-256-Encryption-Key")
  931. contents := "top secret."
  932. checkMetadataCall := func(msg string, f func(o *ObjectHandle) (*ObjectAttrs, error)) {
  933. // Performing a metadata operation without the key should succeed.
  934. attrs, err := f(obj)
  935. if err != nil {
  936. t.Fatalf("%s: %v", msg, err)
  937. }
  938. // The key hash should match...
  939. if got, want := attrs.CustomerKeySHA256, keyHashB64; got != want {
  940. t.Errorf("%s: key hash: got %q, want %q", msg, got, want)
  941. }
  942. // ...but CRC and MD5 should not be present.
  943. if attrs.CRC32C != 0 {
  944. t.Errorf("%s: CRC: got %v, want 0", msg, attrs.CRC32C)
  945. }
  946. if len(attrs.MD5) > 0 {
  947. t.Errorf("%s: MD5: got %v, want len == 0", msg, attrs.MD5)
  948. }
  949. // Performing a metadata operation with the key should succeed.
  950. attrs, err = f(obj.Key(key))
  951. if err != nil {
  952. t.Fatalf("%s: %v", msg, err)
  953. }
  954. // Check the key and content hashes.
  955. if got, want := attrs.CustomerKeySHA256, keyHashB64; got != want {
  956. t.Errorf("%s: key hash: got %q, want %q", msg, got, want)
  957. }
  958. if attrs.CRC32C == 0 {
  959. t.Errorf("%s: CRC: got 0, want non-zero", msg)
  960. }
  961. if len(attrs.MD5) == 0 {
  962. t.Errorf("%s: MD5: got len == 0, want len > 0", msg)
  963. }
  964. }
  965. checkRead := func(msg string, o *ObjectHandle, k []byte, wantContents string) {
  966. // Reading the object without the key should fail.
  967. if _, err := readObject(ctx, o); err == nil {
  968. t.Errorf("%s: reading without key: want error, got nil", msg)
  969. }
  970. // Reading the object with the key should succeed.
  971. got := h.mustRead(o.Key(k))
  972. gotContents := string(got)
  973. // And the contents should match what we wrote.
  974. if gotContents != wantContents {
  975. t.Errorf("%s: contents: got %q, want %q", msg, gotContents, wantContents)
  976. }
  977. }
  978. checkReadUnencrypted := func(msg string, obj *ObjectHandle, wantContents string) {
  979. got := h.mustRead(obj)
  980. gotContents := string(got)
  981. if gotContents != wantContents {
  982. t.Errorf("%s: got %q, want %q", msg, gotContents, wantContents)
  983. }
  984. }
  985. // Write to obj using our own encryption key, which is a valid 32-byte
  986. // AES-256 key.
  987. h.mustWrite(obj.Key(key).NewWriter(ctx), []byte(contents))
  988. checkMetadataCall("Attrs", func(o *ObjectHandle) (*ObjectAttrs, error) {
  989. return o.Attrs(ctx)
  990. })
  991. checkMetadataCall("Update", func(o *ObjectHandle) (*ObjectAttrs, error) {
  992. return o.Update(ctx, ObjectAttrsToUpdate{ContentLanguage: "en"})
  993. })
  994. checkRead("first object", obj, key, contents)
  995. obj2 := client.Bucket(bucketName).Object("customer-encryption-2")
  996. // Copying an object without the key should fail.
  997. if _, err := obj2.CopierFrom(obj).Run(ctx); err == nil {
  998. t.Fatal("want error, got nil")
  999. }
  1000. // Copying an object with the key should succeed.
  1001. if _, err := obj2.CopierFrom(obj.Key(key)).Run(ctx); err != nil {
  1002. t.Fatal(err)
  1003. }
  1004. // The destination object is not encrypted; we can read it without a key.
  1005. checkReadUnencrypted("copy dest", obj2, contents)
  1006. // Providing a key on the destination but not the source should fail,
  1007. // since the source is encrypted.
  1008. if _, err := obj2.Key(key2).CopierFrom(obj).Run(ctx); err == nil {
  1009. t.Fatal("want error, got nil")
  1010. }
  1011. // But copying with keys for both source and destination should succeed.
  1012. if _, err := obj2.Key(key2).CopierFrom(obj.Key(key)).Run(ctx); err != nil {
  1013. t.Fatal(err)
  1014. }
  1015. // And the destination should be encrypted, meaning we can only read it
  1016. // with a key.
  1017. checkRead("copy destination", obj2, key2, contents)
  1018. // Change obj2's key to prepare for compose, where all objects must have
  1019. // the same key. Also illustrates key rotation: copy an object to itself
  1020. // with a different key.
  1021. if _, err := obj2.Key(key).CopierFrom(obj2.Key(key2)).Run(ctx); err != nil {
  1022. t.Fatal(err)
  1023. }
  1024. obj3 := client.Bucket(bucketName).Object("customer-encryption-3")
  1025. // Composing without keys should fail.
  1026. if _, err := obj3.ComposerFrom(obj, obj2).Run(ctx); err == nil {
  1027. t.Fatal("want error, got nil")
  1028. }
  1029. // Keys on the source objects result in an error.
  1030. if _, err := obj3.ComposerFrom(obj.Key(key), obj2).Run(ctx); err == nil {
  1031. t.Fatal("want error, got nil")
  1032. }
  1033. // A key on the destination object both decrypts the source objects
  1034. // and encrypts the destination.
  1035. if _, err := obj3.Key(key).ComposerFrom(obj, obj2).Run(ctx); err != nil {
  1036. t.Fatalf("got %v, want nil", err)
  1037. }
  1038. // Check that the destination in encrypted.
  1039. checkRead("compose destination", obj3, key, contents+contents)
  1040. // You can't compose one or more unencrypted source objects into an
  1041. // encrypted destination object.
  1042. _, err := obj2.CopierFrom(obj2.Key(key)).Run(ctx) // unencrypt obj2
  1043. if err != nil {
  1044. t.Fatal(err)
  1045. }
  1046. if _, err := obj3.Key(key).ComposerFrom(obj2).Run(ctx); err == nil {
  1047. t.Fatal("got nil, want error")
  1048. }
  1049. }
  1050. func TestIntegration_NonexistentBucket(t *testing.T) {
  1051. t.Parallel()
  1052. ctx := context.Background()
  1053. client := testConfig(ctx, t)
  1054. defer client.Close()
  1055. bkt := client.Bucket(uidSpace.New())
  1056. if _, err := bkt.Attrs(ctx); err != ErrBucketNotExist {
  1057. t.Errorf("Attrs: got %v, want ErrBucketNotExist", err)
  1058. }
  1059. it := bkt.Objects(ctx, nil)
  1060. if _, err := it.Next(); err != ErrBucketNotExist {
  1061. t.Errorf("Objects: got %v, want ErrBucketNotExist", err)
  1062. }
  1063. }
  1064. func TestIntegration_PerObjectStorageClass(t *testing.T) {
  1065. const (
  1066. defaultStorageClass = "STANDARD"
  1067. newStorageClass = "MULTI_REGIONAL"
  1068. )
  1069. ctx := context.Background()
  1070. client := testConfig(ctx, t)
  1071. defer client.Close()
  1072. h := testHelper{t}
  1073. bkt := client.Bucket(bucketName)
  1074. // The bucket should have the default storage class.
  1075. battrs := h.mustBucketAttrs(bkt)
  1076. if battrs.StorageClass != defaultStorageClass {
  1077. t.Fatalf("bucket storage class: got %q, want %q",
  1078. battrs.StorageClass, defaultStorageClass)
  1079. }
  1080. // Write an object; it should start with the bucket's storage class.
  1081. obj := bkt.Object("posc")
  1082. h.mustWrite(obj.NewWriter(ctx), []byte("foo"))
  1083. oattrs, err := obj.Attrs(ctx)
  1084. if err != nil {
  1085. t.Fatal(err)
  1086. }
  1087. if oattrs.StorageClass != defaultStorageClass {
  1088. t.Fatalf("object storage class: got %q, want %q",
  1089. oattrs.StorageClass, defaultStorageClass)
  1090. }
  1091. // Now use Copy to change the storage class.
  1092. copier := obj.CopierFrom(obj)
  1093. copier.StorageClass = newStorageClass
  1094. oattrs2, err := copier.Run(ctx)
  1095. if err != nil {
  1096. log.Fatal(err)
  1097. }
  1098. if oattrs2.StorageClass != newStorageClass {
  1099. t.Fatalf("new object storage class: got %q, want %q",
  1100. oattrs2.StorageClass, newStorageClass)
  1101. }
  1102. // We can also write a new object using a non-default storage class.
  1103. obj2 := bkt.Object("posc2")
  1104. w := obj2.NewWriter(ctx)
  1105. w.StorageClass = newStorageClass
  1106. h.mustWrite(w, []byte("xxx"))
  1107. if w.Attrs().StorageClass != newStorageClass {
  1108. t.Fatalf("new object storage class: got %q, want %q",
  1109. w.Attrs().StorageClass, newStorageClass)
  1110. }
  1111. }
  1112. func TestIntegration_BucketInCopyAttrs(t *testing.T) {
  1113. // Confirm that if bucket is included in the object attributes of a rewrite
  1114. // call, but object name and content-type aren't, then we get an error. See
  1115. // the comment in Copier.Run.
  1116. ctx := context.Background()
  1117. client := testConfig(ctx, t)
  1118. defer client.Close()
  1119. h := testHelper{t}
  1120. bkt := client.Bucket(bucketName)
  1121. obj := bkt.Object("bucketInCopyAttrs")
  1122. h.mustWrite(obj.NewWriter(ctx), []byte("foo"))
  1123. copier := obj.CopierFrom(obj)
  1124. rawObject := copier.ObjectAttrs.toRawObject(bucketName)
  1125. _, err := copier.callRewrite(ctx, rawObject)
  1126. if err == nil {
  1127. t.Errorf("got nil, want error")
  1128. }
  1129. }
  1130. func TestIntegration_NoUnicodeNormalization(t *testing.T) {
  1131. t.Parallel()
  1132. ctx := context.Background()
  1133. client := testConfig(ctx, t)
  1134. defer client.Close()
  1135. bkt := client.Bucket("storage-library-test-bucket")
  1136. h := testHelper{t}
  1137. for _, tst := range []struct {
  1138. nameQuoted, content string
  1139. }{
  1140. {`"Caf\u00e9"`, "Normalization Form C"},
  1141. {`"Cafe\u0301"`, "Normalization Form D"},
  1142. } {
  1143. name, err := strconv.Unquote(tst.nameQuoted)
  1144. if err != nil {
  1145. t.Fatalf("invalid name: %s: %v", tst.nameQuoted, err)
  1146. }
  1147. if got := string(h.mustRead(bkt.Object(name))); got != tst.content {
  1148. t.Errorf("content of %s is %q, want %q", tst.nameQuoted, got, tst.content)
  1149. }
  1150. }
  1151. }
  1152. func TestIntegration_HashesOnUpload(t *testing.T) {
  1153. // Check that the user can provide hashes on upload, and that these are checked.
  1154. if testing.Short() {
  1155. t.Skip("Integration tests skipped in short mode")
  1156. }
  1157. ctx := context.Background()
  1158. client := testConfig(ctx, t)
  1159. if client == nil {
  1160. t.Skip("Integration tests skipped. See CONTRIBUTING.md for details")
  1161. }
  1162. defer client.Close()
  1163. obj := client.Bucket(bucketName).Object("hashesOnUpload-1")
  1164. data := []byte("I can't wait to be verified")
  1165. write := func(w *Writer) error {
  1166. if _, err := w.Write(data); err != nil {
  1167. _ = w.Close()
  1168. return err
  1169. }
  1170. return w.Close()
  1171. }
  1172. crc32c := crc32.Checksum(data, crc32cTable)
  1173. // The correct CRC should succeed.
  1174. w := obj.NewWriter(ctx)
  1175. w.CRC32C = crc32c
  1176. w.SendCRC32C = true
  1177. if err := write(w); err != nil {
  1178. t.Fatal(err)
  1179. }
  1180. // If we change the CRC, validation should fail.
  1181. w = obj.NewWriter(ctx)
  1182. w.CRC32C = crc32c + 1
  1183. w.SendCRC32C = true
  1184. if err := write(w); err == nil {
  1185. t.Fatal("write with bad CRC32c: want error, got nil")
  1186. }
  1187. // If we have the wrong CRC but forget to send it, we succeed.
  1188. w = obj.NewWriter(ctx)
  1189. w.CRC32C = crc32c + 1
  1190. if err := write(w); err != nil {
  1191. t.Fatal(err)
  1192. }
  1193. // MD5
  1194. md5 := md5.Sum(data)
  1195. // The correct MD5 should succeed.
  1196. w = obj.NewWriter(ctx)
  1197. w.MD5 = md5[:]
  1198. if err := write(w); err != nil {
  1199. t.Fatal(err)
  1200. }
  1201. // If we change the MD5, validation should fail.
  1202. w = obj.NewWriter(ctx)
  1203. w.MD5 = append([]byte(nil), md5[:]...)
  1204. w.MD5[0]++
  1205. if err := write(w); err == nil {
  1206. t.Fatal("write with bad MD5: want error, got nil")
  1207. }
  1208. }
  1209. func TestIntegration_BucketIAM(t *testing.T) {
  1210. ctx := context.Background()
  1211. client := testConfig(ctx, t)
  1212. defer client.Close()
  1213. bkt := client.Bucket(bucketName)
  1214. // This bucket is unique to this test run. So we don't have
  1215. // to worry about other runs interfering with our IAM policy
  1216. // changes.
  1217. member := "projectViewer:" + testutil.ProjID()
  1218. role := iam.RoleName("roles/storage.objectViewer")
  1219. // Get the bucket's IAM policy.
  1220. policy, err := bkt.IAM().Policy(ctx)
  1221. if err != nil {
  1222. t.Fatalf("Getting policy: %v", err)
  1223. }
  1224. // The member should not have the role.
  1225. if policy.HasRole(member, role) {
  1226. t.Errorf("member %q has role %q", member, role)
  1227. }
  1228. // Change the policy.
  1229. policy.Add(member, role)
  1230. if err := bkt.IAM().SetPolicy(ctx, policy); err != nil {
  1231. t.Fatalf("SetPolicy: %v", err)
  1232. }
  1233. // Confirm that the binding was added.
  1234. policy, err = bkt.IAM().Policy(ctx)
  1235. if err != nil {
  1236. t.Fatalf("Getting policy: %v", err)
  1237. }
  1238. if !policy.HasRole(member, role) {
  1239. t.Errorf("member %q does not have role %q", member, role)
  1240. }
  1241. // Check TestPermissions.
  1242. // This client should have all these permissions (and more).
  1243. perms := []string{"storage.buckets.get", "storage.buckets.delete"}
  1244. got, err := bkt.IAM().TestPermissions(ctx, perms)
  1245. if err != nil {
  1246. t.Fatalf("TestPermissions: %v", err)
  1247. }
  1248. sort.Strings(perms)
  1249. sort.Strings(got)
  1250. if !testutil.Equal(got, perms) {
  1251. t.Errorf("got %v, want %v", got, perms)
  1252. }
  1253. }
  1254. func TestIntegration_RequesterPays(t *testing.T) {
  1255. // This test needs a second project and user (token source) to test
  1256. // all possibilities. Since we need these things for Firestore already,
  1257. // we use them here.
  1258. //
  1259. // There are up to three entities involved in a requester-pays call:
  1260. //
  1261. // 1. The user making the request. Here, we use
  1262. // a. The account used to create the token source used for all our
  1263. // integration tests (see testutil.TokenSource).
  1264. // b. The account used for the Firestore tests.
  1265. // 2. The project that owns the requester-pays bucket. Here, that
  1266. // is the test project ID (see testutil.ProjID).
  1267. // 3. The project provided as the userProject parameter of the request;
  1268. // the project to be billed. This test uses:
  1269. // a. The project that owns the requester-pays bucket (same as (2))
  1270. // b. Another project (the Firestore project).
  1271. //
  1272. // The following must hold for this test to work:
  1273. // - (1a) must have resourcemanager.projects.createBillingAssignment permission
  1274. // (Owner role) on (2) (the project, not the bucket).
  1275. // - (1b) must NOT have that permission on (2).
  1276. // - (1b) must have serviceusage.services.use permission (Editor role) on (3b).
  1277. // - (1b) must NOT have that permission on (3a).
  1278. // - (1a) must NOT have that permission on (3b).
  1279. const wantErrorCode = 400
  1280. ctx := context.Background()
  1281. client := testConfig(ctx, t)
  1282. defer client.Close()
  1283. h := testHelper{t}
  1284. bucketName2 := uidSpace.New()
  1285. b1 := client.Bucket(bucketName2)
  1286. projID := testutil.ProjID()
  1287. // Use Firestore project as a project that does not contain the bucket.
  1288. otherProjID := os.Getenv(envFirestoreProjID)
  1289. if otherProjID == "" {
  1290. t.Fatalf("need a second project (env var %s)", envFirestoreProjID)
  1291. }
  1292. ts := testutil.TokenSourceEnv(ctx, envFirestorePrivateKey, ScopeFullControl)
  1293. if ts == nil {
  1294. t.Fatalf("need a second account (env var %s)", envFirestorePrivateKey)
  1295. }
  1296. otherClient, err := NewClient(ctx, option.WithTokenSource(ts))
  1297. if err != nil {
  1298. t.Fatal(err)
  1299. }
  1300. defer otherClient.Close()
  1301. b2 := otherClient.Bucket(bucketName2)
  1302. user, err := keyFileEmail(os.Getenv("GCLOUD_TESTS_GOLANG_KEY"))
  1303. if err != nil {
  1304. t.Fatal(err)
  1305. }
  1306. otherUser, err := keyFileEmail(os.Getenv(envFirestorePrivateKey))
  1307. if err != nil {
  1308. t.Fatal(err)
  1309. }
  1310. // Create a requester-pays bucket. The bucket is contained in the project projID.
  1311. h.mustCreate(b1, projID, &BucketAttrs{RequesterPays: true})
  1312. if err := b1.ACL().Set(ctx, ACLEntity("user-"+otherUser), RoleOwner); err != nil {
  1313. t.Fatal(err)
  1314. }
  1315. // Extract the error code from err if it's a googleapi.Error.
  1316. errCode := func(err error) int {
  1317. if err == nil {
  1318. return 0
  1319. }
  1320. if err, ok := err.(*googleapi.Error); ok {
  1321. return err.Code
  1322. }
  1323. return -1
  1324. }
  1325. // Call f under various conditions.
  1326. // Here b and ob refer to the same bucket, but b is bound to client,
  1327. // while ob is bound to otherClient. The clients differ in their credentials,
  1328. // i.e. the identity of the user making the RPC: b's user is an Owner on the
  1329. // bucket's containing project, ob's is not.
  1330. call := func(msg string, f func(*BucketHandle) error) {
  1331. // user: an Owner on the containing project
  1332. // userProject: absent
  1333. // result: success, by the rule permitting access by owners of the containing bucket.
  1334. if err := f(b1); err != nil {
  1335. t.Errorf("%s: %v, want nil\n"+
  1336. "confirm that %s is an Owner on %s",
  1337. msg, err, user, projID)
  1338. }
  1339. // user: an Owner on the containing project
  1340. // userProject: containing project
  1341. // result: success, by the same rule as above; userProject is unnecessary but allowed.
  1342. if err := f(b1.UserProject(projID)); err != nil {
  1343. t.Errorf("%s: got %v, want nil", msg, err)
  1344. }
  1345. // user: not an Owner on the containing project
  1346. // userProject: absent
  1347. // result: failure, by the standard requester-pays rule
  1348. err := f(b2)
  1349. if got, want := errCode(err), wantErrorCode; got != want {
  1350. t.Errorf("%s: got error %v, want code %d\n"+
  1351. "confirm that %s is NOT an Owner on %s",
  1352. msg, err, want, otherUser, projID)
  1353. }
  1354. // user: not an Owner on the containing project
  1355. // userProject: not the containing one, but user has Editor role on it
  1356. // result: success, by the standard requester-pays rule
  1357. if err := f(b2.UserProject(otherProjID)); err != nil {
  1358. t.Errorf("%s: got %v, want nil\n"+
  1359. "confirm that %s is an Editor on %s and that that project has billing enabled",
  1360. msg, err, otherUser, otherProjID)
  1361. }
  1362. // user: not an Owner on the containing project
  1363. // userProject: the containing one, on which the user does NOT have Editor permission.
  1364. // result: failure
  1365. err = f(b2.UserProject("veener-jba"))
  1366. if got, want := errCode(err), 403; got != want {
  1367. t.Errorf("%s: got error %v, want code %d\n"+
  1368. "confirm that %s is NOT an Editor on %s",
  1369. msg, err, want, otherUser, "veener-jba")
  1370. }
  1371. }
  1372. // Getting its attributes requires a user project.
  1373. var attrs *BucketAttrs
  1374. call("Bucket attrs", func(b *BucketHandle) error {
  1375. a, err := b.Attrs(ctx)
  1376. if a != nil {
  1377. attrs = a
  1378. }
  1379. return err
  1380. })
  1381. if attrs != nil {
  1382. if got, want := attrs.RequesterPays, true; got != want {
  1383. t.Fatalf("attr.RequesterPays = %t, want %t", got, want)
  1384. }
  1385. }
  1386. // Object operations.
  1387. call("write object", func(b *BucketHandle) error {
  1388. return writeObject(ctx, b.Object("foo"), "text/plain", []byte("hello"))
  1389. })
  1390. call("read object", func(b *BucketHandle) error {
  1391. _, err := readObject(ctx, b.Object("foo"))
  1392. return err
  1393. })
  1394. call("object attrs", func(b *BucketHandle) error {
  1395. _, err := b.Object("foo").Attrs(ctx)
  1396. return err
  1397. })
  1398. call("update object", func(b *BucketHandle) error {
  1399. _, err := b.Object("foo").Update(ctx, ObjectAttrsToUpdate{ContentLanguage: "en"})
  1400. return err
  1401. })
  1402. // ACL operations.
  1403. entity := ACLEntity("domain-google.com")
  1404. call("bucket acl set", func(b *BucketHandle) error {
  1405. return b.ACL().Set(ctx, entity, RoleReader)
  1406. })
  1407. call("bucket acl list", func(b *BucketHandle) error {
  1408. _, err := b.ACL().List(ctx)
  1409. return err
  1410. })
  1411. call("bucket acl delete", func(b *BucketHandle) error {
  1412. err := b.ACL().Delete(ctx, entity)
  1413. if errCode(err) == 404 {
  1414. // Since we call the function multiple times, it will
  1415. // fail with NotFound for all but the first.
  1416. return nil
  1417. }
  1418. return err
  1419. })
  1420. call("default object acl set", func(b *BucketHandle) error {
  1421. return b.DefaultObjectACL().Set(ctx, entity, RoleReader)
  1422. })
  1423. call("default object acl list", func(b *BucketHandle) error {
  1424. _, err := b.DefaultObjectACL().List(ctx)
  1425. return err
  1426. })
  1427. call("default object acl delete", func(b *BucketHandle) error {
  1428. err := b.DefaultObjectACL().Delete(ctx, entity)
  1429. if errCode(err) == 404 {
  1430. return nil
  1431. }
  1432. return err
  1433. })
  1434. call("object acl set", func(b *BucketHandle) error {
  1435. return b.Object("foo").ACL().Set(ctx, entity, RoleReader)
  1436. })
  1437. call("object acl list", func(b *BucketHandle) error {
  1438. _, err := b.Object("foo").ACL().List(ctx)
  1439. return err
  1440. })
  1441. call("object acl delete", func(b *BucketHandle) error {
  1442. err := b.Object("foo").ACL().Delete(ctx, entity)
  1443. if errCode(err) == 404 {
  1444. return nil
  1445. }
  1446. return err
  1447. })
  1448. // Copy and compose.
  1449. call("copy", func(b *BucketHandle) error {
  1450. _, err := b.Object("copy").CopierFrom(b.Object("foo")).Run(ctx)
  1451. return err
  1452. })
  1453. call("compose", func(b *BucketHandle) error {
  1454. _, err := b.Object("compose").ComposerFrom(b.Object("foo"), b.Object("copy")).Run(ctx)
  1455. return err
  1456. })
  1457. call("delete object", func(b *BucketHandle) error {
  1458. // Make sure the object exists, so we don't get confused by ErrObjectNotExist.
  1459. // The storage service may perform validation in any order (perhaps in parallel),
  1460. // so if we delete an object that doesn't exist and for which we lack permission,
  1461. // we could see either of those two errors. (See Google-internal bug 78341001.)
  1462. h.mustWrite(b1.Object("foo").NewWriter(ctx), []byte("hello")) // note: b1, not b.
  1463. return b.Object("foo").Delete(ctx)
  1464. })
  1465. b1.Object("foo").Delete(ctx) // Make sure object is deleted.
  1466. for _, obj := range []string{"copy", "compose"} {
  1467. if err := b1.UserProject(projID).Object(obj).Delete(ctx); err != nil {
  1468. t.Fatalf("could not delete %q: %v", obj, err)
  1469. }
  1470. }
  1471. h.mustDeleteBucket(b1)
  1472. }
  1473. // TODO(jba): move to testutil, factor out from firestore/integration_test.go.
  1474. const (
  1475. envFirestoreProjID = "GCLOUD_TESTS_GOLANG_FIRESTORE_PROJECT_ID"
  1476. envFirestorePrivateKey = "GCLOUD_TESTS_GOLANG_FIRESTORE_KEY"
  1477. )
  1478. func keyFileEmail(filename string) (string, error) {
  1479. bytes, err := ioutil.ReadFile(filename)
  1480. if err != nil {
  1481. return "", err
  1482. }
  1483. var v struct {
  1484. ClientEmail string `json:"client_email"`
  1485. }
  1486. if err := json.Unmarshal(bytes, &v); err != nil {
  1487. return "", err
  1488. }
  1489. return v.ClientEmail, nil
  1490. }
  1491. func TestNotifications(t *testing.T) {
  1492. ctx := context.Background()
  1493. client := testConfig(ctx, t)
  1494. defer client.Close()
  1495. bkt := client.Bucket(bucketName)
  1496. checkNotifications := func(msg string, want map[string]*Notification) {
  1497. got, err := bkt.Notifications(ctx)
  1498. if err != nil {
  1499. t.Fatal(err)
  1500. }
  1501. if diff := testutil.Diff(got, want); diff != "" {
  1502. t.Errorf("%s: got=-, want=+:\n%s", msg, diff)
  1503. }
  1504. }
  1505. checkNotifications("initial", map[string]*Notification{})
  1506. nArg := &Notification{
  1507. TopicProjectID: testutil.ProjID(),
  1508. TopicID: "go-storage-notification-test",
  1509. PayloadFormat: NoPayload,
  1510. }
  1511. n, err := bkt.AddNotification(ctx, nArg)
  1512. if err != nil {
  1513. t.Fatal(err)
  1514. }
  1515. nArg.ID = n.ID
  1516. if !testutil.Equal(n, nArg) {
  1517. t.Errorf("got %+v, want %+v", n, nArg)
  1518. }
  1519. checkNotifications("after add", map[string]*Notification{n.ID: n})
  1520. if err := bkt.DeleteNotification(ctx, n.ID); err != nil {
  1521. t.Fatal(err)
  1522. }
  1523. checkNotifications("after delete", map[string]*Notification{})
  1524. }
  1525. func TestIntegration_Public(t *testing.T) {
  1526. // Confirm that an unauthenticated client can access a public bucket.
  1527. // See https://cloud.google.com/storage/docs/public-datasets/landsat
  1528. const landsatBucket = "gcp-public-data-landsat"
  1529. const landsatPrefix = "LC08/PRE/044/034/LC80440342016259LGN00/"
  1530. const landsatObject = landsatPrefix + "LC80440342016259LGN00_MTL.txt"
  1531. // Create an unauthenticated client.
  1532. ctx := context.Background()
  1533. client, err := NewClient(ctx, option.WithoutAuthentication())
  1534. if err != nil {
  1535. t.Fatal(err)
  1536. }
  1537. defer client.Close()
  1538. h := testHelper{t}
  1539. bkt := client.Bucket(landsatBucket)
  1540. obj := bkt.Object(landsatObject)
  1541. // Read a public object.
  1542. bytes := h.mustRead(obj)
  1543. if got, want := len(bytes), 7903; got != want {
  1544. t.Errorf("len(bytes) = %d, want %d", got, want)
  1545. }
  1546. // List objects in a public bucket.
  1547. iter := bkt.Objects(ctx, &Query{Prefix: landsatPrefix})
  1548. gotCount := 0
  1549. for {
  1550. _, err := iter.Next()
  1551. if err == iterator.Done {
  1552. break
  1553. }
  1554. if err != nil {
  1555. t.Fatal(err)
  1556. }
  1557. gotCount++
  1558. }
  1559. if wantCount := 13; gotCount != wantCount {
  1560. t.Errorf("object count: got %d, want %d", gotCount, wantCount)
  1561. }
  1562. errCode := func(err error) int {
  1563. if err, ok := err.(*googleapi.Error); !ok {
  1564. return -1
  1565. } else {
  1566. return err.Code
  1567. }
  1568. }
  1569. // Reading from or writing to a non-public bucket fails.
  1570. c := testConfig(ctx, t)
  1571. defer c.Close()
  1572. nonPublicObj := client.Bucket(bucketName).Object("noauth")
  1573. // Oddly, reading returns 403 but writing returns 401.
  1574. _, err = readObject(ctx, nonPublicObj)
  1575. if got, want := errCode(err), 403; got != want {
  1576. t.Errorf("got code %d; want %d\nerror: %v", got, want, err)
  1577. }
  1578. err = writeObject(ctx, nonPublicObj, "text/plain", []byte("b"))
  1579. if got, want := errCode(err), 401; got != want {
  1580. t.Errorf("got code %d; want %d\nerror: %v", got, want, err)
  1581. }
  1582. }
  1583. func TestIntegration_ReadCRC(t *testing.T) {
  1584. // Test that the checksum is handled correctly when reading files.
  1585. // For gzipped files, see https://github.com/GoogleCloudPlatform/google-cloud-dotnet/issues/1641.
  1586. if testing.Short() {
  1587. t.Skip("Integration tests skipped in short mode")
  1588. }
  1589. const (
  1590. // This is an uncompressed file.
  1591. // See https://cloud.google.com/storage/docs/public-datasets/landsat
  1592. uncompressedBucket = "gcp-public-data-landsat"
  1593. uncompressedObject = "LC08/PRE/044/034/LC80440342016259LGN00/LC80440342016259LGN00_MTL.txt"
  1594. gzippedBucket = "storage-library-test-bucket"
  1595. gzippedObject = "gzipped-text.txt"
  1596. gzippedContents = "hello world" // uncompressed contents of the file
  1597. )
  1598. ctx := context.Background()
  1599. client, err := NewClient(ctx, option.WithoutAuthentication())
  1600. if err != nil {
  1601. t.Fatal(err)
  1602. }
  1603. defer client.Close()
  1604. for _, test := range []struct {
  1605. desc string
  1606. obj *ObjectHandle
  1607. offset, length int64
  1608. readCompressed bool // don't decompress a gzipped file
  1609. wantErr bool
  1610. wantCheck bool // Should Reader try to check the CRC?
  1611. wantChecked bool // Did Reader actually check the CRC?
  1612. }{
  1613. {
  1614. desc: "uncompressed, entire file",
  1615. obj: client.Bucket(uncompressedBucket).Object(uncompressedObject),
  1616. offset: 0,
  1617. length: -1,
  1618. readCompressed: false,
  1619. wantCheck: true,
  1620. wantChecked: true,
  1621. },
  1622. {
  1623. desc: "uncompressed, entire file, don't decompress",
  1624. obj: client.Bucket(uncompressedBucket).Object(uncompressedObject),
  1625. offset: 0,
  1626. length: -1,
  1627. readCompressed: true,
  1628. wantCheck: true,
  1629. wantChecked: true,
  1630. },
  1631. {
  1632. desc: "uncompressed, suffix",
  1633. obj: client.Bucket(uncompressedBucket).Object(uncompressedObject),
  1634. offset: 1,
  1635. length: -1,
  1636. readCompressed: false,
  1637. wantCheck: false,
  1638. wantChecked: false,
  1639. },
  1640. {
  1641. desc: "uncompressed, prefix",
  1642. obj: client.Bucket(uncompressedBucket).Object(uncompressedObject),
  1643. offset: 0,
  1644. length: 18,
  1645. readCompressed: false,
  1646. wantCheck: false,
  1647. wantChecked: false,
  1648. },
  1649. {
  1650. // When a gzipped file is unzipped by GCS, we can't verify the checksum
  1651. // because it was computed against the zipped contents. There is no
  1652. // header that indicates that a gzipped file is being served unzipped.
  1653. // But our CRC check only happens if there is a Content-Length header,
  1654. // and that header is absent for this read.
  1655. desc: "compressed, entire file, server unzips",
  1656. obj: client.Bucket(gzippedBucket).Object(gzippedObject),
  1657. offset: 0,
  1658. length: -1,
  1659. readCompressed: false,
  1660. wantCheck: true,
  1661. wantChecked: false,
  1662. },
  1663. {
  1664. // When we read a gzipped file uncompressed, it's like reading a regular file:
  1665. // the served content and the CRC match.
  1666. desc: "compressed, entire file, read compressed",
  1667. obj: client.Bucket(gzippedBucket).Object(gzippedObject),
  1668. offset: 0,
  1669. length: -1,
  1670. readCompressed: true,
  1671. wantCheck: true,
  1672. wantChecked: true,
  1673. },
  1674. {
  1675. desc: "compressed, partial, server unzips",
  1676. obj: client.Bucket(gzippedBucket).Object(gzippedObject),
  1677. offset: 1,
  1678. length: 8,
  1679. readCompressed: false,
  1680. wantErr: true, // GCS can't serve part of a gzipped object
  1681. wantCheck: false,
  1682. wantChecked: false,
  1683. },
  1684. {
  1685. desc: "compressed, partial, read compressed",
  1686. obj: client.Bucket(gzippedBucket).Object(gzippedObject),
  1687. offset: 1,
  1688. length: 8,
  1689. readCompressed: true,
  1690. wantCheck: false,
  1691. wantChecked: false,
  1692. },
  1693. } {
  1694. obj := test.obj.ReadCompressed(test.readCompressed)
  1695. r, err := obj.NewRangeReader(ctx, test.offset, test.length)
  1696. if err != nil {
  1697. if test.wantErr {
  1698. continue
  1699. }
  1700. t.Fatalf("%s: %v", test.desc, err)
  1701. }
  1702. if got, want := r.checkCRC, test.wantCheck; got != want {
  1703. t.Errorf("%s, checkCRC: got %t, want %t", test.desc, got, want)
  1704. }
  1705. _, err = ioutil.ReadAll(r)
  1706. _ = r.Close()
  1707. if err != nil {
  1708. t.Fatalf("%s: %v", test.desc, err)
  1709. }
  1710. if got, want := r.checkedCRC, test.wantChecked; got != want {
  1711. t.Errorf("%s, checkedCRC: got %t, want %t", test.desc, got, want)
  1712. }
  1713. }
  1714. }
  1715. func TestIntegration_CancelWrite(t *testing.T) {
  1716. // Verify that canceling the writer's context immediately stops uploading an object.
  1717. if testing.Short() {
  1718. t.Skip("Integration tests skipped in short mode")
  1719. }
  1720. ctx := context.Background()
  1721. client := testConfig(ctx, t)
  1722. defer client.Close()
  1723. bkt := client.Bucket(bucketName)
  1724. cctx, cancel := context.WithCancel(ctx)
  1725. defer cancel()
  1726. obj := bkt.Object("cancel-write")
  1727. w := obj.NewWriter(cctx)
  1728. w.ChunkSize = googleapi.MinUploadChunkSize
  1729. buf := make([]byte, w.ChunkSize)
  1730. // Write the first chunk. This is read in its entirety before sending the request
  1731. // (see google.golang.org/api/gensupport.PrepareUpload), so we expect it to return
  1732. // without error.
  1733. _, err := w.Write(buf)
  1734. if err != nil {
  1735. t.Fatal(err)
  1736. }
  1737. // Now cancel the context.
  1738. cancel()
  1739. // The next Write should return context.Canceled.
  1740. _, err = w.Write(buf)
  1741. if err != context.Canceled {
  1742. t.Fatalf("got %v, wanted context.Canceled", err)
  1743. }
  1744. // The Close should too.
  1745. err = w.Close()
  1746. if err != context.Canceled {
  1747. t.Fatalf("got %v, wanted context.Canceled", err)
  1748. }
  1749. }
  1750. func TestIntegration_UpdateCORS(t *testing.T) {
  1751. if testing.Short() {
  1752. t.Skip("Integration tests skipped in short mode")
  1753. }
  1754. ctx := context.Background()
  1755. client := testConfig(ctx, t)
  1756. defer client.Close()
  1757. h := testHelper{t}
  1758. initialSettings := []CORS{
  1759. {
  1760. MaxAge: time.Hour,
  1761. Methods: []string{"POST"},
  1762. Origins: []string{"some-origin.com"},
  1763. ResponseHeaders: []string{"foo-bar"},
  1764. },
  1765. }
  1766. for _, test := range []struct {
  1767. input []CORS
  1768. want []CORS
  1769. }{
  1770. {
  1771. input: []CORS{
  1772. {
  1773. MaxAge: time.Hour,
  1774. Methods: []string{"GET"},
  1775. Origins: []string{"*"},
  1776. ResponseHeaders: []string{"some-header"},
  1777. },
  1778. },
  1779. want: []CORS{
  1780. {
  1781. MaxAge: time.Hour,
  1782. Methods: []string{"GET"},
  1783. Origins: []string{"*"},
  1784. ResponseHeaders: []string{"some-header"},
  1785. },
  1786. },
  1787. },
  1788. {
  1789. input: []CORS{},
  1790. want: nil,
  1791. },
  1792. {
  1793. input: nil,
  1794. want: []CORS{
  1795. {
  1796. MaxAge: time.Hour,
  1797. Methods: []string{"POST"},
  1798. Origins: []string{"some-origin.com"},
  1799. ResponseHeaders: []string{"foo-bar"},
  1800. },
  1801. },
  1802. },
  1803. } {
  1804. bkt := client.Bucket(uidSpace.New())
  1805. h.mustCreate(bkt, testutil.ProjID(), &BucketAttrs{CORS: initialSettings})
  1806. defer h.mustDeleteBucket(bkt)
  1807. h.mustUpdateBucket(bkt, BucketAttrsToUpdate{CORS: test.input})
  1808. attrs := h.mustBucketAttrs(bkt)
  1809. if diff := testutil.Diff(attrs.CORS, test.want); diff != "" {
  1810. t.Errorf("input: %v\ngot=-, want=+:\n%s", test.input, diff)
  1811. }
  1812. }
  1813. }
  1814. func TestIntegration_UpdateRetentionPolicy(t *testing.T) {
  1815. if testing.Short() {
  1816. t.Skip("Integration tests skipped in short mode")
  1817. }
  1818. ctx := context.Background()
  1819. client := testConfig(ctx, t)
  1820. defer client.Close()
  1821. h := testHelper{t}
  1822. initial := &RetentionPolicy{RetentionPeriod: time.Minute}
  1823. for _, test := range []struct {
  1824. input *RetentionPolicy
  1825. want *RetentionPolicy
  1826. }{
  1827. { // Update
  1828. input: &RetentionPolicy{RetentionPeriod: time.Hour},
  1829. want: &RetentionPolicy{RetentionPeriod: time.Hour},
  1830. },
  1831. { // Update even with timestamp (EffectiveTime should be ignored)
  1832. input: &RetentionPolicy{RetentionPeriod: time.Hour, EffectiveTime: time.Now()},
  1833. want: &RetentionPolicy{RetentionPeriod: time.Hour},
  1834. },
  1835. { // Remove
  1836. input: &RetentionPolicy{},
  1837. want: nil,
  1838. },
  1839. { // Remove even with timestamp (EffectiveTime should be ignored)
  1840. input: &RetentionPolicy{EffectiveTime: time.Now()},
  1841. want: nil,
  1842. },
  1843. { // Ignore
  1844. input: nil,
  1845. want: initial,
  1846. },
  1847. } {
  1848. bkt := client.Bucket(uidSpace.New())
  1849. h.mustCreate(bkt, testutil.ProjID(), &BucketAttrs{RetentionPolicy: initial})
  1850. defer h.mustDeleteBucket(bkt)
  1851. h.mustUpdateBucket(bkt, BucketAttrsToUpdate{RetentionPolicy: test.input})
  1852. attrs := h.mustBucketAttrs(bkt)
  1853. if attrs.RetentionPolicy != nil && attrs.RetentionPolicy.EffectiveTime.Unix() == 0 {
  1854. // Should be set by the server and parsed by the client
  1855. t.Fatal("EffectiveTime should be set, but it was not")
  1856. }
  1857. if diff := testutil.Diff(attrs.RetentionPolicy, test.want, cmpopts.IgnoreTypes(time.Time{})); diff != "" {
  1858. t.Errorf("input: %v\ngot=-, want=+:\n%s", test.input, diff)
  1859. }
  1860. }
  1861. }
  1862. func TestIntegration_DeleteObjectInBucketWithRetentionPolicy(t *testing.T) {
  1863. if testing.Short() {
  1864. t.Skip("Integration tests skipped in short mode")
  1865. }
  1866. ctx := context.Background()
  1867. client := testConfig(ctx, t)
  1868. defer client.Close()
  1869. h := testHelper{t}
  1870. bkt := client.Bucket(uidSpace.New())
  1871. h.mustCreate(bkt, testutil.ProjID(), &BucketAttrs{RetentionPolicy: &RetentionPolicy{RetentionPeriod: 25 * time.Hour}})
  1872. oh := bkt.Object("some-object")
  1873. if err := writeObject(ctx, oh, "text/plain", []byte("hello world")); err != nil {
  1874. t.Fatal(err)
  1875. }
  1876. if err := oh.Delete(ctx); err == nil {
  1877. t.Fatal("expected to err deleting an object in a bucket with retention period, but got nil")
  1878. }
  1879. // Remove the retention period
  1880. h.mustUpdateBucket(bkt, BucketAttrsToUpdate{RetentionPolicy: &RetentionPolicy{RetentionPeriod: 0}})
  1881. h.mustDeleteObject(oh)
  1882. h.mustDeleteBucket(bkt)
  1883. }
  1884. func TestIntegration_LockBucket(t *testing.T) {
  1885. if testing.Short() {
  1886. t.Skip("Integration tests skipped in short mode")
  1887. }
  1888. ctx := context.Background()
  1889. client := testConfig(ctx, t)
  1890. defer client.Close()
  1891. h := testHelper{t}
  1892. bkt := client.Bucket(uidSpace.New())
  1893. h.mustCreate(bkt, testutil.ProjID(), &BucketAttrs{RetentionPolicy: &RetentionPolicy{RetentionPeriod: time.Hour * 25}})
  1894. attrs := h.mustBucketAttrs(bkt)
  1895. err := bkt.If(BucketConditions{MetagenerationMatch: attrs.MetaGeneration}).LockRetentionPolicy(ctx)
  1896. if err != nil {
  1897. t.Fatal("could not lock", err)
  1898. }
  1899. _, err = bkt.Update(ctx, BucketAttrsToUpdate{RetentionPolicy: &RetentionPolicy{RetentionPeriod: time.Hour}})
  1900. if err == nil {
  1901. t.Fatal("Expected error updating locked bucket, got nil")
  1902. }
  1903. }
  1904. func TestIntegration_LockBucket_MetagenerationRequired(t *testing.T) {
  1905. if testing.Short() {
  1906. t.Skip("Integration tests skipped in short mode")
  1907. }
  1908. ctx := context.Background()
  1909. client := testConfig(ctx, t)
  1910. defer client.Close()
  1911. h := testHelper{t}
  1912. bkt := client.Bucket(uidSpace.New())
  1913. h.mustCreate(bkt, testutil.ProjID(), &BucketAttrs{
  1914. RetentionPolicy: &RetentionPolicy{RetentionPeriod: time.Hour * 25},
  1915. })
  1916. err := bkt.LockRetentionPolicy(ctx)
  1917. if err == nil {
  1918. t.Fatal("expected error locking bucket without metageneration condition, got nil")
  1919. }
  1920. }
  1921. func TestIntegration_KMS(t *testing.T) {
  1922. if testing.Short() {
  1923. t.Skip("Integration tests skipped in short mode")
  1924. }
  1925. keyRingName := os.Getenv("GCLOUD_TESTS_GOLANG_KEYRING")
  1926. if keyRingName == "" {
  1927. t.Fatal("GCLOUD_TESTS_GOLANG_KEYRING must be set. See CONTRIBUTING.md for details")
  1928. }
  1929. ctx := context.Background()
  1930. client := testConfig(ctx, t)
  1931. defer client.Close()
  1932. h := testHelper{t}
  1933. keyName1 := keyRingName + "/cryptoKeys/key1"
  1934. keyName2 := keyRingName + "/cryptoKeys/key2"
  1935. contents := []byte("my secret")
  1936. write := func(obj *ObjectHandle, setKey bool) {
  1937. w := obj.NewWriter(ctx)
  1938. if setKey {
  1939. w.KMSKeyName = keyName1
  1940. }
  1941. h.mustWrite(w, contents)
  1942. }
  1943. checkRead := func(obj *ObjectHandle) {
  1944. got := h.mustRead(obj)
  1945. if !bytes.Equal(got, contents) {
  1946. t.Errorf("got %v, want %v", got, contents)
  1947. }
  1948. attrs := h.mustObjectAttrs(obj)
  1949. if len(attrs.KMSKeyName) < len(keyName1) || attrs.KMSKeyName[:len(keyName1)] != keyName1 {
  1950. t.Errorf("got %q, want %q", attrs.KMSKeyName, keyName1)
  1951. }
  1952. }
  1953. // Write an object with a key, then read it to verify its contents and the presence of the key name.
  1954. bkt := client.Bucket(bucketName)
  1955. obj := bkt.Object("kms")
  1956. write(obj, true)
  1957. checkRead(obj)
  1958. h.mustDeleteObject(obj)
  1959. // Encrypt an object with a CSEK, then copy it using a CMEK.
  1960. src := bkt.Object("csek").Key(testEncryptionKey)
  1961. if err := writeObject(ctx, src, "text/plain", contents); err != nil {
  1962. t.Fatal(err)
  1963. }
  1964. dest := bkt.Object("cmek")
  1965. c := dest.CopierFrom(src)
  1966. c.DestinationKMSKeyName = keyName1
  1967. if _, err := c.Run(ctx); err != nil {
  1968. t.Fatal(err)
  1969. }
  1970. checkRead(dest)
  1971. src.Delete(ctx)
  1972. dest.Delete(ctx)
  1973. // Create a bucket with a default key, then write and read an object.
  1974. bkt = client.Bucket(uidSpace.New())
  1975. h.mustCreate(bkt, testutil.ProjID(), &BucketAttrs{
  1976. Location: "US",
  1977. Encryption: &BucketEncryption{DefaultKMSKeyName: keyName1},
  1978. })
  1979. defer h.mustDeleteBucket(bkt)
  1980. attrs := h.mustBucketAttrs(bkt)
  1981. if got, want := attrs.Encryption.DefaultKMSKeyName, keyName1; got != want {
  1982. t.Fatalf("got %q, want %q", got, want)
  1983. }
  1984. obj = bkt.Object("kms")
  1985. write(obj, false)
  1986. checkRead(obj)
  1987. h.mustDeleteObject(obj)
  1988. // Update the bucket's default key to a different name.
  1989. // (This key doesn't have to exist.)
  1990. attrs = h.mustUpdateBucket(bkt, BucketAttrsToUpdate{Encryption: &BucketEncryption{DefaultKMSKeyName: keyName2}})
  1991. if got, want := attrs.Encryption.DefaultKMSKeyName, keyName2; got != want {
  1992. t.Fatalf("got %q, want %q", got, want)
  1993. }
  1994. attrs = h.mustBucketAttrs(bkt)
  1995. if got, want := attrs.Encryption.DefaultKMSKeyName, keyName2; got != want {
  1996. t.Fatalf("got %q, want %q", got, want)
  1997. }
  1998. // Remove the default KMS key.
  1999. attrs = h.mustUpdateBucket(bkt, BucketAttrsToUpdate{Encryption: &BucketEncryption{DefaultKMSKeyName: ""}})
  2000. if attrs.Encryption != nil {
  2001. t.Fatalf("got %#v, want nil", attrs.Encryption)
  2002. }
  2003. }
  2004. type testHelper struct {
  2005. t *testing.T
  2006. }
  2007. func (h testHelper) mustCreate(b *BucketHandle, projID string, attrs *BucketAttrs) {
  2008. if err := b.Create(context.Background(), projID, attrs); err != nil {
  2009. h.t.Fatalf("%s: bucket create: %v", loc(), err)
  2010. }
  2011. }
  2012. func (h testHelper) mustDeleteBucket(b *BucketHandle) {
  2013. if err := b.Delete(context.Background()); err != nil {
  2014. h.t.Fatalf("%s: bucket delete: %v", loc(), err)
  2015. }
  2016. }
  2017. func (h testHelper) mustBucketAttrs(b *BucketHandle) *BucketAttrs {
  2018. attrs, err := b.Attrs(context.Background())
  2019. if err != nil {
  2020. h.t.Fatalf("%s: bucket attrs: %v", loc(), err)
  2021. }
  2022. return attrs
  2023. }
  2024. func (h testHelper) mustUpdateBucket(b *BucketHandle, ua BucketAttrsToUpdate) *BucketAttrs {
  2025. attrs, err := b.Update(context.Background(), ua)
  2026. if err != nil {
  2027. h.t.Fatalf("%s: update: %v", loc(), err)
  2028. }
  2029. return attrs
  2030. }
  2031. func (h testHelper) mustObjectAttrs(o *ObjectHandle) *ObjectAttrs {
  2032. attrs, err := o.Attrs(context.Background())
  2033. if err != nil {
  2034. h.t.Fatalf("%s: object attrs: %v", loc(), err)
  2035. }
  2036. return attrs
  2037. }
  2038. func (h testHelper) mustDeleteObject(o *ObjectHandle) {
  2039. if err := o.Delete(context.Background()); err != nil {
  2040. h.t.Fatalf("%s: object delete: %v", loc(), err)
  2041. }
  2042. }
  2043. func (h testHelper) mustWrite(w *Writer, data []byte) {
  2044. if _, err := w.Write(data); err != nil {
  2045. w.Close()
  2046. h.t.Fatalf("%s: write: %v", loc(), err)
  2047. }
  2048. if err := w.Close(); err != nil {
  2049. h.t.Fatalf("%s: close write: %v", loc(), err)
  2050. }
  2051. }
  2052. func (h testHelper) mustRead(obj *ObjectHandle) []byte {
  2053. data, err := readObject(context.Background(), obj)
  2054. if err != nil {
  2055. h.t.Fatalf("%s: read: %v", loc(), err)
  2056. }
  2057. return data
  2058. }
  2059. func (h testHelper) mustNewReader(obj *ObjectHandle) *Reader {
  2060. r, err := obj.NewReader(context.Background())
  2061. if err != nil {
  2062. h.t.Fatalf("%s: new reader: %v", loc(), err)
  2063. }
  2064. return r
  2065. }
  2066. func writeObject(ctx context.Context, obj *ObjectHandle, contentType string, contents []byte) error {
  2067. w := obj.NewWriter(ctx)
  2068. w.ContentType = contentType
  2069. w.CacheControl = "public, max-age=60"
  2070. if contents != nil {
  2071. if _, err := w.Write(contents); err != nil {
  2072. _ = w.Close()
  2073. return err
  2074. }
  2075. }
  2076. return w.Close()
  2077. }
  2078. // loc returns a string describing the file and line of its caller's call site. In
  2079. // other words, if a test function calls a helper, and the helper calls loc, then the
  2080. // string will refer to the line on which the test function called the helper.
  2081. // TODO(jba): use t.Helper once we drop go 1.6.
  2082. func loc() string {
  2083. _, file, line, ok := runtime.Caller(2)
  2084. if !ok {
  2085. return "???"
  2086. }
  2087. return fmt.Sprintf("%s:%d", filepath.Base(file), line)
  2088. }
  2089. func readObject(ctx context.Context, obj *ObjectHandle) ([]byte, error) {
  2090. r, err := obj.NewReader(ctx)
  2091. if err != nil {
  2092. return nil, err
  2093. }
  2094. defer r.Close()
  2095. return ioutil.ReadAll(r)
  2096. }
  2097. // cleanup deletes the bucket used for testing, as well as old
  2098. // testing buckets that weren't cleaned previously.
  2099. func cleanup() error {
  2100. if testing.Short() {
  2101. return nil // Don't clean up in short mode.
  2102. }
  2103. ctx := context.Background()
  2104. client := config(ctx)
  2105. if client == nil {
  2106. return nil // Don't cleanup if we're not configured correctly.
  2107. }
  2108. defer client.Close()
  2109. if err := killBucket(ctx, client, bucketName); err != nil {
  2110. return err
  2111. }
  2112. // Delete buckets whose name begins with our test prefix, and which were
  2113. // created a while ago. (Unfortunately GCS doesn't provide last-modified
  2114. // time, which would be a better way to check for staleness.)
  2115. const expireAge = 24 * time.Hour
  2116. projectID := testutil.ProjID()
  2117. it := client.Buckets(ctx, projectID)
  2118. it.Prefix = testPrefix
  2119. for {
  2120. bktAttrs, err := it.Next()
  2121. if err == iterator.Done {
  2122. break
  2123. }
  2124. if err != nil {
  2125. return err
  2126. }
  2127. if time.Since(bktAttrs.Created) > expireAge {
  2128. log.Printf("deleting bucket %q, which is more than %s old", bktAttrs.Name, expireAge)
  2129. if err := killBucket(ctx, client, bktAttrs.Name); err != nil {
  2130. return err
  2131. }
  2132. }
  2133. }
  2134. return nil
  2135. }
  2136. // killBucket deletes a bucket and all its objects.
  2137. func killBucket(ctx context.Context, client *Client, bucketName string) error {
  2138. bkt := client.Bucket(bucketName)
  2139. // Bucket must be empty to delete.
  2140. it := bkt.Objects(ctx, nil)
  2141. for {
  2142. objAttrs, err := it.Next()
  2143. if err == iterator.Done {
  2144. break
  2145. }
  2146. if err != nil {
  2147. return err
  2148. }
  2149. if err := bkt.Object(objAttrs.Name).Delete(ctx); err != nil {
  2150. return fmt.Errorf("deleting %q: %v", bucketName+"/"+objAttrs.Name, err)
  2151. }
  2152. }
  2153. // GCS is eventually consistent, so this delete may fail because the
  2154. // replica still sees an object in the bucket. We log the error and expect
  2155. // a later test run to delete the bucket.
  2156. if err := bkt.Delete(ctx); err != nil {
  2157. log.Printf("deleting %q: %v", bucketName, err)
  2158. }
  2159. return nil
  2160. }
  2161. func randomContents() []byte {
  2162. h := md5.New()
  2163. io.WriteString(h, fmt.Sprintf("hello world%d", rand.Intn(100000)))
  2164. return h.Sum(nil)
  2165. }
  2166. type zeros struct{}
  2167. func (zeros) Read(p []byte) (int, error) { return len(p), nil }