~ubuntu-branches/ubuntu/vivid/golang/vivid

« back to all changes in this revision

Viewing changes to src/pkg/net/http/serve_test.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-08-20 14:06:23 UTC
  • mfrom: (14.1.23 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130820140623-b414jfxi3m0qkmrq
Tags: 2:1.1.2-2ubuntu1
* Merge from Debian unstable (LP: #1211749, #1202027). Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - d/control,control.cross: Update Breaks/Replaces for Ubuntu
    versions to ensure smooth upgrades, regenerate control file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
10
10
        "bufio"
11
11
        "bytes"
12
12
        "crypto/tls"
 
13
        "errors"
13
14
        "fmt"
14
15
        "io"
15
16
        "io/ioutil"
20
21
        "net/http/httputil"
21
22
        "net/url"
22
23
        "os"
 
24
        "os/exec"
23
25
        "reflect"
 
26
        "runtime"
 
27
        "strconv"
24
28
        "strings"
 
29
        "sync"
 
30
        "sync/atomic"
25
31
        "syscall"
26
32
        "testing"
27
33
        "time"
59
65
        return string(a)
60
66
}
61
67
 
 
68
type noopConn struct{}
 
69
 
 
70
func (noopConn) LocalAddr() net.Addr                { return dummyAddr("local-addr") }
 
71
func (noopConn) RemoteAddr() net.Addr               { return dummyAddr("remote-addr") }
 
72
func (noopConn) SetDeadline(t time.Time) error      { return nil }
 
73
func (noopConn) SetReadDeadline(t time.Time) error  { return nil }
 
74
func (noopConn) SetWriteDeadline(t time.Time) error { return nil }
 
75
 
 
76
type rwTestConn struct {
 
77
        io.Reader
 
78
        io.Writer
 
79
        noopConn
 
80
 
 
81
        closeFunc func() error // called if non-nil
 
82
        closec    chan bool    // else, if non-nil, send value to it on close
 
83
}
 
84
 
 
85
func (c *rwTestConn) Close() error {
 
86
        if c.closeFunc != nil {
 
87
                return c.closeFunc()
 
88
        }
 
89
        select {
 
90
        case c.closec <- true:
 
91
        default:
 
92
        }
 
93
        return nil
 
94
}
 
95
 
62
96
type testConn struct {
63
97
        readBuf  bytes.Buffer
64
98
        writeBuf bytes.Buffer
 
99
        closec   chan bool // if non-nil, send value to it on close
 
100
        noopConn
65
101
}
66
102
 
67
103
func (c *testConn) Read(b []byte) (int, error) {
73
109
}
74
110
 
75
111
func (c *testConn) Close() error {
76
 
        return nil
77
 
}
78
 
 
79
 
func (c *testConn) LocalAddr() net.Addr {
80
 
        return dummyAddr("local-addr")
81
 
}
82
 
 
83
 
func (c *testConn) RemoteAddr() net.Addr {
84
 
        return dummyAddr("remote-addr")
85
 
}
86
 
 
87
 
func (c *testConn) SetDeadline(t time.Time) error {
88
 
        return nil
89
 
}
90
 
 
91
 
func (c *testConn) SetReadDeadline(t time.Time) error {
92
 
        return nil
93
 
}
94
 
 
95
 
func (c *testConn) SetWriteDeadline(t time.Time) error {
 
112
        select {
 
113
        case c.closec <- true:
 
114
        default:
 
115
        }
96
116
        return nil
97
117
}
98
118
 
168
188
        {"http://someHost.com/someDir/apage", "someHost.com/someDir"},
169
189
        {"http://otherHost.com/someDir/apage", "someDir"},
170
190
        {"http://otherHost.com/aDir/apage", "Default"},
 
191
        // redirections for trees
 
192
        {"http://localhost/someDir", "/someDir/"},
 
193
        {"http://someHost.com/someDir", "/someDir/"},
171
194
}
172
195
 
173
196
func TestHostHandlers(t *testing.T) {
 
197
        defer afterTest(t)
 
198
        mux := NewServeMux()
174
199
        for _, h := range handlers {
175
 
                Handle(h.pattern, stringHandler(h.msg))
 
200
                mux.Handle(h.pattern, stringHandler(h.msg))
176
201
        }
177
 
        ts := httptest.NewServer(nil)
 
202
        ts := httptest.NewServer(mux)
178
203
        defer ts.Close()
179
204
 
180
205
        conn, err := net.Dial("tcp", ts.Listener.Addr().String())
199
224
                        t.Errorf("reading response: %v", err)
200
225
                        continue
201
226
                }
202
 
                s := r.Header.Get("Result")
203
 
                if s != vt.expected {
204
 
                        t.Errorf("Get(%q) = %q, want %q", vt.url, s, vt.expected)
 
227
                switch r.StatusCode {
 
228
                case StatusOK:
 
229
                        s := r.Header.Get("Result")
 
230
                        if s != vt.expected {
 
231
                                t.Errorf("Get(%q) = %q, want %q", vt.url, s, vt.expected)
 
232
                        }
 
233
                case StatusMovedPermanently:
 
234
                        s := r.Header.Get("Location")
 
235
                        if s != vt.expected {
 
236
                                t.Errorf("Get(%q) = %q, want %q", vt.url, s, vt.expected)
 
237
                        }
 
238
                default:
 
239
                        t.Errorf("Get(%q) unhandled status code %d", vt.url, r.StatusCode)
205
240
                }
206
241
        }
207
242
}
232
267
}
233
268
 
234
269
func TestServerTimeouts(t *testing.T) {
235
 
        // TODO(bradfitz): convert this to use httptest.Server
236
 
        l, err := net.Listen("tcp", "127.0.0.1:0")
237
 
        if err != nil {
238
 
                t.Fatalf("listen error: %v", err)
239
 
        }
240
 
        addr, _ := l.Addr().(*net.TCPAddr)
241
 
 
 
270
        defer afterTest(t)
242
271
        reqNum := 0
243
 
        handler := HandlerFunc(func(res ResponseWriter, req *Request) {
 
272
        ts := httptest.NewUnstartedServer(HandlerFunc(func(res ResponseWriter, req *Request) {
244
273
                reqNum++
245
274
                fmt.Fprintf(res, "req=%d", reqNum)
246
 
        })
247
 
 
248
 
        server := &Server{Handler: handler, ReadTimeout: 250 * time.Millisecond, WriteTimeout: 250 * time.Millisecond}
249
 
        go server.Serve(l)
250
 
 
251
 
        url := fmt.Sprintf("http://%s/", addr)
 
275
        }))
 
276
        ts.Config.ReadTimeout = 250 * time.Millisecond
 
277
        ts.Config.WriteTimeout = 250 * time.Millisecond
 
278
        ts.Start()
 
279
        defer ts.Close()
252
280
 
253
281
        // Hit the HTTP server successfully.
254
282
        tr := &Transport{DisableKeepAlives: true} // they interfere with this test
 
283
        defer tr.CloseIdleConnections()
255
284
        c := &Client{Transport: tr}
256
 
        r, err := c.Get(url)
 
285
        r, err := c.Get(ts.URL)
257
286
        if err != nil {
258
287
                t.Fatalf("http Get #1: %v", err)
259
288
        }
266
295
 
267
296
        // Slow client that should timeout.
268
297
        t1 := time.Now()
269
 
        conn, err := net.Dial("tcp", addr.String())
 
298
        conn, err := net.Dial("tcp", ts.Listener.Addr().String())
270
299
        if err != nil {
271
300
                t.Fatalf("Dial: %v", err)
272
301
        }
273
302
        buf := make([]byte, 1)
274
303
        n, err := conn.Read(buf)
275
 
        latency := time.Now().Sub(t1)
 
304
        latency := time.Since(t1)
276
305
        if n != 0 || err != io.EOF {
277
306
                t.Errorf("Read = %v, %v, wanted %v, %v", n, err, 0, io.EOF)
278
307
        }
283
312
        // Hit the HTTP server successfully again, verifying that the
284
313
        // previous slow connection didn't run our handler.  (that we
285
314
        // get "req=2", not "req=3")
286
 
        r, err = Get(url)
 
315
        r, err = Get(ts.URL)
287
316
        if err != nil {
288
317
                t.Fatalf("http Get #2: %v", err)
289
318
        }
293
322
                t.Errorf("Get #2 got %q, want %q", string(got), expected)
294
323
        }
