func TestHTTPWithinStopTimeout(t *testing.T) { t.Parallel() hello := []byte("hello") finOkHandler := make(chan struct{}) okHandler := func(w http.ResponseWriter, r *http.Request) { defer close(finOkHandler) w.WriteHeader(200) w.Write(hello) } listener, err := net.Listen("tcp", "127.0.0.1:0") ensure.Nil(t, err) server := &http.Server{Handler: http.HandlerFunc(okHandler)} transport := &http.Transport{} client := &http.Client{Transport: transport} down := &httpdown.HTTP{StopTimeout: time.Minute} s := down.Serve(server, listener) res, err := client.Get(fmt.Sprintf("http://%s/", listener.Addr().String())) ensure.Nil(t, err) finStop := make(chan struct{}) go func() { defer close(finStop) ensure.Nil(t, s.Stop()) }() actualBody, err := ioutil.ReadAll(res.Body) ensure.Nil(t, err) ensure.DeepEqual(t, actualBody, hello) ensure.Nil(t, res.Body.Close()) <-finOkHandler <-finStop }
func TestExistingConnState(t *testing.T) { t.Parallel() hello := []byte("hello") fin := make(chan struct{}) okHandler := func(w http.ResponseWriter, r *http.Request) { defer close(fin) w.Write(hello) } var called int32 listener, err := net.Listen("tcp", "127.0.0.1:0") ensure.Nil(t, err) server := &http.Server{ Handler: http.HandlerFunc(okHandler), ConnState: func(c net.Conn, s http.ConnState) { atomic.AddInt32(&called, 1) }, } transport := &http.Transport{} client := &http.Client{Transport: transport} down := &httpdown.HTTP{} s := down.Serve(server, listener) res, err := client.Get(fmt.Sprintf("http://%s/", listener.Addr().String())) ensure.Nil(t, err) actualBody, err := ioutil.ReadAll(res.Body) ensure.Nil(t, err) ensure.DeepEqual(t, actualBody, hello) ensure.Nil(t, res.Body.Close()) ensure.Nil(t, s.Stop()) <-fin ensure.True(t, atomic.LoadInt32(&called) > 0) }
func TestNewRequestAfterStop(t *testing.T) { t.Parallel() const count = 10000 hello := []byte("hello") finOkHandler := make(chan struct{}) unblockOkHandler := make(chan struct{}) okHandler := func(w http.ResponseWriter, r *http.Request) { defer close(finOkHandler) w.WriteHeader(200) const diff = 500 for i := 0; i < count-diff; i++ { w.Write(hello) } <-unblockOkHandler for i := 0; i < diff; i++ { w.Write(hello) } } listener, err := net.Listen("tcp", "127.0.0.1:0") listener, onClose := NewOnCloseListener(listener) ensure.Nil(t, err) server := &http.Server{Handler: http.HandlerFunc(okHandler)} transport := &http.Transport{} client := &http.Client{Transport: transport} down := &httpdown.HTTP{} s := down.Serve(server, listener) res, err := client.Get(fmt.Sprintf("http://%s/", listener.Addr().String())) ensure.Nil(t, err) finStop := make(chan struct{}) go func() { defer close(finStop) ensure.Nil(t, s.Stop()) }() // Wait until the listener is closed. <-onClose // Now the next request should not be able to connect as the listener is // now closed. _, err = client.Get(fmt.Sprintf("http://%s/", listener.Addr().String())) // We should just get "connection refused" here, but sometimes, very rarely, // we get a "connection reset" instead. Unclear why this happens. ensure.Err(t, err, regexp.MustCompile("(connection refused|connection reset by peer)$")) // Unblock the handler and ensure we finish writing the rest of the body // successfully. close(unblockOkHandler) actualBody, err := ioutil.ReadAll(res.Body) ensure.Nil(t, err) ensure.DeepEqual(t, actualBody, bytes.Repeat(hello, count)) ensure.Nil(t, res.Body.Close()) <-finOkHandler <-finStop }
func TestDoubleStop(t *testing.T) { t.Parallel() listener, err := net.Listen("tcp", "127.0.0.1:0") ensure.Nil(t, err) server := &http.Server{} down := &httpdown.HTTP{} s := down.Serve(server, listener) ensure.Nil(t, s.Stop()) ensure.Nil(t, s.Stop()) }
func TestHTTPStopTimeoutMissed(t *testing.T) { t.Parallel() klock := clock.NewMock() const count = 10000 hello := []byte("hello") finOkHandler := make(chan struct{}) unblockOkHandler := make(chan struct{}) okHandler := func(w http.ResponseWriter, r *http.Request) { defer close(finOkHandler) w.Header().Set("Content-Length", fmt.Sprint(len(hello)*count)) w.WriteHeader(200) for i := 0; i < count/2; i++ { w.Write(hello) } <-unblockOkHandler for i := 0; i < count/2; i++ { w.Write(hello) } } listener, err := net.Listen("tcp", "127.0.0.1:0") ensure.Nil(t, err) server := &http.Server{Handler: http.HandlerFunc(okHandler)} transport := &http.Transport{} client := &http.Client{Transport: transport} down := &httpdown.HTTP{ StopTimeout: time.Minute, Clock: klock, } s := down.Serve(server, listener) res, err := client.Get(fmt.Sprintf("http://%s/", listener.Addr().String())) ensure.Nil(t, err) finStop := make(chan struct{}) go func() { defer close(finStop) ensure.Nil(t, s.Stop()) }() klock.Wait(clock.Calls{After: 1}) // wait for Stop to call After klock.Add(down.StopTimeout) _, err = ioutil.ReadAll(res.Body) ensure.Err(t, err, regexp.MustCompile("^unexpected EOF$")) ensure.Nil(t, res.Body.Close()) close(unblockOkHandler) <-finOkHandler <-finStop }
func TestHTTPServeError(t *testing.T) { t.Parallel() expectedError := errors.New("foo") listener, err := net.Listen("tcp", "127.0.0.1:0") errChan := make(chan error) listener = &acceptErrListener{Listener: listener, err: errChan} ensure.Nil(t, err) server := &http.Server{} down := &httpdown.HTTP{} s := down.Serve(server, listener) errChan <- expectedError ensure.DeepEqual(t, s.Wait(), expectedError) ensure.Nil(t, s.Stop()) }
func TestMuxContextMakerError(t *testing.T) { givenErr := errors.New("") var actualErr error mux, err := ctxmux.New( ctxmux.MuxContextMaker(func(r *http.Request) (context.Context, error) { return nil, givenErr }), ctxmux.MuxErrorHandler( func(ctx context.Context, w http.ResponseWriter, r *http.Request, err error) { ensure.DeepEqual(t, ctx, context.Background()) actualErr = err }), ) ensure.Nil(t, err) hw := httptest.NewRecorder() hr := &http.Request{ Method: "GET", URL: &url.URL{ Path: "/", }, } mux.GET(hr.URL.Path, func(context.Context, http.ResponseWriter, *http.Request) error { panic("not reached") }) mux.ServeHTTP(hw, hr) ensure.DeepEqual(t, actualErr, givenErr) }
func TestServerAbort(t *testing.T) { t.Parallel() for _, code := range []int{200, 500} { server := httptest.NewServer( http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { w.Header().Add("Content-Length", "4000") w.WriteHeader(code) w.Write(bytes.Repeat([]byte("a"), 3000)) }, ), ) u, err := url.Parse(server.URL) ensure.Nil(t, err) c := &parse.Client{ Credentials: defaultRestAPIKey, BaseURL: u, } res := make(map[string]interface{}) _, err = c.Get(nil, res) ensure.NotNil(t, err) server.CloseClientConnections() server.Close() } }
func TestServeCombinedURLWithExt(t *testing.T) { contents := [][]byte{ []byte("foo"), []byte("bar"), } var count int h := Handler{ Path: "/", Box: funcBox(func(name string) ([]byte, error) { defer func() { count++ }() return contents[count], nil }), } v, err := h.URL("n1.js", "n2") ensure.Nil(t, err) ensure.DeepEqual(t, v, "/W1sibjEuanMiLCJhY2JkMThkYiJdLFsibjIiLCIzN2I1MWQxOSJdXQ.js") w := httptest.NewRecorder() r := &http.Request{ URL: &url.URL{ Path: v, }, } h.ServeHTTP(w, r) ensure.DeepEqual(t, w.Code, http.StatusOK) ensure.DeepEqual(t, w.Body.String(), "foobar") ensure.DeepEqual(t, w.Header(), http.Header{ "Content-Length": []string{"6"}, "Cache-Control": []string{cacheControl}, "Content-Type": []string{"application/javascript"}, }) }
func TestServerAbort(t *testing.T) { t.Parallel() for _, code := range []int{200, 500} { server := httptest.NewServer( http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { w.Header().Add("Content-Length", "4000") w.WriteHeader(code) w.Write(bytes.Repeat([]byte("a"), 3000)) }, ), ) u, err := url.Parse(server.URL) ensure.Nil(t, err) c := &fbapi.Client{ Transport: defaultHTTPTransport, BaseURL: u, } res := make(map[string]interface{}) _, err = c.Do(&http.Request{Method: "GET"}, res) ensure.NotNil(t, err) ensure.StringContains(t, err.Error(), fmt.Sprintf(`GET %s`, server.URL)) server.CloseClientConnections() server.Close() } }
func TestDecodeMultiple(t *testing.T) { value, err := decode("W1siZm9vMSIsImJhcjEiXSxbImZvbzIiLCJiYXIyIl1d") ensure.Nil(t, err) ensure.DeepEqual(t, value, []file{ {Name: "foo1", Hash: "bar1"}, {Name: "foo2", Hash: "bar2"}, }) }
func TestNilStruct(t *testing.T) { var c capture ensure.Nil(&c, typ{}) c.Equal(t, `ensure_test.go:131: expected nil value but got: (ensure_test.typ) { Answer: (int) 0 }`) }
func TestEncodeMultiple(t *testing.T) { files := []file{ {Name: "foo1", Hash: "bar1"}, {Name: "foo2", Hash: "bar2"}, } value, err := encode(files) ensure.Nil(t, err) ensure.DeepEqual(t, value, "W1siZm9vMSIsImJhcjEiXSxbImZvbzIiLCJiYXIyIl1d") }
func TestExplicitAreIgnored(t *testing.T) { const name = "TestExplicitAreIgnored" s := flag.NewFlagSet(name, flag.PanicOnError) const bar = int(43) barActual := s.Int("bar", 0, "") s.Parse([]string{"-bar", fmt.Sprint(bar)}) os.Setenv(named(name, "bar"), "44") ensure.Nil(t, flagenv.ParseSet(name, s)) ensure.DeepEqual(t, *barActual, bar) }
func TestSimple(t *testing.T) { t.Parallel() var out bytes.Buffer w := htmlwriter.New(&out) const original = "hello & world" n, err := w.Write([]byte(original)) ensure.Nil(t, err) ensure.DeepEqual(t, n, 17) ensure.DeepEqual(t, out.String(), html.EscapeString(original)) }
func TestLoadFromCache(t *testing.T) { const magic = "foo" h := Handler{ Box: funcBox(func(name string) ([]byte, error) { ensure.DeepEqual(t, name, magic) return []byte(magic), nil }), } f, err := h.load(magic) ensure.Nil(t, err) ensure.DeepEqual(t, f, file{ Name: magic, Content: []byte(magic), Hash: "acbd18db", }) h.Box = nil f2, err := h.load(magic) ensure.Nil(t, err) ensure.DeepEqual(t, f2, f) }
func TestHTTPListenerCloseError(t *testing.T) { t.Parallel() expectedError := errors.New("foo") listener, err := net.Listen("tcp", "127.0.0.1:0") listener = &closeErrListener{Listener: listener, err: expectedError} ensure.Nil(t, err) server := &http.Server{} down := &httpdown.HTTP{} s := down.Serve(server, listener) ensure.DeepEqual(t, s.Stop(), expectedError) }
func TestRestAPIKeyModify(t *testing.T) { t.Parallel() var req http.Request k := parse.RestAPIKey{ ApplicationID: defaultApplicationID, RestAPIKey: "42", } ensure.Nil(t, k.Modify(&req)) ensure.DeepEqual(t, req.Header.Get("X-Parse-Application-ID"), k.ApplicationID) ensure.DeepEqual(t, req.Header.Get("X-Parse-REST-API-Key"), k.RestAPIKey) }
func TestHTTPStopWithFinishedRequest(t *testing.T) { t.Parallel() hello := []byte("hello") fin := make(chan struct{}) okHandler := func(w http.ResponseWriter, r *http.Request) { defer close(fin) w.Write(hello) } listener, err := net.Listen("tcp", "127.0.0.1:0") ensure.Nil(t, err) server := &http.Server{Handler: http.HandlerFunc(okHandler)} transport := &http.Transport{} client := &http.Client{Transport: transport} down := &httpdown.HTTP{} s := down.Serve(server, listener) res, err := client.Get(fmt.Sprintf("http://%s/", listener.Addr().String())) ensure.Nil(t, err) actualBody, err := ioutil.ReadAll(res.Body) ensure.Nil(t, err) ensure.DeepEqual(t, actualBody, hello) ensure.Nil(t, res.Body.Close()) // At this point the request is finished, and the connection should be alive // but idle (because we have keep alive enabled by default in our Transport). ensure.Nil(t, s.Stop()) <-fin ensure.Nil(t, s.Wait()) }
func TestAFewFlags(t *testing.T) { const name = "TestAFewFlags" s := flag.NewFlagSet(name, flag.PanicOnError) const foo = "42" const bar = int(43) fooActual := s.String("foo", "", "") barActual := s.Int("bar", 0, "") os.Setenv(named(name, "foo"), foo) os.Setenv(named(name, "bar"), fmt.Sprint(bar)) ensure.Nil(t, flagenv.ParseSet(name, s)) ensure.DeepEqual(t, *fooActual, foo) ensure.DeepEqual(t, *barActual, bar) }
func TestSessionTokenModify(t *testing.T) { t.Parallel() st := parse.SessionToken{ ApplicationID: defaultApplicationID, RestAPIKey: "42", SessionToken: "43", } var req http.Request ensure.Nil(t, st.Modify(&req)) ensure.DeepEqual(t, req.Header.Get("X-Parse-Application-ID"), st.ApplicationID) ensure.DeepEqual(t, req.Header.Get("X-Parse-REST-API-Key"), st.RestAPIKey) ensure.DeepEqual(t, req.Header.Get("X-Parse-Session-Token"), st.SessionToken) }
func TestHTTPHandlerFunc(t *testing.T) { w := httptest.NewRecorder() r := &http.Request{} var actualW http.ResponseWriter var actualR *http.Request h := ctxmux.HTTPHandlerFunc(func(w http.ResponseWriter, r *http.Request) { actualW = w actualR = r }) ensure.Nil(t, h(nil, w, r)) ensure.DeepEqual(t, actualW, w) ensure.DeepEqual(t, actualR, r) }
func TestPublicGetDiscardBody(t *testing.T) { t.Parallel() res, err := defaultFbClient.Do( &http.Request{ Method: "GET", URL: &url.URL{ Path: "5526183", }, }, nil, ) ensure.Nil(t, err) ensure.DeepEqual(t, res.StatusCode, 200) }
func TestLinkStyleInvalidHREF(t *testing.T) { givenErr := errors.New("") l := LinkStyle{ Handler: &Handler{ Box: funcBox(func(name string) ([]byte, error) { return nil, givenErr }), }, HREF: []string{"foo"}, } v, err := l.HTML() ensure.Nil(t, v) ensure.DeepEqual(t, err, givenErr) }
func TestImgInvalidSrc(t *testing.T) { givenErr := errors.New("") l := Img{ Handler: &Handler{ Box: funcBox(func(name string) ([]byte, error) { return nil, givenErr }), }, Src: "foo", } v, err := l.HTML() ensure.Nil(t, v) ensure.DeepEqual(t, err, givenErr) }
func TestLinkStyle(t *testing.T) { l := LinkStyle{ Handler: &Handler{ Box: funcBox(func(name string) ([]byte, error) { return []byte("foo"), nil }), }, HREF: []string{"foo"}, } v, err := l.HTML() ensure.Nil(t, err) ensure.DeepEqual(t, v, &h.LinkStyle{ HREF: "W1siZm9vIiwiYWNiZDE4ZGIiXV0", }) }
func TestHTTPStopWithNoRequest(t *testing.T) { t.Parallel() listener, err := net.Listen("tcp", "127.0.0.1:0") ensure.Nil(t, err) statsDone := make(chan struct{}, 2) hc := &stats.HookClient{ BumpSumHook: func(key string, val float64) { if key == "serve" && val == 1 { statsDone <- struct{}{} } if key == "stop" && val == 1 { statsDone <- struct{}{} } }, } server := &http.Server{} down := &httpdown.HTTP{Stats: hc} s := down.Serve(server, listener) ensure.Nil(t, s.Stop()) <-statsDone <-statsDone }
func TestScriptInvalidSrc(t *testing.T) { givenErr := errors.New("") h := Handler{ Box: funcBox(func(name string) ([]byte, error) { return nil, givenErr }), } l := Script{ Handler: &h, Src: []string{"foo"}, } v, err := l.HTML() ensure.Nil(t, v) ensure.DeepEqual(t, err, givenErr) }
func TestCombinedURLExt(t *testing.T) { contents := [][]byte{ []byte("foo"), []byte("bar"), } var count int h := Handler{ Box: funcBox(func(name string) ([]byte, error) { defer func() { count++ }() return contents[count], nil }), } v, err := h.URL("n1.js", "n2") ensure.Nil(t, err) ensure.DeepEqual(t, v, "W1sibjEuanMiLCJhY2JkMThkYiJdLFsibjIiLCIzN2I1MWQxOSJdXQ.js") }
func TestSuccessfulRequest(t *testing.T) { t.Parallel() expected := map[string]int{"answer": 42} c := &parse.Client{ Transport: transportFunc(func(r *http.Request) (*http.Response, error) { return &http.Response{ StatusCode: http.StatusOK, Body: ioutil.NopCloser(bytes.NewReader(jsonB(t, expected))), }, nil }), } var m map[string]int _, err := c.Post(nil, true, &m) ensure.Nil(t, err) ensure.DeepEqual(t, m, expected) }