@@ -51,10 +51,22 @@ func assertStatusCode(t *testing.T, w *httptest.ResponseRecorder, code int) {
5151 }
5252}
5353
54- func assertHeader (t * testing.T , w * httptest.ResponseRecorder , key , val string ) {
54+ // assertHeader asserts that a header key has a specific value in a
55+ // response-like object. x must be *httptest.ResponseRecorder or *http.Response
56+ func assertHeader (t * testing.T , x interface {}, key , want string ) {
5557 t .Helper ()
56- if w .Header ().Get (key ) != val {
57- t .Fatalf ("expected header %s=%#v, got %#v" , key , val , w .Header ().Get (key ))
58+
59+ var got string
60+ switch r := x .(type ) {
61+ case * httptest.ResponseRecorder :
62+ got = r .Header ().Get (key )
63+ case * http.Response :
64+ got = r .Header .Get (key )
65+ default :
66+ t .Fatalf ("expected *httptest.ResponseRecorder or *http.Response, got %t" , x )
67+ }
68+ if want != got {
69+ t .Fatalf ("expected header %s=%#v, got %#v" , key , want , got )
5870 }
5971}
6072
@@ -1705,31 +1717,30 @@ func TestStream(t *testing.T) {
17051717 test := test
17061718 t .Run ("ok" + test .url , func (t * testing.T ) {
17071719 t .Parallel ()
1708- r , _ := http .NewRequest ("GET" , test .url , nil )
1709- w := httptest .NewRecorder ()
1710- app .ServeHTTP (w , r )
1720+ srv := httptest .NewServer (app )
1721+ defer srv .Close ()
17111722
1712- // TODO: The stdlib seems to automagically unchunk these responses
1713- // and I'm not quite sure how to test this:
1714- //
1715- // assertHeader(t, w, "Transfer-Encoding", "chunked")
1716- //
1717- // Instead, we assert that we got no Content-Length header, which
1718- // is an indication that the Go stdlib streamed the response.
1719- assertHeader (t , w , "Content-Length" , "" )
1723+ resp , err := http .Get (srv .URL + test .url )
1724+ assertNil (t , err )
1725+ defer resp .Body .Close ()
17201726
1721- var resp * streamResponse
1722- var err error
1727+ // Expect empty content-length due to streaming response
1728+ assertHeader (t , resp , "Content-Length" , "" )
1729+
1730+ if len (resp .TransferEncoding ) != 1 || resp .TransferEncoding [0 ] != "chunked" {
1731+ t .Fatalf ("expected Transfer-Encoding: chunked, got %#v" , resp .TransferEncoding )
1732+ }
1733+
1734+ var sr * streamResponse
17231735
17241736 i := 0
1725- scanner := bufio .NewScanner (w .Body )
1737+ scanner := bufio .NewScanner (resp .Body )
17261738 for scanner .Scan () {
1727- err = json .Unmarshal (scanner .Bytes (), & resp )
1728- if err != nil {
1739+ if err := json .Unmarshal (scanner .Bytes (), & sr ); err != nil {
17291740 t .Fatalf ("error unmarshalling response: %s" , err )
17301741 }
1731- if resp .ID != i {
1732- t .Fatalf ("bad id: %v != %v" , resp .ID , i )
1742+ if sr .ID != i {
1743+ t .Fatalf ("bad id: %v != %v" , sr .ID , i )
17331744 }
17341745 i ++
17351746 }
@@ -1920,6 +1931,51 @@ func TestDrip(t *testing.T) {
19201931 })
19211932 }
19221933
1934+ t .Run ("writes are actually incremmental" , func (t * testing.T ) {
1935+ t .Parallel ()
1936+
1937+ srv := httptest .NewServer (app )
1938+ defer srv .Close ()
1939+
1940+ var (
1941+ duration = 100 * time .Millisecond
1942+ numBytes = 3
1943+ wantDelay = duration / time .Duration (numBytes )
1944+ wantBytes = []byte {'*' }
1945+ )
1946+ resp , err := http .Get (srv .URL + fmt .Sprintf ("/drip?duration=%s&delay=%s&numbytes=%d" , duration , wantDelay , numBytes ))
1947+ if err != nil {
1948+ t .Fatalf ("unexpected error: %s" , err )
1949+ }
1950+ defer resp .Body .Close ()
1951+
1952+ // Here we read from the response one byte at a time, and ensure that
1953+ // at least the expected delay occurs for each read.
1954+ //
1955+ // The request above includes an initial delay equal to the expected
1956+ // wait between writes so that even the first iteration of this loop
1957+ // expects to wait the same amount of time for a read.
1958+ buf := make ([]byte , 1 )
1959+ for {
1960+ start := time .Now ()
1961+ n , err := resp .Body .Read (buf )
1962+ gotDelay := time .Since (start )
1963+
1964+ if err == io .EOF {
1965+ break
1966+ }
1967+ assertNil (t , err )
1968+ assertIntEqual (t , n , 1 )
1969+ if ! reflect .DeepEqual (buf , wantBytes ) {
1970+ t .Fatalf ("unexpected bytes read: got %v, want %v" , buf , wantBytes )
1971+ }
1972+
1973+ if gotDelay < wantDelay {
1974+ t .Fatalf ("to wait at least %s between reads, waited %s" , wantDelay , gotDelay )
1975+ }
1976+ }
1977+ })
1978+
19231979 t .Run ("handle cancelation during initial delay" , func (t * testing.T ) {
19241980 t .Parallel ()
19251981 srv := httptest .NewServer (app )
@@ -2466,21 +2522,25 @@ func TestStreamBytes(t *testing.T) {
24662522 test := test
24672523 t .Run ("ok" + test .url , func (t * testing.T ) {
24682524 t .Parallel ()
2469- r , _ := http .NewRequest ("GET" , test .url , nil )
2470- w := httptest .NewRecorder ()
2471- app .ServeHTTP (w , r )
24722525
2473- // TODO: The stdlib seems to automagically unchunk these responses
2474- // and I'm not quite sure how to test this:
2475- //
2476- // assertHeader(t, w, "Transfer-Encoding", "chunked")
2477- //
2478- // Instead, we assert that we got no Content-Length header, which
2479- // is an indication that the Go stdlib streamed the response.
2480- assertHeader (t , w , "Content-Length" , "" )
2526+ srv := httptest .NewServer (app )
2527+ defer srv .Close ()
24812528
2482- if len (w .Body .Bytes ()) != test .expectedContentLength {
2483- t .Fatalf ("expected body of length %d, got %d" , test .expectedContentLength , len (w .Body .Bytes ()))
2529+ resp , err := http .Get (srv .URL + test .url )
2530+ assertNil (t , err )
2531+ defer resp .Body .Close ()
2532+
2533+ if len (resp .TransferEncoding ) != 1 || resp .TransferEncoding [0 ] != "chunked" {
2534+ t .Fatalf ("expected Transfer-Encoding: chunked, got %#v" , resp .TransferEncoding )
2535+ }
2536+
2537+ // Expect empty content-length due to streaming response
2538+ assertHeader (t , resp , "Content-Length" , "" )
2539+
2540+ body , err := io .ReadAll (resp .Body )
2541+ assertNil (t , err )
2542+ if len (body ) != test .expectedContentLength {
2543+ t .Fatalf ("expected body of length %d, got %d" , test .expectedContentLength , len (body ))
24842544 }
24852545 })
24862546 }
0 commit comments