295
324
 
296
 
        l.Close()
297
 
}
298
 
 
299
 
// TestIdentityResponse verifies that a handler can unset 
 
325
        if !testing.Short() {
 
326
                conn, err := net.Dial("tcp", ts.Listener.Addr().String())
 
327
                if err != nil {
 
328
                        t.Fatalf("Dial: %v", err)
 
329
                }
 
330
                defer conn.Close()
 
331
                go io.Copy(ioutil.Discard, conn)
 
332
                for i := 0; i < 5; i++ {
 
333
                        _, err := conn.Write([]byte("GET / HTTP/1.1\r\nHost: foo\r\n\r\n"))
 
334
                        if err != nil {
 
335
                                t.Fatalf("on write %d: %v", i, err)
 
336
                        }
 
337
                        time.Sleep(ts.Config.ReadTimeout / 2)
 
338
                }
 
339
        }
 
340
}
 
341
 
 
342
// golang.org/issue/4741 -- setting only a write timeout that triggers
 
343
// shouldn't cause a handler to block forever on reads (next HTTP
 
344
// request) that will never happen.
 
345
func TestOnlyWriteTimeout(t *testing.T) {
 
346
        defer afterTest(t)
 
347
        var conn net.Conn
 
348
        var afterTimeoutErrc = make(chan error, 1)
 
349
        ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, req *Request) {
 
350
                buf := make([]byte, 512<<10)
 
351
                _, err := w.Write(buf)
 
352
                if err != nil {
 
353
                        t.Errorf("handler Write error: %v", err)
 
354
                        return
 
355
                }
 
356
                conn.SetWriteDeadline(time.Now().Add(-30 * time.Second))
 
357
                _, err = w.Write(buf)
 
358
                afterTimeoutErrc <- err
 
359
        }))
 
360
        ts.Listener = trackLastConnListener{ts.Listener, &conn}
 
361
        ts.Start()
 
362
        defer ts.Close()
 
363
 
 
364
        tr := &Transport{DisableKeepAlives: false}
 
365
        defer tr.CloseIdleConnections()
 
366
        c := &Client{Transport: tr}
 
367
 
 
368
        errc := make(chan error)
 
369
        go func() {
 
370
                res, err := c.Get(ts.URL)
 
371
                if err != nil {
 
372
                        errc <- err
 
373
                        return
 
374
                }
 
375
                _, err = io.Copy(ioutil.Discard, res.Body)
 
376
                errc <- err
 
377
        }()
 
378
        select {
 
379
        case err := <-errc:
 
380
                if err == nil {
 
381
                        t.Errorf("expected an error from Get request")
 
382
                }
 
383
        case <-time.After(5 * time.Second):
 
384
                t.Fatal("timeout waiting for Get error")
 
385
        }
 
386
        if err := <-afterTimeoutErrc; err == nil {
 
387
                t.Error("expected write error after timeout")
 
388
        }
 
389
}
 
390
 
 
391
// trackLastConnListener tracks the last net.Conn that was accepted.
 
392
type trackLastConnListener struct {
 
393
        net.Listener
 
394
        last *net.Conn // destination
 
395
}
 
396
 
 
397
func (l trackLastConnListener) Accept() (c net.Conn, err error) {
 
398
        c, err = l.Listener.Accept()
 
399
        *l.last = c
 
400
        return
 
401
}
 
402
 
 
403
// TestIdentityResponse verifies that a handler can unset
300
404
func TestIdentityResponse(t *testing.T) {
 
405
        defer afterTest(t)
301
406
        handler := HandlerFunc(func(rw ResponseWriter, req *Request) {
302
407
                rw.Header().Set("Content-Length", "3")
303
408
                rw.Header().Set("Transfer-Encoding", req.FormValue("te"))
343
448
 
344
449
        // Verify that ErrContentLength is returned
345
450
        url := ts.URL + "/?overwrite=1"
346
 
        _, err := Get(url)
 
451
        res, err := Get(url)
347
452
        if err != nil {
348
453
                t.Fatalf("error with Get of %s: %v", url, err)
349
454
        }
 
455
        res.Body.Close()
 
456
 
350
457
        // Verify that the connection is closed when the declared Content-Length
351
458
        // is larger than what the handler wrote.
352
459
        conn, err := net.Dial("tcp", ts.Listener.Addr().String())
370
477
        })
371
478
}
372
479
 
373
 
func testTcpConnectionCloses(t *testing.T, req string, h Handler) {
 
480
func testTCPConnectionCloses(t *testing.T, req string, h Handler) {
 
481
        defer afterTest(t)
374
482
        s := httptest.NewServer(h)
375
483
        defer s.Close()
376
484
 
386
494
        }
387
495
 
388
496
        r := bufio.NewReader(conn)
389
 
        _, err = ReadResponse(r, &Request{Method: "GET"})
 
497
        res, err := ReadResponse(r, &Request{Method: "GET"})
390
498
        if err != nil {
391
499
                t.Fatal("ReadResponse error:", err)
392
500
        }
393
501
 
394
 
        success := make(chan bool)
 
502
        didReadAll := make(chan bool, 1)
395
503
        go func() {
396
504
                select {
397
505
                case <-time.After(5 * time.Second):
398
 
                        t.Fatal("body not closed after 5s")
399
 
                case <-success:
 
506
                        t.Error("body not closed after 5s")
 
507
                        return
 
508
                case <-didReadAll:
400
509
                }
401
510
        }()
402
511
 
404
513
        if err != nil {
405
514
                t.Fatal("read error:", err)
406
515
        }
 
516
        didReadAll <- true
407
517
 
408
 
        success <- true
 
518
        if !res.Close {
 
519
                t.Errorf("Response.Close = false; want true")
 
520
        }
409
521
}
410
522
 
411
523
// TestServeHTTP10Close verifies that HTTP/1.0 requests won't be kept alive.
412
524
func TestServeHTTP10Close(t *testing.T) {
413
 
        testTcpConnectionCloses(t, "GET / HTTP/1.0\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
 
525
        testTCPConnectionCloses(t, "GET / HTTP/1.0\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
414
526
                ServeFile(w, r, "testdata/file")
415
527
        }))
416
528
}
417
529
 
 
530
// TestClientCanClose verifies that clients can also force a connection to close.
 
531
func TestClientCanClose(t *testing.T) {
 
532
        testTCPConnectionCloses(t, "GET / HTTP/1.1\r\nConnection: close\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
 
533
                // Nothing.
 
534
        }))
 
535
}
 
536
 
418
537
// TestHandlersCanSetConnectionClose verifies that handlers can force a connection to close,
419
538
// even for HTTP/1.1 requests.
420
539
func TestHandlersCanSetConnectionClose11(t *testing.T) {
421
 
        testTcpConnectionCloses(t, "GET / HTTP/1.1\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
 
540
        testTCPConnectionCloses(t, "GET / HTTP/1.1\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
422
541
                w.Header().Set("Connection", "close")
423
542
        }))
