You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

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