Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(66)

Delta Between Two Patch Sets: src/pkg/net/http/serve_test.go

Issue 8101043: code review 8101043: net/http: more tests, better comments, remove an allocation (Closed)
Left Patch Set: Created 11 years, 11 months ago
Right Patch Set: diff -r 457cc24872ec https://go.googlecode.com/hg/ Created 11 years, 11 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | src/pkg/net/http/server.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
(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 "fmt" 14 "fmt"
14 "io" 15 "io"
15 "io/ioutil" 16 "io/ioutil"
16 "log" 17 "log"
17 "net" 18 "net"
18 . "net/http" 19 . "net/http"
19 "net/http/httptest" 20 "net/http/httptest"
20 "net/http/httputil" 21 "net/http/httputil"
21 "net/url" 22 "net/url"
22 "os" 23 "os"
(...skipping 1421 matching lines...) Expand 10 before | Expand all | Expand 10 after
1444 res, err = Get(ts.URL + "/second") 1445 res, err = Get(ts.URL + "/second")
1445 if err != nil { 1446 if err != nil {
1446 t.Fatal(err) 1447 t.Fatal(err)
1447 } 1448 }
1448 res.Body.Close() 1449 res.Body.Close()
1449 if got := <-uric; got != "/second" { 1450 if got := <-uric; got != "/second" {
1450 t.Errorf("Handler saw request for %q; want /second", got) 1451 t.Errorf("Handler saw request for %q; want /second", got)
1451 } 1452 }
1452 } 1453 }
1453 1454
1455 // Tests regarding the ordering of Write, WriteHeader, Header, and
1456 // Flush calls. In Go 1.0, rw.WriteHeader immediately flushed the
1457 // (*response).header to the wire. In Go 1.1, the actual wire flush is
1458 // delayed, so we could maybe tack on a Content-Length and better
1459 // Content-Type after we see more (or all) of the output. To preserve
1460 // compatibility with Go 1, we need to be careful to track which
1461 // headers were live at the time of WriteHeader, so we write the same
1462 // ones, even if the handler modifies them (~erroneously) after the
1463 // first Write.
1464 func TestHeaderToWire(t *testing.T) {
1465 req := []byte(strings.Replace(`GET / HTTP/1.1
1466 Host: golang.org
1467
1468 `, "\n", "\r\n", -1))
1469
1470 tests := []struct {
1471 name string
1472 handler func(ResponseWriter, *Request)
1473 check func(output string) error
1474 }{
1475 {
1476 name: "write without Header",
1477 handler: func(rw ResponseWriter, r *Request) {
1478 rw.Write([]byte("hello world"))
1479 },
1480 check: func(got string) error {
1481 if !strings.Contains(got, "Content-Length:") {
1482 return errors.New("no content-length")
1483 }
1484 if !strings.Contains(got, "Content-Type: text/pl ain") {
1485 return errors.New("no content-length")
1486 }
1487 return nil
1488 },
1489 },
1490 {
1491 name: "Header mutation before write",
1492 handler: func(rw ResponseWriter, r *Request) {
1493 h := rw.Header()
1494 h.Set("Content-Type", "some/type")
1495 rw.Write([]byte("hello world"))
1496 h.Set("Too-Late", "bogus")
1497 },
1498 check: func(got string) error {
1499 if !strings.Contains(got, "Content-Length:") {
1500 return errors.New("no content-length")
1501 }
1502 if !strings.Contains(got, "Content-Type: some/ty pe") {
1503 return errors.New("wrong content-type")
1504 }
1505 if strings.Contains(got, "Too-Late") {
1506 return errors.New("don't want too-late h eader")
1507 }
1508 return nil
1509 },
1510 },
1511 {
1512 name: "write then useless Header mutation",
1513 handler: func(rw ResponseWriter, r *Request) {
1514 rw.Write([]byte("hello world"))
1515 rw.Header().Set("Too-Late", "Write already wrote headers")
1516 },
1517 check: func(got string) error {
1518 if strings.Contains(got, "Too-Late") {
1519 return errors.New("header appeared from after WriteHeader")
1520 }
1521 return nil
1522 },
1523 },
1524 {
1525 name: "flush then write",
1526 handler: func(rw ResponseWriter, r *Request) {
1527 rw.(Flusher).Flush()
1528 rw.Write([]byte("post-flush"))
1529 rw.Header().Set("Too-Late", "Write already wrote headers")
1530 },
1531 check: func(got string) error {
1532 if !strings.Contains(got, "Transfer-Encoding: ch unked") {
1533 return errors.New("not chunked")
1534 }
1535 if strings.Contains(got, "Too-Late") {
1536 return errors.New("header appeared from after WriteHeader")
1537 }
1538 return nil
1539 },
1540 },
1541 {
1542 name: "header then flush",
1543 handler: func(rw ResponseWriter, r *Request) {
1544 rw.Header().Set("Content-Type", "some/type")
1545 rw.(Flusher).Flush()
1546 rw.Write([]byte("post-flush"))
1547 rw.Header().Set("Too-Late", "Write already wrote headers")
1548 },
1549 check: func(got string) error {
1550 if !strings.Contains(got, "Transfer-Encoding: ch unked") {
1551 return errors.New("not chunked")
1552 }
1553 if strings.Contains(got, "Too-Late") {
1554 return errors.New("header appeared from after WriteHeader")
1555 }
1556 if !strings.Contains(got, "Content-Type: some/ty pe") {
1557 return errors.New("wrong content-length" )
1558 }
1559 return nil
1560 },
1561 },
1562 {
1563 name: "sniff-on-first-write content-type",
1564 handler: func(rw ResponseWriter, r *Request) {
1565 rw.Write([]byte("<html><head></head><body>some h tml</body></html>"))
1566 rw.Header().Set("Content-Type", "x/wrong")
1567 },
1568 check: func(got string) error {
1569 if !strings.Contains(got, "Content-Type: text/ht ml") {
1570 return errors.New("wrong content-length; want html")
1571 }
1572 return nil
1573 },
1574 },
1575 {
1576 name: "explicit content-type wins",
1577 handler: func(rw ResponseWriter, r *Request) {
1578 rw.Header().Set("Content-Type", "some/type")
1579 rw.Write([]byte("<html><head></head><body>some h tml</body></html>"))
1580 },
1581 check: func(got string) error {
1582 if !strings.Contains(got, "Content-Type: some/ty pe") {
1583 return errors.New("wrong content-length; want html")
1584 }
1585 return nil
1586 },
1587 },
1588 {
1589 name: "empty handler",
1590 handler: func(rw ResponseWriter, r *Request) {
1591 },
1592 check: func(got string) error {
1593 if !strings.Contains(got, "Content-Type: text/pl ain") {
1594 return errors.New("wrong content-length; want text/plain")
1595 }
1596 if !strings.Contains(got, "Content-Length: 0") {
1597 return errors.New("want 0 content-length ")
1598 }
1599 return nil
1600 },
1601 },
1602 {
1603 name: "only Header, no write",
1604 handler: func(rw ResponseWriter, r *Request) {
1605 rw.Header().Set("Some-Header", "some-value")
1606 },
1607 check: func(got string) error {
1608 if !strings.Contains(got, "Some-Header") {
1609 return errors.New("didn't get header")
1610 }
1611 return nil
1612 },
1613 },
1614 {
1615 name: "WriteHeader call",
1616 handler: func(rw ResponseWriter, r *Request) {
1617 rw.WriteHeader(404)
1618 rw.Header().Set("Too-Late", "some-value")
1619 },
1620 check: func(got string) error {
1621 if !strings.Contains(got, "404") {
1622 return errors.New("wrong status")
1623 }
1624 if strings.Contains(got, "Some-Header") {
1625 return errors.New("shouldn't have seen T oo-Late")
1626 }
1627 return nil
1628 },
1629 },
1630 }
1631 for _, tc := range tests {
1632 var output bytes.Buffer
1633 conn := &rwTestConn{
1634 Reader: bytes.NewReader(req),
1635 Writer: &output,
1636 closec: make(chan bool, 1),
1637 }
1638 ln := &oneConnListener{conn: conn}
1639 go Serve(ln, HandlerFunc(tc.handler))
1640 <-conn.closec
1641 if err := tc.check(output.String()); err != nil {
1642 t.Errorf("%s: %v\nGot response:\n%s", tc.name, err, outp ut.Bytes())
1643 }
1644 }
1645 }
1646
1454 // goTimeout runs f, failing t if f takes more than ns to complete. 1647 // goTimeout runs f, failing t if f takes more than ns to complete.
1455 func goTimeout(t *testing.T, d time.Duration, f func()) { 1648 func goTimeout(t *testing.T, d time.Duration, f func()) {
1456 ch := make(chan bool, 2) 1649 ch := make(chan bool, 2)
1457 timer := time.AfterFunc(d, func() { 1650 timer := time.AfterFunc(d, func() {
1458 t.Errorf("Timeout expired after %v", d) 1651 t.Errorf("Timeout expired after %v", d)
1459 ch <- true 1652 ch <- true
1460 }) 1653 })
1461 defer timer.Stop() 1654 defer timer.Stop()
1462 go func() { 1655 go func() {
1463 defer func() { ch <- true }() 1656 defer func() { ch <- true }()
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
1703 rw.Header().Set("Content-Type", "text/html; charset=utf-8") 1896 rw.Header().Set("Content-Type", "text/html; charset=utf-8")
1704 rw.Write(res) 1897 rw.Write(res)
1705 }) 1898 })
1706 ln := &oneConnListener{conn: conn} 1899 ln := &oneConnListener{conn: conn}
1707 go Serve(ln, handler) 1900 go Serve(ln, handler)
1708 <-conn.closec 1901 <-conn.closec
1709 if b.N != handled { 1902 if b.N != handled {
1710 b.Errorf("b.N=%d but handled %d", b.N, handled) 1903 b.Errorf("b.N=%d but handled %d", b.N, handled)
1711 } 1904 }
1712 } 1905 }
1906
1907 // same as above, but representing the most simple possible request
1908 // and handler. Notably: the handler does not call rw.Header().
1909 func BenchmarkServerFakeConnWithKeepAliveLite(b *testing.B) {
1910 b.ReportAllocs()
1911
1912 req := []byte(strings.Replace(`GET / HTTP/1.1
1913 Host: golang.org
1914
1915 `, "\n", "\r\n", -1))
1916 res := []byte("Hello world!\n")
1917
1918 conn := &rwTestConn{
1919 Reader: &repeatReader{content: req, count: b.N},
1920 Writer: ioutil.Discard,
1921 closec: make(chan bool, 1),
1922 }
1923 handled := 0
1924 handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
1925 handled++
1926 rw.Write(res)
1927 })
1928 ln := &oneConnListener{conn: conn}
1929 go Serve(ln, handler)
1930 <-conn.closec
1931 if b.N != handled {
1932 b.Errorf("b.N=%d but handled %d", b.N, handled)
1933 }
1934 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b