OLD | NEW |
(Empty) | |
| 1 package store_test |
| 2 |
| 3 import ( |
| 4 "bytes" |
| 5 "fmt" |
| 6 "io/ioutil" |
| 7 . "launchpad.net/gocheck" |
| 8 "net/http" |
| 9 "net/url" |
| 10 "os" |
| 11 "time" |
| 12 ) |
| 13 |
| 14 type HTTPSuite struct{} |
| 15 |
| 16 var testServer = NewTestHTTPServer("http://localhost:4444", 5*time.Second) |
| 17 |
| 18 func (s *HTTPSuite) SetUpSuite(c *C) { |
| 19 testServer.Start() |
| 20 } |
| 21 |
| 22 func (s *HTTPSuite) TearDownTest(c *C) { |
| 23 testServer.Flush() |
| 24 } |
| 25 |
| 26 type TestHTTPServer struct { |
| 27 URL string |
| 28 Timeout time.Duration |
| 29 started bool |
| 30 request chan *http.Request |
| 31 response chan ResponseFunc |
| 32 pending chan bool |
| 33 } |
| 34 |
| 35 func NewTestHTTPServer(url_ string, timeout time.Duration) *TestHTTPServer { |
| 36 return &TestHTTPServer{URL: url_, Timeout: timeout} |
| 37 } |
| 38 |
| 39 type Response struct { |
| 40 Status int |
| 41 Headers map[string]string |
| 42 Body string |
| 43 } |
| 44 |
| 45 type ResponseFunc func(path string) Response |
| 46 |
| 47 func (s *TestHTTPServer) Start() { |
| 48 if s.started { |
| 49 return |
| 50 } |
| 51 s.started = true |
| 52 |
| 53 s.request = make(chan *http.Request, 64) |
| 54 s.response = make(chan ResponseFunc, 64) |
| 55 s.pending = make(chan bool, 64) |
| 56 |
| 57 url_, _ := url.Parse(s.URL) |
| 58 go http.ListenAndServe(url_.Host, s) |
| 59 |
| 60 s.Response(203, nil, "") |
| 61 for { |
| 62 // Wait for it to be up. |
| 63 resp, err := http.Get(s.URL) |
| 64 if err == nil && resp.StatusCode == 203 { |
| 65 break |
| 66 } |
| 67 time.Sleep(1e8) |
| 68 } |
| 69 s.WaitRequest() // Consume dummy request. |
| 70 } |
| 71 |
| 72 // FlushRequests discards requests which were not yet consumed by WaitRequest. |
| 73 func (s *TestHTTPServer) Flush() { |
| 74 for { |
| 75 select { |
| 76 case <-s.request: |
| 77 case <-s.response: |
| 78 default: |
| 79 return |
| 80 } |
| 81 } |
| 82 } |
| 83 |
| 84 func body(req *http.Request) string { |
| 85 data, err := ioutil.ReadAll(req.Body) |
| 86 if err != nil { |
| 87 panic(err) |
| 88 } |
| 89 return string(data) |
| 90 } |
| 91 |
| 92 func (s *TestHTTPServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { |
| 93 req.ParseMultipartForm(1e6) |
| 94 data, err := ioutil.ReadAll(req.Body) |
| 95 if err != nil { |
| 96 panic(err) |
| 97 } |
| 98 req.Body = ioutil.NopCloser(bytes.NewBuffer(data)) |
| 99 s.request <- req |
| 100 var resp Response |
| 101 select { |
| 102 case respFunc := <-s.response: |
| 103 resp = respFunc(req.URL.Path) |
| 104 case <-time.After(s.Timeout): |
| 105 const msg = "ERROR: Timeout waiting for test to prepare a respon
se\n" |
| 106 fmt.Fprintf(os.Stderr, msg) |
| 107 resp = Response{500, nil, msg} |
| 108 } |
| 109 if resp.Headers != nil { |
| 110 h := w.Header() |
| 111 for k, v := range resp.Headers { |
| 112 h.Set(k, v) |
| 113 } |
| 114 } |
| 115 if resp.Status != 0 { |
| 116 w.WriteHeader(resp.Status) |
| 117 } |
| 118 w.Write([]byte(resp.Body)) |
| 119 } |
| 120 |
| 121 // WaitRequests returns the next n requests made to the http server from |
| 122 // the queue. If not enough requests were previously made, it waits until |
| 123 // the timeout value for them to be made. |
| 124 func (s *TestHTTPServer) WaitRequests(n int) []*http.Request { |
| 125 reqs := make([]*http.Request, 0, n) |
| 126 for i := 0; i < n; i++ { |
| 127 select { |
| 128 case req := <-s.request: |
| 129 reqs = append(reqs, req) |
| 130 case <-time.After(s.Timeout): |
| 131 panic("Timeout waiting for request") |
| 132 } |
| 133 } |
| 134 return reqs |
| 135 } |
| 136 |
| 137 // WaitRequest returns the next request made to the http server from |
| 138 // the queue. If no requests were previously made, it waits until the |
| 139 // timeout value for one to be made. |
| 140 func (s *TestHTTPServer) WaitRequest() *http.Request { |
| 141 return s.WaitRequests(1)[0] |
| 142 } |
| 143 |
| 144 // ResponseFunc prepares the test server to respond the following n |
| 145 // requests using f to build each response. |
| 146 func (s *TestHTTPServer) ResponseFunc(n int, f ResponseFunc) { |
| 147 for i := 0; i < n; i++ { |
| 148 s.response <- f |
| 149 } |
| 150 } |
| 151 |
| 152 // ResponseMap maps request paths to responses. |
| 153 type ResponseMap map[string]Response |
| 154 |
| 155 // ResponseMap prepares the test server to respond the following n |
| 156 // requests using the m to obtain the responses. |
| 157 func (s *TestHTTPServer) ResponseMap(n int, m ResponseMap) { |
| 158 f := func(path string) Response { |
| 159 for rpath, resp := range m { |
| 160 if rpath == path { |
| 161 return resp |
| 162 } |
| 163 } |
| 164 return Response{Status: 500, Body: "Path not found in response m
ap: " + path} |
| 165 } |
| 166 s.ResponseFunc(n, f) |
| 167 } |
| 168 |
| 169 // Responses prepares the test server to respond the following n requests |
| 170 // using the provided response parameters. |
| 171 func (s *TestHTTPServer) Responses(n int, status int, headers map[string]string,
body string) { |
| 172 f := func(path string) Response { |
| 173 return Response{status, headers, body} |
| 174 } |
| 175 s.ResponseFunc(n, f) |
| 176 } |
| 177 |
| 178 // Response prepares the test server to respond the following request |
| 179 // using the provided response parameters. |
| 180 func (s *TestHTTPServer) Response(status int, headers map[string]string, body st
ring) { |
| 181 s.Responses(1, status, headers, body) |
| 182 } |
| 183 |
OLD | NEW |