X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/c502c5a50aae825683ee4cff629c6839a4209501..1c50d29ea10fa90a379ee1d3fe7d8e05681d8622:/services/keep-web/s3_test.go diff --git a/services/keep-web/s3_test.go b/services/keep-web/s3_test.go index a2e61e9b78..aa91d82ae3 100644 --- a/services/keep-web/s3_test.go +++ b/services/keep-web/s3_test.go @@ -11,6 +11,7 @@ import ( "crypto/sha256" "fmt" "io/ioutil" + "mime" "net/http" "net/http/httptest" "net/url" @@ -53,6 +54,9 @@ func (s *IntegrationSuite) s3setup(c *check.C) s3stage { "group": map[string]interface{}{ "group_class": "project", "name": "keep-web s3 test", + "properties": map[string]interface{}{ + "project-properties-key": "project properties value", + }, }, "ensure_unique_name": true, }) @@ -74,9 +78,15 @@ func (s *IntegrationSuite) s3setup(c *check.C) s3stage { "name": "keep-web s3 test collection", "manifest_text": ". d41d8cd98f00b204e9800998ecf8427e+0 0:0:emptyfile\n./emptydir d41d8cd98f00b204e9800998ecf8427e+0 0:0:.\n", "properties": map[string]interface{}{ - "string": "string value", - "array": []string{"element1", "element2"}, - "object": map[string]interface{}{"key": map[string]interface{}{"key2": "value"}}, + "string": "string value", + "array": []string{"element1", "element2"}, + "object": map[string]interface{}{"key": map[string]interface{}{"key2": "value⛵"}}, + "nonascii": "⛵", + "newline": "foo\r\nX-Bad: header", + // This key cannot be expressed as a MIME + // header key, so it will be silently skipped + // (see "Inject" in PropertiesAsMetadata test) + "a: a\r\nInject": "bogus", }, }}) c.Assert(err, check.IsNil) @@ -234,9 +244,9 @@ func (s *IntegrationSuite) testS3GetObject(c *check.C, bucket *s3.Bucket, prefix c.Check(exists, check.Equals, true) } -func (s *IntegrationSuite) checkMetaEquals(c *check.C, resp *http.Response, expect map[string]string) { +func (s *IntegrationSuite) checkMetaEquals(c *check.C, hdr http.Header, expect map[string]string) { got := map[string]string{} - for hk, hv := range resp.Header { + for hk, hv := range hdr { if k := strings.TrimPrefix(hk, "X-Amz-Meta-"); k != hk && len(hv) == 1 { got[k] = hv[0] } @@ -249,42 +259,71 @@ func (s *IntegrationSuite) TestS3PropertiesAsMetadata(c *check.C) { defer stage.teardown(c) expectCollectionTags := map[string]string{ - "String": "string value", - "Array": `["element1","element2"]`, - "Object": `{"key":{"key2":"value"}}`, + "String": "string value", + "Array": `["element1","element2"]`, + "Object": mime.BEncoding.Encode("UTF-8", `{"key":{"key2":"value⛵"}}`), + "Nonascii": "=?UTF-8?b?4pu1?=", + "Newline": mime.BEncoding.Encode("UTF-8", "foo\r\nX-Bad: header"), } expectSubprojectTags := map[string]string{ "Subproject_properties_key": "subproject properties value", } + expectProjectTags := map[string]string{ + "Project-Properties-Key": "project properties value", + } + c.Log("HEAD object with metadata from collection") resp, err := stage.collbucket.Head("sailboat.txt", nil) c.Assert(err, check.IsNil) - s.checkMetaEquals(c, resp, expectCollectionTags) + s.checkMetaEquals(c, resp.Header, expectCollectionTags) + c.Log("GET object with metadata from collection") + rdr, hdr, err := stage.collbucket.GetReaderWithHeaders("sailboat.txt") + c.Assert(err, check.IsNil) + content, err := ioutil.ReadAll(rdr) + c.Check(err, check.IsNil) + rdr.Close() + c.Check(content, check.HasLen, 4) + s.checkMetaEquals(c, hdr, expectCollectionTags) + c.Check(hdr["Inject"], check.IsNil) + + c.Log("HEAD bucket with metadata from collection") + resp, err = stage.collbucket.Head("/", nil) + c.Assert(err, check.IsNil) + s.checkMetaEquals(c, resp.Header, expectCollectionTags) + + c.Log("HEAD directory placeholder with metadata from collection") resp, err = stage.projbucket.Head("keep-web s3 test collection/", nil) c.Assert(err, check.IsNil) - s.checkMetaEquals(c, resp, expectCollectionTags) + s.checkMetaEquals(c, resp.Header, expectCollectionTags) + c.Log("HEAD file with metadata from collection") resp, err = stage.projbucket.Head("keep-web s3 test collection/sailboat.txt", nil) c.Assert(err, check.IsNil) - s.checkMetaEquals(c, resp, expectCollectionTags) + s.checkMetaEquals(c, resp.Header, expectCollectionTags) + c.Log("HEAD directory placeholder with metadata from subproject") resp, err = stage.projbucket.Head("keep-web s3 test subproject/", nil) c.Assert(err, check.IsNil) - s.checkMetaEquals(c, resp, expectSubprojectTags) + s.checkMetaEquals(c, resp.Header, expectSubprojectTags) + + c.Log("HEAD bucket with metadata from project") + resp, err = stage.projbucket.Head("/", nil) + c.Assert(err, check.IsNil) + s.checkMetaEquals(c, resp.Header, expectProjectTags) } func (s *IntegrationSuite) TestS3CollectionPutObjectSuccess(c *check.C) { stage := s.s3setup(c) defer stage.teardown(c) - s.testS3PutObjectSuccess(c, stage.collbucket, "") + s.testS3PutObjectSuccess(c, stage.collbucket, "", stage.coll.UUID) } func (s *IntegrationSuite) TestS3ProjectPutObjectSuccess(c *check.C) { stage := s.s3setup(c) defer stage.teardown(c) - s.testS3PutObjectSuccess(c, stage.projbucket, stage.coll.Name+"/") + s.testS3PutObjectSuccess(c, stage.projbucket, stage.coll.Name+"/", stage.coll.UUID) } -func (s *IntegrationSuite) testS3PutObjectSuccess(c *check.C, bucket *s3.Bucket, prefix string) { +func (s *IntegrationSuite) testS3PutObjectSuccess(c *check.C, bucket *s3.Bucket, prefix string, collUUID string) { for _, trial := range []struct { path string size int @@ -328,7 +367,7 @@ func (s *IntegrationSuite) testS3PutObjectSuccess(c *check.C, bucket *s3.Bucket, if !c.Check(err, check.NotNil) { continue } - c.Check(err.(*s3.Error).StatusCode, check.Equals, 404) + c.Check(err.(*s3.Error).StatusCode, check.Equals, http.StatusNotFound) c.Check(err.(*s3.Error).Code, check.Equals, `NoSuchKey`) if !c.Check(err, check.ErrorMatches, `The specified key does not exist.`) { continue @@ -351,6 +390,14 @@ func (s *IntegrationSuite) testS3PutObjectSuccess(c *check.C, bucket *s3.Bucket, c.Check(err, check.IsNil) c.Check(buf2, check.HasLen, len(buf)) c.Check(bytes.Equal(buf, buf2), check.Equals, true) + + // Check that the change is immediately visible via + // (non-S3) webdav request. + _, resp := s.do("GET", "http://"+collUUID+".keep-web.example/"+trial.path, arvadostest.ActiveTokenV2, nil) + c.Check(resp.Code, check.Equals, http.StatusOK) + if !strings.HasSuffix(trial.path, "/") { + c.Check(resp.Body.Len(), check.Equals, trial.size) + } } }