integration_test.go 80 KB

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