424
543
}
425
544
 
426
545
func TestHandlersCanSetConnectionClose10(t *testing.T) {
427
 
        testTcpConnectionCloses(t, "GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
 
546
        testTCPConnectionCloses(t, "GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
428
547
                w.Header().Set("Connection", "close")
429
548
        }))
430
549
}
431
550
 
432
551
func TestSetsRemoteAddr(t *testing.T) {
 
552
        defer afterTest(t)
433
553
        ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
434
554
                fmt.Fprintf(w, "%s", r.RemoteAddr)
435
555
        }))
450
570
}
451
571
 
452
572
func TestChunkedResponseHeaders(t *testing.T) {
 
573
        defer afterTest(t)
453
574
        log.SetOutput(ioutil.Discard) // is noisy otherwise
454
575
        defer log.SetOutput(os.Stderr)
455
576
 
456
577
        ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
457
578
                w.Header().Set("Content-Length", "intentional gibberish") // we check that this is deleted
 
579
                w.(Flusher).Flush()
458
580
                fmt.Fprintf(w, "I am a chunked response.")
459
581
        }))
460
582
        defer ts.Close()
463
585
        if err != nil {
464
586
                t.Fatalf("Get error: %v", err)
465
587
        }
 
588
        defer res.Body.Close()
466
589
        if g, e := res.ContentLength, int64(-1); g != e {
467
590
                t.Errorf("expected ContentLength of %d; got %d", e, g)
468
591
        }
478
601
// chunking in their response headers and aren't allowed to produce
479
602
// output.
480
603
func Test304Responses(t *testing.T) {
 
604
        defer afterTest(t)
481
605
        ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
482
606
                w.WriteHeader(StatusNotModified)
483
607
                _, err := w.Write([]byte("illegal body"))
507
631
// allowed to produce output, and don't set a Content-Type since
508
632
// the real type of the body data cannot be inferred.
509
633
func TestHeadResponses(t *testing.T) {
 
634
        defer afterTest(t)
510
635
        ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
511
636
                _, err := w.Write([]byte("Ignored body"))
512
637
                if err != ErrBodyNotAllowed {
541
666
}
542
667
 
543
668
func TestTLSHandshakeTimeout(t *testing.T) {
 
669
        defer afterTest(t)
544
670
        ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
545
671
        ts.Config.ReadTimeout = 250 * time.Millisecond
546
672
        ts.StartTLS()
560
686
}
561
687
 
562
688
func TestTLSServer(t *testing.T) {
 
689
        defer afterTest(t)
563
690
        ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
564
691
                if r.TLS != nil {
565
692
                        w.Header().Set("X-TLS-Set", "true")
642
769
// Tests that the server responds to the "Expect" request header
643
770
// correctly.
644
771
func TestServerExpect(t *testing.T) {
 
772
        defer afterTest(t)
645
773
        ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
646
774
                // Note using r.FormValue("readbody") because for POST
647
775
                // requests that would read from r.Body, which we only
661
789
                        t.Fatalf("Dial: %v", err)
662
790
                }
663
791
                defer conn.Close()
664
 
                sendf := func(format string, args ...interface{}) {
665
 
                        _, err := fmt.Fprintf(conn, format, args...)
666
 
                        if err != nil {
667
 
                                t.Fatalf("On test %#v, error writing %q: %v", test, format, err)
668
 
                        }
669
 
                }
 
792
 
 
793
                // Only send the body immediately if we're acting like an HTTP client
 
794
                // that doesn't send 100-continue expectations.
 
795
                writeBody := test.contentLength > 0 && strings.ToLower(test.expectation) != "100-continue"
 
796
 
670
797
                go func() {
671
 
                        sendf("POST /?readbody=%v HTTP/1.1\r\n"+
 
798
                        _, err := fmt.Fprintf(conn, "POST /?readbody=%v HTTP/1.1\r\n"+
672
799
                                "Connection: close\r\n"+
673
800
                                "Content-Length: %d\r\n"+
674
801
                                "Expect: %s\r\nHost: foo\r\n\r\n",
675
802
                                test.readBody, test.contentLength, test.expectation)
676
 
                        if test.contentLength > 0 && strings.ToLower(test.expectation) != "100-continue" {
 
803
                        if err != nil {
 
804
                                t.Errorf("On test %#v, error writing request headers: %v", test, err)
 
805
                                return
 
806
                        }
 
807
                        if writeBody {
677
808
                                body := strings.Repeat("A", test.contentLength)
678
 
                                sendf(body)
 
809
                                _, err = fmt.Fprint(conn, body)
 
810
                                if err != nil {
 
811
                                        if !test.readBody {
 
812
                                                // Server likely already hung up on us.
 
813
                                                // See larger comment below.
 
814
                                                t.Logf("On test %#v, acceptable error writing request body: %v", test, err)
 
815
                                                return
 
816
                                        }
 
817
                                        t.Errorf("On test %#v, error writing request body: %v", test, err)
 
818
                                }
679
819
                        }
680
820
                }()
681
821
                bufr := bufio.NewReader(conn)
682
822
                line, err := bufr.ReadString('\n')
683
823
                if err != nil {
684
 
                        t.Fatalf("ReadString: %v", err)
 
824
                        if writeBody && !test.readBody {
 
825
                                // This is an acceptable failure due to a possible TCP race:
 
826
                                // We were still writing data and the server hung up on us. A TCP
 
827
                                // implementation may send a RST if our request body data was known
 
828
                                // to be lost, which may trigger our reads to fail.
 
829
                                // See RFC 1122 page 88.
 
830
                                t.Logf("On test %#v, acceptable error from ReadString: %v", test, err)
 
831
                                return
 
832
                        }
 
833
                        t.Fatalf("On test %#v, ReadString: %v", test, err)
685
834
                }
686
835
                if !strings.Contains(line, test.expectedResponse) {
687
 
                        t.Errorf("for test %#v got first line=%q", test, line)
 
836
                        t.Errorf("On test %#v, got first line = %q; want %q", test, line, test.expectedResponse)
688
837
                }
689
838
        }
690
839
 
714
863
                        t.Errorf("on request, read buffer length is %d; expected about 100 KB", conn.readBuf.Len())
715
864
                }
716
865
                rw.WriteHeader(200)
 
866
                rw.(Flusher).Flush()
717
867
                if g, e := conn.readBuf.Len(), 0; g != e {
718
868
                        t.Errorf("after WriteHeader, read buffer length is %d; want %d", g, e)
719
869
                }
736
886
                        "Content-Length: %d\r\n"+
737
887
                        "\r\n", len(body))))
738
888
        conn.readBuf.Write([]byte(body))
739
 
 
740
 
        done := make(chan bool)
 
889
        conn.closec = make(chan bool, 1)
741
890
 
742
891
        ls := &oneConnListener{conn}
743
892
        go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
744
 
                defer close(done)
745
893
                if conn.readBuf.Len() < len(body)/2 {
746
894
                        t.Errorf("on request, read buffer length is %d; expected about 1MB", conn.readBuf.Len())
747
895
                }
748
896
                rw.WriteHeader(200)
 
897
                rw.(Flusher).Flush()
749
898
                if conn.readBuf.Len() < len(body)/2 {
750
899
                        t.Errorf("post-WriteHeader, read buffer length is %d; expected about 1MB", conn.readBuf.Len())
751
900
                }
752
 
                if c := rw.Header().Get("Connection"); c != "close" {
753
 
                        t.Errorf(`Connection header = %q; want "close"`, c)
754
 
                }
755
901
        }))
