1// Copyright 2015 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// +build !plan9 6 7package ctxhttp 8 9import ( 10 "io" 11 "io/ioutil" 12 "net/http" 13 "net/http/httptest" 14 "testing" 15 "time" 16 17 "golang.org/x/net/context" 18) 19 20const ( 21 requestDuration = 100 * time.Millisecond 22 requestBody = "ok" 23) 24 25func okHandler(w http.ResponseWriter, r *http.Request) { 26 time.Sleep(requestDuration) 27 io.WriteString(w, requestBody) 28} 29 30func TestNoTimeout(t *testing.T) { 31 ts := httptest.NewServer(http.HandlerFunc(okHandler)) 32 defer ts.Close() 33 34 ctx := context.Background() 35 res, err := Get(ctx, nil, ts.URL) 36 if err != nil { 37 t.Fatal(err) 38 } 39 defer res.Body.Close() 40 slurp, err := ioutil.ReadAll(res.Body) 41 if err != nil { 42 t.Fatal(err) 43 } 44 if string(slurp) != requestBody { 45 t.Errorf("body = %q; want %q", slurp, requestBody) 46 } 47} 48 49func TestCancelBeforeHeaders(t *testing.T) { 50 ctx, cancel := context.WithCancel(context.Background()) 51 52 blockServer := make(chan struct{}) 53 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 54 cancel() 55 <-blockServer 56 io.WriteString(w, requestBody) 57 })) 58 defer ts.Close() 59 defer close(blockServer) 60 61 res, err := Get(ctx, nil, ts.URL) 62 if err == nil { 63 res.Body.Close() 64 t.Fatal("Get returned unexpected nil error") 65 } 66 if err != context.Canceled { 67 t.Errorf("err = %v; want %v", err, context.Canceled) 68 } 69} 70 71func TestCancelAfterHangingRequest(t *testing.T) { 72 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 73 w.WriteHeader(http.StatusOK) 74 w.(http.Flusher).Flush() 75 <-w.(http.CloseNotifier).CloseNotify() 76 })) 77 defer ts.Close() 78 79 ctx, cancel := context.WithCancel(context.Background()) 80 resp, err := Get(ctx, nil, ts.URL) 81 if err != nil { 82 t.Fatalf("unexpected error in Get: %v", err) 83 } 84 85 // Cancel befer reading the body. 86 // Reading Request.Body should fail, since the request was 87 // canceled before anything was written. 88 cancel() 89 90 done := make(chan struct{}) 91 92 go func() { 93 b, err := ioutil.ReadAll(resp.Body) 94 if len(b) != 0 || err == nil { 95 t.Errorf(`Read got (%q, %v); want ("", error)`, b, err) 96 } 97 close(done) 98 }() 99 100 select { 101 case <-time.After(1 * time.Second): 102 t.Errorf("Test timed out") 103 case <-done: 104 } 105} 106