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  }