756
 
        <-done
 
902
        <-conn.closec
 
903
 
 
904
        if res := conn.writeBuf.String(); !strings.Contains(res, "Connection: close") {
 
905
                t.Errorf("Expected a Connection: close header; got response: %s", res)
 
906
        }
757
907
}
758
908
 
759
909
func TestTimeoutHandler(t *testing.T) {
 
910
        defer afterTest(t)
760
911
        sendHi := make(chan bool, 1)
761
912
        writeErrors := make(chan error, 1)
762
913
        sayHi := HandlerFunc(func(w ResponseWriter, r *Request) {
831
982
// the previous request's body, which is not optimal for zero-lengthed bodies,
832
983
// as the client would then see http.ErrBodyReadAfterClose and not 0, io.EOF.
833
984
func TestZeroLengthPostAndResponse(t *testing.T) {
 
985
        defer afterTest(t)
834
986
        ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
835
987
                all, err := ioutil.ReadAll(r.Body)
836
988
                if err != nil {
868
1020
        }
869
1021
}
870
1022
 
 
1023
func TestHandlerPanicNil(t *testing.T) {
 
1024
        testHandlerPanic(t, false, nil)
 
1025
}
 
1026
 
871
1027
func TestHandlerPanic(t *testing.T) {
872
 
        testHandlerPanic(t, false)
 
1028
        testHandlerPanic(t, false, "intentional death for testing")
873
1029
}
874
1030
 
875
1031
func TestHandlerPanicWithHijack(t *testing.T) {
876
 
        testHandlerPanic(t, true)
 
1032
        testHandlerPanic(t, true, "intentional death for testing")
877
1033
}
878
1034
 
879
 
func testHandlerPanic(t *testing.T, withHijack bool) {
 
1035
func testHandlerPanic(t *testing.T, withHijack bool, panicValue interface{}) {
 
1036
        defer afterTest(t)
880
1037
        // Unlike the other tests that set the log output to ioutil.Discard
881
1038
        // to quiet the output, this test uses a pipe.  The pipe serves three
882
1039
        // purposes:
896
1053
        pr, pw := io.Pipe()
897
1054
        log.SetOutput(pw)
898
1055
        defer log.SetOutput(os.Stderr)
 
1056
        defer pw.Close()
899
1057
 
900
1058
        ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
901
1059
                if withHijack {
905
1063
                        }
906
1064
                        defer rwc.Close()
907
1065
                }
908
 
                panic("intentional death for testing")
 
1066
                panic(panicValue)
909
1067
        }))
910
1068
        defer ts.Close()
911
1069
 
917
1075
                buf := make([]byte, 4<<10)
918
1076
                _, err := pr.Read(buf)
919
1077
                pr.Close()
920
 
                if err != nil {
921
 
                        t.Fatal(err)
 
1078
                if err != nil && err != io.EOF {
 
1079
                        t.Error(err)
922
1080
                }
923
1081
                done <- true
924
1082
        }()
928
1086
                t.Logf("expected an error")
929
1087
        }
930
1088
 
 
1089
        if panicValue == nil {
 
1090
                return
 
1091
        }
 
1092
 
931
1093
        select {
932
1094
        case <-done:
933
1095
                return
937
1099
}
938
1100
 
939
1101
func TestNoDate(t *testing.T) {
 
1102
        defer afterTest(t)
940
1103
        ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
941
1104
                w.Header()["Date"] = nil
942
1105
        }))
952
1115
}
953
1116
 
954
1117
func TestStripPrefix(t *testing.T) {
 
1118
        defer afterTest(t)
955
1119
        h := HandlerFunc(func(w ResponseWriter, r *Request) {
956
1120
                w.Header().Set("X-Path", r.URL.Path)
957
1121
        })
965
1129
        if g, e := res.Header.Get("X-Path"), "/bar"; g != e {
966
1130
                t.Errorf("test 1: got %s, want %s", g, e)
967
1131
        }
 
1132
        res.Body.Close()
968
1133
 
969
1134
        res, err = Get(ts.URL + "/bar")
970
1135
        if err != nil {
973
1138
        if g, e := res.StatusCode, 404; g != e {
974
1139
                t.Errorf("test 2: got status %v, want %v", g, e)
975
1140
        }
 
1141
        res.Body.Close()
976
1142
}
977
1143
 
978
1144
func TestRequestLimit(t *testing.T) {
 
1145
        defer afterTest(t)
979
1146
        ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
980
1147
                t.Fatalf("didn't expect to get request in Handler")
981
1148
        }))
992
1159
                // we do support it (at least currently), so we expect a response below.
993
1160
                t.Fatalf("Do: %v", err)
994
1161
        }
 
1162
        defer res.Body.Close()
995
1163
        if res.StatusCode != 413 {
996
1164
                t.Fatalf("expected 413 response status; got: %d %s", res.StatusCode, res.Status)
997
1165
        }
1013
1181
 
1014
1182
func (cr countReader) Read(p []byte) (n int, err error) {
1015
1183
        n, err = cr.r.Read(p)
1016
 
        *cr.n += int64(n)
 
1184
        atomic.AddInt64(cr.n, int64(n))
1017
1185
        return
1018
1186
}
1019
1187
 
1020
1188
func TestRequestBodyLimit(t *testing.T) {
 
1189
        defer afterTest(t)
1021
1190
        const limit = 1 << 20
1022
1191
        ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
1023
1192
                r.Body = MaxBytesReader(w, r.Body, limit)
1031
1200
        }))
1032
1201
        defer ts.Close()
1033
1202
 
1034
 
        nWritten := int64(0)
1035
 
        req, _ := NewRequest("POST", ts.URL, io.LimitReader(countReader{neverEnding('a'), &nWritten}, limit*200))
 
1203
        nWritten := new(int64)
 
1204
        req, _ := NewRequest("POST", ts.URL, io.LimitReader(countReader{neverEnding('a'), nWritten}, limit*200))
1036
1205
 
1037
1206
        // Send the POST, but don't care it succeeds or not.  The
1038
1207
        // remote side is going to reply and then close the TCP
1045
1214
        // the remote side hung up on us before we wrote too much.
1046
1215
        _, _ = DefaultClient.Do(req)
1047
1216
 
1048
 
        if nWritten > limit*100 {
 
1217
        if atomic.LoadInt64(nWritten) > limit*100 {
1049
1218
                t.Errorf("handler restricted the request body to %d bytes, but client managed to write %d",
1050
1219
                        limit, nWritten)
1051
1220
        }
1054
1223
// TestClientWriteShutdown tests that if the client shuts down the write
1055
1224
// side of their TCP connection, the server doesn't send a 400 Bad Request.
1056
1225
func TestClientWriteShutdown(t *testing.T) {
 
1226
        defer afterTest(t)
1057
1227
        ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
1058
1228
        defer ts.Close()
1059
1229
        conn, err := net.Dial("tcp", ts.Listener.Addr().String())
1086
1256
// Tests that chunked server responses that write 1 byte at a time are
1087
1257
// buffered before chunk headers are added, not after chunk headers.
1088
1258
func TestServerBufferedChunking(t *testing.T) {
1089
 
        if true {
1090
 
                t.Logf("Skipping known broken test; see Issue 2357")
1091
 
                return
1092
 
        }
1093
1259
        conn := new(testConn)
1094
1260
        conn.readBuf.Write([]byte("GET / HTTP/1.1\r\n\r\n"))
1095
 
        done := make(chan bool)
 
1261
        conn.closec = make(chan bool, 1)
1096
1262
        ls := &oneConnListener{conn}
1097
1263
        go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
1098
 
                defer close(done)
1099
 
                rw.Header().Set("Content-Type", "text/plain") // prevent sniffing, which buffers
 
1264
                rw.(Flusher).Flush() // force the Header to be sent, in chunking mode, not counting the length
1100
1265
                rw.Write([]byte{'x'})
1101
1266
                rw.Write([]byte{'y'})
1102
1267
                rw.Write([]byte{'z'})
1103
1268
        }))
