github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/resource/api/client/client_upload_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package client_test 5 6 import ( 7 "fmt" 8 "io" 9 "net/http" 10 "strings" 11 12 "github.com/juju/errors" 13 "github.com/juju/testing" 14 jc "github.com/juju/testing/checkers" 15 "github.com/juju/utils" 16 gc "gopkg.in/check.v1" 17 "gopkg.in/juju/charm.v6-unstable" 18 charmresource "gopkg.in/juju/charm.v6-unstable/resource" 19 20 "github.com/juju/juju/charmstore" 21 "github.com/juju/juju/resource/api/client" 22 ) 23 24 var _ = gc.Suite(&UploadSuite{}) 25 26 type UploadSuite struct { 27 BaseSuite 28 } 29 30 func (s *UploadSuite) TestOkay(c *gc.C) { 31 data := "<data>" 32 reader := &stubFile{stub: s.stub} 33 reader.returnRead = strings.NewReader(data) 34 cl := client.NewClient(s.facade, s, s.facade) 35 36 _, s.response.Resource = newResource(c, "spam", "a-user", data) 37 38 err := cl.Upload("a-application", "spam", "foo.zip", reader) 39 c.Assert(err, jc.ErrorIsNil) 40 41 fp, err := charmresource.GenerateFingerprint(strings.NewReader(data)) 42 c.Assert(err, jc.ErrorIsNil) 43 req, err := http.NewRequest("PUT", "/applications/a-application/resources/spam", nil) 44 c.Assert(err, jc.ErrorIsNil) 45 req.Header.Set("Content-Type", "application/octet-stream") 46 req.Header.Set("Content-SHA384", fp.String()) 47 req.Header.Set("Content-Length", fmt.Sprint(len(data))) 48 req.Header.Set("Content-Disposition", "form-data; filename=foo.zip") 49 req.ContentLength = int64(len(data)) 50 51 s.stub.CheckCallNames(c, "Read", "Read", "Seek", "Do") 52 s.stub.CheckCall(c, 3, "Do", req, reader, s.response) 53 } 54 55 func (s *UploadSuite) TestBadService(c *gc.C) { 56 cl := client.NewClient(s.facade, s, s.facade) 57 58 err := cl.Upload("???", "spam", "file.zip", nil) 59 60 c.Check(err, gc.ErrorMatches, `.*invalid application.*`) 61 s.stub.CheckNoCalls(c) 62 } 63 64 func (s *UploadSuite) TestBadRequest(c *gc.C) { 65 reader := &stubFile{stub: s.stub} 66 cl := client.NewClient(s.facade, s, s.facade) 67 failure := errors.New("<failure>") 68 s.stub.SetErrors(failure) 69 70 err := cl.Upload("a-application", "spam", "file.zip", reader) 71 72 c.Check(errors.Cause(err), gc.Equals, failure) 73 s.stub.CheckCallNames(c, "Read") 74 } 75 76 func (s *UploadSuite) TestRequestFailed(c *gc.C) { 77 reader := &stubFile{stub: s.stub} 78 reader.returnRead = strings.NewReader("<data>") 79 cl := client.NewClient(s.facade, s, s.facade) 80 failure := errors.New("<failure>") 81 s.stub.SetErrors(nil, nil, nil, failure) 82 83 err := cl.Upload("a-application", "spam", "file.zip", reader) 84 85 c.Check(errors.Cause(err), gc.Equals, failure) 86 s.stub.CheckCallNames(c, "Read", "Read", "Seek", "Do") 87 } 88 89 func (s *UploadSuite) TestPendingResources(c *gc.C) { 90 res, apiResult := newResourceResult(c, "a-application", "spam") 91 resources := []charmresource.Resource{res[0].Resource} 92 uuid, err := utils.NewUUID() 93 c.Assert(err, jc.ErrorIsNil) 94 expected := []string{uuid.String()} 95 s.response.Resource = apiResult.Resources[0] 96 s.facade.pendingIDs = expected 97 cURL := charm.MustParseURL("cs:~a-user/trusty/spam-5") 98 cl := client.NewClient(s.facade, s, s.facade) 99 100 pendingIDs, err := cl.AddPendingResources(client.AddPendingResourcesArgs{ 101 ApplicationID: "a-application", 102 CharmID: charmstore.CharmID{ 103 URL: cURL, 104 }, 105 Resources: resources, 106 }) 107 c.Assert(err, jc.ErrorIsNil) 108 109 s.stub.CheckCallNames(c, "FacadeCall") 110 //s.stub.CheckCall(c, 0, "FacadeCall", "AddPendingResources", args, result) 111 c.Check(pendingIDs, jc.DeepEquals, expected) 112 } 113 114 func (s *UploadSuite) TestPendingResourceOkay(c *gc.C) { 115 res, apiResult := newResourceResult(c, "a-application", "spam") 116 uuid, err := utils.NewUUID() 117 c.Assert(err, jc.ErrorIsNil) 118 expected := uuid.String() 119 s.response.Resource = apiResult.Resources[0] 120 data := "<data>" 121 reader := &stubFile{stub: s.stub} 122 reader.returnRead = strings.NewReader(data) 123 s.facade.pendingIDs = []string{expected} 124 cl := client.NewClient(s.facade, s, s.facade) 125 126 uploadID, err := cl.AddPendingResource("a-application", res[0].Resource, "file.zip", reader) 127 c.Assert(err, jc.ErrorIsNil) 128 129 s.stub.CheckCallNames(c, 130 "FacadeCall", 131 "Read", 132 "Read", 133 "Seek", 134 "Do", 135 ) 136 137 fp, err := charmresource.GenerateFingerprint(strings.NewReader(data)) 138 c.Assert(err, jc.ErrorIsNil) 139 req, err := http.NewRequest("PUT", "/applications/a-application/resources/spam", nil) 140 c.Assert(err, jc.ErrorIsNil) 141 req.Header.Set("Content-Type", "application/octet-stream") 142 req.Header.Set("Content-SHA384", fp.String()) 143 req.Header.Set("Content-Length", fmt.Sprint(len(data))) 144 req.ContentLength = int64(len(data)) 145 req.URL.RawQuery = "pendingid=" + expected 146 req.Header.Set("Content-Disposition", "form-data; filename=file.zip") 147 148 s.stub.CheckCall(c, 4, "Do", req, reader, s.response) 149 c.Check(uploadID, gc.Equals, expected) 150 } 151 152 func (s *UploadSuite) TestPendingResourceNoFile(c *gc.C) { 153 res, apiResult := newResourceResult(c, "a-application", "spam") 154 uuid, err := utils.NewUUID() 155 c.Assert(err, jc.ErrorIsNil) 156 expected := uuid.String() 157 s.response.Resource = apiResult.Resources[0] 158 s.facade.pendingIDs = []string{expected} 159 cl := client.NewClient(s.facade, s, s.facade) 160 161 uploadID, err := cl.AddPendingResource("a-application", res[0].Resource, "file.zip", nil) 162 c.Assert(err, jc.ErrorIsNil) 163 164 s.stub.CheckCallNames(c, 165 "FacadeCall", 166 ) 167 c.Check(uploadID, gc.Equals, expected) 168 } 169 170 func (s *UploadSuite) TestPendingResourceBadService(c *gc.C) { 171 res, _ := newResourceResult(c, "a-application", "spam") 172 s.facade.FacadeCallFn = nil 173 cl := client.NewClient(s.facade, s, s.facade) 174 175 _, err := cl.AddPendingResource("???", res[0].Resource, "file.zip", nil) 176 177 c.Check(err, gc.ErrorMatches, `.*invalid application.*`) 178 s.stub.CheckNoCalls(c) 179 } 180 181 func (s *UploadSuite) TestPendingResourceBadRequest(c *gc.C) { 182 res, _ := newResource(c, "spam", "", "") 183 chRes := res.Resource 184 reader := &stubFile{stub: s.stub} 185 s.facade.pendingIDs = []string{"some-unique-id"} 186 cl := client.NewClient(s.facade, s, s.facade) 187 failure := errors.New("<failure>") 188 s.stub.SetErrors(nil, failure) 189 190 _, err := cl.AddPendingResource("a-application", chRes, "file.zip", reader) 191 192 c.Check(errors.Cause(err), gc.Equals, failure) 193 s.stub.CheckCallNames(c, "FacadeCall", "Read") 194 } 195 196 func (s *UploadSuite) TestPendingResourceRequestFailed(c *gc.C) { 197 res, _ := newResourceResult(c, "a-application", "spam") 198 reader := &stubFile{stub: s.stub} 199 reader.returnRead = strings.NewReader("<data>") 200 s.facade.pendingIDs = []string{"some-unique-id"} 201 cl := client.NewClient(s.facade, s, s.facade) 202 failure := errors.New("<failure>") 203 s.stub.SetErrors(nil, nil, nil, nil, failure) 204 205 _, err := cl.AddPendingResource("a-application", res[0].Resource, "file.zip", reader) 206 207 c.Check(errors.Cause(err), gc.Equals, failure) 208 s.stub.CheckCallNames(c, 209 "FacadeCall", 210 "Read", 211 "Read", 212 "Seek", 213 "Do", 214 ) 215 } 216 217 type stubFile struct { 218 stub *testing.Stub 219 220 returnRead io.Reader 221 returnSeek int64 222 } 223 224 func (s *stubFile) Read(buf []byte) (int, error) { 225 s.stub.AddCall("Read", buf) 226 if err := s.stub.NextErr(); err != nil { 227 return 0, errors.Trace(err) 228 } 229 230 return s.returnRead.Read(buf) 231 } 232 233 func (s *stubFile) Seek(offset int64, whence int) (int64, error) { 234 s.stub.AddCall("Seek", offset, whence) 235 if err := s.stub.NextErr(); err != nil { 236 return 0, errors.Trace(err) 237 } 238 239 return s.returnSeek, nil 240 } 241 242 func (s *stubFile) Close() error { 243 s.stub.AddCall("Close") 244 if err := s.stub.NextErr(); err != nil { 245 return errors.Trace(err) 246 } 247 248 return nil 249 }