1
// Copyright 2012, 2013 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
15
. "launchpad.net/gocheck"
18
type HTTPSuite struct{}
20
var Server = NewHTTPServer(5 * time.Second)
22
func (s *HTTPSuite) SetUpSuite(c *C) {
25
func (s *HTTPSuite) TearDownSuite(c *C) {}
27
func (s *HTTPSuite) SetUpTest(c *C) {}
29
func (s *HTTPSuite) TearDownTest(c *C) {
33
func (s *HTTPSuite) URL(path string) string {
34
return Server.URL + path
37
type HTTPServer struct {
41
request chan *http.Request
42
response chan ResponseFunc
45
func NewHTTPServer(timeout time.Duration) *HTTPServer {
46
return &HTTPServer{Timeout: timeout}
49
type Response struct {
51
Headers map[string]string
55
type ResponseFunc func(path string) Response
57
func (s *HTTPServer) Start() {
62
s.request = make(chan *http.Request, 64)
63
s.response = make(chan ResponseFunc, 64)
65
l, err := net.Listen("tcp", "localhost:0")
69
port := l.Addr().(*net.TCPAddr).Port
70
s.URL = fmt.Sprintf("http://localhost:%d", port)
73
s.Response(203, nil, nil)
75
// Wait for it to be up.
76
resp, err := http.Get(s.URL)
77
if err == nil && resp.StatusCode == 203 {
82
s.WaitRequest() // Consume dummy request.
85
// Flush discards all pending requests and responses.
86
func (s *HTTPServer) Flush() {
97
func body(req *http.Request) string {
98
data, err := ioutil.ReadAll(req.Body)
105
func (s *HTTPServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
106
req.ParseMultipartForm(1e6)
107
data, err := ioutil.ReadAll(req.Body)
111
req.Body = ioutil.NopCloser(bytes.NewBuffer(data))
115
case respFunc := <-s.response:
116
resp = respFunc(req.URL.Path)
117
case <-time.After(s.Timeout):
118
const msg = "ERROR: Timeout waiting for test to prepare a response\n"
119
fmt.Fprintf(os.Stderr, msg)
120
resp = Response{500, nil, []byte(msg)}
122
if resp.Headers != nil {
124
for k, v := range resp.Headers {
128
if resp.Status != 0 {
129
w.WriteHeader(resp.Status)
134
// WaitRequests returns the next n requests made to the http server from
135
// the queue. If not enough requests were previously made, it waits until
136
// the timeout value for them to be made.
137
func (s *HTTPServer) WaitRequests(n int) []*http.Request {
138
reqs := make([]*http.Request, 0, n)
139
for i := 0; i < n; i++ {
141
case req := <-s.request:
142
reqs = append(reqs, req)
143
case <-time.After(s.Timeout):
144
panic("Timeout waiting for request")
150
// WaitRequest returns the next request made to the http server from
151
// the queue. If no requests were previously made, it waits until the
152
// timeout value for one to be made.
153
func (s *HTTPServer) WaitRequest() *http.Request {
154
return s.WaitRequests(1)[0]
157
// ResponseFunc prepares the test server to respond the following n
158
// requests using f to build each response.
159
func (s *HTTPServer) ResponseFunc(n int, f ResponseFunc) {
160
for i := 0; i < n; i++ {
165
// ResponseMap maps request paths to responses.
166
type ResponseMap map[string]Response
168
// ResponseMap prepares the test server to respond the following n
169
// requests using the m to obtain the responses.
170
func (s *HTTPServer) ResponseMap(n int, m ResponseMap) {
171
f := func(path string) Response {
172
for rpath, resp := range m {
177
body := []byte("Path not found in response map: " + path)
178
return Response{Status: 500, Body: body}
183
// Responses prepares the test server to respond the following n requests
184
// using the provided response parameters.
185
func (s *HTTPServer) Responses(n int, status int, headers map[string]string, body []byte) {
186
f := func(path string) Response {
187
return Response{status, headers, body}
192
// Response prepares the test server to respond the following request
193
// using the provided response parameters.
194
func (s *HTTPServer) Response(status int, headers map[string]string, body []byte) {
195
s.Responses(1, status, headers, body)