1104
 
        <-done
 
1269
        <-conn.closec
1105
1270
        if !bytes.HasSuffix(conn.writeBuf.Bytes(), []byte("\r\n\r\n3\r\nxyz\r\n0\r\n\r\n")) {
1106
1271
                t.Errorf("response didn't end with a single 3 byte 'xyz' chunk; got:\n%q",
1107
1272
                        conn.writeBuf.Bytes())
1108
1273
        }
1109
1274
}
1110
1275
 
 
1276
// Tests that the server flushes its response headers out when it's
 
1277
// ignoring the response body and waits a bit before forcefully
 
1278
// closing the TCP connection, causing the client to get a RST.
 
1279
// See http://golang.org/issue/3595
 
1280
func TestServerGracefulClose(t *testing.T) {
 
1281
        defer afterTest(t)
 
1282
        ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 
1283
                Error(w, "bye", StatusUnauthorized)
 
1284
        }))
 
1285
        defer ts.Close()
 
1286
 
 
1287
        conn, err := net.Dial("tcp", ts.Listener.Addr().String())
 
1288
        if err != nil {
 
1289
                t.Fatal(err)
 
1290
        }
 
1291
        defer conn.Close()
 
1292
        const bodySize = 5 << 20
 
1293
        req := []byte(fmt.Sprintf("POST / HTTP/1.1\r\nHost: foo.com\r\nContent-Length: %d\r\n\r\n", bodySize))
 
1294
        for i := 0; i < bodySize; i++ {
 
1295
                req = append(req, 'x')
 
1296
        }
 
1297
        writeErr := make(chan error)
 
1298
        go func() {
 
1299
                _, err := conn.Write(req)
 
1300
                writeErr <- err
 
1301
        }()
 
1302
        br := bufio.NewReader(conn)
 
1303
        lineNum := 0
 
1304
        for {
 
1305
                line, err := br.ReadString('\n')
 
1306
                if err == io.EOF {
 
1307
                        break
 
1308
                }
 
1309
                if err != nil {
 
1310
                        t.Fatalf("ReadLine: %v", err)
 
1311
                }
 
1312
                lineNum++
 
1313
                if lineNum == 1 && !strings.Contains(line, "401 Unauthorized") {
 
1314
                        t.Errorf("Response line = %q; want a 401", line)
 
1315
                }
 
1316
        }
 
1317
        // Wait for write to finish. This is a broken pipe on both
 
1318
        // Darwin and Linux, but checking this isn't the point of
 
1319
        // the test.
 
1320
        <-writeErr
 
1321
}
 
1322
 
 
1323
func TestCaseSensitiveMethod(t *testing.T) {
 
1324
        defer afterTest(t)
 
1325
        ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 
1326
                if r.Method != "get" {
 
1327
                        t.Errorf(`Got method %q; want "get"`, r.Method)
 
1328
                }
 
1329
        }))
 
1330
        defer ts.Close()
 
1331
        req, _ := NewRequest("get", ts.URL, nil)
 
1332
        res, err := DefaultClient.Do(req)
 
1333
        if err != nil {
 
1334
                t.Error(err)
 
1335
                return
 
1336
        }
 
1337
        res.Body.Close()
 
1338
}
 
1339
 
 
1340
// TestContentLengthZero tests that for both an HTTP/1.0 and HTTP/1.1
 
1341
// request (both keep-alive), when a Handler never writes any
 
1342
// response, the net/http package adds a "Content-Length: 0" response
 
1343
// header.
 
1344
func TestContentLengthZero(t *testing.T) {
 
1345
        ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {}))
 
1346
        defer ts.Close()
 
1347
 
 
1348
        for _, version := range []string{"HTTP/1.0", "HTTP/1.1"} {
 
1349
                conn, err := net.Dial("tcp", ts.Listener.Addr().String())
 
1350
                if err != nil {
 
1351
                        t.Fatalf("error dialing: %v", err)
 
1352
                }
 
1353
                _, err = fmt.Fprintf(conn, "GET / %v\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n", version)
 
1354
                if err != nil {
 
1355
                        t.Fatalf("error writing: %v", err)
 
1356
                }
 
1357
                req, _ := NewRequest("GET", "/", nil)
 
1358
                res, err := ReadResponse(bufio.NewReader(conn), req)
 
1359
                if err != nil {
 
1360
                        t.Fatalf("error reading response: %v", err)
 
1361
                }
 
1362
                if te := res.TransferEncoding; len(te) > 0 {
 
1363
                        t.Errorf("For version %q, Transfer-Encoding = %q; want none", version, te)
 
1364
                }
 
1365
                if cl := res.ContentLength; cl != 0 {
 
1366
                        t.Errorf("For version %q, Content-Length = %v; want 0", version, cl)
 
1367
                }
 
1368
                conn.Close()
 
1369
        }
 
1370
}
 
1371
 
 
1372
func TestCloseNotifier(t *testing.T) {
 
1373
        defer afterTest(t)
 
1374
        gotReq := make(chan bool, 1)
 
1375
        sawClose := make(chan bool, 1)
 
1376
        ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
 
1377
                gotReq <- true
 
1378
                cc := rw.(CloseNotifier).CloseNotify()
 
1379
                <-cc
 
1380
                sawClose <- true
 
1381
        }))
 
1382
        conn, err := net.Dial("tcp", ts.Listener.Addr().String())
 
1383
        if err != nil {
 
1384
                t.Fatalf("error dialing: %v", err)
 
1385
        }
 
1386
        diec := make(chan bool)
 
1387
        go func() {
 
1388
                _, err = fmt.Fprintf(conn, "GET / HTTP/1.1\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n")
 
1389
                if err != nil {
 
1390
                        t.Fatal(err)
 
1391
                }
 
1392
                <-diec
 
1393
                conn.Close()
 
1394
        }()
 
1395
For:
 
1396
        for {
 
1397
                select {
 
1398
                case <-gotReq:
 
1399
                        diec <- true
 
1400
                case <-sawClose:
 
1401
                        break For
 
1402
                case <-time.After(5 * time.Second):
 
1403
                        t.Fatal("timeout")
 
1404
                }
 
1405
        }
 
1406
        ts.Close()
 
1407
}
 
1408
 
 
1409
func TestCloseNotifierChanLeak(t *testing.T) {
 
1410
        defer afterTest(t)
 
1411
        req := []byte(strings.Replace(`GET / HTTP/1.0
 
1412
Host: golang.org
 
1413
 
 
1414
`, "\n", "\r\n", -1))
 
1415
        for i := 0; i < 20; i++ {
 
1416
                var output bytes.Buffer
 
1417
                conn := &rwTestConn{
 
1418
                        Reader: bytes.NewReader(req),
 
1419
                        Writer: &output,
 
1420
                        closec: make(chan bool, 1),
 
1421
                }
 
1422
                ln := &oneConnListener{conn: conn}
 
1423
                handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
 
1424
                        // Ignore the return value and never read from
 
1425
                        // it, testing that we don't leak goroutines
 
1426
                        // on the sending side:
 
1427
                        _ = rw.(CloseNotifier).CloseNotify()
 
1428
                })
 
1429
                go Serve(ln, handler)
 
1430
                <-conn.closec
 
1431
        }
 
1432
}
 
