ctxhttp_test.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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. // +build !plan9
  5. package ctxhttp
  6. import (
  7. "io/ioutil"
  8. "net/http"
  9. "net/http/httptest"
  10. "testing"
  11. "time"
  12. "golang.org/x/net/context"
  13. )
  14. const (
  15. requestDuration = 100 * time.Millisecond
  16. requestBody = "ok"
  17. )
  18. func TestNoTimeout(t *testing.T) {
  19. ctx := context.Background()
  20. resp, err := doRequest(ctx)
  21. if resp == nil || err != nil {
  22. t.Fatalf("error received from client: %v %v", err, resp)
  23. }
  24. }
  25. func TestCancel(t *testing.T) {
  26. ctx, cancel := context.WithCancel(context.Background())
  27. go func() {
  28. time.Sleep(requestDuration / 2)
  29. cancel()
  30. }()
  31. resp, err := doRequest(ctx)
  32. if resp != nil || err == nil {
  33. t.Fatalf("expected error, didn't get one. resp: %v", resp)
  34. }
  35. if err != ctx.Err() {
  36. t.Fatalf("expected error from context but got: %v", err)
  37. }
  38. }
  39. func TestCancelAfterRequest(t *testing.T) {
  40. ctx, cancel := context.WithCancel(context.Background())
  41. resp, err := doRequest(ctx)
  42. // Cancel before reading the body.
  43. // Request.Body should still be readable after the context is canceled.
  44. cancel()
  45. b, err := ioutil.ReadAll(resp.Body)
  46. if err != nil || string(b) != requestBody {
  47. t.Fatalf("could not read body: %q %v", b, err)
  48. }
  49. }
  50. func TestCancelAfterHangingRequest(t *testing.T) {
  51. handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  52. w.WriteHeader(http.StatusOK)
  53. w.(http.Flusher).Flush()
  54. <-w.(http.CloseNotifier).CloseNotify()
  55. })
  56. serv := httptest.NewServer(handler)
  57. defer serv.Close()
  58. ctx, cancel := context.WithCancel(context.Background())
  59. resp, err := Get(ctx, nil, serv.URL)
  60. if err != nil {
  61. t.Fatalf("unexpected error in Get: %v", err)
  62. }
  63. // Cancel befer reading the body.
  64. // Reading Request.Body should fail, since the request was
  65. // canceled before anything was written.
  66. cancel()
  67. done := make(chan struct{})
  68. go func() {
  69. b, err := ioutil.ReadAll(resp.Body)
  70. if len(b) != 0 || err == nil {
  71. t.Errorf(`Read got (%q, %v); want ("", error)`, b, err)
  72. }
  73. close(done)
  74. }()
  75. select {
  76. case <-time.After(1 * time.Second):
  77. t.Errorf("Test timed out")
  78. case <-done:
  79. }
  80. }
  81. func doRequest(ctx context.Context) (*http.Response, error) {
  82. var okHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  83. time.Sleep(requestDuration)
  84. w.Write([]byte(requestBody))
  85. })
  86. serv := httptest.NewServer(okHandler)
  87. defer serv.Close()
  88. return Get(ctx, nil, serv.URL)
  89. }