-
Notifications
You must be signed in to change notification settings - Fork 130
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(config): Use latest value when checking release stage
A serialization bug in crash reports would erroneously allow or prevent crash reports from being delivered when the value of release stage or notify release stages were changed after start() was called, or in a subsequent build of the same app. Some values in config are serialized as nested values, while others are at the "top" level of config when written to disk. This change checks the expected position and fallback value for every config option. Fixes #405
- Loading branch information
Showing
5 changed files
with
174 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
103 changes: 103 additions & 0 deletions
103
features/fixtures/ios-swift-cocoapods/iOSTestApp/scenarios/ReleaseStageScenarios.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import UIKit | ||
|
||
class MagicError : NSError {} | ||
|
||
class NotifyWhenReleaseStageInNotifyReleaseStages : Scenario { | ||
|
||
override func startBugsnag() { | ||
self.config.shouldAutoCaptureSessions = false; | ||
self.config.releaseStage = "prod" | ||
self.config.notifyReleaseStages = ["dev", "prod"] | ||
super.startBugsnag() | ||
} | ||
|
||
override func run() { | ||
Bugsnag.notifyError(MagicError(domain: "com.example", | ||
code: 43, | ||
userInfo: [NSLocalizedDescriptionKey: "incoming!"])) | ||
} | ||
} | ||
|
||
class CrashWhenReleaseStageInNotifyReleaseStages : Scenario { | ||
|
||
override func startBugsnag() { | ||
self.config.shouldAutoCaptureSessions = false; | ||
self.config.releaseStage = "prod" | ||
self.config.notifyReleaseStages = ["dev", "prod"] | ||
super.startBugsnag() | ||
} | ||
|
||
override func run() { | ||
abort(); | ||
} | ||
} | ||
|
||
class CrashWhenReleaseStageInNotifyReleaseStagesChanges : Scenario { | ||
|
||
override func startBugsnag() { | ||
self.config.shouldAutoCaptureSessions = false; | ||
if (self.eventMode == "noevent") { | ||
// The event is evaluated whether to be sent | ||
self.config.releaseStage = "test" | ||
} else { | ||
// A crash will occur | ||
self.config.releaseStage = "prod" | ||
} | ||
self.config.notifyReleaseStages = ["dev", "prod"] | ||
super.startBugsnag() | ||
} | ||
|
||
override func run() { | ||
abort(); | ||
} | ||
} | ||
|
||
class CrashWhenReleaseStageNotInNotifyReleaseStagesChanges : Scenario { | ||
|
||
override func startBugsnag() { | ||
self.config.shouldAutoCaptureSessions = false; | ||
if (self.eventMode == "noevent") { | ||
// The event is evaluated whether to be sent | ||
self.config.releaseStage = "prod" | ||
} else { | ||
// A crash will occur | ||
self.config.releaseStage = "test" | ||
} | ||
self.config.notifyReleaseStages = ["dev", "prod"] | ||
super.startBugsnag() | ||
} | ||
|
||
override func run() { | ||
abort(); | ||
} | ||
} | ||
|
||
class NotifyWhenReleaseStageNotInNotifyReleaseStages : Scenario { | ||
|
||
override func startBugsnag() { | ||
self.config.shouldAutoCaptureSessions = false; | ||
self.config.releaseStage = "dev" | ||
self.config.notifyReleaseStages = ["prod"] | ||
super.startBugsnag() | ||
} | ||
|
||
override func run() { | ||
Bugsnag.notifyError(MagicError(domain: "com.example", | ||
code: 43, | ||
userInfo: [NSLocalizedDescriptionKey: "incoming!"])) | ||
} | ||
} | ||
|
||
class CrashWhenReleaseStageNotInNotifyReleaseStages : Scenario { | ||
|
||
override func startBugsnag() { | ||
self.config.shouldAutoCaptureSessions = false; | ||
self.config.releaseStage = "dev" | ||
self.config.notifyReleaseStages = ["prod"] | ||
super.startBugsnag() | ||
} | ||
|
||
override func run() { | ||
abort(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
Feature: Discarding reports based on release stage | ||
|
||
Scenario: Crash when release stage is not present in "notify release stages" | ||
When I crash the app using "CrashWhenReleaseStageNotInNotifyReleaseStages" | ||
And I relaunch the app | ||
And I wait for 10 seconds | ||
Then I should receive 0 requests | ||
|
||
Scenario: Crash when release stage is present in "notify release stages" | ||
When I crash the app using "CrashWhenReleaseStageInNotifyReleaseStages" | ||
And I relaunch the app | ||
And I wait for a request | ||
Then the request is valid for the error reporting API | ||
And the exception "errorClass" equals "SIGABRT" | ||
And the event "unhandled" is true | ||
And the event "app.releaseStage" equals "prod" | ||
|
||
Scenario: Crash when release stage is changed to not present in "notify release stages" before the event | ||
If the current run has a different release stage than the crashing context, | ||
the report should only be sent if the release stage was in "notify release stages" | ||
at the time of the crash. Release stages can change for a single build of an app | ||
if the app is used as a test harness or if the build can receive code updates, | ||
such as JavaScript execution contexts. | ||
|
||
When I crash the app using "CrashWhenReleaseStageNotInNotifyReleaseStagesChanges" | ||
And I relaunch the app | ||
And I wait for 10 seconds | ||
Then I should receive 0 requests | ||
|
||
Scenario: Crash when release stage is changed to be present in "notify release stages" before the event | ||
When I crash the app using "CrashWhenReleaseStageInNotifyReleaseStagesChanges" | ||
And I relaunch the app | ||
And I wait for a request | ||
Then the request is valid for the error reporting API | ||
And the exception "errorClass" equals "SIGABRT" | ||
And the event "unhandled" is true | ||
And the event "app.releaseStage" equals "prod" | ||
|
||
Scenario: Notify when release stage is not present in "notify release stages" | ||
When I run "NotifyWhenReleaseStageNotInNotifyReleaseStages" | ||
And I wait for 10 seconds | ||
Then I should receive 0 requests | ||
|
||
Scenario: Notify when release stage is present in "notify release stages" | ||
When I run "NotifyWhenReleaseStageInNotifyReleaseStages" | ||
And I wait for a request | ||
Then the request is valid for the error reporting API | ||
And the exception "errorClass" equals "iOSTestApp.MagicError" | ||
And the exception "message" equals "incoming!" | ||
And the event "unhandled" is false | ||
And the event "app.releaseStage" equals "prod" |