1433
 
 
1434
func TestOptions(t *testing.T) {
 
1435
        uric := make(chan string, 2) // only expect 1, but leave space for 2
 
1436
        mux := NewServeMux()
 
1437
        mux.HandleFunc("/", func(w ResponseWriter, r *Request) {
 
1438
                uric <- r.RequestURI
 
1439
        })
 
1440
        ts := httptest.NewServer(mux)
 
1441
        defer ts.Close()
 
1442
 
 
1443
        conn, err := net.Dial("tcp", ts.Listener.Addr().String())
 
1444
        if err != nil {
 
1445
                t.Fatal(err)
 
1446
        }
 
1447
        defer conn.Close()
 
1448
 
 
1449
        // An OPTIONS * request should succeed.
 
1450
        _, err = conn.Write([]byte("OPTIONS * HTTP/1.1\r\nHost: foo.com\r\n\r\n"))
 
1451
        if err != nil {
 
1452
                t.Fatal(err)
 
1453
        }
 
1454
        br := bufio.NewReader(conn)
 
1455
        res, err := ReadResponse(br, &Request{Method: "OPTIONS"})
 
1456
        if err != nil {
 
1457
                t.Fatal(err)
 
1458
        }
 
1459
        if res.StatusCode != 200 {
 
1460
                t.Errorf("Got non-200 response to OPTIONS *: %#v", res)
 
1461
        }
 
1462
 
 
1463
        // A GET * request on a ServeMux should fail.
 
1464
        _, err = conn.Write([]byte("GET * HTTP/1.1\r\nHost: foo.com\r\n\r\n"))
 
1465
        if err != nil {
 
1466
                t.Fatal(err)
 
1467
        }
 
1468
        res, err = ReadResponse(br, &Request{Method: "GET"})
 
1469
        if err != nil {
 
1470
                t.Fatal(err)
 
1471
        }
 
1472
        if res.StatusCode != 400 {
 
1473
                t.Errorf("Got non-400 response to GET *: %#v", res)
 
1474
        }
 
1475
 
 
1476
        res, err = Get(ts.URL + "/second")
 
1477
        if err != nil {
 
1478
                t.Fatal(err)
 
1479
        }
 
1480
        res.Body.Close()
 
1481
        if got := <-uric; got != "/second" {
 
1482
                t.Errorf("Handler saw request for %q; want /second", got)
 
1483
        }
 
1484
}
 
1485
 
 
1486
// Tests regarding the ordering of Write, WriteHeader, Header, and
 
1487
// Flush calls.  In Go 1.0, rw.WriteHeader immediately flushed the
 
1488
// (*response).header to the wire. In Go 1.1, the actual wire flush is
 
1489
// delayed, so we could maybe tack on a Content-Length and better
 
1490
// Content-Type after we see more (or all) of the output. To preserve
 
1491
// compatibility with Go 1, we need to be careful to track which
 
1492
// headers were live at the time of WriteHeader, so we write the same
 
1493
// ones, even if the handler modifies them (~erroneously) after the
 
1494
// first Write.
 
1495
func TestHeaderToWire(t *testing.T) {
 
1496
        req := []byte(strings.Replace(`GET / HTTP/1.1
 
1497
Host: golang.org
 
1498
 
 
1499
`, "\n", "\r\n", -1))
 
1500
 
 
1501
        tests := []struct {
 
1502
                name    string
 
1503
                handler func(ResponseWriter, *Request)
 
1504
                check   func(output string) error
 
1505
        }{
 
1506
                {
 
1507
                        name: "write without Header",
 
1508
                        handler: func(rw ResponseWriter, r *Request) {
 
1509
                                rw.Write([]byte("hello world"))
 
1510
                        },
 
1511
                        check: func(got string) error {
 
1512
                                if !strings.Contains(got, "Content-Length:") {
 
1513
                                        return errors.New("no content-length")
 
1514
                                }
 
1515
                                if !strings.Contains(got, "Content-Type: text/plain") {
 
1516
                                        return errors.New("no content-length")
 
1517
                                }
 
1518
                                return nil
 
1519
                        },
 
1520
                },
 
1521
                {
 
1522
                        name: "Header mutation before write",
 
1523
                        handler: func(rw ResponseWriter, r *Request) {
 
1524
                                h := rw.Header()
 
1525
                                h.Set("Content-Type", "some/type")
 
1526
                                rw.Write([]byte("hello world"))
 
1527
                                h.Set("Too-Late", "bogus")
 
1528
                        },
 
1529
                        check: func(got string) error {
 
1530
                                if !strings.Contains(got, "Content-Length:") {
 
1531
                                        return errors.New("no content-length")
 
1532
                                }
 
1533
                                if !strings.Contains(got, "Content-Type: some/type") {
 
1534
                                        return errors.New("wrong content-type")
 
1535
                                }
 
1536
                                if strings.Contains(got, "Too-Late") {
 
1537
                                        return errors.New("don't want too-late header")
 
1538
                                }
 
1539
                                return nil
 
1540
                        },
 
1541
                },
 
1542
                {
 
1543
                        name: "write then useless Header mutation",
 
1544
                        handler: func(rw ResponseWriter, r *Request) {
 
1545
                                rw.Write([]byte("hello world"))
 
1546
                                rw.Header().Set("Too-Late", "Write already wrote headers")
 
1547
                        },
 
1548
                        check: func(got string) error {
 
1549
                                if strings.Contains(got, "Too-Late") {
 
1550
                                        return errors.New("header appeared from after WriteHeader")
 
1551
                                }
 
1552
                                return nil
 
1553
                        },
 
1554
                },
 
1555
                {
 
1556
                        name: "flush then write",
 
1557
                        handler: func(rw ResponseWriter, r *Request) {
 
1558
                                rw.(Flusher).Flush()
 
1559
                                rw.Write([]byte("post-flush"))
 
1560
                                rw.Header().Set("Too-Late", "Write already wrote headers")
 
1561
                        },
 
1562
                        check: func(got string) error {
 
1563
                                if !strings.Contains(got, "Transfer-Encoding: chunked") {
 
1564
                                        return errors.New("not chunked")
 
1565
                                }
 
1566
                                if strings.Contains(got, "Too-Late") {
 
1567
                                        return errors.New("header appeared from after WriteHeader")
 
1568
                                }
 
1569
                                return nil
 
1570
                        },
 
1571
                },
 
1572
                {
 
1573
                        name: "header then flush",
 
1574
                        handler: func(rw ResponseWriter, r *Request) {
 
1575
                                rw.Header().Set("Content-Type", "some/type")
 
1576
                                rw.(Flusher).Flush()
 
1577
                                rw.Write([]byte("post-flush"))
 
1578
                                rw.Header().Set("Too-Late", "Write already wrote headers")
 
1579
                        },
 
1580
                        check: func(got string) error {
 
1581
                                if !strings.Contains(got, "Transfer-Encoding: chunked") {
 
1582
                                        return errors.New("not chunked")
 
1583
                                }
 
1584
                                if strings.Contains(got, "Too-Late") {
 
1585
                                        return errors.New("header appeared from after WriteHeader")
 
1586
                                }
 
1587
                                if !strings.Contains(got, "Content-Type: some/type") {
 
1588
                                        return errors.New("wrong content-length")
 
1589
                                }
 
1590
                                return nil
 
1591
                        },
 
1592
                },
 
1593
                {
 
1594
                        name: "sniff-on-first-write content-type",
 
1595
                        handler: func(rw ResponseWriter, r *Request) {
 
1596
                                rw.Write([]byte("<html><head></head><body>some html</body></html>"))
 
1597
                                rw.Header().Set("Content-Type", "x/wrong")
 
1598
                        },
 
1599
                        check: func(got string) error {
 
1600
                                if !strings.Contains(got, "Content-Type: text/html") {
 
1601
                                        return errors.New("wrong content-length; want html")
 
1602
                                }
 
1603
                                return nil
 
1604
                        },
 
1605
                },
 
1606
                {
 
1607
                        name: "explicit content-type wins",
 
1608
                        handler: func(rw ResponseWriter, r *Request) {
 
1609
                                rw.Header().Set("Content-Type", "some/type")
 
1610
                                rw.Write([]byte("<html><head></head><body>some html</body></html>"))
 
1611
                        },
 
1612
                        check: func(got string) error {
 
1613
                                if !strings.Contains(got, "Content-Type: some/type") {
 
1614
                                        return errors.New("wrong content-length; want html")
 
1615
                                }
 
1616
                                return nil
 
1617
                        },
 
1618
                },
 
1619
                {
 
1620
                        name: "empty handler",
 
1621
                        handler: func(rw ResponseWriter, r *Request) {
 
1622
                        },
 
1623
                        check: func(got string) error {
 
1624
                                if !strings.Contains(got, "Content-Type: text/plain") {
 
1625
                                        return errors.New("wrong content-length; want text/plain")
 
1626
                                }
 
1627
                                if !strings.Contains(got, "Content-Length: 0") {
 
1628
                                        return errors.New("want 0 content-length")
 
1629
                                }
 
1630
                                return nil
 
1631
                        },
 
1632
                },
 
1633
                {
 
1634
                        name: "only Header, no write",
 
1635
                        handler: func(rw ResponseWriter, r *Request) {
 
1636
                                rw.Header().Set("Some-Header", "some-value")
 
1637
                        },
 
1638
                        check: func(got string) error {
 
1639
                                if !strings.Contains(got, "Some-Header") {
 
1640
                                        return errors.New("didn't get header")
 
1641
                                }
 
1642
                                return nil
 
1643
                        },
 
1644
                },
 
1645
                {
 
1646
                        name: "WriteHeader call",
 
1647
                        handler: func(rw ResponseWriter, r *Request) {
 
1648
                                rw.WriteHeader(404)
 
1649
                                rw.Header().Set("Too-Late", "some-value")
 
1650
                        },
 
1651
                        check: func(got string) error {
 
1652
                                if !strings.Contains(got, "404") {
 
1653
                                        return errors.New("wrong status")
 
1654
                                }
 
1655
                                if strings.Contains(got, "Some-Header") {
 
1656
                                        return errors.New("shouldn't have seen Too-Late")
 
1657
                                }
 
1658
                                return nil
 
1659
                        },
 
1660
                },
 
1661
        }
 
1662
        for _, tc := range tests {
 
1663
                var output bytes.Buffer
 
1664
                conn := &rwTestConn{
 
1665
                        Reader: bytes.NewReader(req),
 
1666
                        Writer: &output,
 
1667
                        closec: make(chan bool, 1),
 
1668
                }
 
1669
                ln := &oneConnListener{conn: conn}
 
1670
                go Serve(ln, HandlerFunc(tc.handler))
 
1671
                <-conn.closec
 
1672
                if err := tc.check(output.String()); err != nil {
 
1673
                        t.Errorf("%s: %v\nGot response:\n%s", tc.name, err, output.Bytes())
 
1674
                }
 
1675
        }
 
1676
}
 
