From 57225ebf5daea39e43d468892c9c2de1b0f7f902 Mon Sep 17 00:00:00 2001 From: Daria Bialobrzeska Date: Wed, 14 Aug 2024 19:51:43 +0200 Subject: [PATCH] Configure bugsnag at the start of testapp, rewrite net-http tests --- .gitignore | 2 - features/configuration.feature | 20 ++-- features/fixtures/app/Dockerfile | 3 + .../{autoconfig.go => autoconfig_scenario.go} | 20 ++-- features/fixtures/app/configure.go | 15 --- features/fixtures/app/handled_scenario.go | 42 +++---- features/fixtures/app/main.go | 104 +++++++++--------- features/fixtures/app/metadata_scenario.go | 12 +- .../main.go => app/nethttp_scenario.go} | 62 +++-------- features/fixtures/app/panic_scenario.go | 12 +- features/fixtures/app/run.sh | 27 +++++ features/fixtures/app/session_scenario.go | 11 +- features/fixtures/app/unhandled_scenario.go | 12 +- features/fixtures/app/user_scenario.go | 6 +- features/fixtures/app/utils.go | 2 +- features/fixtures/docker-compose.yml | 30 +---- features/fixtures/net_http/Dockerfile | 33 ------ features/handled.feature | 8 +- features/net-http/appversion.feature | 30 ++--- features/net-http/autocapturesessions.feature | 24 ---- features/net-http/autonotify.feature | 25 ++--- features/net-http/handled.feature | 42 ++++--- features/net-http/onbeforenotify.feature | 20 ++-- features/net-http/recover.feature | 18 +-- features/net-http/releasestage.feature | 30 +++-- features/net-http/request.feature | 14 +-- features/net-http/user.feature | 17 +-- features/panics.feature | 12 +- features/sessioncontext.feature | 5 +- features/steps/go_steps.rb | 46 -------- 30 files changed, 243 insertions(+), 461 deletions(-) rename features/fixtures/app/{autoconfig.go => autoconfig_scenario.go} (52%) delete mode 100644 features/fixtures/app/configure.go rename features/fixtures/{net_http/main.go => app/nethttp_scenario.go} (59%) create mode 100644 features/fixtures/app/run.sh delete mode 100644 features/fixtures/net_http/Dockerfile delete mode 100644 features/net-http/autocapturesessions.feature diff --git a/.gitignore b/.gitignore index 9cd08e81..fac2921d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,5 @@ maze_output vendor -features/fixtures/testbuild - # ignore the gemfile to prevent testing against stale versions Gemfile.lock diff --git a/features/configuration.feature b/features/configuration.feature index d7306102..8d61b286 100644 --- a/features/configuration.feature +++ b/features/configuration.feature @@ -40,10 +40,12 @@ Feature: Configure integration with environment variables When I start the service "app" And I run "AutoconfigPanicScenario" And I wait to receive an error - And the in-project frames of the stacktrace are: - | file | method | lineNumber | - | cases.go | explicitPanic | 22 | - | main.go | main | 11 | + And the "file" of stack frame 0 equals "features/fixtures/app/autoconfig_scenario.go" + And the "method" of stack frame 0 equals "AutoconfigPanicScenario.func1" + And the "lineNumber" of stack frame 0 equals 11 + And the "file" of stack frame 1 equals "features/fixtures/app/main.go" + And the "method" of stack frame 1 equals "main" + And the "lineNumber" of stack frame 1 equals 65 Scenario: Configuring source root Given I set environment variable "BUGSNAG_SOURCE_ROOT" to "/app/src/features/fixtures/app/" @@ -51,10 +53,12 @@ Feature: Configure integration with environment variables When I start the service "app" And I run "AutoconfigPanicScenario" And I wait to receive an error - And the in-project frames of the stacktrace are: - | file | method | lineNumber | - | cases.go | explicitPanic | 22 | - | main.go | main | 11 | + And the "file" of stack frame 0 equals "autoconfig_scenario.go" + And the "method" of stack frame 0 equals "AutoconfigPanicScenario.func1" + And the "lineNumber" of stack frame 0 equals 11 + And the "file" of stack frame 1 equals "main.go" + And the "method" of stack frame 1 equals "main" + And the "lineNumber" of stack frame 1 equals 65 Scenario: Delivering events filtering through notify release stages Given I set environment variable "BUGSNAG_NOTIFY_RELEASE_STAGES" to "prod,beta" diff --git a/features/fixtures/app/Dockerfile b/features/fixtures/app/Dockerfile index 42d2f860..61400ce0 100644 --- a/features/fixtures/app/Dockerfile +++ b/features/fixtures/app/Dockerfile @@ -29,3 +29,6 @@ WORKDIR /app/src/features/fixtures/app RUN go mod init && go mod tidy && \ echo "replace github.com/bugsnag/bugsnag-go/v2 => /app/src/github.com/bugsnag/bugsnag-go/v2" >> go.mod && \ go mod tidy + +RUN chmod +x run.sh +CMD ["/app/src/features/fixtures/app/run.sh"] \ No newline at end of file diff --git a/features/fixtures/app/autoconfig.go b/features/fixtures/app/autoconfig_scenario.go similarity index 52% rename from features/fixtures/app/autoconfig.go rename to features/fixtures/app/autoconfig_scenario.go index 4d825c5c..453eee3a 100644 --- a/features/fixtures/app/autoconfig.go +++ b/features/fixtures/app/autoconfig_scenario.go @@ -6,27 +6,21 @@ import ( bugsnag "github.com/bugsnag/bugsnag-go/v2" ) -func AutoconfigPanicScenario(command Command) (bugsnag.Configuration, func()) { - config := ConfigureBugsnag(command) - +func AutoconfigPanicScenario(command Command) func() { scenarioFunc := func() { panic("PANIQ!") } - return config, scenarioFunc + return scenarioFunc } -func AutoconfigHandledScenario(command Command) (bugsnag.Configuration, func()) { - config := ConfigureBugsnag(command) - +func AutoconfigHandledScenario(command Command) func() { scenarioFunc := func() { bugsnag.Notify(fmt.Errorf("gone awry!")) } - return config, scenarioFunc + return scenarioFunc } -func AutoconfigMetadataScenario(command Command) (bugsnag.Configuration, func()) { - config := ConfigureBugsnag(command) - +func AutoconfigMetadataScenario(command Command) func() { scenarioFunc := func() { bugsnag.OnBeforeNotify(func(event *bugsnag.Event, config *bugsnag.Configuration) error { event.MetaData.Add("fruit", "Tomato", "beefsteak") @@ -35,5 +29,5 @@ func AutoconfigMetadataScenario(command Command) (bugsnag.Configuration, func()) }) bugsnag.Notify(fmt.Errorf("gone awry!")) } - return config, scenarioFunc -} \ No newline at end of file + return scenarioFunc +} diff --git a/features/fixtures/app/configure.go b/features/fixtures/app/configure.go deleted file mode 100644 index 20d8d138..00000000 --- a/features/fixtures/app/configure.go +++ /dev/null @@ -1,15 +0,0 @@ -package main - -import ( - bugsnag "github.com/bugsnag/bugsnag-go/v2" -) - -func ConfigureBugsnag(command Command) bugsnag.Configuration { - config := bugsnag.Configuration{} - - config.APIKey = command.APIKey - config.Endpoints.Sessions = command.SessionsEndpoint - config.Endpoints.Notify = command.NotifyEndpoint - - return config -} diff --git a/features/fixtures/app/handled_scenario.go b/features/fixtures/app/handled_scenario.go index 7337ff48..ba0974ec 100644 --- a/features/fixtures/app/handled_scenario.go +++ b/features/fixtures/app/handled_scenario.go @@ -9,9 +9,7 @@ import ( "github.com/bugsnag/bugsnag-go/v2" ) -func HandledErrorScenario(command Command) (bugsnag.Configuration, func()) { - config := ConfigureBugsnag(command) - +func HandledErrorScenario(command Command) func() { scenarioFunc := func() { if _, err := os.Open("nonexistent_file.txt"); err != nil { if errClass := os.Getenv("ERROR_CLASS"); errClass != "" { @@ -21,25 +19,22 @@ func HandledErrorScenario(command Command) (bugsnag.Configuration, func()) { } } } - return config, scenarioFunc + return scenarioFunc } -func MultipleHandledErrorsScenario(command Command) (bugsnag.Configuration, func()) { +func MultipleHandledErrorsScenario(command Command) func() { //Make the order of the below predictable - config := ConfigureBugsnag(command) - config.Synchronous = true + bugsnag.Configure(bugsnag.Configuration{Synchronous: true}) scenarioFunc := func() { ctx := bugsnag.StartSession(context.Background()) bugsnag.Notify(fmt.Errorf("oops"), ctx) bugsnag.Notify(fmt.Errorf("oops"), ctx) } - return config, scenarioFunc + return scenarioFunc } -func NestedHandledErrorScenario(command Command) (bugsnag.Configuration, func()) { - config := ConfigureBugsnag(command) - +func NestedHandledErrorScenario(command Command) func() { scenarioFunc := func() { if err := Login("token " + os.Getenv("API_KEY")); err != nil { bugsnag.Notify(NewCustomErr("terminate process", err)) @@ -47,21 +42,19 @@ func NestedHandledErrorScenario(command Command) (bugsnag.Configuration, func()) i := len(os.Getenv("API_KEY")) // Some nonsense to avoid inlining checkValue if val, err := CheckValue(i); err != nil { - fmt.Printf("err: %v, val: %d", err, val) + fmt.Printf("err: %v, val: %d\n", err, val) } if val, err := CheckValue(i - 46); err != nil { - fmt.Printf("err: %v, val: %d", err, val) + fmt.Printf("err: %v, val: %d\n", err, val) } log.Fatalf("This test is broken - no error was generated.") } } - return config, scenarioFunc + return scenarioFunc } -func HandledCallbackErrorScenario(command Command) (bugsnag.Configuration, func()) { - config := ConfigureBugsnag(command) - +func HandledCallbackErrorScenario(command Command) func() { scenarioFunc := func() { bugsnag.Notify(fmt.Errorf("inadequent Prep Error"), func(event *bugsnag.Event) { event.Context = "nonfatal.go:14" @@ -71,24 +64,21 @@ func HandledCallbackErrorScenario(command Command) (bugsnag.Configuration, func( event.Stacktrace[1].LineNumber = 0 }) } - return config, scenarioFunc + return scenarioFunc } -func HandledToUnhandledScenario(command Command) (bugsnag.Configuration, func()) { - config := ConfigureBugsnag(command) - +func HandledToUnhandledScenario(command Command) func() { scenarioFunc := func() { bugsnag.Notify(fmt.Errorf("unknown event"), func(event *bugsnag.Event) { event.Unhandled = true event.Severity = bugsnag.SeverityError }) } - return config, scenarioFunc + return scenarioFunc } -func OnBeforeNotifyScenario(command Command) (bugsnag.Configuration, func()) { - config := ConfigureBugsnag(command) - config.Synchronous = true +func OnBeforeNotifyScenario(command Command) func() { + bugsnag.Configure(bugsnag.Configuration{Synchronous: true}) scenarioFunc := func() { bugsnag.OnBeforeNotify( @@ -106,5 +96,5 @@ func OnBeforeNotifyScenario(command Command) (bugsnag.Configuration, func()) { bugsnag.Notify(fmt.Errorf("don't ignore this error")) bugsnag.Notify(fmt.Errorf("change error message")) } - return config, scenarioFunc + return scenarioFunc } diff --git a/features/fixtures/app/main.go b/features/fixtures/app/main.go index 80728eb4..7332a1a0 100644 --- a/features/fixtures/app/main.go +++ b/features/fixtures/app/main.go @@ -3,70 +3,68 @@ package main import ( "fmt" "os" - "os/signal" - "syscall" "time" "github.com/bugsnag/bugsnag-go/v2" ) -var scenariosMap = map[string] func(Command)(bugsnag.Configuration, func()){ - "UnhandledScenario": UnhandledCrashScenario, - "HandledScenario": HandledErrorScenario, - "MultipleUnhandledScenario": MultipleUnhandledErrorsScenario, - "MultipleHandledScenario": MultipleHandledErrorsScenario, - "NestedErrorScenario": NestedHandledErrorScenario, - "MetadataScenario": MetadataScenario, - "FilteredMetadataScenario": FilteredMetadataScenario, +var scenariosMap = map[string]func(Command) func(){ + "UnhandledScenario": UnhandledCrashScenario, + "HandledScenario": HandledErrorScenario, + "MultipleUnhandledScenario": MultipleUnhandledErrorsScenario, + "MultipleHandledScenario": MultipleHandledErrorsScenario, + "NestedErrorScenario": NestedHandledErrorScenario, + "MetadataScenario": MetadataScenario, + "FilteredMetadataScenario": FilteredMetadataScenario, "HandledCallbackErrorScenario": HandledCallbackErrorScenario, - "SendSessionScenario": SendSessionScenario, - "HandledToUnhandledScenario": HandledToUnhandledScenario, - "SetUserScenario": SetUserScenario, - "RecoverAfterPanicScenario": RecoverAfterPanicScenario, - "AutonotifyPanicScenario": AutonotifyPanicScenario, - "SessionAndErrorScenario": SessionAndErrorScenario, - "OnBeforeNotifyScenario": OnBeforeNotifyScenario, - "AutoconfigPanicScenario": AutoconfigPanicScenario, - "AutoconfigHandledScenario": AutoconfigHandledScenario, - "AutoconfigMetadataScenario": AutoconfigMetadataScenario, + "SendSessionScenario": SendSessionScenario, + "HandledToUnhandledScenario": HandledToUnhandledScenario, + "SetUserScenario": SetUserScenario, + "RecoverAfterPanicScenario": RecoverAfterPanicScenario, + "AutonotifyPanicScenario": AutonotifyPanicScenario, + "SessionAndErrorScenario": SessionAndErrorScenario, + "OnBeforeNotifyScenario": OnBeforeNotifyScenario, + "AutoconfigPanicScenario": AutoconfigPanicScenario, + "AutoconfigHandledScenario": AutoconfigHandledScenario, + "AutoconfigMetadataScenario": AutoconfigMetadataScenario, + "HttpServerScenario": HttpServerScenario, } func main() { - // Listening to the OS Signals - signalsChan := make(chan os.Signal, 1) - signal.Notify(signalsChan, syscall.SIGINT, syscall.SIGTERM) - ticker := time.NewTicker(1 * time.Second) + addr := os.Getenv("DEFAULT_MAZE_ADDRESS") + if addr == "" { + addr = DEFAULT_MAZE_ADDRESS + } - // Increase publish rate for testing - bugsnag.DefaultSessionPublishInterval = time.Millisecond * 50 + endpoints := bugsnag.Endpoints{ + Notify: fmt.Sprintf("%+v/notify", addr), + Sessions: fmt.Sprintf("%+v/sessions", addr), + } + // HAS TO RUN FIRST BECAUSE OF PANIC WRAP + // https://github.com/bugsnag/panicwrap/blob/master/panicwrap.go#L177-L203 + bugsnag.Configure(bugsnag.Configuration{ + APIKey: "166f5ad3590596f9aa8d601ea89af845", + Endpoints: endpoints, + }) + // Increase publish rate for testing + bugsnag.DefaultSessionPublishInterval = time.Millisecond * 50 - addr := os.Getenv("DEFAULT_MAZE_ADDRESS") - if (addr == "") { - addr = DEFAULT_MAZE_ADDRESS - } - - for { - select { - case <-ticker.C: - command := GetCommand(addr) - fmt.Printf("[Bugsnag] Received command: %+v\n", command) - - if command.Action == "run-scenario" { - prepareScenarioFunc, ok := scenariosMap[command.ScenarioName] - if ok { - config, scenarioFunc := prepareScenarioFunc(command) - bugsnag.Configure(config) - time.Sleep(200 * time.Millisecond) - scenarioFunc() - time.Sleep(200 * time.Millisecond) - } - } - case <-signalsChan: - fmt.Println("[Bugsnag] Context is done, closing") - ticker.Stop() - return + // Listening to the OS Signals + ticker := time.NewTicker(1 * time.Second) + for { + select { + case <-ticker.C: + command := GetCommand(addr) + fmt.Printf("[Bugsnag] Received command: %+v\n", command) + if command.Action != "run-scenario" { + continue + } + prepareScenarioFunc, ok := scenariosMap[command.ScenarioName] + if ok { + scenarioFunc := prepareScenarioFunc(command) + scenarioFunc() + time.Sleep(200 * time.Millisecond) } } + } } - - diff --git a/features/fixtures/app/metadata_scenario.go b/features/fixtures/app/metadata_scenario.go index c8afdcfe..e4cb7f70 100644 --- a/features/fixtures/app/metadata_scenario.go +++ b/features/fixtures/app/metadata_scenario.go @@ -6,9 +6,7 @@ import ( "github.com/bugsnag/bugsnag-go/v2" ) -func MetadataScenario(command Command) (bugsnag.Configuration, func()) { - config := ConfigureBugsnag(command) - +func MetadataScenario(command Command) func() { scenarioFunc := func() { customerData := map[string]string{"Name": "Joe Bloggs", "Age": "21"} bugsnag.Notify(fmt.Errorf("oops"), bugsnag.MetaData{ @@ -18,12 +16,10 @@ func MetadataScenario(command Command) (bugsnag.Configuration, func()) { }, }) } - return config, scenarioFunc + return scenarioFunc } -func FilteredMetadataScenario(command Command) (bugsnag.Configuration, func()) { - config := ConfigureBugsnag(command) - +func FilteredMetadataScenario(command Command) func() { scenarioFunc := func() { bugsnag.Notify(fmt.Errorf("oops"), bugsnag.MetaData{ "Account": { @@ -32,5 +28,5 @@ func FilteredMetadataScenario(command Command) (bugsnag.Configuration, func()) { }, }) } - return config, scenarioFunc + return scenarioFunc } diff --git a/features/fixtures/net_http/main.go b/features/fixtures/app/nethttp_scenario.go similarity index 59% rename from features/fixtures/net_http/main.go rename to features/fixtures/app/nethttp_scenario.go index ac359263..e90a4357 100644 --- a/features/fixtures/net_http/main.go +++ b/features/fixtures/app/nethttp_scenario.go @@ -6,25 +6,25 @@ import ( "log" "net/http" "os" - "strconv" - "strings" "time" - bugsnag "github.com/bugsnag/bugsnag-go/v2" + "github.com/bugsnag/bugsnag-go/v2" ) -func main() { - configureBasicBugsnag() - - http.HandleFunc("/handled", handledError) - http.HandleFunc("/autonotify-then-recover", unhandledCrash) - http.HandleFunc("/session", session) - http.HandleFunc("/autonotify", autonotify) - http.HandleFunc("/onbeforenotify", onBeforeNotify) - http.HandleFunc("/recover", dontdie) - http.HandleFunc("/user", user) +func HttpServerScenario(Command) func() { + scenarioFunc := func() { + http.HandleFunc("/handled", handledError) + http.HandleFunc("/autonotify-then-recover", unhandledCrash) + http.HandleFunc("/session", session) + http.HandleFunc("/autonotify", autonotify) + http.HandleFunc("/onbeforenotify", onBeforeNotify) + http.HandleFunc("/recover", dontdie) + http.HandleFunc("/user", user) + + http.ListenAndServe(":4512", recoverWrap(bugsnag.Handler(nil))) + } - http.ListenAndServe(":"+os.Getenv("SERVER_PORT"), recoverWrap(bugsnag.Handler(nil))) + return scenarioFunc } // Simple wrapper to send internal server error on panics @@ -40,40 +40,6 @@ func recoverWrap(h http.Handler) http.Handler { }) } -func configureBasicBugsnag() { - config := bugsnag.Configuration{ - APIKey: os.Getenv("API_KEY"), - Endpoints: bugsnag.Endpoints{ - Notify: os.Getenv("BUGSNAG_ENDPOINT"), - Sessions: os.Getenv("BUGSNAG_ENDPOINT"), - }, - AppVersion: os.Getenv("APP_VERSION"), - AppType: os.Getenv("APP_TYPE"), - Hostname: os.Getenv("HOSTNAME"), - } - - if notifyReleaseStages := os.Getenv("NOTIFY_RELEASE_STAGES"); notifyReleaseStages != "" { - config.NotifyReleaseStages = strings.Split(notifyReleaseStages, ",") - } - - if releaseStage := os.Getenv("RELEASE_STAGE"); releaseStage != "" { - config.ReleaseStage = releaseStage - } - - if filters := os.Getenv("PARAMS_FILTERS"); filters != "" { - config.ParamsFilters = []string{filters} - } - - acs, err := strconv.ParseBool(os.Getenv("AUTO_CAPTURE_SESSIONS")) - if err == nil { - config.AutoCaptureSessions = acs - } - bugsnag.Configure(config) - - // Increase publish rate for testing - bugsnag.DefaultSessionPublishInterval = time.Millisecond * 300 -} - func handledError(w http.ResponseWriter, r *http.Request) { if _, err := os.Open("nonexistent_file.txt"); err != nil { if errClass := os.Getenv("ERROR_CLASS"); errClass != "" { diff --git a/features/fixtures/app/panic_scenario.go b/features/fixtures/app/panic_scenario.go index 74cc6c38..fcd1a3b2 100644 --- a/features/fixtures/app/panic_scenario.go +++ b/features/fixtures/app/panic_scenario.go @@ -4,23 +4,19 @@ import ( "github.com/bugsnag/bugsnag-go/v2" ) -func AutonotifyPanicScenario(command Command) (bugsnag.Configuration, func()) { - config := ConfigureBugsnag(command) - +func AutonotifyPanicScenario(command Command) func() { scenarioFunc := func() { defer bugsnag.AutoNotify() panic("Go routine killed with auto notify") } - return config, scenarioFunc + return scenarioFunc } -func RecoverAfterPanicScenario(command Command) (bugsnag.Configuration, func()) { - config := ConfigureBugsnag(command) - +func RecoverAfterPanicScenario(command Command) func() { scenarioFunc := func() { defer bugsnag.Recover() panic("Go routine killed but recovered") } - return config, scenarioFunc + return scenarioFunc } diff --git a/features/fixtures/app/run.sh b/features/fixtures/app/run.sh new file mode 100644 index 00000000..67eb31d5 --- /dev/null +++ b/features/fixtures/app/run.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +# SIGTERM or SIGINT trapped (likely SIGTERM from docker), pass it onto app +# process +function _term_or_init { + kill -TERM "$APP_PID" 2>/dev/null + wait $APP_PID +} + +# The bugsnag notifier monitor process needs at least 300ms, in order to ensure +# that it can send its notify +function _exit { + sleep 1 +} + +trap _term_or_init SIGTERM SIGINT +trap _exit EXIT + +PROC="${@:1}" +$PROC & + +# Wait on the app process to ensure that this script is able to trap the SIGTERM +# signal +APP_PID=$! +wait $APP_PID + +go run . \ No newline at end of file diff --git a/features/fixtures/app/session_scenario.go b/features/fixtures/app/session_scenario.go index f9f97632..6153b37d 100644 --- a/features/fixtures/app/session_scenario.go +++ b/features/fixtures/app/session_scenario.go @@ -7,20 +7,17 @@ import ( "github.com/bugsnag/bugsnag-go/v2" ) -func SendSessionScenario(command Command) (bugsnag.Configuration, func()) { - config := ConfigureBugsnag(command) - +func SendSessionScenario(command Command) func() { scenarioFunc := func() { bugsnag.StartSession(context.Background()) } - return config, scenarioFunc + return scenarioFunc } -func SessionAndErrorScenario(command Command) (bugsnag.Configuration, func()) { - config := ConfigureBugsnag(command) +func SessionAndErrorScenario(command Command) func() { scenarioFunc := func() { ctx := bugsnag.StartSession(context.Background()) bugsnag.Notify(fmt.Errorf("oops"), ctx) } - return config, scenarioFunc + return scenarioFunc } diff --git a/features/fixtures/app/unhandled_scenario.go b/features/fixtures/app/unhandled_scenario.go index 4bde24c3..f7fdd5ce 100644 --- a/features/fixtures/app/unhandled_scenario.go +++ b/features/fixtures/app/unhandled_scenario.go @@ -8,9 +8,7 @@ import ( ) //go:noinline -func UnhandledCrashScenario(command Command) (bugsnag.Configuration, func()) { - config := ConfigureBugsnag(command) - +func UnhandledCrashScenario(command Command) func() { scenarioFunc := func() { fmt.Printf("Calling panic\n") // Invalid type assertion, will panic @@ -18,12 +16,10 @@ func UnhandledCrashScenario(command Command) (bugsnag.Configuration, func()) { return a.(string) }(struct{}{}) } - return config, scenarioFunc + return scenarioFunc } -func MultipleUnhandledErrorsScenario(command Command) (bugsnag.Configuration, func()) { - config := ConfigureBugsnag(command) - +func MultipleUnhandledErrorsScenario(command Command) func() { scenarioFunc := func() { //Make the order of the below predictable notifier := bugsnag.New(bugsnag.Configuration{Synchronous: true}) @@ -35,5 +31,5 @@ func MultipleUnhandledErrorsScenario(command Command) (bugsnag.Configuration, fu defer notifier.AutoNotify(ctx) panic("oops") } - return config, scenarioFunc + return scenarioFunc } diff --git a/features/fixtures/app/user_scenario.go b/features/fixtures/app/user_scenario.go index c0da6710..a543c623 100644 --- a/features/fixtures/app/user_scenario.go +++ b/features/fixtures/app/user_scenario.go @@ -6,9 +6,7 @@ import ( "github.com/bugsnag/bugsnag-go/v2" ) -func SetUserScenario(command Command) (bugsnag.Configuration, func()) { - config := ConfigureBugsnag(command) - +func SetUserScenario(command Command) func() { scenarioFunc := func() { bugsnag.Notify(fmt.Errorf("oops"), bugsnag.User{ Id: "test-user-id", @@ -17,5 +15,5 @@ func SetUserScenario(command Command) (bugsnag.Configuration, func()) { }) } - return config, scenarioFunc + return scenarioFunc } diff --git a/features/fixtures/app/utils.go b/features/fixtures/app/utils.go index cdc4936c..87937b27 100644 --- a/features/fixtures/app/utils.go +++ b/features/fixtures/app/utils.go @@ -38,7 +38,7 @@ func Login(token string) error { if err != nil { return NewCustomErr("login failed", err) } - fmt.Printf("val: %d", val) + fmt.Printf("val: %d\n", val) return nil } diff --git a/features/fixtures/docker-compose.yml b/features/fixtures/docker-compose.yml index 48ca8f31..a48ece35 100644 --- a/features/fixtures/docker-compose.yml +++ b/features/fixtures/docker-compose.yml @@ -5,10 +5,11 @@ services: dockerfile: ./features/fixtures/app/Dockerfile args: - GO_VERSION + ports: + - "4512:4512" environment: - DEFAULT_MAZE_ADDRESS - ERROR_CLASS - - SERVER_PORT - BUGSNAG_API_KEY - BUGSNAG_APP_TYPE - BUGSNAG_APP_VERSION @@ -30,33 +31,6 @@ services: - BUGSNAG_METADATA_fruit_Tomato - BUGSNAG_METADATA_snacks_Carrot restart: "no" - command: go run . - - nethttp: - build: - context: . - dockerfile: net_http/Dockerfile - args: - - GO_VERSION - ports: - - "4512:4512" - environment: - - API_KEY - - ERROR_CLASS - - BUGSNAG_ENDPOINT - - APP_VERSION - - APP_TYPE - - HOSTNAME - - NOTIFY_RELEASE_STAGES - - RELEASE_STAGE - - PARAMS_FILTERS - - AUTO_CAPTURE_SESSIONS - - SYNCHRONOUS - - SERVER_PORT - - BUGSNAG_SOURCE_ROOT - - BUGSNAG_PROJECT_PACKAGES - restart: "no" - command: go run main.go gin: build: diff --git a/features/fixtures/net_http/Dockerfile b/features/fixtures/net_http/Dockerfile deleted file mode 100644 index d8307933..00000000 --- a/features/fixtures/net_http/Dockerfile +++ /dev/null @@ -1,33 +0,0 @@ -ARG GO_VERSION -FROM golang:${GO_VERSION}-alpine - -RUN apk update && \ - apk upgrade && \ - apk add git - -ENV GOPATH /app - -COPY testbuild /app/src/github.com/bugsnag/bugsnag-go -WORKDIR /app/src/github.com/bugsnag/bugsnag-go/v2 - -# Ensure subsequent steps are re-run if the GO_VERSION variable changes -ARG GO_VERSION - -# Get bugsnag dependencies using a conditional call to run go get or go install based on the go version -RUN if [[ $(echo -e "1.11\n$GO_VERSION\n1.16" | sort -V | head -2 | tail -1) == "$GO_VERSION" ]]; then \ - echo "Version is between 1.11 and 1.16, running go get"; \ - go get ./...; \ - else \ - echo "Version is greater than 1.16, running go install"; \ - go install ./...; \ - fi - -# Copy test scenarios -COPY ./net_http /app/src/test -WORKDIR /app/src/test - -# Create app module - avoid locking bugsnag dep by not checking it in -# Skip on old versions of Go which pre-date modules -RUN if [[ $GO_VERSION != '1.11' && $GO_VERSION != '1.12' ]]; then \ - go mod init && go mod tidy; \ - fi diff --git a/features/handled.feature b/features/handled.feature index 3e12d601..b437a90f 100644 --- a/features/handled.feature +++ b/features/handled.feature @@ -11,7 +11,7 @@ Scenario: A handled error sends a report And the event "unhandled" is false And the event "severity" equals "warning" And the event "severityReason.type" equals "handledError" - And the exception "errorClass" equals "*os.PathError" + And the exception "errorClass" equals "*fs.PathError" And the "file" of stack frame 0 equals "handled_scenario.go" Scenario: A handled error sends a report with a custom name @@ -34,7 +34,7 @@ Scenario: Sending an event using a callback to modify report contents And the event "severityReason.type" equals "userCallbackSetSeverity" And the event "context" equals "nonfatal.go:14" And the "file" of stack frame 0 equals "handled_scenario.go" - And the "lineNumber" of stack frame 0 equals 66 + And the "lineNumber" of stack frame 0 equals 59 And the "file" of stack frame 1 equals ">insertion<" And the "lineNumber" of stack frame 1 equals 0 @@ -47,7 +47,7 @@ Scenario: Marking an error as unhandled in a callback And the event "severityReason.type" equals "userCallbackSetSeverity" And the event "severityReason.unhandledOverridden" is true And the "file" of stack frame 0 equals "handled_scenario.go" - And the "lineNumber" of stack frame 0 equals 81 + And the "lineNumber" of stack frame 0 equals 72 Scenario: Unwrapping the causes of a handled error When I start the service "app" @@ -56,7 +56,7 @@ Scenario: Unwrapping the causes of a handled error And the event "unhandled" is false And the event "severity" equals "warning" And the event "exceptions.0.message" equals "terminate process" - And the "lineNumber" of stack frame 0 equals 45 + And the "lineNumber" of stack frame 0 equals 40 And the "file" of stack frame 0 equals "handled_scenario.go" And the "method" of stack frame 0 equals "NestedHandledErrorScenario.func1" And the event "exceptions.1.message" equals "login failed" diff --git a/features/net-http/appversion.feature b/features/net-http/appversion.feature index 06e9f61e..09f7fa57 100644 --- a/features/net-http/appversion.feature +++ b/features/net-http/appversion.feature @@ -1,28 +1,28 @@ Feature: Configuring app version Background: - Given I set environment variable "API_KEY" to "a35a2a72bd230ac0aa0f52715bbdc6aa" - And I configure the bugsnag endpoint - And I set environment variable "APP_VERSION" to "3.1.2" - And I set environment variable "SERVER_PORT" to "4512" + And I set environment variable "BUGSNAG_APP_VERSION" to "3.1.2" Scenario: A error report contains the configured app type when using a net http app - Given I set environment variable "AUTO_CAPTURE_SESSIONS" to "false" - When I start the service "nethttp" - And I wait for the app to open port "4512" + Given I set environment variable "BUGSNAG_AUTO_CAPTURE_SESSIONS" to "false" + When I start the service "app" + And I run "HttpServerScenario" + And I wait for the host "localhost" to open port "4512" And I wait for 2 seconds And I open the URL "http://localhost:4512/handled" - Then I wait to receive a request - And the request is a valid error report with api key "a35a2a72bd230ac0aa0f52715bbdc6aa" + And I wait to receive an error + And I should receive no sessions + And the error is valid for the error reporting API version "4" for the "Bugsnag Go" notifier And the event "app.version" equals "3.1.2" Scenario: A session report contains the configured app type when using a net http app - Given I set environment variable "AUTO_CAPTURE_SESSIONS" to "true" - When I start the service "nethttp" - And I wait for the app to open port "4512" + Given I set environment variable "BUGSNAG_AUTO_CAPTURE_SESSIONS" to "true" + When I start the service "app" + And I run "HttpServerScenario" + And I wait for the host "localhost" to open port "4512" And I wait for 2 seconds And I open the URL "http://localhost:4512/session" - Then I wait to receive a request after the start up session - And the request is a valid session report with api key "a35a2a72bd230ac0aa0f52715bbdc6aa" - And the payload field "app.version" equals "3.1.2" + And I wait to receive a session + And the session is valid for the session reporting API version "1.0" for the "Bugsnag Go" notifier + And the session payload field "sessions.0.app.version" equals "3.1.2" diff --git a/features/net-http/autocapturesessions.feature b/features/net-http/autocapturesessions.feature deleted file mode 100644 index b7f00bb4..00000000 --- a/features/net-http/autocapturesessions.feature +++ /dev/null @@ -1,24 +0,0 @@ -Feature: Configure auto capture sessions - -Background: - Given I set environment variable "API_KEY" to "a35a2a72bd230ac0aa0f52715bbdc6aa" - And I configure the bugsnag endpoint - And I set environment variable "SERVER_PORT" to "4512" - -Scenario: A session is not sent if auto capture sessions is off - Given I set environment variable "AUTO_CAPTURE_SESSIONS" to "false" - When I start the service "nethttp" - And I wait for the app to open port "4512" - And I wait for 2 seconds - And I open the URL "http://localhost:4512/session" - And I wait for 2 seconds - Then I should receive no requests - -Scenario: A session is sent if auto capture sessions is on - Given I set environment variable "AUTO_CAPTURE_SESSIONS" to "true" - When I start the service "nethttp" - And I wait for the app to open port "4512" - And I wait for 2 seconds - And I open the URL "http://localhost:4512/session" - Then I wait to receive a request after the start up session - And the request is a valid session report with api key "a35a2a72bd230ac0aa0f52715bbdc6aa" diff --git a/features/net-http/autonotify.feature b/features/net-http/autonotify.feature index baf4198c..041142ec 100644 --- a/features/net-http/autonotify.feature +++ b/features/net-http/autonotify.feature @@ -1,30 +1,25 @@ Feature: Using auto notify -Background: - Given I set environment variable "API_KEY" to "a35a2a72bd230ac0aa0f52715bbdc6aa" - And I configure the bugsnag endpoint - And I set environment variable "SERVER_PORT" to "4512" - Scenario: An error report is sent when an AutoNotified crash occurs which later gets recovered - Given I set environment variable "AUTO_CAPTURE_SESSIONS" to "false" - When I start the service "nethttp" - And I wait for the app to open port "4512" + Given I set environment variable "BUGSNAG_AUTO_CAPTURE_SESSIONS" to "false" + When I start the service "app" + And I run "HttpServerScenario" + And I wait for the host "localhost" to open port "4512" And I wait for 2 seconds And I open the URL "http://localhost:4512/autonotify-then-recover" - Then I wait to receive a request - And the request is a valid error report with api key "a35a2a72bd230ac0aa0f52715bbdc6aa" + Then I wait to receive an error And the event "unhandled" is true And the exception "errorClass" equals "*runtime.TypeAssertionError" And the exception "message" matches "interface conversion: interface ({} )?is struct {}, not string" Scenario: An error report is sent when a go routine crashes which is reported through auto notify - Given I set environment variable "AUTO_CAPTURE_SESSIONS" to "false" - When I start the service "nethttp" - And I wait for the app to open port "4512" + Given I set environment variable "BUGSNAG_AUTO_CAPTURE_SESSIONS" to "false" + When I start the service "app" + And I run "HttpServerScenario" + And I wait for the host "localhost" to open port "4512" And I wait for 2 seconds And I open the URL "http://localhost:4512/autonotify" - Then I wait to receive a request - And the request is a valid error report with api key "a35a2a72bd230ac0aa0f52715bbdc6aa" + Then I wait to receive an error And the event "unhandled" is true And the exception "errorClass" equals "*errors.errorString" And the exception "message" equals "Go routine killed with auto notify" diff --git a/features/net-http/handled.feature b/features/net-http/handled.feature index 4c9eb4cc..fcb16882 100644 --- a/features/net-http/handled.feature +++ b/features/net-http/handled.feature @@ -1,35 +1,31 @@ Feature: Handled errors Background: - Given I set environment variable "API_KEY" to "a35a2a72bd230ac0aa0f52715bbdc6aa" - Given I set environment variable "BUGSNAG_SOURCE_ROOT" to the app directory - And I configure the bugsnag endpoint - And I set environment variable "SERVER_PORT" to "4512" - And I set environment variable "AUTO_CAPTURE_SESSIONS" to "false" + Given I set environment variable "BUGSNAG_SOURCE_ROOT" to "/app/src/features/fixtures/app/" Scenario: A handled error sends a report - When I start the service "nethttp" - And I wait for the app to open port "4512" + When I start the service "app" + And I run "HttpServerScenario" + And I wait for the host "localhost" to open port "4512" And I wait for 2 seconds And I open the URL "http://localhost:4512/handled" - Then I wait to receive a request - And the request 0 is a valid error report with api key "a35a2a72bd230ac0aa0f52715bbdc6aa" - And the event "unhandled" is false for request 0 - And the event "severity" equals "warning" for request 0 - And the event "severityReason.type" equals "handledError" for request 0 - And the exception is a PathError for request 0 - And the "file" of stack frame 0 equals "main.go" for request 0 + Then I wait to receive an error + And the event "unhandled" is false + And the event "severity" equals "warning" + And the event "severityReason.type" equals "handledError" + And the exception "errorClass" equals "*os.PathError" + And the "file" of stack frame 0 equals "nethttp_scenario.go" Scenario: A handled error sends a report with a custom name Given I set environment variable "ERROR_CLASS" to "MyCustomErrorClass" - When I start the service "nethttp" - And I wait for the app to open port "4512" + When I start the service "app" + And I run "HttpServerScenario" + And I wait for the host "localhost" to open port "4512" And I wait for 2 seconds And I open the URL "http://localhost:4512/handled" - Then I wait to receive a request - And the request 0 is a valid error report with api key "a35a2a72bd230ac0aa0f52715bbdc6aa" - And the event "unhandled" is false for request 0 - And the event "severity" equals "warning" for request 0 - And the event "severityReason.type" equals "handledError" for request 0 - And the exception "errorClass" equals "MyCustomErrorClass" for request 0 - And the "file" of stack frame 0 equals "main.go" for request 0 + Then I wait to receive an error + And the event "unhandled" is false + And the event "severity" equals "warning" + And the event "severityReason.type" equals "handledError" + And the exception "errorClass" equals "MyCustomErrorClass" + And the "file" of stack frame 0 equals "nethttp_scenario.go" diff --git a/features/net-http/onbeforenotify.feature b/features/net-http/onbeforenotify.feature index d0b519c4..9d7bcfe2 100644 --- a/features/net-http/onbeforenotify.feature +++ b/features/net-http/onbeforenotify.feature @@ -1,18 +1,12 @@ Feature: Configuring on before notify -Background: - Given I set environment variable "API_KEY" to "a35a2a72bd230ac0aa0f52715bbdc6aa" - And I configure the bugsnag endpoint - And I set environment variable "SERVER_PORT" to "4512" - And I set environment variable "AUTO_CAPTURE_SESSIONS" to "false" - Scenario: Send three bugsnags and use on before notify to drop one and modify the message of another - When I start the service "nethttp" - And I wait for the app to open port "4512" + When I start the service "app" + And I run "HttpServerScenario" + And I wait for the host "localhost" to open port "4512" And I wait for 2 seconds And I open the URL "http://localhost:4512/onbeforenotify" - Then I wait to receive 2 requests - And the request 0 is a valid error report with api key "a35a2a72bd230ac0aa0f52715bbdc6aa" - And the exception "message" equals "Don't ignore this error" for request 0 - And the request 1 is a valid error report with api key "a35a2a72bd230ac0aa0f52715bbdc6aa" - And the exception "message" equals "Error message was changed" for request 1 + Then I wait to receive 2 errors + And the exception "message" equals "Don't ignore this error" + And I discard the oldest error + And the exception "message" equals "Error message was changed" diff --git a/features/net-http/recover.feature b/features/net-http/recover.feature index 5f64d78b..2cf2edc0 100644 --- a/features/net-http/recover.feature +++ b/features/net-http/recover.feature @@ -1,17 +1,11 @@ Feature: Using recover -Background: - Given I set environment variable "API_KEY" to "a35a2a72bd230ac0aa0f52715bbdc6aa" - And I configure the bugsnag endpoint - And I set environment variable "SERVER_PORT" to "4512" - And I set environment variable "AUTO_CAPTURE_SESSIONS" to "false" - Scenario: An error report is sent when request crashes but is recovered - When I start the service "nethttp" - And I wait for the app to open port "4512" + When I start the service "app" + And I run "HttpServerScenario" + And I wait for the host "localhost" to open port "4512" And I wait for 2 seconds And I open the URL "http://localhost:4512/recover" - Then I wait to receive a request - And the request 0 is a valid error report with api key "a35a2a72bd230ac0aa0f52715bbdc6aa" - And the exception "errorClass" equals "*errors.errorString" for request 0 - And the exception "message" equals "Request killed but recovered" for request 0 + Then I wait to receive an error + And the exception "errorClass" equals "*errors.errorString" + And the exception "message" equals "Request killed but recovered" diff --git a/features/net-http/releasestage.feature b/features/net-http/releasestage.feature index e1b50169..d412efc8 100644 --- a/features/net-http/releasestage.feature +++ b/features/net-http/releasestage.feature @@ -1,27 +1,25 @@ Feature: Configuring release stage Background: - Given I set environment variable "API_KEY" to "a35a2a72bd230ac0aa0f52715bbdc6aa" - And I configure the bugsnag endpoint - And I set environment variable "SERVER_PORT" to "4512" - And I set environment variable "RELEASE_STAGE" to "my-stage" + Given I set environment variable "BUGSNAG_RELEASE_STAGE" to "my-stage" Scenario: An error report is sent with configured release stage - Given I set environment variable "AUTO_CAPTURE_SESSIONS" to "false" - When I start the service "nethttp" - And I wait for the app to open port "4512" + Given I set environment variable "BUGSNAG_AUTO_CAPTURE_SESSIONS" to "false" + When I start the service "app" + And I run "HttpServerScenario" + And I wait for the host "localhost" to open port "4512" And I wait for 2 seconds And I open the URL "http://localhost:4512/handled" - Then I wait to receive a request - And the request 0 is a valid error report with api key "a35a2a72bd230ac0aa0f52715bbdc6aa" - And the event "app.releaseStage" equals "my-stage" for request 0 + Then I wait to receive an error + And the event "app.releaseStage" equals "my-stage" Scenario: A session report contains the configured app type - Given I set environment variable "AUTO_CAPTURE_SESSIONS" to "true" - When I start the service "nethttp" - And I wait for the app to open port "4512" + Given I set environment variable "BUGSNAG_AUTO_CAPTURE_SESSIONS" to "true" + When I start the service "app" + And I run "HttpServerScenario" + And I wait for the host "localhost" to open port "4512" And I wait for 2 seconds And I open the URL "http://localhost:4512/session" - Then I wait to receive a request after the start up session - And the request is a valid session report with api key "a35a2a72bd230ac0aa0f52715bbdc6aa" - And the payload field "app.releaseStage" equals "my-stage" + Then I wait to receive a session + And I wait to receive an error + And the session payload field "sessions.0.app.releaseStage" equals "my-stage" diff --git a/features/net-http/request.feature b/features/net-http/request.feature index ecf7f347..56d24e6c 100644 --- a/features/net-http/request.feature +++ b/features/net-http/request.feature @@ -1,18 +1,12 @@ Feature: Capturing request information automatically -Background: - Given I set environment variable "API_KEY" to "a35a2a72bd230ac0aa0f52715bbdc6aa" - And I configure the bugsnag endpoint - And I set environment variable "SERVER_PORT" to "4512" - Scenario: An error report will automatically contain request information - Given I set environment variable "AUTO_CAPTURE_SESSIONS" to "false" - When I start the service "nethttp" - And I wait for the app to open port "4512" + When I start the service "app" + And I run "HttpServerScenario" + And I wait for the host "localhost" to open port "4512" And I wait for 2 seconds And I open the URL "http://localhost:4512/handled" - Then I wait to receive a request - And the request is a valid error report with api key "a35a2a72bd230ac0aa0f52715bbdc6aa" + Then I wait to receive an error And the event "request.clientIp" is not null And the event "request.headers.User-Agent" equals "Ruby" And the event "request.httpMethod" equals "GET" diff --git a/features/net-http/user.feature b/features/net-http/user.feature index dd03d9cd..bd7b5bee 100644 --- a/features/net-http/user.feature +++ b/features/net-http/user.feature @@ -1,21 +1,12 @@ Feature: Sending user data -Background: - Given I set environment variable "API_KEY" to "a35a2a72bd230ac0aa0f52715bbdc6aa" - And I configure the bugsnag endpoint - And I set environment variable "SERVER_PORT" to "4512" - And I set environment variable "AUTO_CAPTURE_SESSIONS" to "false" - Scenario: An error report contains custom user data - Given I set environment variable "USER_ID" to "test-user-id" - And I set environment variable "USER_NAME" to "test-user-name" - And I set environment variable "USER_EMAIL" to "test-user-email" - When I start the service "nethttp" - And I wait for the app to open port "4512" + When I start the service "app" + And I run "HttpServerScenario" + And I wait for the host "localhost" to open port "4512" And I wait for 2 seconds And I open the URL "http://localhost:4512/user" - Then I wait to receive a request - And the request is a valid error report with api key "a35a2a72bd230ac0aa0f52715bbdc6aa" + Then I wait to receive an error And the event "user.id" equals "test-user-id" And the event "user.name" equals "test-user-name" And the event "user.email" equals "test-user-email" diff --git a/features/panics.feature b/features/panics.feature index f2dfd012..d872a8de 100644 --- a/features/panics.feature +++ b/features/panics.feature @@ -12,10 +12,8 @@ Feature: Panic handling And the event "severity" equals "error" And the event "severityReason.type" equals "unhandledPanic" And the exception "errorClass" equals "panic" - #And the exception "message" is one of: - # | interface conversion: interface is struct {}, not string | - # | interface conversion: interface {} is struct {}, not string | - #And the in-project frames of the stacktrace are: - # | file | method | - # | main.go | unhandledCrash.func1 | - # | main.go | unhandledCrash | + And the exception "message" matches "^interface conversion: interface.*?is struct {}, not string" + And the "file" of stack frame 0 equals "unhandled_scenario.go" + And the "method" of stack frame 0 equals "UnhandledCrashScenario.func1.1" + And the "file" of stack frame 1 equals "unhandled_scenario.go" + And the "method" of stack frame 1 equals "UnhandledCrashScenario.func1" diff --git a/features/sessioncontext.feature b/features/sessioncontext.feature index 35034a1f..8cc09a14 100644 --- a/features/sessioncontext.feature +++ b/features/sessioncontext.feature @@ -4,7 +4,10 @@ Scenario: An error report contains a session count when part of a session When I start the service "app" And I run "SessionAndErrorScenario" Then I wait to receive 1 error - And I wait to receive 1 session + # one session is created on start + And I wait to receive 2 session And the error is valid for the error reporting API version "4" for the "Bugsnag Go" notifier And the session is valid for the session reporting API version "1.0" for the "Bugsnag Go" notifier + And I discard the oldest session + And the session is valid for the session reporting API version "1.0" for the "Bugsnag Go" notifier And the session payload has a valid sessions array \ No newline at end of file diff --git a/features/steps/go_steps.rb b/features/steps/go_steps.rb index bd9fd916..bed304e3 100644 --- a/features/steps/go_steps.rb +++ b/features/steps/go_steps.rb @@ -39,49 +39,3 @@ def local_ip ip_list.captures.first end end - -# Then(/^the exception is a PathError for request (\d+)$/) do |request_index| -# body = find_request(request_index)[:body] -# error_class = body["events"][0]["exceptions"][0]["errorClass"] -# if ['1.11', '1.12', '1.13', '1.14', '1.15'].include? ENV['GO_VERSION'] -# assert_equal(error_class, '*os.PathError') -# else -# assert_equal(error_class, '*fs.PathError') -# end -# end -# # -# Then(/^the event unhandled sessions count equals (\d+) for request (\d+)$/) do |count, request_index| -# step "the payload field \"events.0.session.events.unhandled\" equals #{count} for request #{request_index}" -# end -# -# Then(/^the event handled sessions count equals (\d+) for request (\d+)$/) do |count, request_index| -# step "the payload field \"events.0.session.events.handled\" equals #{count} for request #{request_index}" -# end -# -# Then(/^the number of sessions started equals (\d+) for request (\d+)$/) do |count, request_index| -# step "the payload field \"sessionCounts.0.sessionsStarted\" equals #{count} for request #{request_index}" -# end -# -# Then("the in-project frames of the stacktrace are:") do |table| -# body = find_request(0)[:body] -# stacktrace = body["events"][0]["exceptions"][0]["stacktrace"] -# found = 0 # counts matching frames and ensures ordering is correct -# expected = table.hashes.length -# stacktrace.each do |frame| -# if found < expected and frame["inProject"] and -# frame["file"] == table.hashes[found]["file"] and -# frame["method"] == table.hashes[found]["method"] -# found = found + 1 -# end -# end -# assert_equal(found, expected, "expected #{expected} matching frames but found #{found}. stacktrace:\n#{stacktrace}") -# end -# -# -# Then("the exception {string} is one of:") do |key, table| -# body = find_request(0)[:body] -# exception = body["events"][0]["exceptions"][0] -# options = table.raw.flatten -# assert(options.include?(exception[key]), "expected '#{key}' to be one of #{options}") -# end -# \ No newline at end of file