http2_test.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // Copyright 2014 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. // See https://code.google.com/p/go/source/browse/CONTRIBUTORS
  5. // Licensed under the same terms as Go itself:
  6. // https://code.google.com/p/go/source/browse/LICENSE
  7. package http2
  8. import (
  9. "errors"
  10. "fmt"
  11. "io"
  12. "net/http"
  13. "net/http/httptest"
  14. "os/exec"
  15. "strconv"
  16. "strings"
  17. "sync/atomic"
  18. "testing"
  19. "time"
  20. )
  21. func TestServer(t *testing.T) {
  22. requireCurl(t)
  23. ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  24. io.WriteString(w, "Hello, test.")
  25. }))
  26. ConfigureServer(ts.Config, &Server{})
  27. ts.TLS = ts.Config.TLSConfig // the httptest.Server has its own copy of this TLS config
  28. ts.StartTLS()
  29. defer ts.Close()
  30. var gotConn int32
  31. testHookOnConn = func() { atomic.StoreInt32(&gotConn, 1) }
  32. t.Logf("Running test server for curl to hit at: %s", ts.URL)
  33. container := curl(t, "--silent", "--http2", "--insecure", "-v", ts.URL)
  34. defer kill(container)
  35. resc := make(chan interface{}, 1)
  36. go func() {
  37. res, err := dockerLogs(container)
  38. if err != nil {
  39. resc <- err
  40. } else {
  41. resc <- res
  42. }
  43. }()
  44. select {
  45. case res := <-resc:
  46. if err, ok := res.(error); ok {
  47. t.Fatal(err)
  48. }
  49. t.Logf("Got: %s", res)
  50. case <-time.After(3 * time.Second):
  51. t.Errorf("timeout waiting for curl")
  52. }
  53. if atomic.LoadInt32(&gotConn) == 0 {
  54. t.Error("never saw an http2 connection")
  55. }
  56. }
  57. func dockerLogs(container string) ([]byte, error) {
  58. out, err := exec.Command("docker", "wait", container).CombinedOutput()
  59. if err != nil {
  60. return out, err
  61. }
  62. exitStatus, err := strconv.Atoi(strings.TrimSpace(string(out)))
  63. if err != nil {
  64. return out, errors.New("unexpected exit status from docker wait")
  65. }
  66. out, err = exec.Command("docker", "logs", container).CombinedOutput()
  67. exec.Command("docker", "rm", container).Run()
  68. if err == nil && exitStatus != 0 {
  69. err = fmt.Errorf("exit status %d", exitStatus)
  70. }
  71. return out, err
  72. }
  73. func kill(container string) {
  74. exec.Command("docker", "kill", container).Run()
  75. exec.Command("docker", "rm", container).Run()
  76. }
  77. // Verify that curl has http2.
  78. func requireCurl(t *testing.T) {
  79. out, err := dockerLogs(curl(t, "--version"))
  80. if err != nil {
  81. t.Skipf("failed to determine curl features; skipping test")
  82. }
  83. if !strings.Contains(string(out), "HTTP2") {
  84. t.Skip("curl doesn't support HTTP2; skipping test")
  85. }
  86. }
  87. func curl(t *testing.T, args ...string) (container string) {
  88. out, err := exec.Command("docker", append([]string{"run", "-d", "--net=host", "gohttp2/curl"}, args...)...).CombinedOutput()
  89. if err != nil {
  90. t.Fatalf("Failed to run curl in docker: %v, %s", err, out)
  91. }
  92. return strings.TrimSpace(string(out))
  93. }