1677
 
1111
1678
// goTimeout runs f, failing t if f takes more than ns to complete.
1112
1679
func goTimeout(t *testing.T, d time.Duration, f func()) {
1113
1680
        ch := make(chan bool, 2)
1184
1751
 
1185
1752
        b.StopTimer()
1186
1753
}
 
1754
 
 
1755
func BenchmarkClientServerParallel4(b *testing.B) {
 
1756
        benchmarkClientServerParallel(b, 4)
 
1757
}
 
1758
 
 
1759
func BenchmarkClientServerParallel64(b *testing.B) {
 
1760
        benchmarkClientServerParallel(b, 64)
 
1761
}
 
1762
 
 
1763
func benchmarkClientServerParallel(b *testing.B, conc int) {
 
1764
        b.StopTimer()
 
1765
        ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
 
1766
                fmt.Fprintf(rw, "Hello world.\n")
 
1767
        }))
 
1768
        defer ts.Close()
 
1769
        b.StartTimer()
 
1770
 
 
1771
        numProcs := runtime.GOMAXPROCS(-1) * conc
 
1772
        var wg sync.WaitGroup
 
1773
        wg.Add(numProcs)
 
1774
        n := int32(b.N)
 
1775
        for p := 0; p < numProcs; p++ {
 
1776
                go func() {
 
1777
                        for atomic.AddInt32(&n, -1) >= 0 {
 
1778
                                res, err := Get(ts.URL)
 
1779
                                if err != nil {
 
1780
                                        b.Logf("Get: %v", err)
 
1781
                                        continue
 
1782
                                }
 
1783
                                all, err := ioutil.ReadAll(res.Body)
 
1784
                                if err != nil {
 
1785
                                        b.Logf("ReadAll: %v", err)
 
1786
                                        continue
 
1787
                                }
 
1788
                                body := string(all)
 
1789
                                if body != "Hello world.\n" {
 
1790
                                        panic("Got body: " + body)
 
1791
                                }
 
1792
                        }
 
1793
                        wg.Done()
 
1794
                }()
 
1795
        }
 
1796
        wg.Wait()
 
1797
}
 
1798
 
 
1799
// A benchmark for profiling the server without the HTTP client code.
 
1800
// The client code runs in a subprocess.
 
1801
//
 
1802
// For use like:
 
1803
//   $ go test -c
 
1804
//   $ ./http.test -test.run=XX -test.bench=BenchmarkServer -test.benchtime=15s -test.cpuprofile=http.prof
 
1805
//   $ go tool pprof http.test http.prof
 
1806
//   (pprof) web
 
1807
func BenchmarkServer(b *testing.B) {
 
1808
        // Child process mode;
 
1809
        if url := os.Getenv("TEST_BENCH_SERVER_URL"); url != "" {
 
1810
                n, err := strconv.Atoi(os.Getenv("TEST_BENCH_CLIENT_N"))
 
1811
                if err != nil {
 
1812
                        panic(err)
 
1813
                }
 
1814
                for i := 0; i < n; i++ {
 
1815
                        res, err := Get(url)
 
1816
                        if err != nil {
 
1817
                                log.Panicf("Get: %v", err)
 
1818
                        }
 
1819
                        all, err := ioutil.ReadAll(res.Body)
 
1820
                        if err != nil {
 
1821
                                log.Panicf("ReadAll: %v", err)
 
1822
                        }
 
1823
                        body := string(all)
 
1824
                        if body != "Hello world.\n" {
 
1825
                                log.Panicf("Got body: %q", body)
 
1826
                        }
 
1827
                }
 
1828
                os.Exit(0)
 
1829
                return
 
1830
        }
 
1831
 
 
1832
        var res = []byte("Hello world.\n")
 
1833
        b.StopTimer()
 
1834
        ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
 
1835
                rw.Header().Set("Content-Type", "text/html; charset=utf-8")
 
1836
                rw.Write(res)
 
1837
        }))
 
1838
        defer ts.Close()
 
1839
        b.StartTimer()
 
1840
 
 
1841
        cmd := exec.Command(os.Args[0], "-test.run=XXXX", "-test.bench=BenchmarkServer")
 
1842
        cmd.Env = append([]string{
 
1843
                fmt.Sprintf("TEST_BENCH_CLIENT_N=%d", b.N),
 
1844
                fmt.Sprintf("TEST_BENCH_SERVER_URL=%s", ts.URL),
 
1845
        }, os.Environ()...)
 
