github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/resource/api/server/handler_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package server_test 5 6 import ( 7 "encoding/json" 8 "fmt" 9 "net/http" 10 "strconv" 11 "strings" 12 13 "github.com/juju/errors" 14 "github.com/juju/testing" 15 jc "github.com/juju/testing/checkers" 16 gc "gopkg.in/check.v1" 17 "gopkg.in/juju/names.v2" 18 19 "github.com/juju/juju/apiserver/params" 20 "github.com/juju/juju/resource/api" 21 "github.com/juju/juju/resource/api/server" 22 ) 23 24 type LegacyHTTPHandlerSuite struct { 25 BaseSuite 26 27 username string 28 req *http.Request 29 header http.Header 30 resp *stubHTTPResponseWriter 31 result *api.UploadResult 32 } 33 34 var _ = gc.Suite(&LegacyHTTPHandlerSuite{}) 35 36 func (s *LegacyHTTPHandlerSuite) SetUpTest(c *gc.C) { 37 s.BaseSuite.SetUpTest(c) 38 39 method := "..." 40 urlStr := "..." 41 body := strings.NewReader("...") 42 req, err := http.NewRequest(method, urlStr, body) 43 c.Assert(err, jc.ErrorIsNil) 44 45 s.req = req 46 s.header = make(http.Header) 47 s.resp = &stubHTTPResponseWriter{ 48 stub: s.stub, 49 returnHeader: s.header, 50 } 51 s.result = &api.UploadResult{} 52 } 53 54 func (s *LegacyHTTPHandlerSuite) connect(req *http.Request) (server.DataStore, names.Tag, error) { 55 s.stub.AddCall("Connect", req) 56 if err := s.stub.NextErr(); err != nil { 57 return nil, nil, errors.Trace(err) 58 } 59 60 tag := names.NewUserTag(s.username) 61 return s.data, tag, nil 62 } 63 64 func (s *LegacyHTTPHandlerSuite) handleUpload(username string, st server.DataStore, req *http.Request) (*api.UploadResult, error) { 65 s.stub.AddCall("HandleUpload", username, st, req) 66 if err := s.stub.NextErr(); err != nil { 67 return nil, errors.Trace(err) 68 } 69 70 return s.result, nil 71 } 72 73 func (s *LegacyHTTPHandlerSuite) TestServeHTTPConnectFailure(c *gc.C) { 74 s.username = "youknowwho" 75 handler := server.LegacyHTTPHandler{ 76 Connect: s.connect, 77 HandleUpload: s.handleUpload, 78 } 79 copied := *s.req 80 req := &copied 81 failure, expected := apiFailure(c, "<failure>", "") 82 s.stub.SetErrors(failure) 83 84 handler.ServeHTTP(s.resp, req) 85 86 s.stub.CheckCallNames(c, 87 "Connect", 88 "Header", 89 "Header", 90 "WriteHeader", 91 "Write", 92 ) 93 s.stub.CheckCall(c, 0, "Connect", req) 94 s.stub.CheckCall(c, 3, "WriteHeader", http.StatusInternalServerError) 95 s.stub.CheckCall(c, 4, "Write", expected) 96 c.Check(req, jc.DeepEquals, s.req) // did not change 97 c.Check(s.header, jc.DeepEquals, http.Header{ 98 "Content-Type": []string{"application/json"}, 99 "Content-Length": []string{strconv.Itoa(len(expected))}, 100 }) 101 } 102 103 func (s *LegacyHTTPHandlerSuite) TestServeHTTPUnsupportedMethod(c *gc.C) { 104 s.username = "youknowwho" 105 handler := server.LegacyHTTPHandler{ 106 Connect: s.connect, 107 HandleUpload: s.handleUpload, 108 } 109 s.req.Method = "POST" 110 copied := *s.req 111 req := &copied 112 _, expected := apiFailure(c, `unsupported method: "POST"`, params.CodeMethodNotAllowed) 113 114 handler.ServeHTTP(s.resp, req) 115 116 s.stub.CheckCallNames(c, 117 "Connect", 118 "Header", 119 "Header", 120 "WriteHeader", 121 "Write", 122 ) 123 s.stub.CheckCall(c, 0, "Connect", req) 124 s.stub.CheckCall(c, 3, "WriteHeader", http.StatusMethodNotAllowed) 125 s.stub.CheckCall(c, 4, "Write", expected) 126 c.Check(req, jc.DeepEquals, s.req) // did not change 127 c.Check(s.header, jc.DeepEquals, http.Header{ 128 "Content-Type": []string{"application/json"}, 129 "Content-Length": []string{strconv.Itoa(len(expected))}, 130 }) 131 } 132 133 func (s *LegacyHTTPHandlerSuite) TestServeHTTPPutSuccess(c *gc.C) { 134 s.result.Resource.Name = "spam" 135 expected, err := json.Marshal(s.result) 136 c.Assert(err, jc.ErrorIsNil) 137 s.username = "youknowwho" 138 handler := server.LegacyHTTPHandler{ 139 Connect: s.connect, 140 HandleUpload: s.handleUpload, 141 } 142 s.req.Method = "PUT" 143 copied := *s.req 144 req := &copied 145 146 handler.ServeHTTP(s.resp, req) 147 148 s.stub.CheckCallNames(c, 149 "Connect", 150 "HandleUpload", 151 "Header", 152 "Header", 153 "WriteHeader", 154 "Write", 155 ) 156 s.stub.CheckCall(c, 0, "Connect", req) 157 s.stub.CheckCall(c, 1, "HandleUpload", "youknowwho", s.data, req) 158 s.stub.CheckCall(c, 4, "WriteHeader", http.StatusOK) 159 s.stub.CheckCall(c, 5, "Write", string(expected)) 160 c.Check(req, jc.DeepEquals, s.req) // did not change 161 c.Check(s.header, jc.DeepEquals, http.Header{ 162 "Content-Type": []string{"application/json"}, 163 "Content-Length": []string{fmt.Sprint(len(expected))}, 164 }) 165 } 166 167 func (s *LegacyHTTPHandlerSuite) TestServeHTTPPutHandleUploadFailure(c *gc.C) { 168 s.username = "youknowwho" 169 handler := server.LegacyHTTPHandler{ 170 Connect: s.connect, 171 HandleUpload: s.handleUpload, 172 } 173 s.req.Method = "PUT" 174 copied := *s.req 175 req := &copied 176 failure, expected := apiFailure(c, "<failure>", "") 177 s.stub.SetErrors(nil, failure) 178 179 handler.ServeHTTP(s.resp, req) 180 181 s.stub.CheckCallNames(c, 182 "Connect", 183 "HandleUpload", 184 "Header", 185 "Header", 186 "WriteHeader", 187 "Write", 188 ) 189 s.stub.CheckCall(c, 0, "Connect", req) 190 s.stub.CheckCall(c, 1, "HandleUpload", "youknowwho", s.data, req) 191 s.stub.CheckCall(c, 4, "WriteHeader", http.StatusInternalServerError) 192 s.stub.CheckCall(c, 5, "Write", expected) 193 c.Check(req, jc.DeepEquals, s.req) // did not change 194 c.Check(s.header, jc.DeepEquals, http.Header{ 195 "Content-Type": []string{"application/json"}, 196 "Content-Length": []string{strconv.Itoa(len(expected))}, 197 }) 198 } 199 200 func apiFailure(c *gc.C, msg, code string) (error, string) { 201 failure := errors.New(msg) 202 203 data, err := json.Marshal(params.ErrorResult{ 204 Error: ¶ms.Error{ 205 Message: msg, 206 Code: code, 207 }, 208 }) 209 c.Assert(err, jc.ErrorIsNil) 210 211 return failure, string(data) 212 } 213 214 type stubHTTPResponseWriter struct { 215 stub *testing.Stub 216 217 returnHeader http.Header 218 } 219 220 func (s *stubHTTPResponseWriter) Header() http.Header { 221 s.stub.AddCall("Header") 222 s.stub.NextErr() // Pop one off. 223 224 return s.returnHeader 225 } 226 227 func (s *stubHTTPResponseWriter) Write(data []byte) (int, error) { 228 s.stub.AddCall("Write", string(data)) 229 if err := s.stub.NextErr(); err != nil { 230 return 0, errors.Trace(err) 231 } 232 233 return len(data), nil 234 } 235 236 func (s *stubHTTPResponseWriter) WriteHeader(code int) { 237 s.stub.AddCall("WriteHeader", code) 238 s.stub.NextErr() // Pop one off. 239 }