LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2010 The Go Authors. All rights reserved. | 1 // Copyright 2010 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // End-to-end serving tests | 5 // End-to-end serving tests |
6 | 6 |
7 package http_test | 7 package http_test |
8 | 8 |
9 import ( | 9 import ( |
10 "bufio" | 10 "bufio" |
11 "bytes" | 11 "bytes" |
12 "crypto/tls" | 12 "crypto/tls" |
13 "errors" | 13 "errors" |
14 "fmt" | 14 "fmt" |
15 "io" | 15 "io" |
16 "io/ioutil" | 16 "io/ioutil" |
17 "log" | 17 "log" |
18 "net" | 18 "net" |
19 . "net/http" | 19 . "net/http" |
20 "net/http/httptest" | 20 "net/http/httptest" |
21 "net/http/httputil" | 21 "net/http/httputil" |
22 "net/url" | 22 "net/url" |
23 "os" | 23 "os" |
24 "os/exec" | 24 "os/exec" |
25 "reflect" | 25 "reflect" |
26 "runtime" | 26 "runtime" |
27 "strconv" | 27 "strconv" |
28 "strings" | 28 "strings" |
| 29 "sync" |
29 "sync/atomic" | 30 "sync/atomic" |
30 "syscall" | 31 "syscall" |
31 "testing" | 32 "testing" |
32 "time" | 33 "time" |
33 ) | 34 ) |
34 | 35 |
35 type dummyAddr string | 36 type dummyAddr string |
36 type oneConnListener struct { | 37 type oneConnListener struct { |
37 conn net.Conn | 38 conn net.Conn |
38 } | 39 } |
(...skipping 2197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2236 res := ExportAppendTime(b[:0], t1) | 2237 res := ExportAppendTime(b[:0], t1) |
2237 t2, err := ParseTime(string(res)) | 2238 t2, err := ParseTime(string(res)) |
2238 if err != nil { | 2239 if err != nil { |
2239 t.Fatalf("Error parsing time: %s", err) | 2240 t.Fatalf("Error parsing time: %s", err) |
2240 } | 2241 } |
2241 if !t1.Equal(t2) { | 2242 if !t1.Equal(t2) { |
2242 t.Fatalf("Times differ; expected: %v, got %v (%s)", t1, t2, stri
ng(res)) | 2243 t.Fatalf("Times differ; expected: %v, got %v (%s)", t1, t2, stri
ng(res)) |
2243 } | 2244 } |
2244 } | 2245 } |
2245 | 2246 |
| 2247 func TestServerConnState(t *testing.T) { |
| 2248 defer afterTest(t) |
| 2249 handler := map[string]func(w ResponseWriter, r *Request){ |
| 2250 "/": func(w ResponseWriter, r *Request) { |
| 2251 fmt.Fprintf(w, "Hello.") |
| 2252 }, |
| 2253 "/close": func(w ResponseWriter, r *Request) { |
| 2254 w.Header().Set("Connection", "close") |
| 2255 fmt.Fprintf(w, "Hello.") |
| 2256 }, |
| 2257 "/hijack": func(w ResponseWriter, r *Request) { |
| 2258 c, _, _ := w.(Hijacker).Hijack() |
| 2259 c.Write([]byte("HTTP/1.0 200 OK\r\nConnection: close\r\n
\r\nHello.")) |
| 2260 c.Close() |
| 2261 }, |
| 2262 } |
| 2263 ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *
Request) { |
| 2264 handler[r.URL.Path](w, r) |
| 2265 })) |
| 2266 defer ts.Close() |
| 2267 |
| 2268 type connIDAndState struct { |
| 2269 connID int |
| 2270 state ConnState |
| 2271 } |
| 2272 var mu sync.Mutex // guard stateLog and connID |
| 2273 var stateLog []connIDAndState |
| 2274 var connID = map[net.Conn]int{} |
| 2275 |
| 2276 ts.Config.ConnState = func(c net.Conn, state ConnState) { |
| 2277 if c == nil { |
| 2278 t.Error("nil conn seen in state %s", state) |
| 2279 return |
| 2280 } |
| 2281 mu.Lock() |
| 2282 defer mu.Unlock() |
| 2283 id, ok := connID[c] |
| 2284 if !ok { |
| 2285 id = len(connID) + 1 |
| 2286 connID[c] = id |
| 2287 } |
| 2288 stateLog = append(stateLog, connIDAndState{id, state}) |
| 2289 } |
| 2290 ts.Start() |
| 2291 |
| 2292 mustGet(t, ts.URL+"/") |
| 2293 mustGet(t, ts.URL+"/close") |
| 2294 |
| 2295 mustGet(t, ts.URL+"/") |
| 2296 mustGet(t, ts.URL+"/", "Connection", "close") |
| 2297 |
| 2298 mustGet(t, ts.URL+"/hijack") |
| 2299 |
| 2300 want := []connIDAndState{ |
| 2301 {1, StateNew}, |
| 2302 {1, StateActive}, |
| 2303 {1, StateIdle}, |
| 2304 {1, StateActive}, |
| 2305 {1, StateClosed}, |
| 2306 |
| 2307 {2, StateNew}, |
| 2308 {2, StateActive}, |
| 2309 {2, StateIdle}, |
| 2310 {2, StateActive}, |
| 2311 {2, StateClosed}, |
| 2312 |
| 2313 {3, StateNew}, |
| 2314 {3, StateActive}, |
| 2315 {3, StateHijacked}, |
| 2316 } |
| 2317 logString := func(l []connIDAndState) string { |
| 2318 var b bytes.Buffer |
| 2319 for _, cs := range l { |
| 2320 fmt.Fprintf(&b, "[%d %s] ", cs.connID, cs.state) |
| 2321 } |
| 2322 return b.String() |
| 2323 } |
| 2324 |
| 2325 for i := 0; i < 5; i++ { |
| 2326 time.Sleep(time.Duration(i) * 50 * time.Millisecond) |
| 2327 mu.Lock() |
| 2328 match := reflect.DeepEqual(stateLog, want) |
| 2329 mu.Unlock() |
| 2330 if match { |
| 2331 return |
| 2332 } |
| 2333 } |
| 2334 |
| 2335 mu.Lock() |
| 2336 t.Errorf("Unexpected events.\nGot log: %s\n Want: %s\n", logString(sta
teLog), logString(want)) |
| 2337 mu.Unlock() |
| 2338 } |
| 2339 |
| 2340 func mustGet(t *testing.T, url string, headers ...string) { |
| 2341 req, err := NewRequest("GET", url, nil) |
| 2342 if err != nil { |
| 2343 t.Fatal(err) |
| 2344 } |
| 2345 for len(headers) > 0 { |
| 2346 req.Header.Add(headers[0], headers[1]) |
| 2347 headers = headers[2:] |
| 2348 } |
| 2349 res, err := DefaultClient.Do(req) |
| 2350 if err != nil { |
| 2351 t.Errorf("Error fetching %s: %v", url, err) |
| 2352 return |
| 2353 } |
| 2354 _, err = ioutil.ReadAll(res.Body) |
| 2355 defer res.Body.Close() |
| 2356 if err != nil { |
| 2357 t.Errorf("Error reading %s: %v", url, err) |
| 2358 } |
| 2359 } |
| 2360 |
2246 func BenchmarkClientServer(b *testing.B) { | 2361 func BenchmarkClientServer(b *testing.B) { |
2247 b.ReportAllocs() | 2362 b.ReportAllocs() |
2248 b.StopTimer() | 2363 b.StopTimer() |
2249 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request)
{ | 2364 ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request)
{ |
2250 fmt.Fprintf(rw, "Hello world.\n") | 2365 fmt.Fprintf(rw, "Hello world.\n") |
2251 })) | 2366 })) |
2252 defer ts.Close() | 2367 defer ts.Close() |
2253 b.StartTimer() | 2368 b.StartTimer() |
2254 | 2369 |
2255 for i := 0; i < b.N; i++ { | 2370 for i := 0; i < b.N; i++ { |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2552 closec: make(chan bool, 1), | 2667 closec: make(chan bool, 1), |
2553 } | 2668 } |
2554 ln := &oneConnListener{conn: conn} | 2669 ln := &oneConnListener{conn: conn} |
2555 for i := 0; i < b.N; i++ { | 2670 for i := 0; i < b.N; i++ { |
2556 conn.Reader = bytes.NewReader(req) | 2671 conn.Reader = bytes.NewReader(req) |
2557 ln.conn = conn | 2672 ln.conn = conn |
2558 Serve(ln, h) | 2673 Serve(ln, h) |
2559 <-conn.closec | 2674 <-conn.closec |
2560 } | 2675 } |
2561 } | 2676 } |
LEFT | RIGHT |