1846
        out, err := cmd.CombinedOutput()
 
1847
        if err != nil {
 
1848
                b.Errorf("Test failure: %v, with output: %s", err, out)
 
1849
        }
 
1850
}
 
1851
 
 
1852
func BenchmarkServerFakeConnNoKeepAlive(b *testing.B) {
 
1853
        b.ReportAllocs()
 
1854
        req := []byte(strings.Replace(`GET / HTTP/1.0
 
1855
Host: golang.org
 
1856
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
 
1857
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17
 
1858
Accept-Encoding: gzip,deflate,sdch
 
1859
Accept-Language: en-US,en;q=0.8
 
1860
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
 
1861
 
 
1862
`, "\n", "\r\n", -1))
 
1863
        res := []byte("Hello world!\n")
 
1864
 
 
1865
        conn := &testConn{
 
1866
                // testConn.Close will not push into the channel
 
1867
                // if it's full.
 
1868
                closec: make(chan bool, 1),
 
1869
        }
 
1870
        handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
 
1871
                rw.Header().Set("Content-Type", "text/html; charset=utf-8")
 
1872
                rw.Write(res)
 
1873
        })
 
1874
        ln := new(oneConnListener)
 
1875
        for i := 0; i < b.N; i++ {
 
1876
                conn.readBuf.Reset()
 
1877
                conn.writeBuf.Reset()
 
1878
                conn.readBuf.Write(req)
 
1879
                ln.conn = conn
 
1880
                Serve(ln, handler)
 
1881
                <-conn.closec
 
1882
        }
 
1883
}
 
1884
 
 
1885
// repeatReader reads content count times, then EOFs.
 
1886
type repeatReader struct {
 
1887
        content []byte
 
1888
        count   int
 
1889
        off     int
 
1890
}
 
1891
 
 
1892
func (r *repeatReader) Read(p []byte) (n int, err error) {
 
1893
        if r.count <= 0 {
 
1894
                return 0, io.EOF
 
1895
        }
 
1896
        n = copy(p, r.content[r.off:])
 
1897
        r.off += n
 
1898
        if r.off == len(r.content) {
 
1899
                r.count--
 
1900
                r.off = 0
 
1901
        }
 
1902
        return
 
1903
}
 
1904
 
 
1905
func BenchmarkServerFakeConnWithKeepAlive(b *testing.B) {
 
1906
        b.ReportAllocs()
 
1907
 
 
1908
        req := []byte(strings.Replace(`GET / HTTP/1.1
 
1909
Host: golang.org
 
1910
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
 
1911
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17
 
1912
Accept-Encoding: gzip,deflate,sdch
 
1913
Accept-Language: en-US,en;q=0.8
 
1914
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
 
1915
 
 
1916
`, "\n", "\r\n", -1))
 
1917
        res := []byte("Hello world!\n")
 
1918
 
 
1919
        conn := &rwTestConn{
 
1920
                Reader: &repeatReader{content: req, count: b.N},
 
1921
                Writer: ioutil.Discard,
 
1922
                closec: make(chan bool, 1),
 
1923
        }
 
1924
        handled := 0
 
1925
        handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
 
1926
                handled++
 
1927
                rw.Header().Set("Content-Type", "text/html; charset=utf-8")
 
1928
                rw.Write(res)
 
1929
        })
 
1930
        ln := &oneConnListener{conn: conn}
 
1931
        go Serve(ln, handler)
 
1932
        <-conn.closec
 
1933
        if b.N != handled {
 
1934
                b.Errorf("b.N=%d but handled %d", b.N, handled)
 
1935
        }
 
1936
}
 
1937
 
 
1938
// same as above, but representing the most simple possible request
 
1939
// and handler. Notably: the handler does not call rw.Header().
 
1940
func BenchmarkServerFakeConnWithKeepAliveLite(b *testing.B) {
 
1941
        b.ReportAllocs()
 
1942
 
 
1943
        req := []byte(strings.Replace(`GET / HTTP/1.1
 
1944
Host: golang.org
 
1945
 
 
1946
`, "\n", "\r\n", -1))
 
1947
        res := []byte("Hello world!\n")
 
1948
 
 
1949
        conn := &rwTestConn{
 
1950
                Reader: &repeatReader{content: req, count: b.N},
 
1951
                Writer: ioutil.Discard,
 
1952
                closec: make(chan bool, 1),
 
1953
        }
 
1954
        handled := 0
 
1955
        handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
 
1956
                handled++
 
1957
                rw.Write(res)
 
1958
        })
 
1959
        ln := &oneConnListener{conn: conn}
 
1960
        go Serve(ln, handler)
 
1961
        <-conn.closec
 
1962
        if b.N != handled {
 
1963
                b.Errorf("b.N=%d but handled %d", b.N, handled)
 
1964
        }
 
1965
}
 
1966
 
 
1967
const someResponse = "<html>some response</html>"
 
1968
 
 
1969
// A Response that's just no bigger than 2KB, the buffer-before-chunking threshold.
 
1970
var response = bytes.Repeat([]byte(someResponse), 2<<10/len(someResponse))
 
1971
 
 
1972
// Both Content-Type and Content-Length set. Should be no buffering.
 
1973
func BenchmarkServerHandlerTypeLen(b *testing.B) {
 
1974
        benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) {
 
1975
                w.Header().Set("Content-Type", "text/html")
 
1976
                w.Header().Set("Content-Length", strconv.Itoa(len(response)))
 
1977
                w.Write(response)
 
1978
        }))
 
1979
}
 
1980
 
 
1981
// A Content-Type is set, but no length. No sniffing, but will count the Content-Length.
 
1982
func BenchmarkServerHandlerNoLen(b *testing.B) {
 
1983
        benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) {
 
1984
                w.Header().Set("Content-Type", "text/html")
 
1985
                w.Write(response)
 
1986
        }))
 
1987
}
 
1988
 
 
1989
// A Content-Length is set, but the Content-Type will be sniffed.
 
1990
func BenchmarkServerHandlerNoType(b *testing.B) {
 
1991
        benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) {
 
1992
                w.Header().Set("Content-Length", strconv.Itoa(len(response)))
 
1993
                w.Write(response)
 
1994
        }))
 
1995
}
 
1996
 
 
1997
// Neither a Content-Type or Content-Length, so sniffed and counted.
 
1998
func BenchmarkServerHandlerNoHeader(b *testing.B) {
 
1999
        benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) {
 
2000
                w.Write(response)
 
2001
        }))
 
2002
}
 
2003
 
 
2004
func benchmarkHandler(b *testing.B, h Handler) {
 
2005
        b.ReportAllocs()
 
2006
        req := []byte(strings.Replace(`GET / HTTP/1.1
 
2007
Host: golang.org
 
2008
 
 
2009
`, "\n", "\r\n", -1))
 
2010
        conn := &rwTestConn{
 
2011
                Reader: &repeatReader{content: req, count: b.N},
 
2012
                Writer: ioutil.Discard,
 
2013
                closec: make(chan bool, 1),
 
2014
        }
 
2015
        handled := 0
 
2016
        handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
 
2017
                handled++
 
2018
                h.ServeHTTP(rw, r)
 
2019
        })
 
2020
        ln := &oneConnListener{conn: conn}
 
2021
        go Serve(ln, handler)
 
2022
        <-conn.closec
 
2023
        if b.N != handled {
 
2024
                b.Errorf("b.N=%d but handled %d", b.N, handled)
 
2025
        }
 
2026
}