Skip to content

Commit

Permalink
It seems http2 errors are not pointer errors
Browse files Browse the repository at this point in the history
The type switch used to match to pointers of the http2.*Error types
which given some production data and a test for one, is that neither one
of the three is actually returned as pointer.

Having tests for GoAway and Connection errors will be nice but I have so
far been able to do so.
  • Loading branch information
mstoykov committed May 15, 2021
1 parent 29d55e2 commit 9972481
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 17 deletions.
10 changes: 5 additions & 5 deletions lib/netext/httpext/error_codes.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,15 +191,15 @@ func errorCodeForError(err error) (errCode, string) {
return blackListedIPErrorCode, blackListedIPErrorCodeMsg
case netext.BlockedHostError:
return blockedHostnameErrorCode, blockedHostnameErrorMsg
case *http2.GoAwayError:
case http2.GoAwayError:
return unknownHTTP2GoAwayErrorCode + http2ErrCodeOffset(e.ErrCode),
fmt.Sprintf(http2GoAwayErrorCodeMsg, e.ErrCode)
case *http2.StreamError:
case http2.StreamError:
return unknownHTTP2StreamErrorCode + http2ErrCodeOffset(e.Code),
fmt.Sprintf(http2StreamErrorCodeMsg, e.Code)
case *http2.ConnectionError:
return unknownHTTP2ConnectionErrorCode + http2ErrCodeOffset(http2.ErrCode(*e)),
fmt.Sprintf(http2ConnectionErrorCodeMsg, http2.ErrCode(*e))
case http2.ConnectionError:
return unknownHTTP2ConnectionErrorCode + http2ErrCodeOffset(http2.ErrCode(e)),
fmt.Sprintf(http2ConnectionErrorCodeMsg, http2.ErrCode(e))
case *net.OpError:
return errorCodeForNetOpError(e)
case *x509.UnknownAuthorityError:
Expand Down
43 changes: 37 additions & 6 deletions lib/netext/httpext/error_codes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"crypto/x509"
"errors"
"fmt"
"io/ioutil"
"net"
"net/http"
"net/url"
Expand All @@ -39,6 +40,7 @@ import (
"golang.org/x/net/http2"

"go.k6.io/k6/lib/netext"
"go.k6.io/k6/lib/testutils/httpmultibin"
)

func TestDefaultError(t *testing.T) {
Expand All @@ -51,13 +53,13 @@ func TestHTTP2Errors(t *testing.T) {
unknownErrorCode := 220
connectionError := http2.ConnectionError(unknownErrorCode)
testTable := map[errCode]error{
unknownHTTP2ConnectionErrorCode + 1: new(http2.ConnectionError),
unknownHTTP2StreamErrorCode + 1: new(http2.StreamError),
unknownHTTP2GoAwayErrorCode + 1: new(http2.GoAwayError),
unknownHTTP2ConnectionErrorCode + 1: http2.ConnectionError(0),
unknownHTTP2StreamErrorCode + 1: http2.StreamError{},
unknownHTTP2GoAwayErrorCode + 1: http2.GoAwayError{},

unknownHTTP2ConnectionErrorCode: &connectionError,
unknownHTTP2StreamErrorCode: &http2.StreamError{Code: 220},
unknownHTTP2GoAwayErrorCode: &http2.GoAwayError{ErrCode: 220},
unknownHTTP2ConnectionErrorCode: connectionError,
unknownHTTP2StreamErrorCode: http2.StreamError{Code: 220},
unknownHTTP2GoAwayErrorCode: http2.GoAwayError{ErrCode: 220},
}
testMapOfErrorCodes(t, testTable)
}
Expand Down Expand Up @@ -218,3 +220,32 @@ func TestDnsResolve(t *testing.T) {
assert.Equal(t, dnsNoSuchHostErrorCode, code)
assert.Equal(t, dnsNoSuchHostErrorCodeMsg, msg)
}

func TestHTTP2StreamError(t *testing.T) {
t.Parallel()
tb := httpmultibin.NewHTTPMultiBin(t)

tb.Mux.HandleFunc("/tsr", func(rw http.ResponseWriter, req *http.Request) {
rw.Header().Set("Content-Length", "100000")
rw.WriteHeader(200)

rw.(http.Flusher).Flush()
time.Sleep(time.Millisecond * 2)
panic("expected internal error")
})
client := http.Client{
Timeout: time.Second * 3,
Transport: tb.HTTPTransport,
}

res, err := client.Get(tb.Replacer.Replace("HTTP2BIN_URL/tsr")) //nolint:noctx
require.NotNil(t, res)
require.NoError(t, err)
_, err = ioutil.ReadAll(res.Body)
_ = res.Body.Close()
require.Error(t, err)

code, msg := errorCodeForError(err)
assert.Equal(t, unknownHTTP2StreamErrorCode+errCode(http2.ErrCodeInternal)+1, code)
assert.Contains(t, msg, fmt.Sprintf(http2StreamErrorCodeMsg, http2.ErrCodeInternal))
}
11 changes: 5 additions & 6 deletions lib/testutils/httpmultibin/httpmultibin.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ import (

"go.k6.io/k6/lib"
"go.k6.io/k6/lib/netext"
"go.k6.io/k6/lib/netext/httpext"
"go.k6.io/k6/lib/types"
)

Expand Down Expand Up @@ -156,7 +155,7 @@ func writeJSON(w io.Writer, v interface{}) error {
return nil
}

func getEncodedHandler(t testing.TB, compressionType httpext.CompressionType) http.Handler {
func getEncodedHandler(t testing.TB, compressionType string) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
var (
encoding string
Expand All @@ -165,10 +164,10 @@ func getEncodedHandler(t testing.TB, compressionType httpext.CompressionType) ht
)

switch compressionType {
case httpext.CompressionTypeBr:
case "br":
encw = brotli.NewWriter(rw)
encoding = "br"
case httpext.CompressionTypeZstd:
case "zstd":
encw, _ = zstd.NewWriter(rw)
encoding = "zstd"
}
Expand Down Expand Up @@ -260,12 +259,12 @@ func (*GRPCStub) HalfDuplexCall(grpctest.TestService_HalfDuplexCallServer) error
func NewHTTPMultiBin(t testing.TB) *HTTPMultiBin {
// Create a http.ServeMux and set the httpbin handler as the default
mux := http.NewServeMux()
mux.Handle("/brotli", getEncodedHandler(t, httpext.CompressionTypeBr))
mux.Handle("/brotli", getEncodedHandler(t, "br"))
mux.Handle("/ws-echo", getWebsocketHandler(true, false))
mux.Handle("/ws-echo-invalid", getWebsocketHandler(true, true))
mux.Handle("/ws-close", getWebsocketHandler(false, false))
mux.Handle("/ws-close-invalid", getWebsocketHandler(false, true))
mux.Handle("/zstd", getEncodedHandler(t, httpext.CompressionTypeZstd))
mux.Handle("/zstd", getEncodedHandler(t, "zstd"))
mux.Handle("/zstd-br", getZstdBrHandler(t))
mux.Handle("/", httpbin.New().Handler())

Expand Down

0 comments on commit 9972481

Please sign in to comment.