http2_test.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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. "bytes"
  10. "errors"
  11. "flag"
  12. "fmt"
  13. "net/http"
  14. "os/exec"
  15. "strconv"
  16. "strings"
  17. "testing"
  18. "github.com/bradfitz/http2/hpack"
  19. )
  20. var knownFailing = flag.Bool("known_failing", false, "Run known-failing tests.")
  21. func condSkipFailingTest(t *testing.T) {
  22. if !*knownFailing {
  23. t.Skip("Skipping known-failing test without --known_failing")
  24. }
  25. }
  26. func init() {
  27. DebugGoroutines = true
  28. flag.BoolVar(&VerboseLogs, "verboseh2", false, "Verbose HTTP/2 debug logging")
  29. }
  30. func TestSettingString(t *testing.T) {
  31. tests := []struct {
  32. s Setting
  33. want string
  34. }{
  35. {Setting{SettingMaxFrameSize, 123}, "[MAX_FRAME_SIZE = 123]"},
  36. {Setting{1<<16 - 1, 123}, "[UNKNOWN_SETTING_65535 = 123]"},
  37. }
  38. for i, tt := range tests {
  39. got := fmt.Sprint(tt.s)
  40. if got != tt.want {
  41. t.Errorf("%d. for %#v, string = %q; want %q", i, tt.s, got, tt.want)
  42. }
  43. }
  44. }
  45. type twriter struct {
  46. t testing.TB
  47. st *serverTester // optional
  48. }
  49. func (w twriter) Write(p []byte) (n int, err error) {
  50. if w.st != nil {
  51. ps := string(p)
  52. for _, phrase := range w.st.logFilter {
  53. if strings.Contains(ps, phrase) {
  54. return len(p), nil // no logging
  55. }
  56. }
  57. }
  58. w.t.Logf("%s", p)
  59. return len(p), nil
  60. }
  61. // like encodeHeader, but don't add implicit psuedo headers.
  62. func encodeHeaderNoImplicit(t *testing.T, headers ...string) []byte {
  63. var buf bytes.Buffer
  64. enc := hpack.NewEncoder(&buf)
  65. for len(headers) > 0 {
  66. k, v := headers[0], headers[1]
  67. headers = headers[2:]
  68. if err := enc.WriteField(hpack.HeaderField{Name: k, Value: v}); err != nil {
  69. t.Fatalf("HPACK encoding error for %q/%q: %v", k, v, err)
  70. }
  71. }
  72. return buf.Bytes()
  73. }
  74. // Verify that curl has http2.
  75. func requireCurl(t *testing.T) {
  76. out, err := dockerLogs(curl(t, "--version"))
  77. if err != nil {
  78. t.Skipf("failed to determine curl features; skipping test")
  79. }
  80. if !strings.Contains(string(out), "HTTP2") {
  81. t.Skip("curl doesn't support HTTP2; skipping test")
  82. }
  83. }
  84. func curl(t *testing.T, args ...string) (container string) {
  85. out, err := exec.Command("docker", append([]string{"run", "-d", "--net=host", "gohttp2/curl"}, args...)...).CombinedOutput()
  86. if err != nil {
  87. t.Skipf("Failed to run curl in docker: %v, %s", err, out)
  88. }
  89. return strings.TrimSpace(string(out))
  90. }
  91. type puppetCommand struct {
  92. fn func(w http.ResponseWriter, r *http.Request)
  93. done chan<- bool
  94. }
  95. type handlerPuppet struct {
  96. ch chan puppetCommand
  97. }
  98. func newHandlerPuppet() *handlerPuppet {
  99. return &handlerPuppet{
  100. ch: make(chan puppetCommand),
  101. }
  102. }
  103. func (p *handlerPuppet) act(w http.ResponseWriter, r *http.Request) {
  104. for cmd := range p.ch {
  105. cmd.fn(w, r)
  106. cmd.done <- true
  107. }
  108. }
  109. func (p *handlerPuppet) done() { close(p.ch) }
  110. func (p *handlerPuppet) do(fn func(http.ResponseWriter, *http.Request)) {
  111. done := make(chan bool)
  112. p.ch <- puppetCommand{fn, done}
  113. <-done
  114. }
  115. func dockerLogs(container string) ([]byte, error) {
  116. out, err := exec.Command("docker", "wait", container).CombinedOutput()
  117. if err != nil {
  118. return out, err
  119. }
  120. exitStatus, err := strconv.Atoi(strings.TrimSpace(string(out)))
  121. if err != nil {
  122. return out, errors.New("unexpected exit status from docker wait")
  123. }
  124. out, err = exec.Command("docker", "logs", container).CombinedOutput()
  125. exec.Command("docker", "rm", container).Run()
  126. if err == nil && exitStatus != 0 {
  127. err = fmt.Errorf("exit status %d: %s", exitStatus, out)
  128. }
  129. return out, err
  130. }
  131. func kill(container string) {
  132. exec.Command("docker", "kill", container).Run()
  133. exec.Command("docker", "rm", container).Run()
  134. }