From 14424109c9d4fdb2bbc7393b75bb745c0addb0cd Mon Sep 17 00:00:00 2001 From: Rodolfo Carvalho Date: Mon, 24 Feb 2020 20:22:38 +0100 Subject: [PATCH 1/3] ci: Build and test all packages Without `./...` only the top-level package was built and tested. --- .travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5dfab84e2..c9c20da31 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,8 +20,8 @@ jobs: export GOPATH= && go env GOPATH script: >- - go test && - go test -race + go test ./... && + go test ./... -race allow_failures: - go: master fast_finish: true @@ -34,9 +34,9 @@ before_install: script: - golangci-lint run --new-from-rev=$(git merge-base origin/master HEAD) - - go build - - go test - - go test -race + - go build ./... + - go test ./... + - go test ./... -race notifications: webhooks: From af658d32d7a614f60a3c7d75e2f1c740b4967c0f Mon Sep 17 00:00:00 2001 From: Rodolfo Carvalho Date: Mon, 24 Feb 2020 16:34:17 +0100 Subject: [PATCH 2/3] test: Add fasthttp integration tests --- fasthttp/sentryfasthttp_test.go | 167 ++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 fasthttp/sentryfasthttp_test.go diff --git a/fasthttp/sentryfasthttp_test.go b/fasthttp/sentryfasthttp_test.go new file mode 100644 index 000000000..462018eed --- /dev/null +++ b/fasthttp/sentryfasthttp_test.go @@ -0,0 +1,167 @@ +package sentryfasthttp_test + +import ( + "net" + "net/http" + "testing" + "time" + + "github.com/getsentry/sentry-go" + sentryfasthttp "github.com/getsentry/sentry-go/fasthttp" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/valyala/fasthttp" + "github.com/valyala/fasthttp/fasthttputil" +) + +func TestIntegration(t *testing.T) { + tests := []struct { + Path string + Method string + Body string + Handler fasthttp.RequestHandler + + WantEvent *sentry.Event + }{ + { + Path: "/panic", + Handler: func(*fasthttp.RequestCtx) { + panic("test") + }, + + WantEvent: &sentry.Event{ + Level: sentry.LevelFatal, + Message: "test", + Request: sentry.Request{ + URL: "http://example.com/panic", + Method: "GET", + Headers: map[string]string{ + "Content-Length": "0", + "Host": "example.com", + "User-Agent": "fasthttp", + }, + }, + }, + }, + { + Path: "/post", + Method: "POST", + Body: "payload", + Handler: func(ctx *fasthttp.RequestCtx) { + hub := sentryfasthttp.GetHubFromContext(ctx) + hub.CaptureMessage("post: " + string(ctx.Request.Body())) + }, + + WantEvent: &sentry.Event{ + Level: sentry.LevelInfo, + Message: "post: payload", + Request: sentry.Request{ + URL: "http://example.com/post", + Method: "POST", + Data: "payload", + Headers: map[string]string{ + "Content-Length": "7", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "example.com", + "User-Agent": "fasthttp", + }, + }, + }, + }, + { + Path: "/get", + Handler: func(ctx *fasthttp.RequestCtx) { + hub := sentryfasthttp.GetHubFromContext(ctx) + hub.CaptureMessage("get") + }, + + WantEvent: &sentry.Event{ + Level: sentry.LevelInfo, + Message: "get", + Request: sentry.Request{ + URL: "http://example.com/get", + Method: "GET", + Headers: map[string]string{ + "Content-Length": "0", + "Host": "example.com", + "User-Agent": "fasthttp", + }, + }, + }, + }, + } + + eventsCh := make(chan *sentry.Event, len(tests)) + err := sentry.Init(sentry.ClientOptions{ + BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event { + eventsCh <- event + return event + }, + }) + if err != nil { + t.Fatal(err) + } + + sentryHandler := sentryfasthttp.New(sentryfasthttp.Options{}) + ln := fasthttputil.NewInmemoryListener() + handler := func(ctx *fasthttp.RequestCtx) { + for _, tt := range tests { + if string(ctx.Path()) == tt.Path { + tt.Handler(ctx) + return + } + } + t.Errorf("Unhandled request: %#v", ctx) + } + done := make(chan struct{}) + go func() { + if err := fasthttp.Serve(ln, sentryHandler.Handle(handler)); err != nil { + t.Errorf("error in Serve: %s", err) + } + close(done) + }() + + c := &fasthttp.Client{ + Dial: func(addr string) (net.Conn, error) { + return ln.Dial() + }, + ReadTimeout: time.Second, + WriteTimeout: time.Second, + } + + var want []*sentry.Event + for _, tt := range tests { + want = append(want, tt.WantEvent) + req, res := fasthttp.AcquireRequest(), fasthttp.AcquireResponse() + req.SetHost("example.com") + req.URI().SetPath(tt.Path) + req.Header.SetMethod(tt.Method) + req.SetBodyString(tt.Body) + if err := c.Do(req, res); err != nil { + t.Fatalf("Request %q failed: %s", tt.Path, err) + } + if res.StatusCode() != http.StatusOK { + t.Errorf("Status code = %d", res.StatusCode()) + } + } + + if ok := sentry.Flush(time.Second); !ok { + t.Fatal("sentry.Flush timed out") + } + close(eventsCh) + var got []*sentry.Event + for e := range eventsCh { + got = append(got, e) + } + opt := cmpopts.IgnoreFields( + sentry.Event{}, + "Contexts", "EventID", "Extra", "Platform", + "Sdk", "ServerName", "Tags", "Timestamp", + ) + if diff := cmp.Diff(want, got, opt); diff != "" { + t.Fatalf("Events mismatch (-want +got):\n%s", diff) + } + + ln.Close() + <-done +} From 078f12a0b587554f8f0d1b1f8576efdce7487b4f Mon Sep 17 00:00:00 2001 From: Rodolfo Carvalho Date: Mon, 24 Feb 2020 19:26:45 +0100 Subject: [PATCH 3/3] test: Add net/http integration tests --- http/sentryhttp_test.go | 166 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 http/sentryhttp_test.go diff --git a/http/sentryhttp_test.go b/http/sentryhttp_test.go new file mode 100644 index 000000000..d0e2ef9fa --- /dev/null +++ b/http/sentryhttp_test.go @@ -0,0 +1,166 @@ +package sentryhttp_test + +import ( + "io/ioutil" + "net/http" + "net/http/httptest" + "strings" + "testing" + "time" + + "github.com/getsentry/sentry-go" + sentryhttp "github.com/getsentry/sentry-go/http" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" +) + +func TestIntegration(t *testing.T) { + tests := []struct { + Path string + Method string + Body string + Handler http.Handler + + WantEvent *sentry.Event + }{ + { + Path: "/panic", + Handler: http.HandlerFunc(func(http.ResponseWriter, *http.Request) { + panic("test") + }), + + WantEvent: &sentry.Event{ + Level: sentry.LevelFatal, + Message: "test", + Request: sentry.Request{ + URL: "/panic", + Method: "GET", + Headers: map[string]string{ + "Accept-Encoding": "gzip", + "User-Agent": "Go-http-client/1.1", + }, + }, + }, + }, + { + Path: "/post", + Method: "POST", + Body: "payload", + Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + hub := sentry.GetHubFromContext(r.Context()) + body, err := ioutil.ReadAll(r.Body) + if err != nil { + t.Error(err) + } + hub.CaptureMessage("post: " + string(body)) + }), + + WantEvent: &sentry.Event{ + Level: sentry.LevelInfo, + Message: "post: payload", + Request: sentry.Request{ + URL: "/post", + Method: "POST", + Data: "payload", + Headers: map[string]string{ + "Accept-Encoding": "gzip", + "Content-Length": "7", + "User-Agent": "Go-http-client/1.1", + }, + }, + }, + }, + { + Path: "/get", + Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + hub := sentry.GetHubFromContext(r.Context()) + hub.CaptureMessage("get") + }), + + WantEvent: &sentry.Event{ + Level: sentry.LevelInfo, + Message: "get", + Request: sentry.Request{ + URL: "/get", + Method: "GET", + Headers: map[string]string{ + "Accept-Encoding": "gzip", + "User-Agent": "Go-http-client/1.1", + }, + }, + }, + }, + } + + eventsCh := make(chan *sentry.Event, len(tests)) + err := sentry.Init(sentry.ClientOptions{ + BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event { + eventsCh <- event + return event + }, + }) + if err != nil { + t.Fatal(err) + } + + sentryHandler := sentryhttp.New(sentryhttp.Options{}) + handler := func(w http.ResponseWriter, r *http.Request) { + for _, tt := range tests { + if r.URL.Path == tt.Path { + tt.Handler.ServeHTTP(w, r) + return + } + } + t.Errorf("Unhandled request: %#v", r) + } + srv := httptest.NewServer(sentryHandler.HandleFunc(handler)) + defer srv.Close() + + c := srv.Client() + c.Timeout = time.Second + + var want []*sentry.Event + for _, tt := range tests { + wantRequest := tt.WantEvent.Request + wantRequest.URL = srv.URL + wantRequest.URL + wantRequest.Headers["Host"] = srv.Listener.Addr().String() + tt.WantEvent.Request = wantRequest + want = append(want, tt.WantEvent) + + req, err := http.NewRequest(tt.Method, srv.URL+tt.Path, strings.NewReader(tt.Body)) + if err != nil { + t.Fatal(err) + } + res, err := c.Do(req) + if err != nil { + t.Fatal(err) + } + if res.StatusCode != http.StatusOK { + t.Errorf("Status code = %d", res.StatusCode) + } + res.Body.Close() + } + + if ok := sentry.Flush(time.Second); !ok { + t.Fatal("sentry.Flush timed out") + } + close(eventsCh) + var got []*sentry.Event + for e := range eventsCh { + got = append(got, e) + } + opts := cmp.Options{ + cmpopts.IgnoreFields( + sentry.Event{}, + "Contexts", "EventID", "Extra", "Platform", + "Sdk", "ServerName", "Tags", "Timestamp", + ), + cmpopts.IgnoreFields( + sentry.Request{}, + "Env", + ), + } + if diff := cmp.Diff(want, got, opts); diff != "" { + t.Fatalf("Events mismatch (-want +got):\n%s", diff) + } +}