github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/net/http2/http2_test.go (about) 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 5 package http2 6 7 import ( 8 "bytes" 9 "errors" 10 "flag" 11 "fmt" 12 "net/http" 13 "os/exec" 14 "strconv" 15 "strings" 16 "testing" 17 18 "golang.org/x/net/http2/hpack" 19 ) 20 21 var knownFailing = flag.Bool("known_failing", false, "Run known-failing tests.") 22 23 func condSkipFailingTest(t *testing.T) { 24 if !*knownFailing { 25 t.Skip("Skipping known-failing test without --known_failing") 26 } 27 } 28 29 func init() { 30 DebugGoroutines = true 31 flag.BoolVar(&VerboseLogs, "verboseh2", false, "Verbose HTTP/2 debug logging") 32 } 33 34 func TestSettingString(t *testing.T) { 35 tests := []struct { 36 s Setting 37 want string 38 }{ 39 {Setting{SettingMaxFrameSize, 123}, "[MAX_FRAME_SIZE = 123]"}, 40 {Setting{1<<16 - 1, 123}, "[UNKNOWN_SETTING_65535 = 123]"}, 41 } 42 for i, tt := range tests { 43 got := fmt.Sprint(tt.s) 44 if got != tt.want { 45 t.Errorf("%d. for %#v, string = %q; want %q", i, tt.s, got, tt.want) 46 } 47 } 48 } 49 50 type twriter struct { 51 t testing.TB 52 st *serverTester // optional 53 } 54 55 func (w twriter) Write(p []byte) (n int, err error) { 56 if w.st != nil { 57 ps := string(p) 58 for _, phrase := range w.st.logFilter { 59 if strings.Contains(ps, phrase) { 60 return len(p), nil // no logging 61 } 62 } 63 } 64 w.t.Logf("%s", p) 65 return len(p), nil 66 } 67 68 // like encodeHeader, but don't add implicit psuedo headers. 69 func encodeHeaderNoImplicit(t *testing.T, headers ...string) []byte { 70 var buf bytes.Buffer 71 enc := hpack.NewEncoder(&buf) 72 for len(headers) > 0 { 73 k, v := headers[0], headers[1] 74 headers = headers[2:] 75 if err := enc.WriteField(hpack.HeaderField{Name: k, Value: v}); err != nil { 76 t.Fatalf("HPACK encoding error for %q/%q: %v", k, v, err) 77 } 78 } 79 return buf.Bytes() 80 } 81 82 // Verify that curl has http2. 83 func requireCurl(t *testing.T) { 84 out, err := dockerLogs(curl(t, "--version")) 85 if err != nil { 86 t.Skipf("failed to determine curl features; skipping test") 87 } 88 if !strings.Contains(string(out), "HTTP2") { 89 t.Skip("curl doesn't support HTTP2; skipping test") 90 } 91 } 92 93 func curl(t *testing.T, args ...string) (container string) { 94 out, err := exec.Command("docker", append([]string{"run", "-d", "--net=host", "gohttp2/curl"}, args...)...).Output() 95 if err != nil { 96 t.Skipf("Failed to run curl in docker: %v, %s", err, out) 97 } 98 return strings.TrimSpace(string(out)) 99 } 100 101 // Verify that h2load exists. 102 func requireH2load(t *testing.T) { 103 out, err := dockerLogs(h2load(t, "--version")) 104 if err != nil { 105 t.Skipf("failed to probe h2load; skipping test: %s", out) 106 } 107 if !strings.Contains(string(out), "h2load nghttp2/") { 108 t.Skipf("h2load not present; skipping test. (Output=%q)", out) 109 } 110 } 111 112 func h2load(t *testing.T, args ...string) (container string) { 113 out, err := exec.Command("docker", append([]string{"run", "-d", "--net=host", "--entrypoint=/usr/local/bin/h2load", "gohttp2/curl"}, args...)...).Output() 114 if err != nil { 115 t.Skipf("Failed to run h2load in docker: %v, %s", err, out) 116 } 117 return strings.TrimSpace(string(out)) 118 } 119 120 type puppetCommand struct { 121 fn func(w http.ResponseWriter, r *http.Request) 122 done chan<- bool 123 } 124 125 type handlerPuppet struct { 126 ch chan puppetCommand 127 } 128 129 func newHandlerPuppet() *handlerPuppet { 130 return &handlerPuppet{ 131 ch: make(chan puppetCommand), 132 } 133 } 134 135 func (p *handlerPuppet) act(w http.ResponseWriter, r *http.Request) { 136 for cmd := range p.ch { 137 cmd.fn(w, r) 138 cmd.done <- true 139 } 140 } 141 142 func (p *handlerPuppet) done() { close(p.ch) } 143 func (p *handlerPuppet) do(fn func(http.ResponseWriter, *http.Request)) { 144 done := make(chan bool) 145 p.ch <- puppetCommand{fn, done} 146 <-done 147 } 148 func dockerLogs(container string) ([]byte, error) { 149 out, err := exec.Command("docker", "wait", container).CombinedOutput() 150 if err != nil { 151 return out, err 152 } 153 exitStatus, err := strconv.Atoi(strings.TrimSpace(string(out))) 154 if err != nil { 155 return out, errors.New("unexpected exit status from docker wait") 156 } 157 out, err = exec.Command("docker", "logs", container).CombinedOutput() 158 exec.Command("docker", "rm", container).Run() 159 if err == nil && exitStatus != 0 { 160 err = fmt.Errorf("exit status %d: %s", exitStatus, out) 161 } 162 return out, err 163 } 164 165 func kill(container string) { 166 exec.Command("docker", "kill", container).Run() 167 exec.Command("docker", "rm", container).Run() 168 } 169 170 func cleanDate(res *http.Response) { 171 if d := res.Header["Date"]; len(d) == 1 { 172 d[0] = "XXX" 173 } 174 }