From 1b05bd2f0567f21b8da79e5798883a09e8261202 Mon Sep 17 00:00:00 2001 From: Steve Kirkland-Walton Date: Mon, 22 Nov 2021 10:43:21 +0000 Subject: [PATCH 01/20] Build on ARM --- .buildkite/pipeline.full.yml | 6 ++---- .buildkite/pipeline.yml | 14 ++++++-------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/.buildkite/pipeline.full.yml b/.buildkite/pipeline.full.yml index 93cc26147..de552e127 100644 --- a/.buildkite/pipeline.full.yml +++ b/.buildkite/pipeline.full.yml @@ -199,14 +199,12 @@ steps: --fail-fast --order=random - # TODO: Skip penmding PLAT-6822 - - label: 'ARM macOS 11.0 E2E tests' - skip: Pending PLAT-6822 + - label: 'ARM macOS 12.0 E2E tests' depends_on: - cocoa_fixture timeout_in_minutes: 60 agents: - queue: opensource-m1-mac-cocoa-11 + queue: opensource-arm-mac-cocoa-12 plugins: artifacts#v1.3.0: download: ["features/fixtures/macos/output/macOSTestApp.zip"] diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index ad2556ed8..97ae3efb0 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -17,11 +17,11 @@ steps: # Build # - - label: Build cocoa IPA + - label: Build test fixtures key: cocoa_fixture - timeout_in_minutes: 20 + timeout_in_minutes: 30 agents: - queue: opensource-mac-cocoa-11 + queue: opensource-arm-mac-cocoa-12 artifact_paths: - features/fixtures/ios/output/iOSTestApp.ipa - features/fixtures/macos/output/macOSTestApp.zip @@ -59,7 +59,7 @@ steps: - label: ARM macOS 11 unit tests timeout_in_minutes: 10 agents: - queue: opensource-m1-mac-cocoa-11 + queue: opensource-arm-mac-cocoa-12 commands: - ./scripts/run-unit-tests.sh PLATFORM=macOS artifact_paths: @@ -230,14 +230,12 @@ steps: --fail-fast --order=random - # TODO: Skip pending PLAT-6822 - - label: 'ARM macOS 11 barebones E2E tests' - skip: Pending PLAT-6822 + - label: 'ARM macOS 12 barebones E2E tests' depends_on: - cocoa_fixture timeout_in_minutes: 10 agents: - queue: opensource-m1-mac-cocoa-11 + queue: opensource-arm-mac-cocoa-12 plugins: artifacts#v1.3.0: download: "features/fixtures/macos/output/macOSTestApp.zip" From b08d8f61e8f7e46cb611d7492f9173eec606040a Mon Sep 17 00:00:00 2001 From: Steve Kirkland-Walton Date: Mon, 22 Nov 2021 16:39:21 +0000 Subject: [PATCH 02/20] Build for all architectures --- features/fixtures/macos/Podfile | 6 ++++++ features/scripts/export_mac_app.sh | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/features/fixtures/macos/Podfile b/features/fixtures/macos/Podfile index 9b65ea769..ad92e820c 100644 --- a/features/fixtures/macos/Podfile +++ b/features/fixtures/macos/Podfile @@ -19,5 +19,11 @@ post_install do |installer| end end end + + if target.name == "Bugsnag" || target.name == "BugsnagNetworkRequestPlugin" + target.build_configurations.each do |config| + config.build_settings['ONLY_ACTIVE_ARCH'] = 'NO' + end + end end end diff --git a/features/scripts/export_mac_app.sh b/features/scripts/export_mac_app.sh index 54c696ea1..5e0bfeeea 100755 --- a/features/scripts/export_mac_app.sh +++ b/features/scripts/export_mac_app.sh @@ -16,7 +16,8 @@ xcrun xcodebuild \ -configuration Debug \ -archivePath archive/macOSTestApp.xcarchive \ -quiet \ - archive + archive \ + ONLY_ACTIVE_ARCH=NO echo "--- macOSTestApp: xcodebuild -exportArchive" From 6b5268a8c897126168849780823572eceb0cf5b9 Mon Sep 17 00:00:00 2001 From: Steve Kirkland-Walton Date: Mon, 29 Nov 2021 23:20:42 +0000 Subject: [PATCH 03/20] Corrections to ARM e2e steps [full ci] --- .buildkite/pipeline.full.yml | 10 ++++++---- .buildkite/pipeline.yml | 3 +-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.buildkite/pipeline.full.yml b/.buildkite/pipeline.full.yml index de552e127..9599c8139 100644 --- a/.buildkite/pipeline.full.yml +++ b/.buildkite/pipeline.full.yml @@ -207,17 +207,19 @@ steps: queue: opensource-arm-mac-cocoa-12 plugins: artifacts#v1.3.0: - download: ["features/fixtures/macos/output/macOSTestApp.zip"] - upload: ["macOSTestApp.log", "appium_server.log", "maze_output/failed/**/*"] + download: "features/fixtures/macos/output/macOSTestApp.zip" + upload: + - "macOSTestApp.log" + - "appium_server.log" + - "maze_output/failed/**/*" commands: - bundle config set --local path 'vendor/bundle' - bundle install - bundle exec maze-runner --farm=local --os=macos - --os-version=11 + --os-version=12 --app=macOSTestApp - --fail-fast --order=random - label: 'macOS 10.13 E2E tests' diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 97ae3efb0..bacee04b6 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -250,9 +250,8 @@ steps: features/barebone_tests.feature --farm=local --os=macos - --os-version=11 + --os-version=12 --app=macOSTestApp - --fail-fast --order=random - label: 'macOS 10.15 stress test' From 6767b234643480bb59c4eae0e4363dcea1490884 Mon Sep 17 00:00:00 2001 From: Steve Kirkland-Walton Date: Wed, 1 Dec 2021 00:01:20 +0000 Subject: [PATCH 04/20] Remove any lingering test fixture [full ci] --- features/support/env.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/features/support/env.rb b/features/support/env.rb index 897acb4d9..cdcf395e5 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -24,6 +24,12 @@ `cd #{fixture_dir} && unzip #{zip_name}` end + # Remove test fixture from /Applications if present from an earlier run + if File.exist?("#{app_dir}/#{app_name}") + $logger.warn("Removing existing app from #{app_dir}/#{app_name}") + FileUtils.rm_rf "#{app_dir}/#{app_name}" + end + FileUtils.mv("#{fixture_dir}/#{app_name}", "#{app_dir}/#{app_name}") end end From 31cc58b24e605d348042f80e10054de71674248f Mon Sep 17 00:00:00 2001 From: Steve Kirkland Date: Wed, 1 Dec 2021 16:44:27 +0000 Subject: [PATCH 05/20] Remove unnecessary setting of build configuration. Co-authored-by: Nick Dowell [full ci] --- features/fixtures/macos/Podfile | 6 ------ 1 file changed, 6 deletions(-) diff --git a/features/fixtures/macos/Podfile b/features/fixtures/macos/Podfile index ad92e820c..9b65ea769 100644 --- a/features/fixtures/macos/Podfile +++ b/features/fixtures/macos/Podfile @@ -19,11 +19,5 @@ post_install do |installer| end end end - - if target.name == "Bugsnag" || target.name == "BugsnagNetworkRequestPlugin" - target.build_configurations.each do |config| - config.build_settings['ONLY_ACTIVE_ARCH'] = 'NO' - end - end end end From c0f1c903cf2dc6516c3543c77bd004b4317d4fdf Mon Sep 17 00:00:00 2001 From: Nick Dowell Date: Thu, 2 Dec 2021 11:04:54 +0000 Subject: [PATCH 06/20] Send sessions without requiring disk storage --- Bugsnag/BugsnagSessionTracker.m | 8 +-- .../BugsnagSessionTrackingApiClient.h | 13 ++-- .../BugsnagSessionTrackingApiClient.m | 71 ++++++++++++++----- 3 files changed, 60 insertions(+), 32 deletions(-) diff --git a/Bugsnag/BugsnagSessionTracker.m b/Bugsnag/BugsnagSessionTracker.m index 07389b4fb..947f0f2b1 100644 --- a/Bugsnag/BugsnagSessionTracker.m +++ b/Bugsnag/BugsnagSessionTracker.m @@ -8,7 +8,6 @@ #import "BugsnagSessionTracker.h" -#import "BSGFileLocations.h" #import "BSG_KSSystemInfo.h" #import "BugsnagApp+Private.h" #import "BugsnagClient+Private.h" @@ -17,7 +16,6 @@ #import "BugsnagDevice+Private.h" #import "BugsnagLogger.h" #import "BugsnagSession+Private.h" -#import "BugsnagSessionFileStore.h" #import "BugsnagSessionTrackingApiClient.h" #import "BugsnagSessionTrackingPayload.h" @@ -37,7 +35,6 @@ @interface BugsnagSessionTracker () @property (strong, nonatomic) BugsnagConfiguration *config; @property (weak, nonatomic) BugsnagClient *client; -@property (strong, nonatomic) BugsnagSessionFileStore *sessionStore; @property (strong, nonatomic) BugsnagSessionTrackingApiClient *apiClient; @property (strong, nonatomic) NSDate *backgroundStartTime; @@ -59,8 +56,6 @@ - (instancetype)initWithConfig:(BugsnagConfiguration *)config _client = client; _apiClient = [[BugsnagSessionTrackingApiClient alloc] initWithConfig:config queueName:@"Session API queue" notifier:client.notifier]; _callback = callback; - - _sessionStore = [BugsnagSessionFileStore storeWithPath:[BSGFileLocations current].sessions maxPersistedSessions:config.maxPersistedSessions]; _extraRuntimeInfo = [NSMutableDictionary new]; } return self; @@ -205,14 +200,13 @@ - (void)startNewSessionWithAutoCaptureValue:(BOOL)isAutoCaptured { } self.currentSession = newSession; - [self.sessionStore write:self.currentSession]; if (self.callback) { self.callback(self.currentSession); } [self postUpdateNotice]; - [self.apiClient deliverSessionsInStore:self.sessionStore]; + [self.apiClient deliverSession:newSession]; } - (void)addRuntimeVersionInfo:(NSString *)info diff --git a/Bugsnag/Delivery/BugsnagSessionTrackingApiClient.h b/Bugsnag/Delivery/BugsnagSessionTrackingApiClient.h index 2cb08547b..c9e05918b 100644 --- a/Bugsnag/Delivery/BugsnagSessionTrackingApiClient.h +++ b/Bugsnag/Delivery/BugsnagSessionTrackingApiClient.h @@ -8,21 +8,20 @@ @class BugsnagConfiguration; @class BugsnagNotifier; -@class BugsnagSessionFileStore; +@class BugsnagSession; + +NS_ASSUME_NONNULL_BEGIN @interface BugsnagSessionTrackingApiClient : BugsnagApiClient - (instancetype)initWithConfig:(BugsnagConfiguration *)configuration queueName:(NSString *)queueName notifier:(BugsnagNotifier *)notifier; -/** - * Asynchronously delivers sessions written to the store - * - * @param store The store containing the sessions to deliver - */ -- (void)deliverSessionsInStore:(BugsnagSessionFileStore *)store; +- (void)deliverSession:(BugsnagSession *)session; @property (copy, nonatomic) NSString *codeBundleId; @property (nonatomic) BugsnagNotifier *notifier; @end + +NS_ASSUME_NONNULL_END diff --git a/Bugsnag/Delivery/BugsnagSessionTrackingApiClient.m b/Bugsnag/Delivery/BugsnagSessionTrackingApiClient.m index 684e0f180..3c8f7de11 100644 --- a/Bugsnag/Delivery/BugsnagSessionTrackingApiClient.m +++ b/Bugsnag/Delivery/BugsnagSessionTrackingApiClient.m @@ -5,17 +5,21 @@ #import "BugsnagSessionTrackingApiClient.h" +#import "BSGFileLocations.h" +#import "BSG_RFC3339DateTool.h" +#import "BugsnagCollections.h" #import "BugsnagConfiguration+Private.h" -#import "BugsnagSessionTrackingPayload.h" -#import "BugsnagSessionFileStore.h" #import "BugsnagLogger.h" -#import "BugsnagSession.h" #import "BugsnagSession+Private.h" -#import "BSG_RFC3339DateTool.h" +#import "BugsnagSession.h" +#import "BugsnagSessionFileStore.h" +#import "BugsnagSessionTrackingPayload.h" + @interface BugsnagSessionTrackingApiClient () @property (nonatomic) NSMutableSet *activeIds; @property(nonatomic) BugsnagConfiguration *config; +@property (nonatomic) BugsnagSessionFileStore *fileStore; @end @@ -25,6 +29,7 @@ - (instancetype)initWithConfig:(BugsnagConfiguration *)configuration queueName:( if ((self = [super initWithSession:configuration.session queueName:queueName])) { _activeIds = [NSMutableSet new]; _config = configuration; + _fileStore = [BugsnagSessionFileStore storeWithPath:[BSGFileLocations current].sessions maxPersistedSessions:configuration.maxPersistedSessions]; _notifier = notifier; } return self; @@ -34,15 +39,24 @@ - (NSOperation *)deliveryOperation { return [NSOperation new]; } -- (void)deliverSessionsInStore:(BugsnagSessionFileStore *)store { - NSString *apiKey = [self.config.apiKey copy]; - NSURL *sessionURL = [self.config.sessionURL copy]; - - if (!apiKey) { - bsg_log_err(@"No API key set. Refusing to send sessions."); - return; - } +- (void)deliverSession:(BugsnagSession *)session { + [self sendSession:session completionHandler:^(BugsnagApiClientDeliveryStatus status) { + switch (status) { + case BugsnagApiClientDeliveryStatusDelivered: + [self deliverSessionsInStore:self.fileStore]; + break; + + case BugsnagApiClientDeliveryStatusFailed: + [self.fileStore write:session]; // Retry later + break; + + case BugsnagApiClientDeliveryStatusUndeliverable: + break; + } + }]; +} +- (void)deliverSessionsInStore:(BugsnagSessionFileStore *)store { [[store allFilesByName] enumerateKeysAndObjectsUsingBlock:^(NSString *fileId, NSDictionary *fileContents, __attribute__((unused)) BOOL *stop) { // De-duplicate files as deletion of the file is asynchronous and so multiple calls // to this method will result in multiple send requests @@ -55,6 +69,28 @@ - (void)deliverSessionsInStore:(BugsnagSessionFileStore *)store { BugsnagSession *session = [[BugsnagSession alloc] initWithDictionary:fileContents]; + [self sendSession:session completionHandler:^(BugsnagApiClientDeliveryStatus status) { + if (status != BugsnagApiClientDeliveryStatusFailed) { + [store deleteFileWithId:fileId]; + } + @synchronized (self.activeIds) { + [self.activeIds removeObject:fileId]; + } + }]; + }]; +} + +- (void)sendSession:(BugsnagSession *)session completionHandler:(void (^)(BugsnagApiClientDeliveryStatus status))completionHandler { + NSString *apiKey = [self.config.apiKey copy]; + NSURL *sessionURL = [self.config.sessionURL copy]; + + if (!apiKey) { + bsg_log_err(@"Cannot send session because no apiKey is configured."); + completionHandler(BugsnagApiClientDeliveryStatusUndeliverable); + return; + } + + if (sessionURL) { [self.sendQueue addOperationWithBlock:^{ BugsnagSessionTrackingPayload *payload = [[BugsnagSessionTrackingPayload alloc] initWithSessions:@[session] @@ -72,22 +108,21 @@ - (void)deliverSessionsInStore:(BugsnagSessionFileStore *)store { switch (status) { case BugsnagApiClientDeliveryStatusDelivered: bsg_log_info(@"Sent session %@", session.id); - [store deleteFileWithId:fileId]; break; case BugsnagApiClientDeliveryStatusFailed: bsg_log_warn(@"Failed to send sessions: %@", error); break; case BugsnagApiClientDeliveryStatusUndeliverable: bsg_log_warn(@"Failed to send sessions: %@", error); - [store deleteFileWithId:fileId]; break; } - @synchronized (self.activeIds) { - [self.activeIds removeObject:fileId]; - } + completionHandler(status); }]; }]; - }]; + } else { + bsg_log_err(@"Cannot send session because no endpoint is configured."); + completionHandler(BugsnagApiClientDeliveryStatusUndeliverable); + } } @end From 8fb08120aefde49120eebf4e0be07ea6404de8bf Mon Sep 17 00:00:00 2001 From: Nick Dowell Date: Thu, 2 Dec 2021 11:10:25 +0000 Subject: [PATCH 07/20] Stop subclassing BugsnagApiClient --- Bugsnag/BugsnagSessionTracker.m | 2 +- .../Delivery/BugsnagSessionTrackingApiClient.h | 5 ++--- .../Delivery/BugsnagSessionTrackingApiClient.m | 15 +++++++-------- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/Bugsnag/BugsnagSessionTracker.m b/Bugsnag/BugsnagSessionTracker.m index 947f0f2b1..394879287 100644 --- a/Bugsnag/BugsnagSessionTracker.m +++ b/Bugsnag/BugsnagSessionTracker.m @@ -54,7 +54,7 @@ - (instancetype)initWithConfig:(BugsnagConfiguration *)config if ((self = [super init])) { _config = config; _client = client; - _apiClient = [[BugsnagSessionTrackingApiClient alloc] initWithConfig:config queueName:@"Session API queue" notifier:client.notifier]; + _apiClient = [[BugsnagSessionTrackingApiClient alloc] initWithConfig:config notifier:client.notifier]; _callback = callback; _extraRuntimeInfo = [NSMutableDictionary new]; } diff --git a/Bugsnag/Delivery/BugsnagSessionTrackingApiClient.h b/Bugsnag/Delivery/BugsnagSessionTrackingApiClient.h index c9e05918b..085bd2617 100644 --- a/Bugsnag/Delivery/BugsnagSessionTrackingApiClient.h +++ b/Bugsnag/Delivery/BugsnagSessionTrackingApiClient.h @@ -4,7 +4,6 @@ // #import -#import "BugsnagApiClient.h" @class BugsnagConfiguration; @class BugsnagNotifier; @@ -12,9 +11,9 @@ NS_ASSUME_NONNULL_BEGIN -@interface BugsnagSessionTrackingApiClient : BugsnagApiClient +@interface BugsnagSessionTrackingApiClient : NSObject -- (instancetype)initWithConfig:(BugsnagConfiguration *)configuration queueName:(NSString *)queueName notifier:(BugsnagNotifier *)notifier; +- (instancetype)initWithConfig:(BugsnagConfiguration *)configuration notifier:(BugsnagNotifier *)notifier; - (void)deliverSession:(BugsnagSession *)session; diff --git a/Bugsnag/Delivery/BugsnagSessionTrackingApiClient.m b/Bugsnag/Delivery/BugsnagSessionTrackingApiClient.m index 3c8f7de11..ce31d15e0 100644 --- a/Bugsnag/Delivery/BugsnagSessionTrackingApiClient.m +++ b/Bugsnag/Delivery/BugsnagSessionTrackingApiClient.m @@ -7,6 +7,7 @@ #import "BSGFileLocations.h" #import "BSG_RFC3339DateTool.h" +#import "BugsnagApiClient.h" #import "BugsnagCollections.h" #import "BugsnagConfiguration+Private.h" #import "BugsnagLogger.h" @@ -18,6 +19,7 @@ @interface BugsnagSessionTrackingApiClient () @property (nonatomic) NSMutableSet *activeIds; +@property (nonatomic) BugsnagApiClient *apiClient; @property(nonatomic) BugsnagConfiguration *config; @property (nonatomic) BugsnagSessionFileStore *fileStore; @end @@ -25,9 +27,10 @@ @interface BugsnagSessionTrackingApiClient () @implementation BugsnagSessionTrackingApiClient -- (instancetype)initWithConfig:(BugsnagConfiguration *)configuration queueName:(NSString *)queueName notifier:(BugsnagNotifier *)notifier { - if ((self = [super initWithSession:configuration.session queueName:queueName])) { +- (instancetype)initWithConfig:(BugsnagConfiguration *)configuration notifier:(BugsnagNotifier *)notifier { + if ((self = [super init])) { _activeIds = [NSMutableSet new]; + _apiClient = [[BugsnagApiClient alloc] initWithSession:configuration.session queueName:@"Session API queue"]; _config = configuration; _fileStore = [BugsnagSessionFileStore storeWithPath:[BSGFileLocations current].sessions maxPersistedSessions:configuration.maxPersistedSessions]; _notifier = notifier; @@ -35,10 +38,6 @@ - (instancetype)initWithConfig:(BugsnagConfiguration *)configuration queueName:( return self; } -- (NSOperation *)deliveryOperation { - return [NSOperation new]; -} - - (void)deliverSession:(BugsnagSession *)session { [self sendSession:session completionHandler:^(BugsnagApiClientDeliveryStatus status) { switch (status) { @@ -91,7 +90,7 @@ - (void)sendSession:(BugsnagSession *)session completionHandler:(void (^)(Bugsna } if (sessionURL) { - [self.sendQueue addOperationWithBlock:^{ + [self.apiClient.sendQueue addOperationWithBlock:^{ BugsnagSessionTrackingPayload *payload = [[BugsnagSessionTrackingPayload alloc] initWithSessions:@[session] config:self.config @@ -103,7 +102,7 @@ - (void)sendSession:(BugsnagSession *)session completionHandler:(void (^)(Bugsna BugsnagHTTPHeaderNamePayloadVersion: @"1.0", BugsnagHTTPHeaderNameSentAt: [BSG_RFC3339DateTool stringFromDate:[NSDate date]] }; - [self sendJSONPayload:data headers:HTTPHeaders toURL:sessionURL + [self.apiClient sendJSONPayload:data headers:HTTPHeaders toURL:sessionURL completionHandler:^(BugsnagApiClientDeliveryStatus status, NSError *error) { switch (status) { case BugsnagApiClientDeliveryStatusDelivered: From 592d9368e30dd97b8bedea161298d41dc59b57ca Mon Sep 17 00:00:00 2001 From: Nick Dowell Date: Thu, 2 Dec 2021 11:16:05 +0000 Subject: [PATCH 08/20] Rename to BSGSessionUploader --- Bugsnag.xcodeproj/project.pbxproj | 40 +++++++++---------- Bugsnag/BugsnagSessionTracker.h | 2 +- Bugsnag/BugsnagSessionTracker.m | 10 ++--- Bugsnag/Client/BugsnagClient.m | 1 - ...ackingApiClient.h => BSGSessionUploader.h} | 10 +++-- ...ackingApiClient.m => BSGSessionUploader.m} | 22 +++++----- .../BugsnagTests/BugsnagSessionTrackerTest.m | 1 - 7 files changed, 44 insertions(+), 42 deletions(-) rename Bugsnag/Delivery/{BugsnagSessionTrackingApiClient.h => BSGSessionUploader.h} (66%) rename Bugsnag/Delivery/{BugsnagSessionTrackingApiClient.m => BSGSessionUploader.m} (88%) diff --git a/Bugsnag.xcodeproj/project.pbxproj b/Bugsnag.xcodeproj/project.pbxproj index 7fd1e694a..a0f27c5ff 100644 --- a/Bugsnag.xcodeproj/project.pbxproj +++ b/Bugsnag.xcodeproj/project.pbxproj @@ -207,9 +207,9 @@ 008967E92486DA2D00DC48C2 /* BugsnagErrorTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 008967CF2486DA2D00DC48C2 /* BugsnagErrorTypes.m */; }; 008967EA2486DA2D00DC48C2 /* BugsnagErrorTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 008967CF2486DA2D00DC48C2 /* BugsnagErrorTypes.m */; }; 008967EB2486DA2D00DC48C2 /* BugsnagErrorTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 008967CF2486DA2D00DC48C2 /* BugsnagErrorTypes.m */; }; - 008967F42486DA4500DC48C2 /* BugsnagSessionTrackingApiClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 008967EC2486DA4400DC48C2 /* BugsnagSessionTrackingApiClient.h */; }; - 008967F52486DA4500DC48C2 /* BugsnagSessionTrackingApiClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 008967EC2486DA4400DC48C2 /* BugsnagSessionTrackingApiClient.h */; }; - 008967F62486DA4500DC48C2 /* BugsnagSessionTrackingApiClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 008967EC2486DA4400DC48C2 /* BugsnagSessionTrackingApiClient.h */; }; + 008967F42486DA4500DC48C2 /* BSGSessionUploader.h in Headers */ = {isa = PBXBuildFile; fileRef = 008967EC2486DA4400DC48C2 /* BSGSessionUploader.h */; }; + 008967F52486DA4500DC48C2 /* BSGSessionUploader.h in Headers */ = {isa = PBXBuildFile; fileRef = 008967EC2486DA4400DC48C2 /* BSGSessionUploader.h */; }; + 008967F62486DA4500DC48C2 /* BSGSessionUploader.h in Headers */ = {isa = PBXBuildFile; fileRef = 008967EC2486DA4400DC48C2 /* BSGSessionUploader.h */; }; 008967F72486DA4500DC48C2 /* BugsnagApiClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 008967ED2486DA4400DC48C2 /* BugsnagApiClient.h */; }; 008967F82486DA4500DC48C2 /* BugsnagApiClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 008967ED2486DA4400DC48C2 /* BugsnagApiClient.h */; }; 008967F92486DA4500DC48C2 /* BugsnagApiClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 008967ED2486DA4400DC48C2 /* BugsnagApiClient.h */; }; @@ -217,10 +217,10 @@ 008967FB2486DA4500DC48C2 /* BugsnagApiClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 008967EE2486DA4400DC48C2 /* BugsnagApiClient.m */; }; 008967FC2486DA4500DC48C2 /* BugsnagApiClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 008967EE2486DA4400DC48C2 /* BugsnagApiClient.m */; }; 008967FD2486DA4500DC48C2 /* BugsnagApiClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 008967EE2486DA4400DC48C2 /* BugsnagApiClient.m */; }; - 008967FE2486DA4500DC48C2 /* BugsnagSessionTrackingApiClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 008967EF2486DA4500DC48C2 /* BugsnagSessionTrackingApiClient.m */; }; - 008967FF2486DA4500DC48C2 /* BugsnagSessionTrackingApiClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 008967EF2486DA4500DC48C2 /* BugsnagSessionTrackingApiClient.m */; }; - 008968002486DA4500DC48C2 /* BugsnagSessionTrackingApiClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 008967EF2486DA4500DC48C2 /* BugsnagSessionTrackingApiClient.m */; }; - 008968012486DA4500DC48C2 /* BugsnagSessionTrackingApiClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 008967EF2486DA4500DC48C2 /* BugsnagSessionTrackingApiClient.m */; }; + 008967FE2486DA4500DC48C2 /* BSGSessionUploader.m in Sources */ = {isa = PBXBuildFile; fileRef = 008967EF2486DA4500DC48C2 /* BSGSessionUploader.m */; }; + 008967FF2486DA4500DC48C2 /* BSGSessionUploader.m in Sources */ = {isa = PBXBuildFile; fileRef = 008967EF2486DA4500DC48C2 /* BSGSessionUploader.m */; }; + 008968002486DA4500DC48C2 /* BSGSessionUploader.m in Sources */ = {isa = PBXBuildFile; fileRef = 008967EF2486DA4500DC48C2 /* BSGSessionUploader.m */; }; + 008968012486DA4500DC48C2 /* BSGSessionUploader.m in Sources */ = {isa = PBXBuildFile; fileRef = 008967EF2486DA4500DC48C2 /* BSGSessionUploader.m */; }; 008968022486DA4500DC48C2 /* BSGConnectivity.m in Sources */ = {isa = PBXBuildFile; fileRef = 008967F02486DA4500DC48C2 /* BSGConnectivity.m */; }; 008968032486DA4500DC48C2 /* BSGConnectivity.m in Sources */ = {isa = PBXBuildFile; fileRef = 008967F02486DA4500DC48C2 /* BSGConnectivity.m */; }; 008968042486DA4500DC48C2 /* BSGConnectivity.m in Sources */ = {isa = PBXBuildFile; fileRef = 008967F02486DA4500DC48C2 /* BSGConnectivity.m */; }; @@ -925,7 +925,7 @@ E746294124890D2F00F92D67 /* BSGConfigurationBuilder.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 008967CA2486DA2D00DC48C2 /* BSGConfigurationBuilder.h */; }; E746294524890D2F00F92D67 /* BSGConnectivity.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 008967F22486DA4500DC48C2 /* BSGConnectivity.h */; }; E746294624890D2F00F92D67 /* BugsnagApiClient.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 008967ED2486DA4400DC48C2 /* BugsnagApiClient.h */; }; - E746294824890D2F00F92D67 /* BugsnagSessionTrackingApiClient.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 008967EC2486DA4400DC48C2 /* BugsnagSessionTrackingApiClient.h */; }; + E746294824890D2F00F92D67 /* BSGSessionUploader.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 008967EC2486DA4400DC48C2 /* BSGSessionUploader.h */; }; E746294924890D2F00F92D67 /* BSGSerialization.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 008968112486DA5600DC48C2 /* BSGSerialization.h */; }; E746294A24890D2F00F92D67 /* BugsnagCollections.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 008968102486DA5600DC48C2 /* BugsnagCollections.h */; }; E746294B24890D2F00F92D67 /* BugsnagKeys.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 008968152486DA5600DC48C2 /* BugsnagKeys.h */; }; @@ -1050,7 +1050,7 @@ E746294124890D2F00F92D67 /* BSGConfigurationBuilder.h in CopyFiles */, E746294524890D2F00F92D67 /* BSGConnectivity.h in CopyFiles */, E746294624890D2F00F92D67 /* BugsnagApiClient.h in CopyFiles */, - E746294824890D2F00F92D67 /* BugsnagSessionTrackingApiClient.h in CopyFiles */, + E746294824890D2F00F92D67 /* BSGSessionUploader.h in CopyFiles */, E746294924890D2F00F92D67 /* BSGSerialization.h in CopyFiles */, E746294A24890D2F00F92D67 /* BugsnagCollections.h in CopyFiles */, E746294B24890D2F00F92D67 /* BugsnagKeys.h in CopyFiles */, @@ -1189,10 +1189,10 @@ 008967CB2486DA2D00DC48C2 /* BugsnagConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BugsnagConfiguration.m; sourceTree = ""; }; 008967CC2486DA2D00DC48C2 /* BSGConfigurationBuilder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BSGConfigurationBuilder.m; sourceTree = ""; }; 008967CF2486DA2D00DC48C2 /* BugsnagErrorTypes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BugsnagErrorTypes.m; sourceTree = ""; }; - 008967EC2486DA4400DC48C2 /* BugsnagSessionTrackingApiClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BugsnagSessionTrackingApiClient.h; sourceTree = ""; }; + 008967EC2486DA4400DC48C2 /* BSGSessionUploader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BSGSessionUploader.h; sourceTree = ""; }; 008967ED2486DA4400DC48C2 /* BugsnagApiClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BugsnagApiClient.h; sourceTree = ""; }; 008967EE2486DA4400DC48C2 /* BugsnagApiClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BugsnagApiClient.m; sourceTree = ""; }; - 008967EF2486DA4500DC48C2 /* BugsnagSessionTrackingApiClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BugsnagSessionTrackingApiClient.m; sourceTree = ""; }; + 008967EF2486DA4500DC48C2 /* BSGSessionUploader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BSGSessionUploader.m; sourceTree = ""; }; 008967F02486DA4500DC48C2 /* BSGConnectivity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BSGConnectivity.m; sourceTree = ""; }; 008967F22486DA4500DC48C2 /* BSGConnectivity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BSGConnectivity.h; sourceTree = ""; }; 008968102486DA5600DC48C2 /* BugsnagCollections.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BugsnagCollections.h; sourceTree = ""; }; @@ -1868,10 +1868,10 @@ 0126F79A25DD510E008483C2 /* BSGEventUploadObjectOperation.m */, 0126F78925DD508C008483C2 /* BSGEventUploadOperation.h */, 0126F78A25DD508C008483C2 /* BSGEventUploadOperation.m */, + 008967EC2486DA4400DC48C2 /* BSGSessionUploader.h */, + 008967EF2486DA4500DC48C2 /* BSGSessionUploader.m */, 008967ED2486DA4400DC48C2 /* BugsnagApiClient.h */, 008967EE2486DA4400DC48C2 /* BugsnagApiClient.m */, - 008967EC2486DA4400DC48C2 /* BugsnagSessionTrackingApiClient.h */, - 008967EF2486DA4500DC48C2 /* BugsnagSessionTrackingApiClient.m */, ); path = Delivery; sourceTree = ""; @@ -2134,7 +2134,7 @@ 0089681E2486DA5600DC48C2 /* BugsnagPlatformConditional.h in Headers */, 008969602486DAD000DC48C2 /* BSG_KSSysCtl.h in Headers */, 010FF28425ED2A8D00E4F2B0 /* BSGAppHangDetector.h in Headers */, - 008967F42486DA4500DC48C2 /* BugsnagSessionTrackingApiClient.h in Headers */, + 008967F42486DA4500DC48C2 /* BSGSessionUploader.h in Headers */, 0126DF1B257A92860031A70C /* BugsnagSession+Private.h in Headers */, 008969E12486DAD100DC48C2 /* BSG_KSSystemInfo.h in Headers */, 00896A0E2486DAD100DC48C2 /* BSG_KSCrashSentry.h in Headers */, @@ -2238,7 +2238,7 @@ 0089688C2486DA9600DC48C2 /* BugsnagStacktrace.h in Headers */, 0089681F2486DA5600DC48C2 /* BugsnagPlatformConditional.h in Headers */, 008969612486DAD000DC48C2 /* BSG_KSSysCtl.h in Headers */, - 008967F52486DA4500DC48C2 /* BugsnagSessionTrackingApiClient.h in Headers */, + 008967F52486DA4500DC48C2 /* BSGSessionUploader.h in Headers */, 010FF28525ED2A8D00E4F2B0 /* BSGAppHangDetector.h in Headers */, 008969E22486DAD100DC48C2 /* BSG_KSSystemInfo.h in Headers */, 0126DF1C257A92860031A70C /* BugsnagSession+Private.h in Headers */, @@ -2343,7 +2343,7 @@ 0089688D2486DA9600DC48C2 /* BugsnagStacktrace.h in Headers */, 008968202486DA5600DC48C2 /* BugsnagPlatformConditional.h in Headers */, 008969622486DAD000DC48C2 /* BSG_KSSysCtl.h in Headers */, - 008967F62486DA4500DC48C2 /* BugsnagSessionTrackingApiClient.h in Headers */, + 008967F62486DA4500DC48C2 /* BSGSessionUploader.h in Headers */, 010FF28625ED2A8D00E4F2B0 /* BSGAppHangDetector.h in Headers */, 008969E32486DAD100DC48C2 /* BSG_KSSystemInfo.h in Headers */, 0126DF1D257A92860031A70C /* BugsnagSession+Private.h in Headers */, @@ -2711,7 +2711,7 @@ 008967BE2486DA1900DC48C2 /* BugsnagClient.m in Sources */, 008968952486DA9600DC48C2 /* BugsnagHandledState.m in Sources */, 008969C32486DAD100DC48C2 /* BSG_KSObjC.c in Sources */, - 008967FE2486DA4500DC48C2 /* BugsnagSessionTrackingApiClient.m in Sources */, + 008967FE2486DA4500DC48C2 /* BSGSessionUploader.m in Sources */, 0089686B2486DA9500DC48C2 /* BugsnagEvent.m in Sources */, 008969A82486DAD100DC48C2 /* BSG_KSSysCtl.c in Sources */, 008969692486DAD000DC48C2 /* BSG_KSMach_Arm.c in Sources */, @@ -2885,7 +2885,7 @@ 008967BF2486DA1900DC48C2 /* BugsnagClient.m in Sources */, 008968962486DA9600DC48C2 /* BugsnagHandledState.m in Sources */, 008969C42486DAD100DC48C2 /* BSG_KSObjC.c in Sources */, - 008967FF2486DA4500DC48C2 /* BugsnagSessionTrackingApiClient.m in Sources */, + 008967FF2486DA4500DC48C2 /* BSGSessionUploader.m in Sources */, 0089686C2486DA9500DC48C2 /* BugsnagEvent.m in Sources */, 008969A92486DAD100DC48C2 /* BSG_KSSysCtl.c in Sources */, 0089696A2486DAD000DC48C2 /* BSG_KSMach_Arm.c in Sources */, @@ -3055,7 +3055,7 @@ 008967C02486DA1900DC48C2 /* BugsnagClient.m in Sources */, 008968972486DA9600DC48C2 /* BugsnagHandledState.m in Sources */, 008969C52486DAD100DC48C2 /* BSG_KSObjC.c in Sources */, - 008968002486DA4500DC48C2 /* BugsnagSessionTrackingApiClient.m in Sources */, + 008968002486DA4500DC48C2 /* BSGSessionUploader.m in Sources */, 0089686D2486DA9500DC48C2 /* BugsnagEvent.m in Sources */, 008969AA2486DAD100DC48C2 /* BSG_KSSysCtl.c in Sources */, 0089696B2486DAD000DC48C2 /* BSG_KSMach_Arm.c in Sources */, @@ -3224,7 +3224,7 @@ 010FF28A25ED2A8D00E4F2B0 /* BSGAppHangDetector.m in Sources */, 00E636C224878D84006CBF1A /* BSG_RFC3339DateTool.m in Sources */, 0089687F2486DA9600DC48C2 /* BugsnagBreadcrumb.m in Sources */, - 008968012486DA4500DC48C2 /* BugsnagSessionTrackingApiClient.m in Sources */, + 008968012486DA4500DC48C2 /* BSGSessionUploader.m in Sources */, 008968322486DA5600DC48C2 /* BugsnagCollections.m in Sources */, 01468F5825876DC1002B0519 /* BSGNotificationBreadcrumbs.m in Sources */, 008968832486DA9600DC48C2 /* BugsnagAppWithState.m in Sources */, diff --git a/Bugsnag/BugsnagSessionTracker.h b/Bugsnag/BugsnagSessionTracker.h index 1ca1dba35..fcc406c4b 100644 --- a/Bugsnag/BugsnagSessionTracker.h +++ b/Bugsnag/BugsnagSessionTracker.h @@ -13,7 +13,7 @@ NS_ASSUME_NONNULL_BEGIN -@class BugsnagSessionTrackingApiClient; +@class BSGSessionUploader; typedef void (^SessionTrackerCallback)(BugsnagSession *_Nullable newSession); diff --git a/Bugsnag/BugsnagSessionTracker.m b/Bugsnag/BugsnagSessionTracker.m index 394879287..6f77be901 100644 --- a/Bugsnag/BugsnagSessionTracker.m +++ b/Bugsnag/BugsnagSessionTracker.m @@ -8,6 +8,7 @@ #import "BugsnagSessionTracker.h" +#import "BSGSessionUploader.h" #import "BSG_KSSystemInfo.h" #import "BugsnagApp+Private.h" #import "BugsnagClient+Private.h" @@ -16,7 +17,6 @@ #import "BugsnagDevice+Private.h" #import "BugsnagLogger.h" #import "BugsnagSession+Private.h" -#import "BugsnagSessionTrackingApiClient.h" #import "BugsnagSessionTrackingPayload.h" #if TARGET_OS_IOS || TARGET_OS_TV @@ -35,7 +35,7 @@ @interface BugsnagSessionTracker () @property (strong, nonatomic) BugsnagConfiguration *config; @property (weak, nonatomic) BugsnagClient *client; -@property (strong, nonatomic) BugsnagSessionTrackingApiClient *apiClient; +@property (strong, nonatomic) BSGSessionUploader *sessionUploader; @property (strong, nonatomic) NSDate *backgroundStartTime; /** @@ -54,7 +54,7 @@ - (instancetype)initWithConfig:(BugsnagConfiguration *)config if ((self = [super init])) { _config = config; _client = client; - _apiClient = [[BugsnagSessionTrackingApiClient alloc] initWithConfig:config notifier:client.notifier]; + _sessionUploader = [[BSGSessionUploader alloc] initWithConfig:config notifier:client.notifier]; _callback = callback; _extraRuntimeInfo = [NSMutableDictionary new]; } @@ -115,7 +115,7 @@ - (void)startWithNotificationCenter:(NSNotificationCenter *)notificationCenter i - (void)setCodeBundleId:(NSString *)codeBundleId { _codeBundleId = codeBundleId; - self.apiClient.codeBundleId = codeBundleId; + self.sessionUploader.codeBundleId = codeBundleId; } #pragma mark - Creating and sending a new session @@ -206,7 +206,7 @@ - (void)startNewSessionWithAutoCaptureValue:(BOOL)isAutoCaptured { } [self postUpdateNotice]; - [self.apiClient deliverSession:newSession]; + [self.sessionUploader uploadSession:newSession]; } - (void)addRuntimeVersionInfo:(NSString *)info diff --git a/Bugsnag/Client/BugsnagClient.m b/Bugsnag/Client/BugsnagClient.m index f336db1c9..6f7ac19f5 100644 --- a/Bugsnag/Client/BugsnagClient.m +++ b/Bugsnag/Client/BugsnagClient.m @@ -66,7 +66,6 @@ #import "BugsnagPluginClient.h" #import "BugsnagSession+Private.h" #import "BugsnagSessionTracker.h" -#import "BugsnagSessionTrackingApiClient.h" #import "BugsnagStackframe+Private.h" #import "BugsnagStateEvent.h" #import "BugsnagSystemState.h" diff --git a/Bugsnag/Delivery/BugsnagSessionTrackingApiClient.h b/Bugsnag/Delivery/BSGSessionUploader.h similarity index 66% rename from Bugsnag/Delivery/BugsnagSessionTrackingApiClient.h rename to Bugsnag/Delivery/BSGSessionUploader.h index 085bd2617..e7e21da52 100644 --- a/Bugsnag/Delivery/BugsnagSessionTrackingApiClient.h +++ b/Bugsnag/Delivery/BSGSessionUploader.h @@ -1,6 +1,8 @@ // -// Created by Jamie Lynch on 30/11/2017. -// Copyright (c) 2017 Bugsnag. All rights reserved. +// BSGSessionUploader.h +// Bugsnag +// +// Copyright © 2021 Bugsnag Inc. All rights reserved. // #import @@ -11,11 +13,11 @@ NS_ASSUME_NONNULL_BEGIN -@interface BugsnagSessionTrackingApiClient : NSObject +@interface BSGSessionUploader : NSObject - (instancetype)initWithConfig:(BugsnagConfiguration *)configuration notifier:(BugsnagNotifier *)notifier; -- (void)deliverSession:(BugsnagSession *)session; +- (void)uploadSession:(BugsnagSession *)session; @property (copy, nonatomic) NSString *codeBundleId; diff --git a/Bugsnag/Delivery/BugsnagSessionTrackingApiClient.m b/Bugsnag/Delivery/BSGSessionUploader.m similarity index 88% rename from Bugsnag/Delivery/BugsnagSessionTrackingApiClient.m rename to Bugsnag/Delivery/BSGSessionUploader.m index ce31d15e0..4418c3d04 100644 --- a/Bugsnag/Delivery/BugsnagSessionTrackingApiClient.m +++ b/Bugsnag/Delivery/BSGSessionUploader.m @@ -1,9 +1,11 @@ // -// Created by Jamie Lynch on 30/11/2017. -// Copyright (c) 2017 Bugsnag. All rights reserved. +// BSGSessionUploader.m +// Bugsnag +// +// Copyright © 2021 Bugsnag Inc. All rights reserved. // -#import "BugsnagSessionTrackingApiClient.h" +#import "BSGSessionUploader.h" #import "BSGFileLocations.h" #import "BSG_RFC3339DateTool.h" @@ -17,7 +19,7 @@ #import "BugsnagSessionTrackingPayload.h" -@interface BugsnagSessionTrackingApiClient () +@interface BSGSessionUploader () @property (nonatomic) NSMutableSet *activeIds; @property (nonatomic) BugsnagApiClient *apiClient; @property(nonatomic) BugsnagConfiguration *config; @@ -25,7 +27,7 @@ @interface BugsnagSessionTrackingApiClient () @end -@implementation BugsnagSessionTrackingApiClient +@implementation BSGSessionUploader - (instancetype)initWithConfig:(BugsnagConfiguration *)configuration notifier:(BugsnagNotifier *)notifier { if ((self = [super init])) { @@ -38,11 +40,11 @@ - (instancetype)initWithConfig:(BugsnagConfiguration *)configuration notifier:(B return self; } -- (void)deliverSession:(BugsnagSession *)session { +- (void)uploadSession:(BugsnagSession *)session { [self sendSession:session completionHandler:^(BugsnagApiClientDeliveryStatus status) { switch (status) { case BugsnagApiClientDeliveryStatusDelivered: - [self deliverSessionsInStore:self.fileStore]; + [self uploadStoredSessions]; break; case BugsnagApiClientDeliveryStatusFailed: @@ -55,8 +57,8 @@ - (void)deliverSession:(BugsnagSession *)session { }]; } -- (void)deliverSessionsInStore:(BugsnagSessionFileStore *)store { - [[store allFilesByName] enumerateKeysAndObjectsUsingBlock:^(NSString *fileId, NSDictionary *fileContents, __attribute__((unused)) BOOL *stop) { +- (void)uploadStoredSessions { + [[self.fileStore allFilesByName] enumerateKeysAndObjectsUsingBlock:^(NSString *fileId, NSDictionary *fileContents, __unused BOOL *stop) { // De-duplicate files as deletion of the file is asynchronous and so multiple calls // to this method will result in multiple send requests @synchronized (self.activeIds) { @@ -70,7 +72,7 @@ - (void)deliverSessionsInStore:(BugsnagSessionFileStore *)store { [self sendSession:session completionHandler:^(BugsnagApiClientDeliveryStatus status) { if (status != BugsnagApiClientDeliveryStatusFailed) { - [store deleteFileWithId:fileId]; + [self.fileStore deleteFileWithId:fileId]; } @synchronized (self.activeIds) { [self.activeIds removeObject:fileId]; diff --git a/Tests/BugsnagTests/BugsnagSessionTrackerTest.m b/Tests/BugsnagTests/BugsnagSessionTrackerTest.m index 597666976..2a8689c67 100644 --- a/Tests/BugsnagTests/BugsnagSessionTrackerTest.m +++ b/Tests/BugsnagTests/BugsnagSessionTrackerTest.m @@ -12,7 +12,6 @@ #import "BugsnagConfiguration+Private.h" #import "BugsnagSession+Private.h" #import "BugsnagSessionTracker.h" -#import "BugsnagSessionTrackingApiClient.h" #import "BugsnagTestConstants.h" @interface BugsnagSessionTrackerTest : XCTestCase From 58948b78cae85388e7910179f53edd735bf63f76 Mon Sep 17 00:00:00 2001 From: Nick Dowell Date: Thu, 2 Dec 2021 11:27:31 +0000 Subject: [PATCH 09/20] Remove unused logic from BugsnagApiClient --- Bugsnag/Delivery/BSGEventUploader.m | 2 +- Bugsnag/Delivery/BSGSessionUploader.m | 64 +++++++++++++-------------- Bugsnag/Delivery/BugsnagApiClient.h | 11 +---- Bugsnag/Delivery/BugsnagApiClient.m | 25 +---------- 4 files changed, 34 insertions(+), 68 deletions(-) diff --git a/Bugsnag/Delivery/BSGEventUploader.m b/Bugsnag/Delivery/BSGEventUploader.m index 6639cbe6d..095ee2a3d 100644 --- a/Bugsnag/Delivery/BSGEventUploader.m +++ b/Bugsnag/Delivery/BSGEventUploader.m @@ -41,7 +41,7 @@ @implementation BSGEventUploader - (instancetype)initWithConfiguration:(BugsnagConfiguration *)configuration notifier:(BugsnagNotifier *)notifier { if ((self = [super init])) { - _apiClient = [[BugsnagApiClient alloc] initWithSession:configuration.session queueName:@""]; + _apiClient = [[BugsnagApiClient alloc] initWithSession:configuration.session]; _configuration = configuration; _eventsDirectory = [BSGFileLocations current].events; _kscrashReportsDirectory = [BSGFileLocations current].kscrashReports; diff --git a/Bugsnag/Delivery/BSGSessionUploader.m b/Bugsnag/Delivery/BSGSessionUploader.m index 4418c3d04..57834a0e5 100644 --- a/Bugsnag/Delivery/BSGSessionUploader.m +++ b/Bugsnag/Delivery/BSGSessionUploader.m @@ -32,7 +32,7 @@ @implementation BSGSessionUploader - (instancetype)initWithConfig:(BugsnagConfiguration *)configuration notifier:(BugsnagNotifier *)notifier { if ((self = [super init])) { _activeIds = [NSMutableSet new]; - _apiClient = [[BugsnagApiClient alloc] initWithSession:configuration.session queueName:@"Session API queue"]; + _apiClient = [[BugsnagApiClient alloc] initWithSession:configuration.session]; _config = configuration; _fileStore = [BugsnagSessionFileStore storeWithPath:[BSGFileLocations current].sessions maxPersistedSessions:configuration.maxPersistedSessions]; _notifier = notifier; @@ -83,47 +83,45 @@ - (void)uploadStoredSessions { - (void)sendSession:(BugsnagSession *)session completionHandler:(void (^)(BugsnagApiClientDeliveryStatus status))completionHandler { NSString *apiKey = [self.config.apiKey copy]; - NSURL *sessionURL = [self.config.sessionURL copy]; - if (!apiKey) { bsg_log_err(@"Cannot send session because no apiKey is configured."); completionHandler(BugsnagApiClientDeliveryStatusUndeliverable); return; } - if (sessionURL) { - [self.apiClient.sendQueue addOperationWithBlock:^{ - BugsnagSessionTrackingPayload *payload = [[BugsnagSessionTrackingPayload alloc] - initWithSessions:@[session] - config:self.config - codeBundleId:self.codeBundleId - notifier:self.notifier]; - NSMutableDictionary *data = [payload toJson]; - NSDictionary *HTTPHeaders = @{ - BugsnagHTTPHeaderNameApiKey: apiKey ?: @"", - BugsnagHTTPHeaderNamePayloadVersion: @"1.0", - BugsnagHTTPHeaderNameSentAt: [BSG_RFC3339DateTool stringFromDate:[NSDate date]] - }; - [self.apiClient sendJSONPayload:data headers:HTTPHeaders toURL:sessionURL - completionHandler:^(BugsnagApiClientDeliveryStatus status, NSError *error) { - switch (status) { - case BugsnagApiClientDeliveryStatusDelivered: - bsg_log_info(@"Sent session %@", session.id); - break; - case BugsnagApiClientDeliveryStatusFailed: - bsg_log_warn(@"Failed to send sessions: %@", error); - break; - case BugsnagApiClientDeliveryStatusUndeliverable: - bsg_log_warn(@"Failed to send sessions: %@", error); - break; - } - completionHandler(status); - }]; - }]; - } else { + NSURL *sessionURL = self.config.sessionURL; + if (!sessionURL) { bsg_log_err(@"Cannot send session because no endpoint is configured."); completionHandler(BugsnagApiClientDeliveryStatusUndeliverable); + return; } + + NSDictionary *JSONPayload = + [[[BugsnagSessionTrackingPayload alloc] initWithSessions:@[session] + config:self.config + codeBundleId:self.codeBundleId + notifier:self.notifier] toJson]; + + NSDictionary *HTTPHeaders = @{ + BugsnagHTTPHeaderNameApiKey: apiKey, + BugsnagHTTPHeaderNamePayloadVersion: @"1.0", + BugsnagHTTPHeaderNameSentAt: [BSG_RFC3339DateTool stringFromDate:[NSDate date]] ?: [NSNull null] + }; + + [self.apiClient sendJSONPayload:JSONPayload headers:HTTPHeaders toURL:sessionURL completionHandler:^(BugsnagApiClientDeliveryStatus status, NSError *error) { + switch (status) { + case BugsnagApiClientDeliveryStatusDelivered: + bsg_log_info(@"Sent session %@", session.id); + break; + case BugsnagApiClientDeliveryStatusFailed: + bsg_log_warn(@"Failed to send sessions: %@", error); + break; + case BugsnagApiClientDeliveryStatusUndeliverable: + bsg_log_warn(@"Failed to send sessions: %@", error); + break; + } + completionHandler(status); + }]; } @end diff --git a/Bugsnag/Delivery/BugsnagApiClient.h b/Bugsnag/Delivery/BugsnagApiClient.h index 05016f72f..abdf94cc2 100644 --- a/Bugsnag/Delivery/BugsnagApiClient.h +++ b/Bugsnag/Delivery/BugsnagApiClient.h @@ -26,14 +26,7 @@ typedef NS_ENUM(NSInteger, BugsnagApiClientDeliveryStatus) { @interface BugsnagApiClient : NSObject -- (instancetype)initWithSession:(nullable NSURLSession *)session queueName:(NSString *)queueName; - -/** - * Send outstanding reports - */ -- (void)flushPendingData; - -- (NSOperation *)deliveryOperation; +- (instancetype)initWithSession:(nullable NSURLSession *)session; - (void)sendJSONPayload:(NSDictionary *)payload headers:(NSDictionary *)headers @@ -42,8 +35,6 @@ typedef NS_ENUM(NSInteger, BugsnagApiClientDeliveryStatus) { + (NSString *)SHA1HashStringWithData:(NSData *)data; -@property (readonly, nonatomic) NSOperationQueue *sendQueue; - @end NS_ASSUME_NONNULL_END diff --git a/Bugsnag/Delivery/BugsnagApiClient.m b/Bugsnag/Delivery/BugsnagApiClient.m index 3a17ec2d4..770a63e02 100644 --- a/Bugsnag/Delivery/BugsnagApiClient.m +++ b/Bugsnag/Delivery/BugsnagApiClient.m @@ -42,32 +42,13 @@ @interface BugsnagApiClient() @implementation BugsnagApiClient -- (instancetype)initWithSession:(nullable NSURLSession *)session queueName:(NSString *)queueName { +- (instancetype)initWithSession:(nullable NSURLSession *)session { if ((self = [super init])) { - _sendQueue = [NSOperationQueue new]; - _sendQueue.maxConcurrentOperationCount = 1; - if ([_sendQueue respondsToSelector:@selector(qualityOfService)]) { - _sendQueue.qualityOfService = NSQualityOfServiceUtility; - } - _sendQueue.name = queueName; _session = session ?: [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration]]; } return self; } -- (void)flushPendingData { - [self.sendQueue cancelAllOperations]; - NSOperation *delay = [NSBlockOperation blockOperationWithBlock:^{ [NSThread sleepForTimeInterval:1]; }]; - NSOperation *deliver = [self deliveryOperation]; - [deliver addDependency:delay]; - [self.sendQueue addOperations:@[delay, deliver] waitUntilFinished:NO]; -} - -- (NSOperation *)deliveryOperation { - bsg_log_err(@"Should override deliveryOperation in subclass"); - return [NSOperation new]; -} - #pragma mark - Delivery - (void)sendJSONPayload:(NSDictionary *)payload @@ -163,8 +144,4 @@ + (NSString *)SHA1HashStringWithData:(NSData *)data { md[15], md[16], md[17], md[18], md[19]]; } -- (void)dealloc { - [self.sendQueue cancelAllOperations]; -} - @end From fd9997e8ec1bdd2a31a37ff827174a973919058b Mon Sep 17 00:00:00 2001 From: Karl Stenerud Date: Thu, 2 Dec 2021 14:20:12 +0100 Subject: [PATCH 10/20] Bugsnag.startWithApiKey should use the loaded config, not a fresh config. --- Bugsnag/Bugsnag.m | 3 ++- features/app_and_device_attributes.feature | 8 ++++++++ .../AppAndDeviceAttributesScenario.swift | 19 +++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/Bugsnag/Bugsnag.m b/Bugsnag/Bugsnag.m index 748726267..9f4eb5afd 100644 --- a/Bugsnag/Bugsnag.m +++ b/Bugsnag/Bugsnag.m @@ -49,7 +49,8 @@ + (BugsnagClient *_Nonnull)start { } + (BugsnagClient *_Nonnull)startWithApiKey:(NSString *_Nonnull)apiKey { - BugsnagConfiguration *configuration = [[BugsnagConfiguration alloc] initWithApiKey:apiKey]; + BugsnagConfiguration *configuration = [BugsnagConfiguration loadConfig]; + configuration.apiKey = apiKey; return [self startWithConfiguration:configuration]; } diff --git a/features/app_and_device_attributes.feature b/features/app_and_device_attributes.feature index ed266a1af..6f340b37f 100644 --- a/features/app_and_device_attributes.feature +++ b/features/app_and_device_attributes.feature @@ -92,6 +92,14 @@ Feature: App and Device attributes present And the error payload field "events.0.device.manufacturer" equals "Nokia" And the error payload field "events.0.device.modelNumber" equals "0898" + Scenario: Info.plist settings are used when calling startWithApiKey + When I run "AppAndDeviceAttributesScenarioStartWithApiKey" + And I wait to receive an error + Then the error is valid for the error reporting API + And the error "Bugsnag-API-Key" header equals "12312312312312312312312312312312" + + And the error payload field "events.0.app.releaseStage" equals "beta2" + Scenario: Duration value increments as expected When I run "AppDurationScenario" And I wait to receive 3 errors diff --git a/features/fixtures/shared/scenarios/AppAndDeviceAttributesScenario.swift b/features/fixtures/shared/scenarios/AppAndDeviceAttributesScenario.swift index 724b2144f..b914b5e8b 100644 --- a/features/fixtures/shared/scenarios/AppAndDeviceAttributesScenario.swift +++ b/features/fixtures/shared/scenarios/AppAndDeviceAttributesScenario.swift @@ -78,6 +78,25 @@ class AppAndDeviceAttributesScenarioCallbackOverride: Scenario { // MARK: - +/** + * Call startWithApiKey + */ +class AppAndDeviceAttributesScenarioStartWithApiKey: Scenario { + + override func startBugsnag() { + Bugsnag.start(withApiKey: "12312312312312312312312312312312") + + super.startBugsnag() + } + + override func run() { + let error = NSError(domain: "AppAndDeviceAttributesScenarioStartWithApiKey", code: 100, userInfo: nil) + Bugsnag.notifyError(error) + } +} + +// MARK: - + class AppAndDeviceAttributesInfiniteLaunchDurationScenario: Scenario { override func startBugsnag() { From 9ead29ca6429aec4b84e2df3f55abf73ca8290c9 Mon Sep 17 00:00:00 2001 From: Nick Dowell Date: Thu, 2 Dec 2021 11:39:11 +0000 Subject: [PATCH 11/20] Remove BugsnagSessionTrackingPayload --- Bugsnag.xcodeproj/project.pbxproj | 28 ---- Bugsnag/BugsnagSessionTracker.m | 1 - Bugsnag/Delivery/BSGSessionUploader.m | 18 ++- Bugsnag/Helpers/BugsnagKeys.h | 1 + Bugsnag/Helpers/BugsnagKeys.m | 1 + .../Payload/BugsnagSessionTrackingPayload.h | 27 ---- .../Payload/BugsnagSessionTrackingPayload.m | 66 -------- Tests/BugsnagTests/BugsnagApiClientTest.m | 6 +- .../BugsnagSessionTrackingPayloadTest.m | 150 ------------------ 9 files changed, 16 insertions(+), 282 deletions(-) delete mode 100644 Bugsnag/Payload/BugsnagSessionTrackingPayload.h delete mode 100644 Bugsnag/Payload/BugsnagSessionTrackingPayload.m delete mode 100644 Tests/BugsnagTests/BugsnagSessionTrackingPayloadTest.m diff --git a/Bugsnag.xcodeproj/project.pbxproj b/Bugsnag.xcodeproj/project.pbxproj index a0f27c5ff..7b32efc16 100644 --- a/Bugsnag.xcodeproj/project.pbxproj +++ b/Bugsnag.xcodeproj/project.pbxproj @@ -105,9 +105,6 @@ 0089675A2486D43700DC48C2 /* BugsnagEnabledBreadcrumbTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 008966CB2486D43600DC48C2 /* BugsnagEnabledBreadcrumbTest.m */; }; 0089675B2486D43700DC48C2 /* BugsnagEnabledBreadcrumbTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 008966CB2486D43600DC48C2 /* BugsnagEnabledBreadcrumbTest.m */; }; 0089675C2486D43700DC48C2 /* BugsnagEnabledBreadcrumbTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 008966CB2486D43600DC48C2 /* BugsnagEnabledBreadcrumbTest.m */; }; - 0089675D2486D43700DC48C2 /* BugsnagSessionTrackingPayloadTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 008966CC2486D43600DC48C2 /* BugsnagSessionTrackingPayloadTest.m */; }; - 0089675E2486D43700DC48C2 /* BugsnagSessionTrackingPayloadTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 008966CC2486D43600DC48C2 /* BugsnagSessionTrackingPayloadTest.m */; }; - 0089675F2486D43700DC48C2 /* BugsnagSessionTrackingPayloadTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 008966CC2486D43600DC48C2 /* BugsnagSessionTrackingPayloadTest.m */; }; 008967602486D43700DC48C2 /* BugsnagBreadcrumbsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 008966CD2486D43600DC48C2 /* BugsnagBreadcrumbsTest.m */; }; 008967612486D43700DC48C2 /* BugsnagBreadcrumbsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 008966CD2486D43600DC48C2 /* BugsnagBreadcrumbsTest.m */; }; 008967622486D43700DC48C2 /* BugsnagBreadcrumbsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 008966CD2486D43600DC48C2 /* BugsnagBreadcrumbsTest.m */; }; @@ -297,16 +294,9 @@ 0089689A2486DA9600DC48C2 /* BugsnagStackframe.m in Sources */ = {isa = PBXBuildFile; fileRef = 008968532486DA9400DC48C2 /* BugsnagStackframe.m */; }; 0089689B2486DA9600DC48C2 /* BugsnagStackframe.m in Sources */ = {isa = PBXBuildFile; fileRef = 008968532486DA9400DC48C2 /* BugsnagStackframe.m */; }; 0089689C2486DA9600DC48C2 /* BugsnagStackframe.m in Sources */ = {isa = PBXBuildFile; fileRef = 008968532486DA9400DC48C2 /* BugsnagStackframe.m */; }; - 0089689D2486DA9600DC48C2 /* BugsnagSessionTrackingPayload.m in Sources */ = {isa = PBXBuildFile; fileRef = 008968542486DA9400DC48C2 /* BugsnagSessionTrackingPayload.m */; }; - 0089689E2486DA9600DC48C2 /* BugsnagSessionTrackingPayload.m in Sources */ = {isa = PBXBuildFile; fileRef = 008968542486DA9400DC48C2 /* BugsnagSessionTrackingPayload.m */; }; - 0089689F2486DA9600DC48C2 /* BugsnagSessionTrackingPayload.m in Sources */ = {isa = PBXBuildFile; fileRef = 008968542486DA9400DC48C2 /* BugsnagSessionTrackingPayload.m */; }; - 008968A02486DA9600DC48C2 /* BugsnagSessionTrackingPayload.m in Sources */ = {isa = PBXBuildFile; fileRef = 008968542486DA9400DC48C2 /* BugsnagSessionTrackingPayload.m */; }; 008968A12486DA9600DC48C2 /* BugsnagStateEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 008968552486DA9400DC48C2 /* BugsnagStateEvent.h */; }; 008968A22486DA9600DC48C2 /* BugsnagStateEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 008968552486DA9400DC48C2 /* BugsnagStateEvent.h */; }; 008968A32486DA9600DC48C2 /* BugsnagStateEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 008968552486DA9400DC48C2 /* BugsnagStateEvent.h */; }; - 008968A42486DA9600DC48C2 /* BugsnagSessionTrackingPayload.h in Headers */ = {isa = PBXBuildFile; fileRef = 008968562486DA9400DC48C2 /* BugsnagSessionTrackingPayload.h */; }; - 008968A52486DA9600DC48C2 /* BugsnagSessionTrackingPayload.h in Headers */ = {isa = PBXBuildFile; fileRef = 008968562486DA9400DC48C2 /* BugsnagSessionTrackingPayload.h */; }; - 008968A62486DA9600DC48C2 /* BugsnagSessionTrackingPayload.h in Headers */ = {isa = PBXBuildFile; fileRef = 008968562486DA9400DC48C2 /* BugsnagSessionTrackingPayload.h */; }; 008968A72486DA9600DC48C2 /* BugsnagSession.m in Sources */ = {isa = PBXBuildFile; fileRef = 008968572486DA9400DC48C2 /* BugsnagSession.m */; }; 008968A82486DA9600DC48C2 /* BugsnagSession.m in Sources */ = {isa = PBXBuildFile; fileRef = 008968572486DA9400DC48C2 /* BugsnagSession.m */; }; 008968A92486DA9600DC48C2 /* BugsnagSession.m in Sources */ = {isa = PBXBuildFile; fileRef = 008968572486DA9400DC48C2 /* BugsnagSession.m */; }; @@ -933,7 +923,6 @@ E746294D24890D2F00F92D67 /* BugsnagPlatformConditional.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 008968122486DA5600DC48C2 /* BugsnagPlatformConditional.h */; }; E746295824890D3000F92D67 /* BugsnagHandledState.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0089684E2486DA9400DC48C2 /* BugsnagHandledState.h */; }; E746295924890D3000F92D67 /* BugsnagNotifier.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 008968622486DA9500DC48C2 /* BugsnagNotifier.h */; }; - E746295C24890D3000F92D67 /* BugsnagSessionTrackingPayload.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 008968562486DA9400DC48C2 /* BugsnagSessionTrackingPayload.h */; }; E746295E24890D3000F92D67 /* BugsnagStacktrace.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0089684F2486DA9400DC48C2 /* BugsnagStacktrace.h */; }; E746295F24890D3000F92D67 /* BugsnagStateEvent.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 008968552486DA9400DC48C2 /* BugsnagStateEvent.h */; }; E746296324890D3000F92D67 /* BugsnagPluginClient.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 008968D92486DAA700DC48C2 /* BugsnagPluginClient.h */; }; @@ -1058,7 +1047,6 @@ E746294D24890D2F00F92D67 /* BugsnagPlatformConditional.h in CopyFiles */, E746295824890D3000F92D67 /* BugsnagHandledState.h in CopyFiles */, E746295924890D3000F92D67 /* BugsnagNotifier.h in CopyFiles */, - E746295C24890D3000F92D67 /* BugsnagSessionTrackingPayload.h in CopyFiles */, E746295E24890D3000F92D67 /* BugsnagStacktrace.h in CopyFiles */, E746295F24890D3000F92D67 /* BugsnagStateEvent.h in CopyFiles */, E746296324890D3000F92D67 /* BugsnagPluginClient.h in CopyFiles */, @@ -1154,7 +1142,6 @@ 008966C92486D43600DC48C2 /* BugsnagOnCrashTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BugsnagOnCrashTest.m; sourceTree = ""; }; 008966CA2486D43600DC48C2 /* BugsnagClientMirrorTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BugsnagClientMirrorTest.m; sourceTree = ""; }; 008966CB2486D43600DC48C2 /* BugsnagEnabledBreadcrumbTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BugsnagEnabledBreadcrumbTest.m; sourceTree = ""; }; - 008966CC2486D43600DC48C2 /* BugsnagSessionTrackingPayloadTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BugsnagSessionTrackingPayloadTest.m; sourceTree = ""; }; 008966CD2486D43600DC48C2 /* BugsnagBreadcrumbsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BugsnagBreadcrumbsTest.m; sourceTree = ""; }; 008966CF2486D43600DC48C2 /* BugsnagNotifierTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BugsnagNotifierTest.m; sourceTree = ""; }; 008966D02486D43600DC48C2 /* BugsnagSessionTrackerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BugsnagSessionTrackerTest.m; sourceTree = ""; }; @@ -1214,9 +1201,7 @@ 008968512486DA9400DC48C2 /* BugsnagError.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BugsnagError.m; sourceTree = ""; }; 008968522486DA9400DC48C2 /* BugsnagHandledState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BugsnagHandledState.m; sourceTree = ""; }; 008968532486DA9400DC48C2 /* BugsnagStackframe.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BugsnagStackframe.m; sourceTree = ""; }; - 008968542486DA9400DC48C2 /* BugsnagSessionTrackingPayload.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BugsnagSessionTrackingPayload.m; sourceTree = ""; }; 008968552486DA9400DC48C2 /* BugsnagStateEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BugsnagStateEvent.h; sourceTree = ""; }; - 008968562486DA9400DC48C2 /* BugsnagSessionTrackingPayload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BugsnagSessionTrackingPayload.h; sourceTree = ""; }; 008968572486DA9400DC48C2 /* BugsnagSession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BugsnagSession.m; sourceTree = ""; }; 008968582486DA9500DC48C2 /* BugsnagStateEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BugsnagStateEvent.m; sourceTree = ""; }; 0089685A2486DA9500DC48C2 /* BugsnagDeviceWithState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BugsnagDeviceWithState.m; sourceTree = ""; }; @@ -1784,7 +1769,6 @@ 008966B62486D43500DC48C2 /* BugsnagSessionTest.m */, 008966C32486D43600DC48C2 /* BugsnagSessionTrackerStopTest.m */, 008966D02486D43600DC48C2 /* BugsnagSessionTrackerTest.m */, - 008966CC2486D43600DC48C2 /* BugsnagSessionTrackingPayloadTest.m */, 008966BA2486D43500DC48C2 /* BugsnagStackframeTest.m */, 008966BB2486D43500DC48C2 /* BugsnagStacktraceTest.m */, 008966BD2486D43500DC48C2 /* BugsnagStateEventTest.m */, @@ -1940,8 +1924,6 @@ 0089684D2486DA9400DC48C2 /* BugsnagNotifier.m */, 008968572486DA9400DC48C2 /* BugsnagSession.m */, 0126DF1A257A92860031A70C /* BugsnagSession+Private.h */, - 008968562486DA9400DC48C2 /* BugsnagSessionTrackingPayload.h */, - 008968542486DA9400DC48C2 /* BugsnagSessionTrackingPayload.m */, 008968532486DA9400DC48C2 /* BugsnagStackframe.m */, 0198762E2567D5AB000A7AF3 /* BugsnagStackframe+Private.h */, 0089684F2486DA9400DC48C2 /* BugsnagStacktrace.h */, @@ -2112,7 +2094,6 @@ 0089697E2486DAD100DC48C2 /* BSG_KSArchSpecific.h in Headers */, 008969BA2486DAD100DC48C2 /* BSG_KSJSONCodec.h in Headers */, 008969E72486DAD100DC48C2 /* BSG_KSSystemInfoC.h in Headers */, - 008968A42486DA9600DC48C2 /* BugsnagSessionTrackingPayload.h in Headers */, CBAA6ABB250BA70E00713376 /* BugsnagKVStore.h in Headers */, 00AD1F102486A17900A27979 /* BugsnagSessionTracker.h in Headers */, 0126F79B25DD510E008483C2 /* BSGEventUploadObjectOperation.h in Headers */, @@ -2217,7 +2198,6 @@ 0089697F2486DAD100DC48C2 /* BSG_KSArchSpecific.h in Headers */, 008969BB2486DAD100DC48C2 /* BSG_KSJSONCodec.h in Headers */, 008969E82486DAD100DC48C2 /* BSG_KSSystemInfoC.h in Headers */, - 008968A52486DA9600DC48C2 /* BugsnagSessionTrackingPayload.h in Headers */, CBAA6ABC250BA70E00713376 /* BugsnagKVStore.h in Headers */, 00AD1F112486A17900A27979 /* BugsnagSessionTracker.h in Headers */, 008968F52486DAB800DC48C2 /* BugsnagSessionFileStore.h in Headers */, @@ -2322,7 +2302,6 @@ 008969802486DAD100DC48C2 /* BSG_KSArchSpecific.h in Headers */, 008969BC2486DAD100DC48C2 /* BSG_KSJSONCodec.h in Headers */, 008969E92486DAD100DC48C2 /* BSG_KSSystemInfoC.h in Headers */, - 008968A62486DA9600DC48C2 /* BugsnagSessionTrackingPayload.h in Headers */, CBAA6ABD250BA70F00713376 /* BugsnagKVStore.h in Headers */, 00AD1F122486A17900A27979 /* BugsnagSessionTracker.h in Headers */, 008968F62486DAB800DC48C2 /* BugsnagSessionFileStore.h in Headers */, @@ -2693,7 +2672,6 @@ 0126F7BE25DD512B008483C2 /* BSGEventUploadKSCrashReportOperation.m in Sources */, 008969B12486DAD100DC48C2 /* BSG_KSMach_x86_64.c in Sources */, 0089696C2486DAD000DC48C2 /* BSG_KSJSONCodecObjC.m in Sources */, - 0089689D2486DA9600DC48C2 /* BugsnagSessionTrackingPayload.m in Sources */, 008969B72486DAD100DC48C2 /* BSG_KSSignalInfo.c in Sources */, 008968992486DA9600DC48C2 /* BugsnagStackframe.m in Sources */, 00896A022486DAD100DC48C2 /* BSG_KSCrashSentry_NSException.m in Sources */, @@ -2773,7 +2751,6 @@ 012482A325627B51003F7243 /* UIKitTests.m in Sources */, 008967482486D43700DC48C2 /* BugsnagUserTest.m in Sources */, 008967962486D43700DC48C2 /* KSCrashState_Tests.m in Sources */, - 0089675D2486D43700DC48C2 /* BugsnagSessionTrackingPayloadTest.m in Sources */, 008967A52486D43700DC48C2 /* KSString_Tests.m in Sources */, 008967122486D43700DC48C2 /* BugsnagEventTests.m in Sources */, 008966FD2486D43700DC48C2 /* BugsnagOnBreadcrumbTest.m in Sources */, @@ -2867,7 +2844,6 @@ 008969B22486DAD100DC48C2 /* BSG_KSMach_x86_64.c in Sources */, 0126F7BF25DD512B008483C2 /* BSGEventUploadKSCrashReportOperation.m in Sources */, 0089696D2486DAD000DC48C2 /* BSG_KSJSONCodecObjC.m in Sources */, - 0089689E2486DA9600DC48C2 /* BugsnagSessionTrackingPayload.m in Sources */, 008969B82486DAD100DC48C2 /* BSG_KSSignalInfo.c in Sources */, 0089689A2486DA9600DC48C2 /* BugsnagStackframe.m in Sources */, 00896A032486DAD100DC48C2 /* BSG_KSCrashSentry_NSException.m in Sources */, @@ -2955,7 +2931,6 @@ 008967582486D43700DC48C2 /* BugsnagClientMirrorTest.m in Sources */, 0089676A2486D43700DC48C2 /* BugsnagSessionTrackerTest.m in Sources */, 008967792486D43700DC48C2 /* BSG_KSMachHeadersTests.m in Sources */, - 0089675E2486D43700DC48C2 /* BugsnagSessionTrackingPayloadTest.m in Sources */, 008967A92486D43700DC48C2 /* KSCrashIdentifierTests.m in Sources */, 01847DAD26441A5E00ADA4C7 /* BSGInternalErrorReporterTests.m in Sources */, 0089672B2486D43700DC48C2 /* BugsnagStacktraceTest.m in Sources */, @@ -3037,7 +3012,6 @@ 008969B32486DAD100DC48C2 /* BSG_KSMach_x86_64.c in Sources */, 0126F7C025DD512B008483C2 /* BSGEventUploadKSCrashReportOperation.m in Sources */, 0089696E2486DAD000DC48C2 /* BSG_KSJSONCodecObjC.m in Sources */, - 0089689F2486DA9600DC48C2 /* BugsnagSessionTrackingPayload.m in Sources */, 008969B92486DAD100DC48C2 /* BSG_KSSignalInfo.c in Sources */, 0089689B2486DA9600DC48C2 /* BugsnagStackframe.m in Sources */, 00896A042486DAD100DC48C2 /* BSG_KSCrashSentry_NSException.m in Sources */, @@ -3125,7 +3099,6 @@ E701FAA12490EF4A008D842F /* BugsnagApiValidationTest.m in Sources */, 01B6BB7E25D5777F00FC4DE6 /* BugsnagSwiftPublicAPITests.swift in Sources */, 0089677A2486D43700DC48C2 /* BSG_KSMachHeadersTests.m in Sources */, - 0089675F2486D43700DC48C2 /* BugsnagSessionTrackingPayloadTest.m in Sources */, 008967AA2486D43700DC48C2 /* KSCrashIdentifierTests.m in Sources */, 0089672C2486D43700DC48C2 /* BugsnagStacktraceTest.m in Sources */, 008966F32486D43700DC48C2 /* BugsnagMetadataRedactionTest.m in Sources */, @@ -3247,7 +3220,6 @@ 0089683D2486DA6C00DC48C2 /* BugsnagMetadata.m in Sources */, 0089682E2486DA5600DC48C2 /* BSGSerialization.m in Sources */, 015F528725C15BB7000D1915 /* MRCCanary.m in Sources */, - 008968A02486DA9600DC48C2 /* BugsnagSessionTrackingPayload.m in Sources */, 0089686E2486DA9500DC48C2 /* BugsnagEvent.m in Sources */, 0126F79125DD508C008483C2 /* BSGEventUploadOperation.m in Sources */, 008967EB2486DA2D00DC48C2 /* BugsnagErrorTypes.m in Sources */, diff --git a/Bugsnag/BugsnagSessionTracker.m b/Bugsnag/BugsnagSessionTracker.m index 6f77be901..fbf29548f 100644 --- a/Bugsnag/BugsnagSessionTracker.m +++ b/Bugsnag/BugsnagSessionTracker.m @@ -17,7 +17,6 @@ #import "BugsnagDevice+Private.h" #import "BugsnagLogger.h" #import "BugsnagSession+Private.h" -#import "BugsnagSessionTrackingPayload.h" #if TARGET_OS_IOS || TARGET_OS_TV #import "BSGUIKit.h" diff --git a/Bugsnag/Delivery/BSGSessionUploader.m b/Bugsnag/Delivery/BSGSessionUploader.m index 57834a0e5..fd0f3c21d 100644 --- a/Bugsnag/Delivery/BSGSessionUploader.m +++ b/Bugsnag/Delivery/BSGSessionUploader.m @@ -10,13 +10,16 @@ #import "BSGFileLocations.h" #import "BSG_RFC3339DateTool.h" #import "BugsnagApiClient.h" +#import "BugsnagApp+Private.h" #import "BugsnagCollections.h" #import "BugsnagConfiguration+Private.h" +#import "BugsnagDevice+Private.h" +#import "BugsnagKeys.h" #import "BugsnagLogger.h" +#import "BugsnagNotifier.h" #import "BugsnagSession+Private.h" #import "BugsnagSession.h" #import "BugsnagSessionFileStore.h" -#import "BugsnagSessionTrackingPayload.h" @interface BSGSessionUploader () @@ -96,18 +99,19 @@ - (void)sendSession:(BugsnagSession *)session completionHandler:(void (^)(Bugsna return; } - NSDictionary *JSONPayload = - [[[BugsnagSessionTrackingPayload alloc] initWithSessions:@[session] - config:self.config - codeBundleId:self.codeBundleId - notifier:self.notifier] toJson]; - NSDictionary *HTTPHeaders = @{ BugsnagHTTPHeaderNameApiKey: apiKey, BugsnagHTTPHeaderNamePayloadVersion: @"1.0", BugsnagHTTPHeaderNameSentAt: [BSG_RFC3339DateTool stringFromDate:[NSDate date]] ?: [NSNull null] }; + NSDictionary *JSONPayload = @{ + BSGKeyApp: [session.app toDict] ?: [NSNull null], + BSGKeyDevice: [session.device toDictionary] ?: [NSNull null], + BSGKeyNotifier: [self.notifier toDict] ?: [NSNull null], + BSGKeySessions: BSGArrayWithObject([session toJson]) + }; + [self.apiClient sendJSONPayload:JSONPayload headers:HTTPHeaders toURL:sessionURL completionHandler:^(BugsnagApiClientDeliveryStatus status, NSError *error) { switch (status) { case BugsnagApiClientDeliveryStatusDelivered: diff --git a/Bugsnag/Helpers/BugsnagKeys.h b/Bugsnag/Helpers/BugsnagKeys.h index 4cd149fbb..bfc9980fd 100644 --- a/Bugsnag/Helpers/BugsnagKeys.h +++ b/Bugsnag/Helpers/BugsnagKeys.h @@ -77,6 +77,7 @@ extern NSString *const BSGKeyRedactedKeys; extern NSString *const BSGKeyReleaseStage; extern NSString *const BSGKeySendThreads; extern NSString *const BSGKeySession; +extern NSString *const BSGKeySessions; extern NSString *const BSGKeySessionsEndpoint; extern NSString *const BSGKeySeverity; extern NSString *const BSGKeySeverityReason; diff --git a/Bugsnag/Helpers/BugsnagKeys.m b/Bugsnag/Helpers/BugsnagKeys.m index 0ae56b646..8d3670251 100644 --- a/Bugsnag/Helpers/BugsnagKeys.m +++ b/Bugsnag/Helpers/BugsnagKeys.m @@ -76,6 +76,7 @@ NSString *const BSGKeyReleaseStage = @"releaseStage"; NSString *const BSGKeySendThreads = @"sendThreads"; NSString *const BSGKeySession = @"session"; +NSString *const BSGKeySessions = @"sessions"; NSString *const BSGKeySessionsEndpoint = @"sessions"; NSString *const BSGKeySeverity = @"severity"; NSString *const BSGKeySeverityReason = @"severityReason"; diff --git a/Bugsnag/Payload/BugsnagSessionTrackingPayload.h b/Bugsnag/Payload/BugsnagSessionTrackingPayload.h deleted file mode 100644 index 7511dfa87..000000000 --- a/Bugsnag/Payload/BugsnagSessionTrackingPayload.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// BugsnagSessionTrackingPayload.h -// Bugsnag -// -// Created by Jamie Lynch on 27/11/2017. -// Copyright © 2017 Bugsnag. All rights reserved. -// - -#import - -#import - -@class BugsnagConfiguration; -@class BugsnagNotifier; - -@interface BugsnagSessionTrackingPayload : NSObject - -@property (nonatomic) NSArray *sessions; - -- (instancetype)initWithSessions:(NSArray *)sessions - config:(BugsnagConfiguration *)config - codeBundleId:(NSString *)codeBundleId - notifier:(BugsnagNotifier *)notifier; - -- (NSMutableDictionary *)toJson; - -@end diff --git a/Bugsnag/Payload/BugsnagSessionTrackingPayload.m b/Bugsnag/Payload/BugsnagSessionTrackingPayload.m deleted file mode 100644 index 8afa62a53..000000000 --- a/Bugsnag/Payload/BugsnagSessionTrackingPayload.m +++ /dev/null @@ -1,66 +0,0 @@ -// -// BugsnagSessionTrackingPayload.m -// Bugsnag -// -// Created by Jamie Lynch on 27/11/2017. -// Copyright © 2017 Bugsnag. All rights reserved. -// - -#import "BugsnagSessionTrackingPayload.h" - -#import "BugsnagApp+Private.h" -#import "BugsnagCollections.h" -#import "BugsnagClient+Private.h" -#import "BugsnagDevice+Private.h" -#import "Bugsnag+Private.h" -#import "BugsnagKeys.h" -#import "BugsnagNotifier.h" -#import "BugsnagSession+Private.h" -#import "BSG_KSSystemInfo.h" -#import "BugsnagConfiguration.h" -#import "BugsnagApp.h" - -@interface BugsnagSessionTrackingPayload () -@property (nonatomic) BugsnagConfiguration *config; -@property(nonatomic, copy) NSString *codeBundleId; -@property (nonatomic) BugsnagNotifier *notifier; -@end - -@implementation BugsnagSessionTrackingPayload - -- (instancetype)initWithSessions:(NSArray *)sessions - config:(BugsnagConfiguration *)config - codeBundleId:(NSString *)codeBundleId - notifier:(BugsnagNotifier *)notifier -{ - if ((self = [super init])) { - _sessions = sessions; - _config = config; - _codeBundleId = codeBundleId; - _notifier = notifier; - } - return self; -} - -- (NSMutableDictionary *)toJson -{ - NSMutableDictionary *dict = [NSMutableDictionary new]; - NSMutableArray *sessionData = [NSMutableArray new]; - - for (BugsnagSession *session in self.sessions) { - [sessionData addObject:[session toDictionary]]; - } - dict[@"sessions"] = sessionData; - dict[BSGKeyNotifier] = [self.notifier toDict]; - - // app/device data collection relies on KSCrash reports, - // need to mimic the JSON structure here - BugsnagApp *app = self.sessions[0].app; - dict[BSGKeyApp] = [app toDict]; - - BugsnagDevice *device = self.sessions[0].device; - dict[BSGKeyDevice] = [device toDictionary]; - return dict; -} - -@end diff --git a/Tests/BugsnagTests/BugsnagApiClientTest.m b/Tests/BugsnagTests/BugsnagApiClientTest.m index 38b7c8f75..d18dbb268 100644 --- a/Tests/BugsnagTests/BugsnagApiClientTest.m +++ b/Tests/BugsnagTests/BugsnagApiClientTest.m @@ -19,7 +19,7 @@ @interface BugsnagApiClientTest : XCTestCase @implementation BugsnagApiClientTest - (void)testBadJSON { - BugsnagApiClient *client = [[BugsnagApiClient alloc] initWithSession:nil queueName:@"test"]; + BugsnagApiClient *client = [[BugsnagApiClient alloc] initWithSession:nil]; XCTAssertNoThrow([client sendJSONPayload:(id)@{@1: @"a"} headers:(id)@{@1: @"a"} toURL:[NSURL URLWithString:@"file:///dev/null"] completionHandler:^(BugsnagApiClientDeliveryStatus status, NSError * _Nullable error) {}]); } @@ -27,7 +27,7 @@ - (void)testBadJSON { - (void)testHTTPStatusCodes { NSURL *url = [NSURL URLWithString:@"https://example.com"]; URLSessionMock *session = [[URLSessionMock alloc] init]; - BugsnagApiClient *client = [[BugsnagApiClient alloc] initWithSession:(id)session queueName:@""]; + BugsnagApiClient *client = [[BugsnagApiClient alloc] initWithSession:(id)session]; void (^ test)(NSInteger, BugsnagApiClientDeliveryStatus, BOOL) = ^(NSInteger statusCode, BugsnagApiClientDeliveryStatus expectedDeliveryStatus, BOOL expectError) { @@ -64,7 +64,7 @@ - (void)testHTTPStatusCodes { - (void)testNotConnectedToInternetError { NSURL *url = [NSURL URLWithString:@"https://example.com"]; URLSessionMock *session = [[URLSessionMock alloc] init]; - BugsnagApiClient *client = [[BugsnagApiClient alloc] initWithSession:(id)session queueName:@""]; + BugsnagApiClient *client = [[BugsnagApiClient alloc] initWithSession:(id)session]; XCTestExpectation *expectation = [self expectationWithDescription:@"completionHandler should be called"]; [session mockData:nil response:nil error:[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorNotConnectedToInternet userInfo:@{ diff --git a/Tests/BugsnagTests/BugsnagSessionTrackingPayloadTest.m b/Tests/BugsnagTests/BugsnagSessionTrackingPayloadTest.m deleted file mode 100644 index 334aeca67..000000000 --- a/Tests/BugsnagTests/BugsnagSessionTrackingPayloadTest.m +++ /dev/null @@ -1,150 +0,0 @@ -// -// BugsnagSessionTrackingPayloadTest.m -// Tests -// -// Created by Jamie Lynch on 27/11/2017. -// Copyright © 2017 Bugsnag. All rights reserved. -// - -#import - -#import "BugsnagApp+Private.h" -#import "BugsnagConfiguration+Private.h" -#import "BugsnagDevice+Private.h" -#import "BugsnagNotifier.h" -#import "BugsnagSession+Private.h" -#import "BugsnagSessionTrackingPayload.h" -#import "BugsnagTestConstants.h" - -@interface BugsnagSessionTrackingPayloadTest : XCTestCase -@property NSDictionary *payload; -@property BugsnagApp *app; -@property BugsnagDevice *device; -@end - -@implementation BugsnagSessionTrackingPayloadTest - -- (void)setUp { - self.app = [self generateApp]; - self.device = [self generateDevice]; - - BugsnagConfiguration *config = [[BugsnagConfiguration alloc] initWithApiKey:DUMMY_APIKEY_32CHAR_1]; - config.releaseStage = @"beta"; - - BugsnagSessionTrackingPayload *payload = [[BugsnagSessionTrackingPayload alloc] initWithSessions:@[] - config:config - codeBundleId:nil - notifier:[[BugsnagNotifier alloc] init]]; - BugsnagSession *session = [[BugsnagSession alloc] initWithId:@"test" - startDate:[NSDate date] - user:nil - autoCaptured:NO - app:self.app - device:self.device]; - payload.sessions = @[session]; - self.payload = [payload toJson]; -} - -- (BugsnagApp *)generateApp { - NSDictionary *appData = @{ - @"system": @{ - @"application_stats": @{ - @"active_time_since_launch": @2, - @"background_time_since_launch": @5, - @"application_in_foreground": @YES, - }, - @"CFBundleExecutable": @"MyIosApp", - @"CFBundleIdentifier": @"com.example.foo.MyIosApp", - @"CFBundleShortVersionString": @"5.6.3", - @"CFBundleVersion": @"1", - @"app_uuid": @"dsym-uuid-123" - }, - @"user": @{ - @"config": @{ - @"releaseStage": @"beta" - } - } - }; - - BugsnagConfiguration *config = [[BugsnagConfiguration alloc] initWithDictionaryRepresentation:appData[@"user"][@"config"]]; - config.appType = @"iOS"; - config.bundleVersion = nil; - return [BugsnagApp appWithDictionary:appData config:config codeBundleId:@"bundle-123"]; -} - -- (BugsnagDevice *)generateDevice { - NSDictionary *deviceData = @{ - @"system": @{ - @"model": @"iPhone 6", - @"machine": @"x86_64", - @"system_name": @"iPhone OS", - @"system_version": @"8.1", - @"os_version": @"14B25", - @"clang_version": @"10.0.0 (clang-1000.11.45.5)", - @"jailbroken": @YES, - @"memory": @{ - @"usable": @15065522176, - @"free": @742920192 - }, - @"device_app_hash": @"123" - }, - @"report": @{ - @"timestamp": @"2014-12-02T01:56:13Z" - }, - @"user": @{ - @"state": @{ - @"deviceState": @{ - @"orientation": @"portrait" - } - } - } - }; - BugsnagDevice *device = [BugsnagDevice deviceWithKSCrashReport:deviceData]; - device.locale = @"en-US"; - return device; -} - -- (void)testPayloadSerialisation { - XCTAssertNotNil(self.payload); - - NSArray *sessions = self.payload[@"sessions"]; - NSDictionary *sessionNode = sessions[0]; - XCTAssertNotNil(sessionNode); - XCTAssertEqualObjects(@"test", sessionNode[@"id"]); - - XCTAssertNotNil(self.payload[@"notifier"]); -} - -- (void)testDeviceSerialisation { - NSDictionary *device = self.payload[@"device"]; - XCTAssertNotNil(device); - XCTAssertTrue(device[@"jailbroken"]); - XCTAssertEqualObjects(@"123", device[@"id"]); - XCTAssertEqualObjects(@"en-US", device[@"locale"]); - XCTAssertEqualObjects(@"Apple", device[@"manufacturer"]); - XCTAssertEqualObjects(@"x86_64", device[@"model"]); - XCTAssertEqualObjects(@"iPhone 6", device[@"modelNumber"]); - XCTAssertEqualObjects(@"iPhone OS", device[@"osName"]); - XCTAssertEqualObjects(@"8.1", device[@"osVersion"]); - XCTAssertEqualObjects(@15065522176, device[@"totalMemory"]); - - NSDictionary *runtimeVersions = @{ - @"osBuild": @"14B25", - @"clangVersion": @"10.0.0 (clang-1000.11.45.5)" - }; - XCTAssertEqualObjects(runtimeVersions, device[@"runtimeVersions"]); -} - -- (void)testAppSerialisation { - NSDictionary *app = self.payload[@"app"]; - XCTAssertNotNil(app); - XCTAssertEqualObjects(@"1", app[@"bundleVersion"]); - XCTAssertEqualObjects(@"bundle-123", app[@"codeBundleId"]); - XCTAssertEqualObjects(@[@"dsym-uuid-123"], app[@"dsymUUIDs"]); - XCTAssertEqualObjects(@"com.example.foo.MyIosApp", app[@"id"]); - XCTAssertEqualObjects(@"beta", app[@"releaseStage"]); - XCTAssertEqualObjects(@"iOS", app[@"type"]); - XCTAssertEqualObjects(@"5.6.3", app[@"version"]); -} - -@end From aba47e59ac2444d1d689934f670839f140016c19 Mon Sep 17 00:00:00 2001 From: Nick Dowell Date: Thu, 2 Dec 2021 13:52:39 +0000 Subject: [PATCH 12/20] Fix static analysis issues --- Bugsnag/Delivery/BSGSessionUploader.m | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Bugsnag/Delivery/BSGSessionUploader.m b/Bugsnag/Delivery/BSGSessionUploader.m index fd0f3c21d..bdeee61e6 100644 --- a/Bugsnag/Delivery/BSGSessionUploader.m +++ b/Bugsnag/Delivery/BSGSessionUploader.m @@ -32,12 +32,12 @@ @interface BSGSessionUploader () @implementation BSGSessionUploader -- (instancetype)initWithConfig:(BugsnagConfiguration *)configuration notifier:(BugsnagNotifier *)notifier { +- (instancetype)initWithConfig:(BugsnagConfiguration *)config notifier:(BugsnagNotifier *)notifier { if ((self = [super init])) { _activeIds = [NSMutableSet new]; - _apiClient = [[BugsnagApiClient alloc] initWithSession:configuration.session]; - _config = configuration; - _fileStore = [BugsnagSessionFileStore storeWithPath:[BSGFileLocations current].sessions maxPersistedSessions:configuration.maxPersistedSessions]; + _apiClient = [[BugsnagApiClient alloc] initWithSession:config.session]; + _config = config; + _fileStore = [BugsnagSessionFileStore storeWithPath:[BSGFileLocations current].sessions maxPersistedSessions:config.maxPersistedSessions]; _notifier = notifier; } return self; @@ -84,7 +84,7 @@ - (void)uploadStoredSessions { }]; } -- (void)sendSession:(BugsnagSession *)session completionHandler:(void (^)(BugsnagApiClientDeliveryStatus status))completionHandler { +- (void)sendSession:(BugsnagSession *)session completionHandler:(nonnull void (^)(BugsnagApiClientDeliveryStatus status))completionHandler { NSString *apiKey = [self.config.apiKey copy]; if (!apiKey) { bsg_log_err(@"Cannot send session because no apiKey is configured."); @@ -92,27 +92,27 @@ - (void)sendSession:(BugsnagSession *)session completionHandler:(void (^)(Bugsna return; } - NSURL *sessionURL = self.config.sessionURL; - if (!sessionURL) { + NSURL *url = self.config.sessionURL; + if (!url) { bsg_log_err(@"Cannot send session because no endpoint is configured."); completionHandler(BugsnagApiClientDeliveryStatusUndeliverable); return; } - NSDictionary *HTTPHeaders = @{ + NSDictionary *headers = @{ BugsnagHTTPHeaderNameApiKey: apiKey, BugsnagHTTPHeaderNamePayloadVersion: @"1.0", BugsnagHTTPHeaderNameSentAt: [BSG_RFC3339DateTool stringFromDate:[NSDate date]] ?: [NSNull null] }; - NSDictionary *JSONPayload = @{ + NSDictionary *payload = @{ BSGKeyApp: [session.app toDict] ?: [NSNull null], BSGKeyDevice: [session.device toDictionary] ?: [NSNull null], BSGKeyNotifier: [self.notifier toDict] ?: [NSNull null], BSGKeySessions: BSGArrayWithObject([session toJson]) }; - [self.apiClient sendJSONPayload:JSONPayload headers:HTTPHeaders toURL:sessionURL completionHandler:^(BugsnagApiClientDeliveryStatus status, NSError *error) { + [self.apiClient sendJSONPayload:payload headers:headers toURL:url completionHandler:^(BugsnagApiClientDeliveryStatus status, NSError *error) { switch (status) { case BugsnagApiClientDeliveryStatusDelivered: bsg_log_info(@"Sent session %@", session.id); From 6a606eb945bcdce9e569c521c2086e11f03b9f2c Mon Sep 17 00:00:00 2001 From: Steve Kirkland-Walton Date: Fri, 22 Oct 2021 20:40:28 +0100 Subject: [PATCH 13/20] Add e2e tests for iOS 15 [quick ci] --- .buildkite/pipeline.full.yml | 52 +++++++++++++++++++++++++++++++++++ .buildkite/pipeline.quick.yml | 14 ++++++---- .buildkite/pipeline.yml | 4 +-- 3 files changed, 62 insertions(+), 8 deletions(-) diff --git a/.buildkite/pipeline.full.yml b/.buildkite/pipeline.full.yml index 9599c8139..5c7faa06c 100644 --- a/.buildkite/pipeline.full.yml +++ b/.buildkite/pipeline.full.yml @@ -7,6 +7,58 @@ steps: # E2E tests # + - label: 'iOS 14 E2E tests batch 1' + depends_on: + - cocoa_fixture + timeout_in_minutes: 60 + agents: + queue: opensource + plugins: + artifacts#v1.3.0: + download: ["features/fixtures/ios/output/iOSTestApp.ipa"] + docker-compose#v3.3.0: + run: cocoa-maze-runner + command: + - "--app=/app/build/iOSTestApp.ipa" + - "--farm=bs" + - "--device=IOS_14" + - "--appium-version=1.17.0" + - "--fail-fast" + - "--exclude=features/[h-z].*.feature" + - "--order=random" + concurrency: 9 + concurrency_group: browserstack-app + retry: + automatic: + - exit_status: -1 # Agent was lost + limit: 2 + + - label: 'iOS 14 E2E tests batch 2' + depends_on: + - cocoa_fixture + timeout_in_minutes: 60 + agents: + queue: opensource + plugins: + artifacts#v1.3.0: + download: ["features/fixtures/ios/output/iOSTestApp.ipa"] + docker-compose#v3.3.0: + run: cocoa-maze-runner + command: + - "--app=/app/build/iOSTestApp.ipa" + - "--farm=bs" + - "--device=IOS_14" + - "--appium-version=1.17.0" + - "--fail-fast" + - "--exclude=features/[a-g].*.feature" + - "--order=random" + concurrency: 9 + concurrency_group: browserstack-app + retry: + automatic: + - exit_status: -1 # Agent was lost + limit: 2 + - label: 'iOS 13 E2E tests batch 1' depends_on: - cocoa_fixture diff --git a/.buildkite/pipeline.quick.yml b/.buildkite/pipeline.quick.yml index dab9da9c0..e404850a6 100644 --- a/.buildkite/pipeline.quick.yml +++ b/.buildkite/pipeline.quick.yml @@ -134,7 +134,7 @@ steps: --fail-fast --order=random - - label: 'iOS 14 E2E tests batch 1' + - label: 'iOS 15 E2E tests batch 1' depends_on: - cocoa_fixture timeout_in_minutes: 60 @@ -149,9 +149,10 @@ steps: command: - "--app=@build/ipa_url.txt" - "--farm=bs" - - "--device=IOS_14" + - "--device=IOS_15" - "--appium-version=1.17.0" - - "--fail-fast" +# TODO Readd +# - "--fail-fast" - "--exclude=features/[h-z].*.feature" - "--order=random" concurrency: 9 @@ -162,7 +163,7 @@ steps: - exit_status: -1 # Agent was lost limit: 2 - - label: 'iOS 14 E2E tests batch 2' + - label: 'iOS 15 E2E tests batch 2' depends_on: - cocoa_fixture timeout_in_minutes: 60 @@ -177,9 +178,10 @@ steps: command: - "--app=@build/ipa_url.txt" - "--farm=bs" - - "--device=IOS_14" + - "--device=IOS_15" - "--appium-version=1.17.0" - - "--fail-fast" + # TODO Readd + # - "--fail-fast" - "--exclude=features/[a-g].*.feature" - "--order=random" concurrency: 9 diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index bacee04b6..38c08b598 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -126,7 +126,7 @@ steps: # Barebones E2E tests # - - label: 'iOS 14 barebones E2E tests' + - label: 'iOS 15 barebones E2E tests' depends_on: - cocoa_fixture timeout_in_minutes: 10 @@ -142,7 +142,7 @@ steps: - "features/barebone_tests.feature" - "--app=@build/ipa_url.txt" - "--farm=bs" - - "--device=IOS_14" + - "--device=IOS_15" - "--appium-version=1.17.0" - "--fail-fast" - "--order=random" From 8c0cf7e2b5ea92853a65ac113b8b6d56fbdd3565 Mon Sep 17 00:00:00 2001 From: Steve Kirkland-Walton Date: Mon, 25 Oct 2021 10:39:11 +0100 Subject: [PATCH 14/20] Use Appium 1.22.0 [quick ci] --- .buildkite/block.quick.yml | 4 ++-- .buildkite/pipeline.quick.yml | 4 ++-- .buildkite/pipeline.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.buildkite/block.quick.yml b/.buildkite/block.quick.yml index 5062f04e1..a7ea8a246 100644 --- a/.buildkite/block.quick.yml +++ b/.buildkite/block.quick.yml @@ -1,7 +1,7 @@ steps: - - block: 'Trigger extra iOS 10 and iOS 14 end-to-end tests and all unit tests' + - block: 'Trigger extra iOS 10 and iOS 15 end-to-end tests and all unit tests' key: 'trigger-quick-build' - label: 'Upload the quick test pipeline' depends_on: 'trigger-quick-build' - command: buildkite-agent pipeline upload .buildkite/pipeline.quick.yml \ No newline at end of file + command: buildkite-agent pipeline upload .buildkite/pipeline.quick.yml diff --git a/.buildkite/pipeline.quick.yml b/.buildkite/pipeline.quick.yml index e404850a6..d266f6769 100644 --- a/.buildkite/pipeline.quick.yml +++ b/.buildkite/pipeline.quick.yml @@ -150,7 +150,7 @@ steps: - "--app=@build/ipa_url.txt" - "--farm=bs" - "--device=IOS_15" - - "--appium-version=1.17.0" + - "--appium-version=1.22.0" # TODO Readd # - "--fail-fast" - "--exclude=features/[h-z].*.feature" @@ -179,7 +179,7 @@ steps: - "--app=@build/ipa_url.txt" - "--farm=bs" - "--device=IOS_15" - - "--appium-version=1.17.0" + - "--appium-version=1.22.0" # TODO Readd # - "--fail-fast" - "--exclude=features/[a-g].*.feature" diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 38c08b598..d9694d9e4 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -143,7 +143,7 @@ steps: - "--app=@build/ipa_url.txt" - "--farm=bs" - "--device=IOS_15" - - "--appium-version=1.17.0" + - "--appium-version=1.22.0" - "--fail-fast" - "--order=random" concurrency: 9 From dd7bfec835838d8d9da80246e3b4e03bb5f88b9c Mon Sep 17 00:00:00 2001 From: Alex Moinet Date: Tue, 2 Nov 2021 10:19:08 +0000 Subject: [PATCH 15/20] Testing: Temporarily add internal error reporting to iOS 15 barebones tests --- .buildkite/pipeline.quick.yml | 10 ++++------ .buildkite/pipeline.yml | 3 +-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/.buildkite/pipeline.quick.yml b/.buildkite/pipeline.quick.yml index d266f6769..f938e0592 100644 --- a/.buildkite/pipeline.quick.yml +++ b/.buildkite/pipeline.quick.yml @@ -150,9 +150,8 @@ steps: - "--app=@build/ipa_url.txt" - "--farm=bs" - "--device=IOS_15" - - "--appium-version=1.22.0" -# TODO Readd -# - "--fail-fast" + - "--appium-version=1.21.0" + - "--fail-fast" - "--exclude=features/[h-z].*.feature" - "--order=random" concurrency: 9 @@ -179,9 +178,8 @@ steps: - "--app=@build/ipa_url.txt" - "--farm=bs" - "--device=IOS_15" - - "--appium-version=1.22.0" - # TODO Readd - # - "--fail-fast" + - "--appium-version=1.21.0" + - "--fail-fast" - "--exclude=features/[a-g].*.feature" - "--order=random" concurrency: 9 diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index d9694d9e4..c4b0496e8 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -143,8 +143,7 @@ steps: - "--app=@build/ipa_url.txt" - "--farm=bs" - "--device=IOS_15" - - "--appium-version=1.22.0" - - "--fail-fast" + - "--appium-version=1.21.0" - "--order=random" concurrency: 9 concurrency_group: browserstack-app From ee3ad1cc4648067ae6b9a93c305f9de76f77d5d4 Mon Sep 17 00:00:00 2001 From: Steve Kirkland-Walton Date: Fri, 3 Dec 2021 12:18:27 +0000 Subject: [PATCH 16/20] Use Maze Runner helper routine [quick ci] --- Gemfile | 6 +++--- Gemfile.lock | 10 +++++----- features/steps/app_steps.rb | 14 +++++++------- features/steps/cocoa_steps.rb | 34 +++++++++++++++++++--------------- features/support/env.rb | 8 ++++---- 5 files changed, 38 insertions(+), 34 deletions(-) diff --git a/Gemfile b/Gemfile index 88a9abc97..32433b6a6 100644 --- a/Gemfile +++ b/Gemfile @@ -7,10 +7,10 @@ gem 'xcpretty' # A reference to Maze Runner is only needed for running tests locally and if committed it must be # portable for CI, e.g. a specific release. However, leaving it commented out would mean quicker CI. -gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner', tag: 'v6.5.0' +gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner', tag: 'v6.6.2' -# Use a development branch -#gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner', branch: 'tms/update-cucumber' +# Use a specific branch +#gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner', branch: 'master' # Locally, you can run against Maze Runner branches and uncommitted changes: #gem 'bugsnag-maze-runner', path: '../maze-runner' diff --git a/Gemfile.lock b/Gemfile.lock index efc1166bc..5cbf7a326 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,9 +1,9 @@ GIT remote: https://github.com/bugsnag/maze-runner - revision: fd33f19db2d0b03be857fecb55f1aa4d4033de6c - tag: v6.5.0 + revision: 9efc4f0c876f050d34e0bef54be2599598076818 + tag: v6.6.2 specs: - bugsnag-maze-runner (6.5.0) + bugsnag-maze-runner (6.6.2) appium_lib (~> 11.2.0) bugsnag (~> 6.24) cucumber (~> 7.1) @@ -41,7 +41,7 @@ GEM faye-websocket (~> 0.11.0) selenium-webdriver (~> 3.14, >= 3.14.1) atomos (0.1.3) - bugsnag (6.24.0) + bugsnag (6.24.1) concurrent-ruby (~> 1.0) builder (3.2.4) childprocess (3.0.0) @@ -207,7 +207,7 @@ GEM nokogiri (1.12.5) mini_portile2 (~> 2.6.1) racc (~> 1.4) - nokogiri (1.12.5-x86_64-darwin) + nokogiri (1.12.5-arm64-darwin) racc (~> 1.4) octokit (4.21.0) faraday (>= 0.9) diff --git a/features/steps/app_steps.rb b/features/steps/app_steps.rb index 33ca7b86d..f18813282 100644 --- a/features/steps/app_steps.rb +++ b/features/steps/app_steps.rb @@ -3,8 +3,8 @@ end When('I relaunch the app') do - case Maze.driver.capabilities['platformName'] - when 'Mac' + case Maze::Helper.get_current_platform + when 'macos' app = Maze.driver.capabilities['app'] system("killall #{app} > /dev/null && sleep 1") Maze.driver.get(app) @@ -17,8 +17,8 @@ # This step should only be used when the app has crashed, but the notifier needs a little # time to write the crash report before being forced to reopen. From trials, 2s was not enough. sleep(5) - case Maze.driver.capabilities['platformName'] - when 'Mac' + case Maze::Helper.get_current_platform + when 'macos' Maze.driver.get(Maze.driver.capabilities['app']) else Maze.driver.launch_app @@ -48,10 +48,10 @@ Then('the app is not running') do wait_for_true do - case Maze.driver.capabilities['platformName'] - when 'iOS' + case Maze::Helper.get_current_platform + when 'ios' Maze.driver.app_state('com.bugsnag.iOSTestApp') == :not_running - when 'Mac' + when 'macos' `lsappinfo info -only pid -app com.bugsnag.macOSTestApp`.empty? else raise "Don't know how to query app state on this platform" diff --git a/features/steps/cocoa_steps.rb b/features/steps/cocoa_steps.rb index 9900f5359..9d40bb0c1 100644 --- a/features/steps/cocoa_steps.rb +++ b/features/steps/cocoa_steps.rb @@ -12,7 +12,7 @@ step("I run \"#{event_type}\"") rescue StandardError # Ignore on macOS - AppiumForMac raises an error when clicking a button causes the app to crash - raise unless Maze.driver.capabilities['platformName'].eql?('Mac') + raise unless Maze::Helper.get_current_platform.eql?('macos') $logger.warn 'Ignoring error - this is normal for AppiumForMac if a button click causes the app to crash.' end @@ -25,7 +25,7 @@ Given I click the element "run_scenario" ) rescue StandardError - raise unless Maze.driver.capabilities['platformName'].eql?('Mac') + raise unless Maze::Helper.get_current_platform.eql?('macos') $logger.info 'Ignored error raised by AppiumForMac when clicking run_scenario' end steps %( @@ -52,7 +52,7 @@ def click_if_present(element) end When('I close the keyboard') do - unless Maze.driver.capabilities['platformName'].eql?('Mac') + unless Maze::Helper.get_current_platform.eql?('macos') click_if_present 'close_keyboard' end end @@ -193,49 +193,53 @@ def check_device_model(field, list) end Then('the error is valid for the error reporting API') do - case Maze.driver.capabilities['platformName'] - when 'iOS' + platform = Maze::Helper.get_current_platform + STDOUT.puts "platform: #{platform}" + case platform + when 'ios' steps %( Then the error is valid for the error reporting API version "4.0" for the "iOS Bugsnag Notifier" notifier Then the breadcrumb timestamps are valid for the event ) - when 'Mac' + when 'macos' steps %( Then the error is valid for the error reporting API version "4.0" for the "OSX Bugsnag Notifier" notifier Then the breadcrumb timestamps are valid for the event ) else - raise 'Unknown platformName' + raise "Unknown platform: #{platform}" end end Then('the error is valid for the error reporting API ignoring breadcrumb timestamps') do - case Maze.driver.capabilities['platformName'] - when 'iOS' + platform = Maze::Helper.get_current_platform + case platform + when 'ios' steps %( Then the error is valid for the error reporting API version "4.0" for the "iOS Bugsnag Notifier" notifier ) - when 'Mac' + when 'macos' steps %( Then the error is valid for the error reporting API version "4.0" for the "OSX Bugsnag Notifier" notifier ) else - raise 'Unknown platformName' + raise "Unknown platform: #{platform}" end end Then('the session is valid for the session reporting API') do - case Maze.driver.capabilities['platformName'] - when 'iOS' + platform = Maze::Helper.get_current_platform + case platform + when 'ios' steps %( Then the session is valid for the session reporting API version "1.0" for the "iOS Bugsnag Notifier" notifier ) - when 'Mac' + when 'macos' steps %( Then the session is valid for the session reporting API version "1.0" for the "OSX Bugsnag Notifier" notifier ) else - raise 'Unknown platformName' + raise "Unknown platform: #{platform}" end end diff --git a/features/support/env.rb b/features/support/env.rb index cdcf395e5..3526a3e04 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -44,19 +44,19 @@ end def skip_below(os, version) - skip_this_scenario("Skipping scenario") if Maze.driver.capabilities['platformName'] == os and Maze.config.os_version < version + skip_this_scenario("Skipping scenario") if Maze::Helper.get_current_platform == os and Maze.config.os_version < version end Before('@skip_below_ios_11') do |scenario| - skip_below('iOS', 11) + skip_below('ios', 11) end Before('@skip_below_ios_13') do |scenario| - skip_below('iOS', 13) + skip_below('ios', 13) end Before('@skip_macos') do |scenario| - skip_this_scenario("Skipping scenario") if Maze.driver.capabilities['platformName'] == 'Mac' + skip_this_scenario("Skipping scenario") if Maze::Helper.get_current_platform == 'macos' end # Skip stress tests unless STRESS_TEST env var is set From 2193cd897fc84a2ab975ebd5b513b53203b12fcc Mon Sep 17 00:00:00 2001 From: Steve Kirkland-Walton Date: Mon, 6 Dec 2021 17:00:39 +0000 Subject: [PATCH 17/20] Return nokogiri to x86 [quick ci] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 5cbf7a326..9ac803d38 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -207,7 +207,7 @@ GEM nokogiri (1.12.5) mini_portile2 (~> 2.6.1) racc (~> 1.4) - nokogiri (1.12.5-arm64-darwin) + nokogiri (1.12.5-x86_64-darwin) racc (~> 1.4) octokit (4.21.0) faraday (>= 0.9) From 185098b28bc821d52775633c6ef7e33d1d606075 Mon Sep 17 00:00:00 2001 From: Nick Dowell Date: Tue, 7 Dec 2021 09:28:52 +0000 Subject: [PATCH 18/20] Fix currentAppState when called before UIApplicationMain (#1248) --- Bugsnag.xcodeproj/project.pbxproj | 8 ++++ .../KSCrash/Recording/BSG_KSSystemInfo.m | 24 ++++++++---- CHANGELOG.md | 8 ++++ .../BugsnagTests/BugsnagConfigurationTests.m | 2 + Tests/BugsnagTests/UIApplicationStub.h | 26 +++++++++++++ Tests/BugsnagTests/UIApplicationStub.m | 38 +++++++++++++++++++ Tests/KSCrashTests/KSCrashState_Tests.m | 15 ++++++++ Tests/KSCrashTests/KSSystemInfo_Tests.m | 8 +++- 8 files changed, 121 insertions(+), 8 deletions(-) create mode 100644 Tests/BugsnagTests/UIApplicationStub.h create mode 100644 Tests/BugsnagTests/UIApplicationStub.m diff --git a/Bugsnag.xcodeproj/project.pbxproj b/Bugsnag.xcodeproj/project.pbxproj index 7b32efc16..a0ba6858d 100644 --- a/Bugsnag.xcodeproj/project.pbxproj +++ b/Bugsnag.xcodeproj/project.pbxproj @@ -659,6 +659,8 @@ 01847DAD26441A5E00ADA4C7 /* BSGInternalErrorReporterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 01847DAB26441A5E00ADA4C7 /* BSGInternalErrorReporterTests.m */; }; 01847DAE26441A5E00ADA4C7 /* BSGInternalErrorReporterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 01847DAB26441A5E00ADA4C7 /* BSGInternalErrorReporterTests.m */; }; 0187D464255BD7B800C503D9 /* BugsnagApiClientTest.m in Sources */ = {isa = PBXBuildFile; fileRef = CB9103632502320A00E9D1E2 /* BugsnagApiClientTest.m */; }; + 01935AE2275E68E9007498B3 /* UIApplicationStub.m in Sources */ = {isa = PBXBuildFile; fileRef = 01935AE1275E68E9007498B3 /* UIApplicationStub.m */; }; + 01935AE3275E68E9007498B3 /* UIApplicationStub.m in Sources */ = {isa = PBXBuildFile; fileRef = 01935AE1275E68E9007498B3 /* UIApplicationStub.m */; }; 019480D42625F3EB00E833ED /* BSGAppKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 019480D32625F3EB00E833ED /* BSGAppKitTests.m */; }; 01A2C542271EB9B400A27B23 /* BSG_Symbolicate.c in Sources */ = {isa = PBXBuildFile; fileRef = 01A2C540271EB9B300A27B23 /* BSG_Symbolicate.c */; }; 01A2C543271EB9B400A27B23 /* BSG_Symbolicate.c in Sources */ = {isa = PBXBuildFile; fileRef = 01A2C540271EB9B300A27B23 /* BSG_Symbolicate.c */; }; @@ -1336,6 +1338,8 @@ 01847D942644140F00ADA4C7 /* BSGInternalErrorReporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BSGInternalErrorReporter.h; sourceTree = ""; }; 01847D952644140F00ADA4C7 /* BSGInternalErrorReporter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BSGInternalErrorReporter.m; sourceTree = ""; }; 01847DAB26441A5E00ADA4C7 /* BSGInternalErrorReporterTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BSGInternalErrorReporterTests.m; sourceTree = ""; }; + 01935AE0275E68E9007498B3 /* UIApplicationStub.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UIApplicationStub.h; sourceTree = ""; }; + 01935AE1275E68E9007498B3 /* UIApplicationStub.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UIApplicationStub.m; sourceTree = ""; }; 01937CF9257A7B4C00F2DE31 /* Bugsnag+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Bugsnag+Private.h"; sourceTree = ""; }; 01937D11257A814D00F2DE31 /* BugsnagMetadata+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BugsnagMetadata+Private.h"; sourceTree = ""; }; 01937D2E257A83A900F2DE31 /* BugsnagApp+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BugsnagApp+Private.h"; sourceTree = ""; }; @@ -1795,6 +1799,8 @@ 004E35392487B375007FBAE4 /* Tests-Bridging-Header.h */, CBA22499251E429C00B87416 /* TestSupport.h */, CBA2249A251E429C00B87416 /* TestSupport.m */, + 01935AE0275E68E9007498B3 /* UIApplicationStub.h */, + 01935AE1275E68E9007498B3 /* UIApplicationStub.m */, 013D9CCF26C5262F0077F0AD /* UISceneStub.h */, 013D9CD026C5262F0077F0AD /* UISceneStub.m */, 01E8765C256684E700F4B70A /* URLSessionMock.h */, @@ -2780,6 +2786,7 @@ 008967782486D43700DC48C2 /* BSG_KSMachHeadersTests.m in Sources */, 0089673F2486D43700DC48C2 /* BugsnagAppTest.m in Sources */, 0089675A2486D43700DC48C2 /* BugsnagEnabledBreadcrumbTest.m in Sources */, + 01935AE2275E68E9007498B3 /* UIApplicationStub.m in Sources */, 008967422486D43700DC48C2 /* BugsnagSessionTrackerStopTest.m in Sources */, E701FAAF2490EFE8008D842F /* ConfigurationApiValidationTest.m in Sources */, 008967452486D43700DC48C2 /* BugsnagTests.m in Sources */, @@ -3138,6 +3145,7 @@ 01847DAE26441A5E00ADA4C7 /* BSGInternalErrorReporterTests.m in Sources */, 004E35372487AFF2007FBAE4 /* BugsnagHandledStateTest.m in Sources */, 016875C8258D003200DFFF69 /* NSUserDefaultsStub.m in Sources */, + 01935AE3275E68E9007498B3 /* UIApplicationStub.m in Sources */, 01C17AE92542ED7F00C102C9 /* KSCrashReportWriterTests.m in Sources */, 00896A422486DBDD00DC48C2 /* BSGConfigurationBuilderTests.m in Sources */, 008967682486D43700DC48C2 /* BugsnagNotifierTest.m in Sources */, diff --git a/Bugsnag/KSCrash/Source/KSCrash/Recording/BSG_KSSystemInfo.m b/Bugsnag/KSCrash/Source/KSCrash/Recording/BSG_KSSystemInfo.m index 1b0bf77db..1aa4f4bc5 100644 --- a/Bugsnag/KSCrash/Source/KSCrash/Recording/BSG_KSSystemInfo.m +++ b/Bugsnag/KSCrash/Source/KSCrash/Recording/BSG_KSSystemInfo.m @@ -453,6 +453,7 @@ + (BOOL)isRunningInAppExtension { } #if BSG_PLATFORM_IOS || BSG_PLATFORM_TVOS + + (UIApplicationState)currentAppState { // Only checked outside of app extensions since sharedApplication is // unavailable to extension UIKit APIs @@ -460,24 +461,32 @@ + (UIApplicationState)currentAppState { return UIApplicationStateActive; } - UIApplicationState(^getState)(void) = ^() { + UIApplication * (^ getSharedApplication)(void) = ^() { // Calling this API indirectly to avoid a compile-time check that // [UIApplication sharedApplication] is not called from app extensions // (which is handled above) - UIApplication *app = [UIAPPLICATION performSelector:@selector(sharedApplication)]; - return [app applicationState]; + return [UIAPPLICATION performSelector:@selector(sharedApplication)]; }; + __block UIApplication *application = nil; if ([[NSThread currentThread] isMainThread]) { - return getState(); + application = getSharedApplication(); } else { // [UIApplication sharedApplication] is a main thread-only API - __block UIApplicationState state; dispatch_sync(dispatch_get_main_queue(), ^{ - state = getState(); + application = getSharedApplication(); }); - return state; } + + // There will be no UIApplication if UIApplicationMain() has not yet been + // called. This happens if started from a SwiftUI app's init() function or + // UIKit app's main() function. Returning UIApplicationStateActive (0) would + // be higly misleading, so we must check for this condition. + if (!application) { + return UIApplicationStateBackground; + } + + return application.applicationState; } + (BOOL)isInForeground:(UIApplicationState)state { @@ -494,6 +503,7 @@ + (BOOL)isInForeground:(UIApplicationState)state { return state == UIApplicationStateInactive || state == UIApplicationStateActive; } + #endif @end diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fc66e7c7..b5733c17c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ Changelog ========= +## TBD + +### Bug fixes + +* Fix `UIApplicationState` detection when started from a SwiftUI app's `init()` function. + This fixes false positive OOMs on iOS 15 for apps that have been prewarmed without transitioning to the foreground. + [#1248](https://github.com/bugsnag/bugsnag-cocoa/pull/1248) + ## 6.15.0 (2021-12-01) ### Enhancements diff --git a/Tests/BugsnagTests/BugsnagConfigurationTests.m b/Tests/BugsnagTests/BugsnagConfigurationTests.m index 437c3b096..ad75679b9 100644 --- a/Tests/BugsnagTests/BugsnagConfigurationTests.m +++ b/Tests/BugsnagTests/BugsnagConfigurationTests.m @@ -103,6 +103,7 @@ - (void)testAddOnSessionBlock { // Call onSession blocks BugsnagClient *client = [[BugsnagClient alloc] initWithConfiguration:config]; [client start]; + [client resumeSession]; [self waitForExpectationsWithTimeout:5.0 handler:nil]; } @@ -183,6 +184,7 @@ - (void)testAddOnSessionBlockThenRemove { // Call onSession blocks BugsnagClient *client = [[BugsnagClient alloc] initWithConfiguration:config]; [client start]; + [client resumeSession]; [self waitForExpectations:@[expectation1] timeout:1.0]; // Check it's called on new session start diff --git a/Tests/BugsnagTests/UIApplicationStub.h b/Tests/BugsnagTests/UIApplicationStub.h new file mode 100644 index 000000000..ac060b71f --- /dev/null +++ b/Tests/BugsnagTests/UIApplicationStub.h @@ -0,0 +1,26 @@ +// +// UIApplicationStub.h +// Bugsnag +// +// Created by Nick Dowell on 06/12/2021. +// Copyright © 2021 Bugsnag Inc. All rights reserved. +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UIApplicationStub : NSObject + +@property (nonatomic) UIApplicationState applicationState; + +@end + +@interface XCTestCase (UIApplicationStub) + +- (void)setUpUIApplicationStub; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Tests/BugsnagTests/UIApplicationStub.m b/Tests/BugsnagTests/UIApplicationStub.m new file mode 100644 index 000000000..1d347bb1d --- /dev/null +++ b/Tests/BugsnagTests/UIApplicationStub.m @@ -0,0 +1,38 @@ +// +// UIApplicationStub.m +// Bugsnag +// +// Created by Nick Dowell on 06/12/2021. +// Copyright © 2021 Bugsnag Inc. All rights reserved. +// + +#import "UIApplicationStub.h" + +#import + + +@implementation UIApplicationStub + +- (BOOL)isKindOfClass:(Class)aClass { + return aClass == [UIApplication class] || [super isKindOfClass:aClass]; +} + +@end + + +@implementation XCTestCase (UIApplicationStub) + +- (void)setUpUIApplicationStub { + Method method = class_getClassMethod([UIApplication class], @selector(sharedApplication)); + NSParameterAssert(method != NULL); + + void *originalImplementation = method_setImplementation(method, imp_implementationWithBlock(^(){ + return [[UIApplicationStub alloc] init]; + })); + + [self addTeardownBlock:^{ + method_setImplementation(method, originalImplementation); + }]; +} + +@end diff --git a/Tests/KSCrashTests/KSCrashState_Tests.m b/Tests/KSCrashTests/KSCrashState_Tests.m index 9f25d725c..f269a41db 100755 --- a/Tests/KSCrashTests/KSCrashState_Tests.m +++ b/Tests/KSCrashTests/KSCrashState_Tests.m @@ -30,6 +30,10 @@ #import "BSG_KSCrashState.h" #import "BSG_KSCrashC.h" +#if TARGET_OS_TV +#import "UIApplicationStub.h" +#endif + @interface bsg_kscrashstate_Tests : FileBasedTestCase @end @@ -37,6 +41,17 @@ @interface bsg_kscrashstate_Tests : FileBasedTestCase @implementation bsg_kscrashstate_Tests +#if TARGET_OS_TV // Not needed on iOS because there the tests are injected into a host app + +- (void)setUp +{ + [self setUpUIApplicationStub]; // These tests assume applicationState == .active + + [super setUp]; +} + +#endif + - (void) testInitRelaunch { BSG_KSCrash_State context = {0}; diff --git a/Tests/KSCrashTests/KSSystemInfo_Tests.m b/Tests/KSCrashTests/KSSystemInfo_Tests.m index 354e912af..05f5fd755 100755 --- a/Tests/KSCrashTests/KSSystemInfo_Tests.m +++ b/Tests/KSCrashTests/KSSystemInfo_Tests.m @@ -31,6 +31,10 @@ #import "BSG_KSSystemInfo.h" #import "BSG_KSSystemInfoC.h" +#if TARGET_OS_TV +#import "UIApplicationStub.h" +#endif + @interface KSSystemInfo_Tests : XCTestCase @end @@ -61,7 +65,9 @@ - (void) testCopyProcessName #if BSG_PLATFORM_TVOS || BSG_PLATFORM_IOS - (void)testCurrentAppState { - // Should default to active as tests aren't in an app bundle +#if TARGET_OS_TV + [self setUpUIApplicationStub]; +#endif XCTAssertEqual(UIApplicationStateActive, [BSG_KSSystemInfo currentAppState]); } From cf2200db88c379155cddbe4e3752ba5d6f2ea098 Mon Sep 17 00:00:00 2001 From: Steve Kirkland-Walton Date: Tue, 7 Dec 2021 09:55:11 +0000 Subject: [PATCH 19/20] Remove debug output --- features/steps/cocoa_steps.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/features/steps/cocoa_steps.rb b/features/steps/cocoa_steps.rb index 9d40bb0c1..c7c86da00 100644 --- a/features/steps/cocoa_steps.rb +++ b/features/steps/cocoa_steps.rb @@ -194,7 +194,6 @@ def check_device_model(field, list) Then('the error is valid for the error reporting API') do platform = Maze::Helper.get_current_platform - STDOUT.puts "platform: #{platform}" case platform when 'ios' steps %( From 6da32bd371266b6ff4fa6f412878706e0fb2e9bc Mon Sep 17 00:00:00 2001 From: Karl Stenerud Date: Wed, 8 Dec 2021 12:51:20 +0100 Subject: [PATCH 20/20] Release v6.15.1 --- .jazzy.yaml | 4 ++-- Bugsnag.podspec.json | 4 ++-- Bugsnag/Payload/BugsnagNotifier.m | 2 +- BugsnagNetworkRequestPlugin.podspec.json | 6 +++--- CHANGELOG.md | 5 ++++- Framework/Info.plist | 2 +- Tests/BugsnagTests/Info.plist | 2 +- Tests/TestHost-iOS/Info.plist | 2 +- VERSION | 2 +- 9 files changed, 16 insertions(+), 13 deletions(-) diff --git a/.jazzy.yaml b/.jazzy.yaml index 1b2c72c02..58c2ba066 100644 --- a/.jazzy.yaml +++ b/.jazzy.yaml @@ -2,11 +2,11 @@ author_url: "https://www.bugsnag.com" author: "Bugsnag Inc" clean: false # avoid deleting docs/.git framework_root: "Bugsnag" -github_file_prefix: "https://github.com/bugsnag/bugsnag-cocoa/tree/v6.15.0/Bugsnag" +github_file_prefix: "https://github.com/bugsnag/bugsnag-cocoa/tree/v6.15.1/Bugsnag" github_url: "https://github.com/bugsnag/bugsnag-cocoa" hide_documentation_coverage: true module: "Bugsnag" -module_version: "6.15.0" +module_version: "6.15.1" objc: true output: "docs" readme: "README.md" diff --git a/Bugsnag.podspec.json b/Bugsnag.podspec.json index b775e63ed..c5d000204 100644 --- a/Bugsnag.podspec.json +++ b/Bugsnag.podspec.json @@ -1,6 +1,6 @@ { "name": "Bugsnag", - "version": "6.15.0", + "version": "6.15.1", "summary": "The Bugsnag crash reporting framework for Apple platforms.", "homepage": "https://bugsnag.com", "license": "MIT", @@ -9,7 +9,7 @@ }, "source": { "git": "https://github.com/bugsnag/bugsnag-cocoa.git", - "tag": "v6.15.0" + "tag": "v6.15.1" }, "frameworks": [ "Foundation", diff --git a/Bugsnag/Payload/BugsnagNotifier.m b/Bugsnag/Payload/BugsnagNotifier.m index e2b79c329..6f483767a 100644 --- a/Bugsnag/Payload/BugsnagNotifier.m +++ b/Bugsnag/Payload/BugsnagNotifier.m @@ -23,7 +23,7 @@ - (instancetype)init { #else _name = @"Bugsnag Objective-C"; #endif - _version = @"6.15.0"; + _version = @"6.15.1"; _url = @"https://github.com/bugsnag/bugsnag-cocoa"; _dependencies = @[]; } diff --git a/BugsnagNetworkRequestPlugin.podspec.json b/BugsnagNetworkRequestPlugin.podspec.json index 785ee8f18..fc401268b 100644 --- a/BugsnagNetworkRequestPlugin.podspec.json +++ b/BugsnagNetworkRequestPlugin.podspec.json @@ -1,16 +1,16 @@ { "name": "BugsnagNetworkRequestPlugin", - "version": "6.15.0", + "version": "6.15.1", "summary": "Network request monitoring support for Bugsnag.", "homepage": "https://bugsnag.com", "license": "MIT", "authors": { "Bugsnag": "notifiers@bugsnag.com" }, - "readme": "https://raw.githubusercontent.com/bugsnag/bugsnag-cocoa/v6.15.0/BugsnagNetworkRequestPlugin/README.md", + "readme": "https://raw.githubusercontent.com/bugsnag/bugsnag-cocoa/v6.15.1/BugsnagNetworkRequestPlugin/README.md", "source": { "git": "https://github.com/bugsnag/bugsnag-cocoa.git", - "tag": "v6.15.0" + "tag": "v6.15.1" }, "dependencies": { "Bugsnag": "~> 6.13" diff --git a/CHANGELOG.md b/CHANGELOG.md index b5733c17c..025979850 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ Changelog ========= -## TBD +## 6.15.1 (2021-12-08) ### Bug fixes @@ -9,6 +9,9 @@ Changelog This fixes false positive OOMs on iOS 15 for apps that have been prewarmed without transitioning to the foreground. [#1248](https://github.com/bugsnag/bugsnag-cocoa/pull/1248) +* Load configuration from the plist instead of using defaults when calling Bugsnag.start(withApiKey:) + [#1245](https://github.com/bugsnag/bugsnag-cocoa/pull/1245) + ## 6.15.0 (2021-12-01) ### Enhancements diff --git a/Framework/Info.plist b/Framework/Info.plist index e728d3cee..02c4cc05d 100644 --- a/Framework/Info.plist +++ b/Framework/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 6.15.0 + 6.15.1 CFBundleVersion 1 diff --git a/Tests/BugsnagTests/Info.plist b/Tests/BugsnagTests/Info.plist index 6ac8155ed..82d9552c8 100644 --- a/Tests/BugsnagTests/Info.plist +++ b/Tests/BugsnagTests/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 6.15.0 + 6.15.1 CFBundleVersion 1 diff --git a/Tests/TestHost-iOS/Info.plist b/Tests/TestHost-iOS/Info.plist index deaf6d034..b0e9bf1f5 100644 --- a/Tests/TestHost-iOS/Info.plist +++ b/Tests/TestHost-iOS/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 6.15.0 + 6.15.1 CFBundleVersion 1 LSRequiresIPhoneOS diff --git a/VERSION b/VERSION index a3748c562..d36e8d82f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -6.15.0 +6.15.1