From 1db81a4e35d3d55b02ca24651bea37ee25f69342 Mon Sep 17 00:00:00 2001 From: Gustavo Ambrozio Date: Thu, 14 Sep 2023 12:02:39 -1000 Subject: [PATCH 1/3] Fixes issue when using Bugsnag on a WatchOS app The code was trying to access an extension but on latest WatchOS we can have a standalone app. --- Bugsnag/Helpers/BSGRunContext.m | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/Bugsnag/Helpers/BSGRunContext.m b/Bugsnag/Helpers/BSGRunContext.m index d48bc6b85..e06e6b85a 100644 --- a/Bugsnag/Helpers/BSGRunContext.m +++ b/Bugsnag/Helpers/BSGRunContext.m @@ -112,8 +112,13 @@ static bool GetIsActive(void) { #endif #if TARGET_OS_WATCH - WKExtension *ext = [WKExtension sharedExtension]; - return ext && ext.applicationState == WKApplicationStateActive; + if ([BSG_KSSystemInfo isRunningInAppExtension]) { + WKExtension *ext = [WKExtension sharedExtension]; + return ext && ext.applicationState == WKApplicationStateActive; + } else { + WKApplication *app = [WKApplication sharedApplication]; + return app && app.applicationState == WKApplicationStateActive; + } #endif } @@ -170,8 +175,13 @@ static bool GetIsForeground(void) { #endif #if TARGET_OS_WATCH - WKExtension *ext = [WKExtension sharedExtension]; - return ext && ext.applicationState != WKApplicationStateBackground; + if ([BSG_KSSystemInfo isRunningInAppExtension]) { + WKExtension *ext = [WKExtension sharedExtension]; + return ext && ext.applicationState != WKApplicationStateBackground; + } else { + WKApplication *app = [WKApplication sharedApplication]; + return app && app.applicationState == WKApplicationStateBackground; + } #endif } From 214457261d45cbad0eff80e4813c40ed99b7ce0e Mon Sep 17 00:00:00 2001 From: Karl Stenerud Date: Thu, 12 Oct 2023 09:47:08 +0200 Subject: [PATCH 2/3] WKApplication is only available on WatchOS 7+ --- Bugsnag/Helpers/BSGRunContext.m | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Bugsnag/Helpers/BSGRunContext.m b/Bugsnag/Helpers/BSGRunContext.m index e06e6b85a..c7ce2a57b 100644 --- a/Bugsnag/Helpers/BSGRunContext.m +++ b/Bugsnag/Helpers/BSGRunContext.m @@ -115,9 +115,11 @@ static bool GetIsActive(void) { if ([BSG_KSSystemInfo isRunningInAppExtension]) { WKExtension *ext = [WKExtension sharedExtension]; return ext && ext.applicationState == WKApplicationStateActive; - } else { + } else if (@available(watchOS 7.0, *)) { WKApplication *app = [WKApplication sharedApplication]; return app && app.applicationState == WKApplicationStateActive; + } else { + return true; } #endif } @@ -178,9 +180,11 @@ static bool GetIsForeground(void) { if ([BSG_KSSystemInfo isRunningInAppExtension]) { WKExtension *ext = [WKExtension sharedExtension]; return ext && ext.applicationState != WKApplicationStateBackground; - } else { + } else if (@available(watchOS 7.0, *)) { WKApplication *app = [WKApplication sharedApplication]; return app && app.applicationState == WKApplicationStateBackground; + } else { + return true; } #endif } From bbe5cfcd5534572a58453b37c4f1a792f0d6c5ed Mon Sep 17 00:00:00 2001 From: Karl Stenerud Date: Thu, 9 Nov 2023 14:19:56 +0100 Subject: [PATCH 3/3] Override the main bundle in watchos unit tests to add an NSExtension field to the bundle dictionary. --- Bugsnag.xcodeproj/project.pbxproj | 28 +++++- .../BugsnagNetworkRequestPluginTests.m | 1 + Tests/BugsnagTests/BSGAppKitTests.m | 4 +- Tests/BugsnagTests/BSGClientObserverTests.m | 5 +- .../BSGConfigurationBuilderTests.m | 4 +- Tests/BugsnagTests/BSGConnectivityTest.m | 4 +- Tests/BugsnagTests/BSGDefinesTests.m | 4 +- ...SGEventUploadKSCrashReportOperationTests.m | 5 +- Tests/BugsnagTests/BSGFeatureFlagStoreTests.m | 6 +- .../BSGInternalErrorReporterTests.m | 5 +- .../BugsnagTests/BSGJSONSerializationTests.m | 4 +- .../BugsnagTests/BSGNetworkBreadcrumbTests.m | 6 +- .../BSGNotificationBreadcrumbsTests.m | 5 +- Tests/BugsnagTests/BSGOutOfMemoryTests.m | 4 +- Tests/BugsnagTests/BSGRunContextTests.m | 5 +- Tests/BugsnagTests/BSGSerializationTests.m | 4 +- .../BSGStorageMigratorV0V1Tests.m | 6 +- Tests/BugsnagTests/BSGTelemetryTests.m | 4 +- Tests/BugsnagTests/BSGTestCase.h | 17 ++++ Tests/BugsnagTests/BSGTestCase.mm | 91 +++++++++++++++++++ Tests/BugsnagTests/BSGUtilsTests.m | 4 +- Tests/BugsnagTests/BugsnagApiClientTest.m | 5 +- Tests/BugsnagTests/BugsnagApiValidationTest.m | 6 +- Tests/BugsnagTests/BugsnagAppTest.m | 4 +- Tests/BugsnagTests/BugsnagBreadcrumbsTest.m | 5 +- Tests/BugsnagTests/BugsnagClientMirrorTest.m | 6 +- .../BugsnagClientPayloadInfoTest.m | 5 +- Tests/BugsnagTests/BugsnagClientTests.m | 5 +- Tests/BugsnagTests/BugsnagCollectionsTests.m | 5 +- .../BugsnagTests/BugsnagConfigurationTests.m | 4 +- Tests/BugsnagTests/BugsnagDeviceTest.m | 4 +- .../BugsnagEnabledBreadcrumbTest.m | 4 +- Tests/BugsnagTests/BugsnagErrorTest.m | 5 +- .../BugsnagEventFromKSCrashReportTest.m | 4 +- .../BugsnagEventPersistLoadTest.m | 4 +- Tests/BugsnagTests/BugsnagEventTests.m | 5 +- Tests/BugsnagTests/BugsnagHandledStateTest.m | 5 +- .../BugsnagMetadataRedactionTest.m | 4 +- Tests/BugsnagTests/BugsnagMetadataTests.m | 6 +- Tests/BugsnagTests/BugsnagNotifierTest.m | 6 +- Tests/BugsnagTests/BugsnagOnBreadcrumbTest.m | 4 +- Tests/BugsnagTests/BugsnagOnCrashTest.m | 4 +- Tests/BugsnagTests/BugsnagPluginTest.m | 4 +- Tests/BugsnagTests/BugsnagSessionTest.m | 5 +- .../BugsnagSessionTrackerStopTest.m | 4 +- .../BugsnagTests/BugsnagSessionTrackerTest.m | 4 +- Tests/BugsnagTests/BugsnagStackframeTest.m | 5 +- Tests/BugsnagTests/BugsnagStacktraceTest.m | 5 +- .../BugsnagSwiftConfigurationTests.swift | 3 +- .../BugsnagSwiftPublicAPITests.swift | 4 +- Tests/BugsnagTests/BugsnagSwiftTests.swift | 4 +- Tests/BugsnagTests/BugsnagTests.m | 4 +- .../BugsnagThreadSerializationTest.m | 4 +- Tests/BugsnagTests/BugsnagThreadTests.m | 6 +- Tests/BugsnagTests/BugsnagUserTest.m | 4 +- Tests/BugsnagTests/ClientApiValidationTest.m | 6 +- .../ConfigurationApiValidationTest.m | 6 +- Tests/BugsnagTests/EventApiValidationTest.m | 5 +- Tests/BugsnagTests/FileBasedTest.h | 4 +- Tests/BugsnagTests/FileBasedTest.m | 1 + Tests/BugsnagTests/Swizzle.h | 36 ++++++++ Tests/BugsnagTests/Swizzle.mm | 68 ++++++++++++++ Tests/BugsnagTests/Tests-Bridging-Header.h | 1 + Tests/KSCrashTests/BSG_KSFileTests.m | 1 + Tests/KSCrashTests/BSG_KSMachHeadersTests.m | 1 + Tests/KSCrashTests/KSCrashNames_Test.m | 8 -- Tests/KSCrashTests/KSCrashSentry_Tests.m | 1 + 67 files changed, 387 insertions(+), 123 deletions(-) create mode 100644 Tests/BugsnagTests/BSGTestCase.h create mode 100644 Tests/BugsnagTests/BSGTestCase.mm create mode 100644 Tests/BugsnagTests/Swizzle.h create mode 100644 Tests/BugsnagTests/Swizzle.mm diff --git a/Bugsnag.xcodeproj/project.pbxproj b/Bugsnag.xcodeproj/project.pbxproj index d1843abe5..2907142e6 100644 --- a/Bugsnag.xcodeproj/project.pbxproj +++ b/Bugsnag.xcodeproj/project.pbxproj @@ -721,6 +721,14 @@ 01FF490728BF8B7B001F817B /* BugsnagInternals.h in Headers */ = {isa = PBXBuildFile; fileRef = 01FF490528BF8B7B001F817B /* BugsnagInternals.h */; }; 01FF490828BF8B7B001F817B /* BugsnagInternals.h in Headers */ = {isa = PBXBuildFile; fileRef = 01FF490528BF8B7B001F817B /* BugsnagInternals.h */; }; 01FF490928BF8B7B001F817B /* BugsnagInternals.h in Headers */ = {isa = PBXBuildFile; fileRef = 01FF490528BF8B7B001F817B /* BugsnagInternals.h */; }; + 093EB6602AFE447E006EB7E3 /* Swizzle.mm in Sources */ = {isa = PBXBuildFile; fileRef = 093EB65F2AFE447E006EB7E3 /* Swizzle.mm */; }; + 093EB6612AFE447E006EB7E3 /* Swizzle.mm in Sources */ = {isa = PBXBuildFile; fileRef = 093EB65F2AFE447E006EB7E3 /* Swizzle.mm */; }; + 093EB6622AFE447E006EB7E3 /* Swizzle.mm in Sources */ = {isa = PBXBuildFile; fileRef = 093EB65F2AFE447E006EB7E3 /* Swizzle.mm */; }; + 093EB6632AFE447E006EB7E3 /* Swizzle.mm in Sources */ = {isa = PBXBuildFile; fileRef = 093EB65F2AFE447E006EB7E3 /* Swizzle.mm */; }; + 093EB6662AFE4580006EB7E3 /* BSGTestCase.mm in Sources */ = {isa = PBXBuildFile; fileRef = 093EB6652AFE4580006EB7E3 /* BSGTestCase.mm */; }; + 093EB6672AFE4580006EB7E3 /* BSGTestCase.mm in Sources */ = {isa = PBXBuildFile; fileRef = 093EB6652AFE4580006EB7E3 /* BSGTestCase.mm */; }; + 093EB6682AFE4580006EB7E3 /* BSGTestCase.mm in Sources */ = {isa = PBXBuildFile; fileRef = 093EB6652AFE4580006EB7E3 /* BSGTestCase.mm */; }; + 093EB6692AFE4580006EB7E3 /* BSGTestCase.mm in Sources */ = {isa = PBXBuildFile; fileRef = 093EB6652AFE4580006EB7E3 /* BSGTestCase.mm */; }; 3A700A9424A63ABC0068CD1B /* BugsnagThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A700A8024A63A8E0068CD1B /* BugsnagThread.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3A700A9524A63AC50068CD1B /* BugsnagSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A700A8124A63A8E0068CD1B /* BugsnagSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3A700A9624A63AC60068CD1B /* BugsnagStackframe.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A700A8224A63A8E0068CD1B /* BugsnagStackframe.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -1539,6 +1547,10 @@ 01E8765D256684E700F4B70A /* URLSessionMock.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = URLSessionMock.m; sourceTree = ""; }; 01F9FCB528929336005EDD8C /* BSGSerializationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BSGSerializationTests.m; sourceTree = ""; }; 01FF490528BF8B7B001F817B /* BugsnagInternals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BugsnagInternals.h; sourceTree = ""; }; + 093EB65E2AFE447E006EB7E3 /* Swizzle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Swizzle.h; sourceTree = ""; }; + 093EB65F2AFE447E006EB7E3 /* Swizzle.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Swizzle.mm; sourceTree = ""; }; + 093EB6642AFE4580006EB7E3 /* BSGTestCase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BSGTestCase.h; sourceTree = ""; }; + 093EB6652AFE4580006EB7E3 /* BSGTestCase.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = BSGTestCase.mm; sourceTree = ""; }; 3A700A8024A63A8E0068CD1B /* BugsnagThread.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BugsnagThread.h; sourceTree = ""; }; 3A700A8124A63A8E0068CD1B /* BugsnagSession.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BugsnagSession.h; sourceTree = ""; }; 3A700A8224A63A8E0068CD1B /* BugsnagStackframe.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BugsnagStackframe.h; sourceTree = ""; }; @@ -1934,8 +1946,6 @@ 00AD1C7F24869B0E00A27979 /* BugsnagTests */ = { isa = PBXGroup; children = ( - CBEC893E2A4ACD230088A3CE /* FileBasedTest.h */, - CBEC893F2A4ACD230088A3CE /* FileBasedTest.m */, 019480D32625F3EB00E833ED /* BSGAppKitTests.m */, 008966BD2486D43500DC48C2 /* BSGClientObserverTests.m */, 00896A3F2486DBDD00DC48C2 /* BSGConfigurationBuilderTests.m */, @@ -1953,6 +1963,8 @@ 01F9FCB528929336005EDD8C /* BSGSerializationTests.m */, CB6419AA25A73E8C00613D25 /* BSGStorageMigratorV0V1Tests.m */, 017DCF9A287422BB000ECB22 /* BSGTelemetryTests.m */, + 093EB6642AFE4580006EB7E3 /* BSGTestCase.h */, + 093EB6652AFE4580006EB7E3 /* BSGTestCase.mm */, 01DE903B26CEAF9E00455213 /* BSGUtilsTests.m */, CB9103632502320A00E9D1E2 /* BugsnagApiClientTest.m */, E701FA9E2490EF4A008D842F /* BugsnagApiValidationTest.m */, @@ -1995,9 +2007,13 @@ E701FAAE2490EFE8008D842F /* ConfigurationApiValidationTest.m */, 01BDB21425DEC02900A91FAF /* Data */, E701FAAA2490EFD9008D842F /* EventApiValidationTest.m */, + CBEC893E2A4ACD230088A3CE /* FileBasedTest.h */, + CBEC893F2A4ACD230088A3CE /* FileBasedTest.m */, 00E636C324878FFC006CBF1A /* Info.plist */, 01B14C55251CE55F00118748 /* report-react-native-promise-rejection.json */, 008966B72486D43500DC48C2 /* report.json */, + 093EB65E2AFE447E006EB7E3 /* Swizzle.h */, + 093EB65F2AFE447E006EB7E3 /* Swizzle.mm */, 004E35392487B375007FBAE4 /* Tests-Bridging-Header.h */, CBA22499251E429C00B87416 /* TestSupport.h */, CBA2249A251E429C00B87416 /* TestSupport.m */, @@ -3149,6 +3165,7 @@ 0089679F2486D43700DC48C2 /* KSCrashSentry_Tests.m in Sources */, 008967872486D43700DC48C2 /* KSCrashSentry_NSException_Tests.m in Sources */, 0089679C2486D43700DC48C2 /* KSFileUtils_Tests.m in Sources */, + 093EB6602AFE447E006EB7E3 /* Swizzle.mm in Sources */, 008966EE2486D43700DC48C2 /* BugsnagClientPayloadInfoTest.m in Sources */, 010F80C228645B4200D6569E /* BSGDefinesTests.m in Sources */, 01BDB1F525DEBFB200A91FAF /* BSGEventUploadKSCrashReportOperationTests.m in Sources */, @@ -3168,6 +3185,7 @@ 008967152486D43700DC48C2 /* BugsnagCollectionsTests.m in Sources */, 01E8765E256684E700F4B70A /* URLSessionMock.m in Sources */, 008967AB2486D43700DC48C2 /* BSG_KSMachTests.m in Sources */, + 093EB6662AFE4580006EB7E3 /* BSGTestCase.mm in Sources */, 0089672A2486D43700DC48C2 /* BugsnagStacktraceTest.m in Sources */, 01847DAC26441A5E00ADA4C7 /* BSGInternalErrorReporterTests.m in Sources */, 0163BF5925823D8D008DC28B /* BSGNotificationBreadcrumbsTests.m in Sources */, @@ -3315,6 +3333,7 @@ 008967822486D43700DC48C2 /* KSSystemInfo_Tests.m in Sources */, 008967612486D43700DC48C2 /* BugsnagBreadcrumbsTest.m in Sources */, 01DE903D26CEAF9E00455213 /* BSGUtilsTests.m in Sources */, + 093EB6672AFE4580006EB7E3 /* BSGTestCase.mm in Sources */, CB156242270707740097334C /* KSCrashNames_Test.m in Sources */, 008967012486D43700DC48C2 /* BugsnagEventPersistLoadTest.m in Sources */, 0089671C2486D43700DC48C2 /* BugsnagSessionTest.m in Sources */, @@ -3341,6 +3360,7 @@ 004E353B2487B3B3007FBAE4 /* BugsnagSwiftPublicAPITests.swift in Sources */, 0089677C2486D43700DC48C2 /* RFC3339DateTool_Tests.m in Sources */, CBEC89412A4ACD240088A3CE /* FileBasedTest.m in Sources */, + 093EB6612AFE447E006EB7E3 /* Swizzle.mm in Sources */, 01A2958728B667C2005FCC8C /* BSGNetworkBreadcrumbTests.m in Sources */, 008967552486D43700DC48C2 /* BugsnagOnCrashTest.m in Sources */, 008967A02486D43700DC48C2 /* KSCrashSentry_Tests.m in Sources */, @@ -3481,6 +3501,7 @@ 01B6BB7E25D5777F00FC4DE6 /* BugsnagSwiftPublicAPITests.swift in Sources */, 0089677A2486D43700DC48C2 /* BSG_KSMachHeadersTests.m in Sources */, 0089672C2486D43700DC48C2 /* BugsnagStacktraceTest.m in Sources */, + 093EB6682AFE4580006EB7E3 /* BSGTestCase.mm in Sources */, 008966F32486D43700DC48C2 /* BugsnagMetadataRedactionTest.m in Sources */, 008967382486D43700DC48C2 /* BugsnagMetadataTests.m in Sources */, 008967832486D43700DC48C2 /* KSSystemInfo_Tests.m in Sources */, @@ -3514,6 +3535,7 @@ 008967442486D43700DC48C2 /* BugsnagSessionTrackerStopTest.m in Sources */, CB26E9BC28350E0C005A1865 /* UISceneStub.m in Sources */, 008967982486D43700DC48C2 /* KSCrashState_Tests.m in Sources */, + 093EB6622AFE447E006EB7E3 /* Swizzle.mm in Sources */, 008967772486D43700DC48C2 /* XCTestCase+KSCrash.m in Sources */, 01A2958828B667C2005FCC8C /* BSGNetworkBreadcrumbTests.m in Sources */, CBEC89422A4ACD240088A3CE /* FileBasedTest.m in Sources */, @@ -3748,7 +3770,9 @@ CB28F0B828294DE1003AB200 /* BSGConfigurationBuilderTests.m in Sources */, CB28F0DB282A4BA6003AB200 /* BugsnagMetadataTests.m in Sources */, CB28F0B028294D4F003AB200 /* KSFileUtils_Tests.m in Sources */, + 093EB6632AFE447E006EB7E3 /* Swizzle.mm in Sources */, CB28F0DC282A4BEE003AB200 /* BugsnagSessionTrackerTest.m in Sources */, + 093EB6692AFE4580006EB7E3 /* BSGTestCase.mm in Sources */, CB28F0B728294DE1003AB200 /* BSGFeatureFlagStoreTests.m in Sources */, 010F80C528645B4200D6569E /* BSGDefinesTests.m in Sources */, CB28F0A028294D44003AB200 /* BSG_KSFileTests.m in Sources */, diff --git a/BugsnagNetworkRequestPlugin/BugsnagNetworkRequestPluginTests/BugsnagNetworkRequestPluginTests.m b/BugsnagNetworkRequestPlugin/BugsnagNetworkRequestPluginTests/BugsnagNetworkRequestPluginTests.m index f3ce61d3c..0e11b7ffc 100644 --- a/BugsnagNetworkRequestPlugin/BugsnagNetworkRequestPluginTests/BugsnagNetworkRequestPluginTests.m +++ b/BugsnagNetworkRequestPlugin/BugsnagNetworkRequestPluginTests/BugsnagNetworkRequestPluginTests.m @@ -87,6 +87,7 @@ - (void)resetBreadcrumbs { } - (void)setUp { + [super setUp]; [BSGURLSessionTracingDelegate setClient:(id)self]; [self resetBreadcrumbs]; } diff --git a/Tests/BugsnagTests/BSGAppKitTests.m b/Tests/BugsnagTests/BSGAppKitTests.m index c11002925..565d7bac8 100644 --- a/Tests/BugsnagTests/BSGAppKitTests.m +++ b/Tests/BugsnagTests/BSGAppKitTests.m @@ -6,9 +6,9 @@ // Copyright © 2021 Bugsnag Inc. All rights reserved. // -#import +#import "BSGTestCase.h" -@interface BSGAppKitTests : XCTestCase +@interface BSGAppKitTests : BSGTestCase @end diff --git a/Tests/BugsnagTests/BSGClientObserverTests.m b/Tests/BugsnagTests/BSGClientObserverTests.m index 32f165b9c..a9a60f846 100644 --- a/Tests/BugsnagTests/BSGClientObserverTests.m +++ b/Tests/BugsnagTests/BSGClientObserverTests.m @@ -6,7 +6,7 @@ // Copyright © 2020 Bugsnag. All rights reserved. // -#import +#import "BSGTestCase.h" #import "Bugsnag.h" #import "BugsnagClient+Private.h" @@ -15,7 +15,7 @@ #import "BugsnagMetadata+Private.h" #import "BugsnagUser+Private.h" -@interface BSGClientObserverTests : XCTestCase +@interface BSGClientObserverTests : BSGTestCase @property BugsnagClient *client; @property BSGClientObserverEvent event; @property id value; @@ -24,6 +24,7 @@ @interface BSGClientObserverTests : XCTestCase @implementation BSGClientObserverTests - (void)setUp { + [super setUp]; BugsnagConfiguration *config = [[BugsnagConfiguration alloc] initWithApiKey:DUMMY_APIKEY_32CHAR_1]; self.client = [Bugsnag startWithConfiguration:config]; diff --git a/Tests/BugsnagTests/BSGConfigurationBuilderTests.m b/Tests/BugsnagTests/BSGConfigurationBuilderTests.m index 0aa05ce2c..682c79c32 100644 --- a/Tests/BugsnagTests/BSGConfigurationBuilderTests.m +++ b/Tests/BugsnagTests/BSGConfigurationBuilderTests.m @@ -1,4 +1,4 @@ -#import +#import "BSGTestCase.h" #import #import "BSGConfigurationBuilder.h" @@ -6,7 +6,7 @@ #import "BugsnagTestConstants.h" #import -@interface BSGConfigurationBuilderTests : XCTestCase +@interface BSGConfigurationBuilderTests : BSGTestCase @end @implementation BSGConfigurationBuilderTests diff --git a/Tests/BugsnagTests/BSGConnectivityTest.m b/Tests/BugsnagTests/BSGConnectivityTest.m index 75f18f5f2..7eefe6563 100644 --- a/Tests/BugsnagTests/BSGConnectivityTest.m +++ b/Tests/BugsnagTests/BSGConnectivityTest.m @@ -1,9 +1,9 @@ -#import +#import "BSGTestCase.h" #import "BSGConnectivity.h" #import "BSGDefines.h" -@interface BSGConnectivityTest : XCTestCase +@interface BSGConnectivityTest : BSGTestCase @end @implementation BSGConnectivityTest diff --git a/Tests/BugsnagTests/BSGDefinesTests.m b/Tests/BugsnagTests/BSGDefinesTests.m index e68b13b38..dc5154542 100644 --- a/Tests/BugsnagTests/BSGDefinesTests.m +++ b/Tests/BugsnagTests/BSGDefinesTests.m @@ -6,11 +6,11 @@ // Copyright © 2022 Bugsnag Inc. All rights reserved. // -#import +#import "BSGTestCase.h" #import "BSGDefines.h" -@interface BSGDefinesTests : XCTestCase +@interface BSGDefinesTests : BSGTestCase @end diff --git a/Tests/BugsnagTests/BSGEventUploadKSCrashReportOperationTests.m b/Tests/BugsnagTests/BSGEventUploadKSCrashReportOperationTests.m index 86a3bf28d..3874b8e99 100644 --- a/Tests/BugsnagTests/BSGEventUploadKSCrashReportOperationTests.m +++ b/Tests/BugsnagTests/BSGEventUploadKSCrashReportOperationTests.m @@ -6,13 +6,14 @@ // Copyright © 2021 Bugsnag Inc. All rights reserved. // +#import "BSGTestCase.h" + #import -#import #import "BSGEventUploadKSCrashReportOperation.h" #import "BSGInternalErrorReporter.h" -@interface BSGEventUploadKSCrashReportOperationTests : XCTestCase +@interface BSGEventUploadKSCrashReportOperationTests : BSGTestCase @property NSString *errorClass; @property NSString *context; diff --git a/Tests/BugsnagTests/BSGFeatureFlagStoreTests.m b/Tests/BugsnagTests/BSGFeatureFlagStoreTests.m index 8144687d6..296f8cfd5 100644 --- a/Tests/BugsnagTests/BSGFeatureFlagStoreTests.m +++ b/Tests/BugsnagTests/BSGFeatureFlagStoreTests.m @@ -6,11 +6,11 @@ // Copyright © 2021 Bugsnag Inc. All rights reserved. // -#import "BSGFeatureFlagStore.h" +#import "BSGTestCase.h" -#import +#import "BSGFeatureFlagStore.h" -@interface BSGFeatureFlagStoreTests : XCTestCase +@interface BSGFeatureFlagStoreTests : BSGTestCase @end diff --git a/Tests/BugsnagTests/BSGInternalErrorReporterTests.m b/Tests/BugsnagTests/BSGInternalErrorReporterTests.m index 2948d5154..a9f75b620 100644 --- a/Tests/BugsnagTests/BSGInternalErrorReporterTests.m +++ b/Tests/BugsnagTests/BSGInternalErrorReporterTests.m @@ -6,7 +6,7 @@ // Copyright © 2021 Bugsnag Inc. All rights reserved. // -#import +#import "BSGTestCase.h" #import @@ -18,7 +18,7 @@ #import "BugsnagNotifier.h" #import "BSGPersistentDeviceID.h" -@interface BSGInternalErrorReporterTests : XCTestCase +@interface BSGInternalErrorReporterTests : BSGTestCase @property (nonatomic) BugsnagConfiguration *configuration; @@ -27,6 +27,7 @@ @interface BSGInternalErrorReporterTests : XCTestCase @implementation BSGInternalErrorReporterTests - (void)setUp { + [super setUp]; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wnonnull" [BSGInternalErrorReporter setSharedInstance:nil]; diff --git a/Tests/BugsnagTests/BSGJSONSerializationTests.m b/Tests/BugsnagTests/BSGJSONSerializationTests.m index 531768040..2f37482e2 100644 --- a/Tests/BugsnagTests/BSGJSONSerializationTests.m +++ b/Tests/BugsnagTests/BSGJSONSerializationTests.m @@ -6,11 +6,11 @@ // Copyright © 2020 Bugsnag Inc. All rights reserved. // -#import +#import "BSGTestCase.h" #import "BSGJSONSerialization.h" -@interface BSGJSONSerializationTests : XCTestCase +@interface BSGJSONSerializationTests : BSGTestCase @end @implementation BSGJSONSerializationTests diff --git a/Tests/BugsnagTests/BSGNetworkBreadcrumbTests.m b/Tests/BugsnagTests/BSGNetworkBreadcrumbTests.m index e488e03e7..d52968b5d 100644 --- a/Tests/BugsnagTests/BSGNetworkBreadcrumbTests.m +++ b/Tests/BugsnagTests/BSGNetworkBreadcrumbTests.m @@ -5,11 +5,11 @@ // Created by Nick Dowell on 22/09/2021. // -#import "BSGNetworkBreadcrumb.h" +#import "BSGTestCase.h" -#import +#import "BSGNetworkBreadcrumb.h" -@interface BSGNetworkBreadcrumbTests : XCTestCase +@interface BSGNetworkBreadcrumbTests : BSGTestCase @end diff --git a/Tests/BugsnagTests/BSGNotificationBreadcrumbsTests.m b/Tests/BugsnagTests/BSGNotificationBreadcrumbsTests.m index efef0cf7c..98a3614b5 100644 --- a/Tests/BugsnagTests/BSGNotificationBreadcrumbsTests.m +++ b/Tests/BugsnagTests/BSGNotificationBreadcrumbsTests.m @@ -6,7 +6,7 @@ // Copyright © 2020 Bugsnag Inc. All rights reserved. // -#import +#import "BSGTestCase.h" #import @@ -19,7 +19,7 @@ #endif -@interface BSGNotificationBreadcrumbsTests : XCTestCase +@interface BSGNotificationBreadcrumbsTests : BSGTestCase @property NSNotificationCenter *notificationCenter; @property id notificationObject; @@ -114,6 +114,7 @@ @implementation BSGNotificationBreadcrumbsTests #pragma mark Setup - (void)setUp { + [super setUp]; self.breadcrumb = nil; BugsnagConfiguration *configuration = [[BugsnagConfiguration alloc] initWithApiKey:@"0192837465afbecd0192837465afbecd"]; self.notificationBreadcrumbs = [[BSGNotificationBreadcrumbs alloc] initWithConfiguration:configuration breadcrumbSink:self]; diff --git a/Tests/BugsnagTests/BSGOutOfMemoryTests.m b/Tests/BugsnagTests/BSGOutOfMemoryTests.m index aeda8869e..8cafa6c4f 100644 --- a/Tests/BugsnagTests/BSGOutOfMemoryTests.m +++ b/Tests/BugsnagTests/BSGOutOfMemoryTests.m @@ -1,4 +1,4 @@ -#import +#import "BSGTestCase.h" #import "BSGFileLocations.h" #import "BSGRunContext.h" @@ -10,7 +10,7 @@ #import "BugsnagSystemState.h" #import "BugsnagTestConstants.h" -@interface BSGOutOfMemoryTests : XCTestCase +@interface BSGOutOfMemoryTests : BSGTestCase @end @implementation BSGOutOfMemoryTests diff --git a/Tests/BugsnagTests/BSGRunContextTests.m b/Tests/BugsnagTests/BSGRunContextTests.m index 0fb7ee656..beda07936 100644 --- a/Tests/BugsnagTests/BSGRunContextTests.m +++ b/Tests/BugsnagTests/BSGRunContextTests.m @@ -6,18 +6,19 @@ // Copyright © 2022 Bugsnag Inc. All rights reserved. // -#import +#import "BSGTestCase.h" #import "BSGFileLocations.h" #import "BSGRunContext.h" -@interface BSGRunContextTests : XCTestCase +@interface BSGRunContextTests : BSGTestCase @end @implementation BSGRunContextTests - (void)setUp { + [super setUp]; if (!bsg_runContext) { BSGRunContextInit(BSGFileLocations.current.runContext); } diff --git a/Tests/BugsnagTests/BSGSerializationTests.m b/Tests/BugsnagTests/BSGSerializationTests.m index c36621781..1b5dce9ed 100644 --- a/Tests/BugsnagTests/BSGSerializationTests.m +++ b/Tests/BugsnagTests/BSGSerializationTests.m @@ -6,11 +6,11 @@ // Copyright © 2022 Bugsnag Inc. All rights reserved. // -#import +#import "BSGTestCase.h" #import "BSGSerialization.h" -@interface BSGSerializationTests : XCTestCase +@interface BSGSerializationTests : BSGTestCase @end diff --git a/Tests/BugsnagTests/BSGStorageMigratorV0V1Tests.m b/Tests/BugsnagTests/BSGStorageMigratorV0V1Tests.m index 1c928d61c..f4e857a8d 100644 --- a/Tests/BugsnagTests/BSGStorageMigratorV0V1Tests.m +++ b/Tests/BugsnagTests/BSGStorageMigratorV0V1Tests.m @@ -6,13 +6,14 @@ // Copyright © 2021 Bugsnag Inc. All rights reserved. // -#import +#import "BSGTestCase.h" + #import "BSGStorageMigratorV0V1.h" #import "BugsnagClient+Private.h" #import "BugsnagConfiguration+Private.h" #import "BugsnagTestConstants.h" -@interface BSGStorageMigratorV0V1Tests : XCTestCase +@interface BSGStorageMigratorV0V1Tests : BSGTestCase @end @@ -79,6 +80,7 @@ - (NSDictionary *)getFiles { } - (void)setUp { + [super setUp]; NSFileManager *fm = [NSFileManager defaultManager]; NSBundle *bundle = [NSBundle bundleForClass:[self class]]; NSString *cachesPath = [self getCachesDir]; diff --git a/Tests/BugsnagTests/BSGTelemetryTests.m b/Tests/BugsnagTests/BSGTelemetryTests.m index 264cdecc5..889697bd6 100644 --- a/Tests/BugsnagTests/BSGTelemetryTests.m +++ b/Tests/BugsnagTests/BSGTelemetryTests.m @@ -6,14 +6,14 @@ // Copyright © 2022 Bugsnag Inc. All rights reserved. // -#import +#import "BSGTestCase.h" #import #import "BSGTelemetry.h" #import "BugsnagTestConstants.h" -@interface BSGTelemetryTests : XCTestCase +@interface BSGTelemetryTests : BSGTestCase @end diff --git a/Tests/BugsnagTests/BSGTestCase.h b/Tests/BugsnagTests/BSGTestCase.h new file mode 100644 index 000000000..1986a7fe4 --- /dev/null +++ b/Tests/BugsnagTests/BSGTestCase.h @@ -0,0 +1,17 @@ +// +// BSGTestCase.h +// Bugsnag +// +// Created by Karl Stenerud on 10.11.23. +// Copyright © 2023 Bugsnag Inc. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface BSGTestCase : XCTestCase + +@end + +NS_ASSUME_NONNULL_END diff --git a/Tests/BugsnagTests/BSGTestCase.mm b/Tests/BugsnagTests/BSGTestCase.mm new file mode 100644 index 000000000..91008a43d --- /dev/null +++ b/Tests/BugsnagTests/BSGTestCase.mm @@ -0,0 +1,91 @@ +// +// BSGTestCase.m +// Bugsnag +// +// Created by Karl Stenerud on 10.11.23. +// Copyright © 2023 Bugsnag Inc. All rights reserved. +// + +#import "BSGTestCase.h" +#import "Swizzle.h" +#import + +using namespace bugsnag; + +@interface BSGWatchKitBundle: NSProxy + +@property(nonatomic,readwrite) NSBundle *bundle; +@property(nonatomic,readwrite) NSDictionary *dict; + +- (instancetype) initWithBundle:(NSBundle *)bundle; + +@end + +@implementation BSGWatchKitBundle + +- (instancetype) initWithBundle:(NSBundle *)bundle { + // Force the main bundle's dictionary to have an NSExtension section on WatchOS. + // This is necessary because the unit tests run in an extension environment but + // don't set this field that is normally present in a real environment, which + // confuses our extension detection code in + // Bugsnag/KSCrash/Source/KSCrash/Recording/BSG_KSSystemInfo.m + NSMutableDictionary *dict = [NSBundle.mainBundle.infoDictionary mutableCopy]; + if (dict[@"NSExtension"] == nil) { + dict[@"NSExtension"] = @{ + @"NSExtensionAttributes": @{ + @"WKAppBundleIdentifier": @"com.bugsnag.swift-watchos.watchkitapp", + }, + @"NSExtensionPointIdentifier": @"com.apple.watchkit", + }; + } + _dict = dict; + _bundle = bundle; + + return self; +} + +- (void)forwardInvocation:(NSInvocation *)invocation +{ + if (self.bundle) { + [invocation setTarget:self.bundle]; + [invocation invoke]; + } +} + +- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel +{ + if ([self.bundle methodSignatureForSelector:sel]) { + return [self.bundle methodSignatureForSelector:sel]; + } else { + return [super methodSignatureForSelector:sel]; + } +} + +- (NSDictionary *)infoDictionary { + return self.dict; +} + +@end + + +@implementation BSGTestCase + +- (void)setUp { + if ([super respondsToSelector:@selector(setUp)]) { + [super setUp]; + } + +#if TARGET_OS_WATCH + static _Atomic(bool) hasSwizzled = false; + bool expectedValue = false; + if (atomic_compare_exchange_strong(&hasSwizzled, &expectedValue, true)) { + BSGWatchKitBundle *bundleProxy = [[BSGWatchKitBundle alloc] initWithBundle:NSBundle.mainBundle]; + ObjCSwizzle::setClassMethodImplementation(NSBundle.class, @selector(mainBundle), ^NSBundle *{ + return (NSBundle *)bundleProxy; + }); + } + +#endif +} + +@end diff --git a/Tests/BugsnagTests/BSGUtilsTests.m b/Tests/BugsnagTests/BSGUtilsTests.m index 70e9d9853..d87da8441 100644 --- a/Tests/BugsnagTests/BSGUtilsTests.m +++ b/Tests/BugsnagTests/BSGUtilsTests.m @@ -6,11 +6,11 @@ // Copyright © 2021 Bugsnag Inc. All rights reserved. // -#import +#import "BSGTestCase.h" #import "BSGUtils.h" -@interface BSGUtilsTests : XCTestCase +@interface BSGUtilsTests : BSGTestCase @end @implementation BSGUtilsTests diff --git a/Tests/BugsnagTests/BugsnagApiClientTest.m b/Tests/BugsnagTests/BugsnagApiClientTest.m index 4abfb2992..dcdfdf391 100644 --- a/Tests/BugsnagTests/BugsnagApiClientTest.m +++ b/Tests/BugsnagTests/BugsnagApiClientTest.m @@ -6,13 +6,14 @@ // Copyright © 2020 Bugsnag Inc. All rights reserved. // -#import +#import "BSGTestCase.h" + #import "BugsnagApiClient.h" #import #import "BugsnagTestConstants.h" #import "URLSessionMock.h" -@interface BugsnagApiClientTest : XCTestCase +@interface BugsnagApiClientTest : BSGTestCase @end diff --git a/Tests/BugsnagTests/BugsnagApiValidationTest.m b/Tests/BugsnagTests/BugsnagApiValidationTest.m index b204e0c48..0d3dd7a3c 100644 --- a/Tests/BugsnagTests/BugsnagApiValidationTest.m +++ b/Tests/BugsnagTests/BugsnagApiValidationTest.m @@ -6,7 +6,8 @@ // Copyright © 2020 Bugsnag Inc. All rights reserved. // -#import +#import "BSGTestCase.h" + #import #import "BugsnagTestConstants.h" #import "TestSupport.h" @@ -14,13 +15,14 @@ /** * Validates that the Bugsnag API interface handles any invalid input gracefully. */ -@interface BugsnagApiValidationTest : XCTestCase +@interface BugsnagApiValidationTest : BSGTestCase @end @implementation BugsnagApiValidationTest - (void)setUp { + [super setUp]; [TestSupport purgePersistentData]; [Bugsnag startWithApiKey:DUMMY_APIKEY_32CHAR_1]; } diff --git a/Tests/BugsnagTests/BugsnagAppTest.m b/Tests/BugsnagTests/BugsnagAppTest.m index 94f1a19a7..092c85bdf 100644 --- a/Tests/BugsnagTests/BugsnagAppTest.m +++ b/Tests/BugsnagTests/BugsnagAppTest.m @@ -6,7 +6,7 @@ // Copyright © 2020 Bugsnag. All rights reserved. // -#import +#import "BSGTestCase.h" #import "BSG_KSSystemInfo.h" #import "BugsnagApp+Private.h" @@ -16,7 +16,7 @@ #include -@interface BugsnagAppTest : XCTestCase +@interface BugsnagAppTest : BSGTestCase @property NSDictionary *data; @property BugsnagConfiguration *config; @property NSString *codeBundleId; diff --git a/Tests/BugsnagTests/BugsnagBreadcrumbsTest.m b/Tests/BugsnagTests/BugsnagBreadcrumbsTest.m index 465269d06..26edd15d2 100644 --- a/Tests/BugsnagTests/BugsnagBreadcrumbsTest.m +++ b/Tests/BugsnagTests/BugsnagBreadcrumbsTest.m @@ -6,6 +6,8 @@ // // +#import "BSGTestCase.h" + #import "BSGUtils.h" #import "BSG_KSJSONCodec.h" #import "Bugsnag.h" @@ -15,7 +17,6 @@ #import "BugsnagTestConstants.h" #import "BSGDefines.h" -#import #import #import #import @@ -61,7 +62,7 @@ static id JSONObject(void (^ block)(BSG_KSCrashReportWriter *writer)) { }); } -@interface BugsnagBreadcrumbsTest : XCTestCase +@interface BugsnagBreadcrumbsTest : BSGTestCase @property(nonatomic, strong) BugsnagBreadcrumbs *crumbs; @end diff --git a/Tests/BugsnagTests/BugsnagClientMirrorTest.m b/Tests/BugsnagTests/BugsnagClientMirrorTest.m index e31ff1a27..3a5d9acb9 100644 --- a/Tests/BugsnagTests/BugsnagClientMirrorTest.m +++ b/Tests/BugsnagTests/BugsnagClientMirrorTest.m @@ -6,11 +6,12 @@ // Copyright © 2020 Bugsnag. All rights reserved. // -#import +#import "BSGTestCase.h" + #import #import -@interface BugsnagClientMirrorTest : XCTestCase +@interface BugsnagClientMirrorTest : BSGTestCase @property NSSet *clientMethodsNotRequiredOnBugsnag; @property NSSet *bugsnagMethodsNotRequiredOnClient; @end @@ -26,6 +27,7 @@ @interface BugsnagClientMirrorTest : XCTestCase @implementation BugsnagClientMirrorTest - (void)setUp { + [super setUp]; // the following methods are implemented on BugsnagClient but do not need to // be mirrored on the Bugsnag facade self.clientMethodsNotRequiredOnBugsnag = [NSSet setWithArray:@[ diff --git a/Tests/BugsnagTests/BugsnagClientPayloadInfoTest.m b/Tests/BugsnagTests/BugsnagClientPayloadInfoTest.m index 31cca1552..fe60f3a31 100755 --- a/Tests/BugsnagTests/BugsnagClientPayloadInfoTest.m +++ b/Tests/BugsnagTests/BugsnagClientPayloadInfoTest.m @@ -6,20 +6,21 @@ // Copyright © 2020 Bugsnag. All rights reserved. // -#import +#import "BSGTestCase.h" #import "BugsnagAppWithState+Private.h" #import "BugsnagConfiguration.h" #import "BugsnagDeviceWithState+Private.h" #import "BugsnagTestConstants.h" -@interface BugsnagClientPayloadInfoTest : XCTestCase +@interface BugsnagClientPayloadInfoTest : BSGTestCase @end @implementation BugsnagClientPayloadInfoTest - (void)setUp { + [super setUp]; BugsnagConfiguration *configuration = [[BugsnagConfiguration alloc] initWithApiKey:DUMMY_APIKEY_32CHAR_1]; [Bugsnag startWithConfiguration:configuration]; } diff --git a/Tests/BugsnagTests/BugsnagClientTests.m b/Tests/BugsnagTests/BugsnagClientTests.m index 0efbb186c..4dde42d3e 100644 --- a/Tests/BugsnagTests/BugsnagClientTests.m +++ b/Tests/BugsnagTests/BugsnagClientTests.m @@ -6,6 +6,8 @@ // Copyright © 2020 Bugsnag. All rights reserved. // +#import "BSGTestCase.h" + #import "BSGInternalErrorReporter.h" #import "BSGKeys.h" #import "BSGRunContext.h" @@ -19,7 +21,6 @@ #import "BugsnagUser.h" #import -#import /** * Tests for BugsnagClient. @@ -31,7 +32,7 @@ * * For these reasons, test cases should only be added here as a matter of last resort. */ -@interface BugsnagClientTests : XCTestCase +@interface BugsnagClientTests : BSGTestCase @end NSString *BSGFormatSeverity(BSGSeverity severity); diff --git a/Tests/BugsnagTests/BugsnagCollectionsTests.m b/Tests/BugsnagTests/BugsnagCollectionsTests.m index b376fb0cd..3d816573f 100644 --- a/Tests/BugsnagTests/BugsnagCollectionsTests.m +++ b/Tests/BugsnagTests/BugsnagCollectionsTests.m @@ -6,10 +6,11 @@ // Copyright © 2019 Bugsnag. All rights reserved. // -@import XCTest; +#import "BSGTestCase.h" + #import "BugsnagCollections.h" -@interface BugsnagCollectionsTests : XCTestCase +@interface BugsnagCollectionsTests : BSGTestCase @end @interface BugsnagCollectionsTests_DummyObject : NSObject diff --git a/Tests/BugsnagTests/BugsnagConfigurationTests.m b/Tests/BugsnagTests/BugsnagConfigurationTests.m index bbff7fe76..b21702bc9 100644 --- a/Tests/BugsnagTests/BugsnagConfigurationTests.m +++ b/Tests/BugsnagTests/BugsnagConfigurationTests.m @@ -2,7 +2,7 @@ * Unit test the BugsnagConfiguration class */ -#import +#import "BSGTestCase.h" #import "BugsnagConfiguration+Private.h" @@ -19,7 +19,7 @@ // MARK: - Tests // ============================================================================= -@interface BugsnagConfigurationTests : XCTestCase +@interface BugsnagConfigurationTests : BSGTestCase @end @implementation BugsnagConfigurationTests diff --git a/Tests/BugsnagTests/BugsnagDeviceTest.m b/Tests/BugsnagTests/BugsnagDeviceTest.m index d66039f94..f0bfd6e5e 100644 --- a/Tests/BugsnagTests/BugsnagDeviceTest.m +++ b/Tests/BugsnagTests/BugsnagDeviceTest.m @@ -6,13 +6,13 @@ // Copyright © 2020 Bugsnag. All rights reserved. // -#import +#import "BSGTestCase.h" #import "BSG_KSSystemInfo.h" #import "BugsnagDevice+Private.h" #import "BugsnagDeviceWithState+Private.h" -@interface BugsnagDeviceTest : XCTestCase +@interface BugsnagDeviceTest : BSGTestCase @property NSDictionary *data; @end diff --git a/Tests/BugsnagTests/BugsnagEnabledBreadcrumbTest.m b/Tests/BugsnagTests/BugsnagEnabledBreadcrumbTest.m index 06f33e8b9..7af6a20b9 100644 --- a/Tests/BugsnagTests/BugsnagEnabledBreadcrumbTest.m +++ b/Tests/BugsnagTests/BugsnagEnabledBreadcrumbTest.m @@ -6,12 +6,12 @@ // Copyright © 2020 Bugsnag. All rights reserved. // -#import +#import "BSGTestCase.h" #import "BugsnagConfiguration+Private.h" #import "BugsnagTestConstants.h" -@interface BugsnagEnabledBreadcrumbTest : XCTestCase +@interface BugsnagEnabledBreadcrumbTest : BSGTestCase @end diff --git a/Tests/BugsnagTests/BugsnagErrorTest.m b/Tests/BugsnagTests/BugsnagErrorTest.m index 1662f9685..8838cf3cc 100644 --- a/Tests/BugsnagTests/BugsnagErrorTest.m +++ b/Tests/BugsnagTests/BugsnagErrorTest.m @@ -6,7 +6,7 @@ // Copyright © 2020 Bugsnag. All rights reserved. // -#import +#import "BSGTestCase.h" #import "BSGKeys.h" #import "BugsnagError+Private.h" @@ -17,13 +17,14 @@ NSString *BSGParseErrorMessage(NSDictionary *report, NSDictionary *error, NSString *errorType); -@interface BugsnagErrorTest : XCTestCase +@interface BugsnagErrorTest : BSGTestCase @property NSDictionary *event; @end @implementation BugsnagErrorTest - (void)setUp { + [super setUp]; NSDictionary *thread = @{ @"current_thread": @YES, @"crashed": @YES, diff --git a/Tests/BugsnagTests/BugsnagEventFromKSCrashReportTest.m b/Tests/BugsnagTests/BugsnagEventFromKSCrashReportTest.m index eb89ec446..b704af6d2 100644 --- a/Tests/BugsnagTests/BugsnagEventFromKSCrashReportTest.m +++ b/Tests/BugsnagTests/BugsnagEventFromKSCrashReportTest.m @@ -6,12 +6,12 @@ // Copyright © 2019 Bugsnag. All rights reserved. // -@import XCTest; +#import "BSGTestCase.h" #import "Bugsnag+Private.h" #import "BugsnagEvent+Private.h" -@interface BugsnagEventFromKSCrashReportTest : XCTestCase +@interface BugsnagEventFromKSCrashReportTest : BSGTestCase @property BugsnagEvent *event; @end diff --git a/Tests/BugsnagTests/BugsnagEventPersistLoadTest.m b/Tests/BugsnagTests/BugsnagEventPersistLoadTest.m index ad199cca8..10d9ef103 100644 --- a/Tests/BugsnagTests/BugsnagEventPersistLoadTest.m +++ b/Tests/BugsnagTests/BugsnagEventPersistLoadTest.m @@ -6,7 +6,7 @@ // Copyright © 2020 Bugsnag. All rights reserved. // -#import +#import "BSGTestCase.h" #import "BugsnagEvent+Private.h" #import "BugsnagAppWithState.h" @@ -22,7 +22,7 @@ #import "BugsnagStackframe.h" #import "BugsnagThread.h" -@interface BugsnagEventPersistLoadTest : XCTestCase +@interface BugsnagEventPersistLoadTest : BSGTestCase @property NSDictionary *eventData; @end diff --git a/Tests/BugsnagTests/BugsnagEventTests.m b/Tests/BugsnagTests/BugsnagEventTests.m index 7766508fd..a1d06753f 100644 --- a/Tests/BugsnagTests/BugsnagEventTests.m +++ b/Tests/BugsnagTests/BugsnagEventTests.m @@ -6,8 +6,7 @@ // // -#import -#import +#import "BSGTestCase.h" #import "BSG_RFC3339DateTool.h" #import "Bugsnag.h" @@ -22,7 +21,7 @@ #import "BugsnagTestConstants.h" #import "BugsnagTestsDummyClass.h" -@interface BugsnagEventTests : XCTestCase +@interface BugsnagEventTests : BSGTestCase @end @implementation BugsnagEventTests diff --git a/Tests/BugsnagTests/BugsnagHandledStateTest.m b/Tests/BugsnagTests/BugsnagHandledStateTest.m index 0a35ea49c..cf47d6e47 100644 --- a/Tests/BugsnagTests/BugsnagHandledStateTest.m +++ b/Tests/BugsnagTests/BugsnagHandledStateTest.m @@ -6,11 +6,12 @@ // Copyright © 2017 Bugsnag. All rights reserved. // -#import +#import "BSGTestCase.h" + #import #import "BugsnagHandledState.h" -@interface BugsnagHandledStateTest : XCTestCase +@interface BugsnagHandledStateTest : BSGTestCase @end diff --git a/Tests/BugsnagTests/BugsnagMetadataRedactionTest.m b/Tests/BugsnagTests/BugsnagMetadataRedactionTest.m index c0be86955..5b9ce8dbe 100644 --- a/Tests/BugsnagTests/BugsnagMetadataRedactionTest.m +++ b/Tests/BugsnagTests/BugsnagMetadataRedactionTest.m @@ -6,12 +6,12 @@ // Copyright © 2020 Bugsnag. All rights reserved. // -#import +#import "BSGTestCase.h" #import "BugsnagBreadcrumb+Private.h" #import "BugsnagEvent+Private.h" -@interface BugsnagMetadataRedactionTest : XCTestCase +@interface BugsnagMetadataRedactionTest : BSGTestCase @end diff --git a/Tests/BugsnagTests/BugsnagMetadataTests.m b/Tests/BugsnagTests/BugsnagMetadataTests.m index 24a121b9a..42b7677ca 100644 --- a/Tests/BugsnagTests/BugsnagMetadataTests.m +++ b/Tests/BugsnagTests/BugsnagMetadataTests.m @@ -6,17 +6,18 @@ // Copyright © 2020 Bugsnag. All rights reserved. // +#import "BSGTestCase.h" + #import "BugsnagMetadata.h" #import "BugsnagMetadata+Private.h" #import "BSGDefines.h" -#import #import #import // MARK: - Expose tested-class internals -@interface BugsnagMetadataTests : XCTestCase +@interface BugsnagMetadataTests : BSGTestCase @property BOOL delegateCalled; @property BugsnagMetadata *metadata; @end @@ -45,6 +46,7 @@ @implementation BugsnagMetadataTests @synthesize metadata; -(void) setUp { + [super setUp]; metadata = [[BugsnagMetadata alloc] init]; __weak __typeof__(self) weakSelf = self; diff --git a/Tests/BugsnagTests/BugsnagNotifierTest.m b/Tests/BugsnagTests/BugsnagNotifierTest.m index a89435ce1..e5dbe6c03 100644 --- a/Tests/BugsnagTests/BugsnagNotifierTest.m +++ b/Tests/BugsnagTests/BugsnagNotifierTest.m @@ -6,16 +6,18 @@ // Copyright © 2020 Bugsnag. All rights reserved. // -#import +#import "BSGTestCase.h" + #import "BugsnagNotifier.h" -@interface BugsnagNotifierTest : XCTestCase +@interface BugsnagNotifierTest : BSGTestCase @property BugsnagNotifier *notifier; @end @implementation BugsnagNotifierTest - (void)setUp { + [super setUp]; self.notifier = [BugsnagNotifier new]; self.notifier.name = @"Foo Notifier"; self.notifier.version = @"6.0.0"; diff --git a/Tests/BugsnagTests/BugsnagOnBreadcrumbTest.m b/Tests/BugsnagTests/BugsnagOnBreadcrumbTest.m index 877d9a2e0..f73d6b765 100644 --- a/Tests/BugsnagTests/BugsnagOnBreadcrumbTest.m +++ b/Tests/BugsnagTests/BugsnagOnBreadcrumbTest.m @@ -6,7 +6,7 @@ // Copyright © 2020 Bugsnag. All rights reserved. // -#import +#import "BSGTestCase.h" #import "Bugsnag.h" #import "BugsnagBreadcrumb+Private.h" @@ -15,7 +15,7 @@ #import "BugsnagTestConstants.h" #import "BugsnagBreadcrumbs.h" -@interface BugsnagOnBreadcrumbTest : XCTestCase +@interface BugsnagOnBreadcrumbTest : BSGTestCase @end @implementation BugsnagOnBreadcrumbTest diff --git a/Tests/BugsnagTests/BugsnagOnCrashTest.m b/Tests/BugsnagTests/BugsnagOnCrashTest.m index 7dd48d8bb..31bdaf35e 100644 --- a/Tests/BugsnagTests/BugsnagOnCrashTest.m +++ b/Tests/BugsnagTests/BugsnagOnCrashTest.m @@ -6,12 +6,12 @@ // Copyright © 2020 Bugsnag. All rights reserved. // -#import +#import "BSGTestCase.h" #import #import "BugsnagEvent+Private.h" -@interface BugsnagOnCrashTest : XCTestCase +@interface BugsnagOnCrashTest : BSGTestCase @end diff --git a/Tests/BugsnagTests/BugsnagPluginTest.m b/Tests/BugsnagTests/BugsnagPluginTest.m index 3a1393bec..06c89ae51 100644 --- a/Tests/BugsnagTests/BugsnagPluginTest.m +++ b/Tests/BugsnagTests/BugsnagPluginTest.m @@ -6,14 +6,14 @@ // Copyright © 2020 Bugsnag. All rights reserved. // -#import +#import "BSGTestCase.h" #import "BugsnagTestConstants.h" #import "Bugsnag.h" #import "BugsnagClient+Private.h" #import "BugsnagConfiguration+Private.h" -@interface BugsnagPluginTest : XCTestCase +@interface BugsnagPluginTest : BSGTestCase @end diff --git a/Tests/BugsnagTests/BugsnagSessionTest.m b/Tests/BugsnagTests/BugsnagSessionTest.m index a2c48040e..cf4600d63 100644 --- a/Tests/BugsnagTests/BugsnagSessionTest.m +++ b/Tests/BugsnagTests/BugsnagSessionTest.m @@ -6,7 +6,7 @@ // Copyright © 2017 Bugsnag. All rights reserved. // -#import +#import "BSGTestCase.h" #import "BugsnagApp+Private.h" #import "BugsnagConfiguration+Private.h" @@ -16,7 +16,7 @@ #import "BSG_RFC3339DateTool.h" #import "BugsnagTestConstants.h" -@interface BugsnagSessionTest : XCTestCase +@interface BugsnagSessionTest : BSGTestCase @property BugsnagApp *app; @property BugsnagDevice *device; @property NSDictionary *serializedSession; @@ -25,6 +25,7 @@ @interface BugsnagSessionTest : XCTestCase @implementation BugsnagSessionTest - (void)setUp { + [super setUp]; self.app = [self generateApp]; self.device = [self generateDevice]; self.serializedSession = [self generateSerializedSession]; diff --git a/Tests/BugsnagTests/BugsnagSessionTrackerStopTest.m b/Tests/BugsnagTests/BugsnagSessionTrackerStopTest.m index 7e1628330..53416fcc7 100644 --- a/Tests/BugsnagTests/BugsnagSessionTrackerStopTest.m +++ b/Tests/BugsnagTests/BugsnagSessionTrackerStopTest.m @@ -6,13 +6,13 @@ // Copyright © 2019 Bugsnag. All rights reserved. // -#import +#import "BSGTestCase.h" #import "BugsnagSession+Private.h" #import "BugsnagSessionTracker.h" #import "BugsnagTestConstants.h" -@interface BugsnagSessionTrackerStopTest : XCTestCase +@interface BugsnagSessionTrackerStopTest : BSGTestCase @property BugsnagConfiguration *configuration; @property BugsnagSessionTracker *tracker; @end diff --git a/Tests/BugsnagTests/BugsnagSessionTrackerTest.m b/Tests/BugsnagTests/BugsnagSessionTrackerTest.m index 016464429..13bf85853 100644 --- a/Tests/BugsnagTests/BugsnagSessionTrackerTest.m +++ b/Tests/BugsnagTests/BugsnagSessionTrackerTest.m @@ -6,7 +6,7 @@ // Copyright © 2017 Bugsnag. All rights reserved. // -#import +#import "BSGTestCase.h" #import "BugsnagUser.h" #import "BugsnagConfiguration+Private.h" @@ -16,7 +16,7 @@ #import "BSGDefines.h" #import "BSGWatchKit.h" -@interface BugsnagSessionTrackerTest : XCTestCase +@interface BugsnagSessionTrackerTest : BSGTestCase @property BugsnagConfiguration *configuration; @property BugsnagSessionTracker *sessionTracker; @property BugsnagUser *user; diff --git a/Tests/BugsnagTests/BugsnagStackframeTest.m b/Tests/BugsnagTests/BugsnagStackframeTest.m index bb584fd86..d8333fb7d 100644 --- a/Tests/BugsnagTests/BugsnagStackframeTest.m +++ b/Tests/BugsnagTests/BugsnagStackframeTest.m @@ -6,12 +6,12 @@ // Copyright © 2020 Bugsnag. All rights reserved. // -#import +#import "BSGTestCase.h" #import "BSG_KSMachHeaders.h" #import "BugsnagStackframe+Private.h" -@interface BugsnagStackframeTest : XCTestCase +@interface BugsnagStackframeTest : BSGTestCase @property NSDictionary *frameDict; @property NSArray *binaryImages; @end @@ -19,6 +19,7 @@ @interface BugsnagStackframeTest : XCTestCase @implementation BugsnagStackframeTest - (void)setUp { + [super setUp]; self.frameDict = @{ @"symbol_addr": @0x10b574fa0, @"instruction_addr": @0x10b5756bf, diff --git a/Tests/BugsnagTests/BugsnagStacktraceTest.m b/Tests/BugsnagTests/BugsnagStacktraceTest.m index 123184ac8..e11e94611 100644 --- a/Tests/BugsnagTests/BugsnagStacktraceTest.m +++ b/Tests/BugsnagTests/BugsnagStacktraceTest.m @@ -6,11 +6,11 @@ // Copyright © 2020 Bugsnag. All rights reserved. // -#import +#import "BSGTestCase.h" #import "BugsnagStacktrace.h" -@interface BugsnagStacktraceTest : XCTestCase +@interface BugsnagStacktraceTest : BSGTestCase @property NSDictionary *frameDict; @property NSArray *binaryImages; @end @@ -18,6 +18,7 @@ @interface BugsnagStacktraceTest : XCTestCase @implementation BugsnagStacktraceTest - (void)setUp { + [super setUp]; self.frameDict = @{ @"symbol_addr": @0x10b574fa0, @"instruction_addr": @0x10b5756bf, diff --git a/Tests/BugsnagTests/BugsnagSwiftConfigurationTests.swift b/Tests/BugsnagTests/BugsnagSwiftConfigurationTests.swift index b10f56e4f..fa648f29f 100644 --- a/Tests/BugsnagTests/BugsnagSwiftConfigurationTests.swift +++ b/Tests/BugsnagTests/BugsnagSwiftConfigurationTests.swift @@ -6,10 +6,9 @@ // Copyright © 2020 Bugsnag. All rights reserved. // -import XCTest import Bugsnag -class BugsnagSwiftConfigurationTests: XCTestCase { +class BugsnagSwiftConfigurationTests: BSGTestCase { /** * Objective C trailing-NSError* initializers are translated into throwing diff --git a/Tests/BugsnagTests/BugsnagSwiftPublicAPITests.swift b/Tests/BugsnagTests/BugsnagSwiftPublicAPITests.swift index a5b53d9a5..5b4ec5211 100644 --- a/Tests/BugsnagTests/BugsnagSwiftPublicAPITests.swift +++ b/Tests/BugsnagTests/BugsnagSwiftPublicAPITests.swift @@ -6,7 +6,7 @@ // Copyright © 2020 Bugsnag. All rights reserved. // -import XCTest +import Bugsnag /** * Test all public APIs from Swift. Purely existence tests, no attempt to verify correctness @@ -34,7 +34,7 @@ class myMetadata: NSObject, BugsnagMetadataStore, BugsnagClassLevelMetadataStore func clearMetadata(section sectionName: String, key: String) {} } -class BugsnagSwiftPublicAPITests: XCTestCase { +class BugsnagSwiftPublicAPITests: BSGTestCase { let apiKey = "01234567890123456789012345678901" let ex = NSException(name: NSExceptionName("exception"), diff --git a/Tests/BugsnagTests/BugsnagSwiftTests.swift b/Tests/BugsnagTests/BugsnagSwiftTests.swift index a30eab783..2e0511c63 100644 --- a/Tests/BugsnagTests/BugsnagSwiftTests.swift +++ b/Tests/BugsnagTests/BugsnagSwiftTests.swift @@ -7,9 +7,9 @@ // // Swift unit tests of global Bugsnag behaviour -import XCTest +import Bugsnag -class BugsnagSwiftTests: XCTestCase { +class BugsnagSwiftTests: BSGTestCase { /** * Confirm that the addMetadata() method is exposed to Swift correctly diff --git a/Tests/BugsnagTests/BugsnagTests.m b/Tests/BugsnagTests/BugsnagTests.m index 268f76665..da803d83b 100644 --- a/Tests/BugsnagTests/BugsnagTests.m +++ b/Tests/BugsnagTests/BugsnagTests.m @@ -7,7 +7,7 @@ // // Unit tests of global Bugsnag behaviour -#import +#import "BSGTestCase.h" #import "Bugsnag.h" #import "BugsnagClient+Private.h" @@ -18,7 +18,7 @@ // MARK: - BugsnagTests -@interface BugsnagTests : XCTestCase +@interface BugsnagTests : BSGTestCase @end @implementation BugsnagTests diff --git a/Tests/BugsnagTests/BugsnagThreadSerializationTest.m b/Tests/BugsnagTests/BugsnagThreadSerializationTest.m index 0a41b0c29..98e41a76e 100644 --- a/Tests/BugsnagTests/BugsnagThreadSerializationTest.m +++ b/Tests/BugsnagTests/BugsnagThreadSerializationTest.m @@ -3,11 +3,11 @@ // Copyright (c) 2018 Bugsnag. All rights reserved. // -#import +#import "BSGTestCase.h" #import "BugsnagEvent+Private.h" -@interface BugsnagThreadSerializationTest : XCTestCase +@interface BugsnagThreadSerializationTest : BSGTestCase @end @implementation BugsnagThreadSerializationTest diff --git a/Tests/BugsnagTests/BugsnagThreadTests.m b/Tests/BugsnagTests/BugsnagThreadTests.m index 6f664aa1f..75d9305e2 100644 --- a/Tests/BugsnagTests/BugsnagThreadTests.m +++ b/Tests/BugsnagTests/BugsnagThreadTests.m @@ -6,7 +6,7 @@ // Copyright © 2020 Bugsnag. All rights reserved. // -#import +#import "BSGTestCase.h" #import "BSG_KSMachHeaders.h" #import "BugsnagStackframe+Private.h" @@ -15,7 +15,7 @@ #import #import -@interface BugsnagThreadTests : XCTestCase +@interface BugsnagThreadTests : BSGTestCase @property NSArray *binaryImages; @property NSDictionary *thread; @end @@ -23,11 +23,13 @@ @interface BugsnagThreadTests : XCTestCase @implementation BugsnagThreadTests + (void)setUp { + [super setUp]; bsg_mach_headers_initialize(); bsg_mach_headers_get_images(); // Ensure call stack can be symbolicated } - (void)setUp { + [super setUp]; self.thread = @{ @"current_thread": @YES, @"crashed": @YES, diff --git a/Tests/BugsnagTests/BugsnagUserTest.m b/Tests/BugsnagTests/BugsnagUserTest.m index c834b89e3..b74779ed5 100644 --- a/Tests/BugsnagTests/BugsnagUserTest.m +++ b/Tests/BugsnagTests/BugsnagUserTest.m @@ -6,12 +6,12 @@ // Copyright © 2017 Bugsnag. All rights reserved. // -#import +#import "BSGTestCase.h" #import "BugsnagEvent+Private.h" #import "BugsnagUser+Private.h" -@interface BugsnagUserTest : XCTestCase +@interface BugsnagUserTest : BSGTestCase @end @implementation BugsnagUserTest diff --git a/Tests/BugsnagTests/ClientApiValidationTest.m b/Tests/BugsnagTests/ClientApiValidationTest.m index 75a5c3bca..b24edd3ae 100644 --- a/Tests/BugsnagTests/ClientApiValidationTest.m +++ b/Tests/BugsnagTests/ClientApiValidationTest.m @@ -6,20 +6,22 @@ // Copyright © 2020 Bugsnag Inc. All rights reserved. // -#import +#import "BSGTestCase.h" + #import #import "BugsnagTestConstants.h" /** * Validates that the Client API interface handles any invalid input gracefully. */ -@interface ClientApiValidationTest : XCTestCase +@interface ClientApiValidationTest : BSGTestCase @property BugsnagClient *client; @end @implementation ClientApiValidationTest - (void)setUp { + [super setUp]; BugsnagConfiguration *config = [[BugsnagConfiguration alloc] initWithApiKey:DUMMY_APIKEY_32CHAR_1]; [config addOnSendErrorBlock:^BOOL(BugsnagEvent *event) { return NO; diff --git a/Tests/BugsnagTests/ConfigurationApiValidationTest.m b/Tests/BugsnagTests/ConfigurationApiValidationTest.m index 2c4c0fb8b..3cb8a1101 100644 --- a/Tests/BugsnagTests/ConfigurationApiValidationTest.m +++ b/Tests/BugsnagTests/ConfigurationApiValidationTest.m @@ -6,7 +6,8 @@ // Copyright © 2020 Bugsnag Inc. All rights reserved. // -#import +#import "BSGTestCase.h" + #import #import "BugsnagConfiguration+Private.h" #import "BugsnagPlugin.h" @@ -23,13 +24,14 @@ - (void)unload {} /** * Validates that the Configuration API interface handles any invalid input gracefully. */ -@interface ConfigurationApiValidationTest : XCTestCase +@interface ConfigurationApiValidationTest : BSGTestCase @property BugsnagConfiguration *config; @end @implementation ConfigurationApiValidationTest - (void)setUp { + [super setUp]; self.config = [[BugsnagConfiguration alloc] initWithApiKey:DUMMY_APIKEY_32CHAR_1]; } diff --git a/Tests/BugsnagTests/EventApiValidationTest.m b/Tests/BugsnagTests/EventApiValidationTest.m index 164093a9a..5e964756f 100644 --- a/Tests/BugsnagTests/EventApiValidationTest.m +++ b/Tests/BugsnagTests/EventApiValidationTest.m @@ -6,7 +6,7 @@ // Copyright © 2020 Bugsnag Inc. All rights reserved. // -#import +#import "BSGTestCase.h" #import #import "BugsnagEvent+Private.h" @@ -14,13 +14,14 @@ /** * Validates that the Event API interface handles any invalid input gracefully. */ -@interface EventApiValidationTest : XCTestCase +@interface EventApiValidationTest : BSGTestCase @property BugsnagEvent *event; @end @implementation EventApiValidationTest - (void)setUp { + [super setUp]; self.event = [[BugsnagEvent alloc] initWithKSReport:@{@"user": @{}}]; } diff --git a/Tests/BugsnagTests/FileBasedTest.h b/Tests/BugsnagTests/FileBasedTest.h index 70e231638..270e78fd6 100644 --- a/Tests/BugsnagTests/FileBasedTest.h +++ b/Tests/BugsnagTests/FileBasedTest.h @@ -6,9 +6,9 @@ // Copyright © 2023 Bugsnag. All rights reserved. // -#import +#import "BSGTestCase.h" -@interface FileBasedTest : XCTestCase +@interface FileBasedTest : BSGTestCase @property(readwrite, nonatomic) NSString *filePath; diff --git a/Tests/BugsnagTests/FileBasedTest.m b/Tests/BugsnagTests/FileBasedTest.m index 219550380..849f11ab0 100644 --- a/Tests/BugsnagTests/FileBasedTest.m +++ b/Tests/BugsnagTests/FileBasedTest.m @@ -15,6 +15,7 @@ - (NSString *)newPath { } - (void)setUp { + [super setUp]; self.filePath = [self newPath]; } diff --git a/Tests/BugsnagTests/Swizzle.h b/Tests/BugsnagTests/Swizzle.h new file mode 100644 index 000000000..68c22611f --- /dev/null +++ b/Tests/BugsnagTests/Swizzle.h @@ -0,0 +1,36 @@ +// +// Swizzle.h +// Bugsnag +// +// Created by Karl Stenerud on 21.04.23. +// Copyright © 2023 Bugsnag. All rights reserved. +// + +#pragma once + +#import + +namespace bugsnag { + +class ObjCSwizzle { +public: + /** + * Replace a class's current method implementation with a new implementation block, returning the replaced one. + * Returns nil if the method was not found (in the class or any superclass). + */ + static IMP _Nullable setClassMethodImplementation(Class _Nonnull clazz, SEL _Nonnull selector, id _Nonnull implementationBlock) noexcept; + + /** + * Replace a class's override of a method (i.e. only if this class overrides the method). No superclass implementation is replaced. + * Returns nil if no method was replaced (either method not found, or this class doesn't overrde the method). + */ + static IMP _Nullable replaceInstanceMethodOverride(Class _Nonnull cls, SEL _Nonnull name, id _Nonnull block) noexcept; + + /** + * Get any classes or superclasses that implement the specified selector. + */ + static NSArray * _Nonnull getClassesWithSelector(Class _Nullable cls, SEL _Nonnull selector) noexcept; + +}; + +} diff --git a/Tests/BugsnagTests/Swizzle.mm b/Tests/BugsnagTests/Swizzle.mm new file mode 100644 index 000000000..abc784471 --- /dev/null +++ b/Tests/BugsnagTests/Swizzle.mm @@ -0,0 +1,68 @@ +// +// Swizzle.mm +// Bugsnag +// +// Created by Karl Stenerud on 21.04.23. +// Copyright © 2023 Bugsnag. All rights reserved. +// + +#import "Swizzle.h" +#import + +namespace bugsnag { + +IMP ObjCSwizzle::setClassMethodImplementation(Class _Nonnull clazz, SEL selector, id _Nonnull implementationBlock) noexcept { + Method method = class_getClassMethod(clazz, selector); + if (method) { + return method_setImplementation(method, imp_implementationWithBlock(implementationBlock)); + } else { + NSLog(@"Could not set IMP for selector %s on class %@", sel_getName(selector), clazz); + return nil; + } +} + +IMP ObjCSwizzle::replaceInstanceMethodOverride(Class clazz, SEL selector, id block) noexcept { + Method method = nullptr; + + // Not using class_getInstanceMethod because we don't want to modify the + // superclass's implementation. + auto methodCount = 0U; + Method *methods = class_copyMethodList(clazz, &methodCount); + if (methods) { + for (auto i = 0U; i < methodCount; i++) { + if (sel_isEqual(method_getName(methods[i]), selector)) { + method = methods[i]; + break; + } + } + free(methods); + } + + if (!method) { + // This is not considered an error. + return nil; + } + + return method_setImplementation(method, imp_implementationWithBlock(block)); +} + +NSArray *ObjCSwizzle::getClassesWithSelector(Class cls, SEL selector) noexcept { + NSMutableArray *result = [NSMutableArray new]; + for (; class_getInstanceMethod(cls, selector); cls = [cls superclass]) { + if (!cls) { + break; + } + Class superCls = [cls superclass]; + Method classMethod = class_getInstanceMethod(cls, selector); + Method superMethod = class_getInstanceMethod(superCls, selector); + IMP classIMP = classMethod ? method_getImplementation(classMethod) : nil; + IMP superIMP = superMethod ? method_getImplementation(superMethod) : nil; + if (classIMP != superIMP) { + [result addObject:(Class _Nonnull)cls]; + } + } + return result; +}; + + +} diff --git a/Tests/BugsnagTests/Tests-Bridging-Header.h b/Tests/BugsnagTests/Tests-Bridging-Header.h index c54081022..3603229d8 100644 --- a/Tests/BugsnagTests/Tests-Bridging-Header.h +++ b/Tests/BugsnagTests/Tests-Bridging-Header.h @@ -5,3 +5,4 @@ #import #import "BugsnagTestConstants.h" +#import "BSGTestCase.h" diff --git a/Tests/KSCrashTests/BSG_KSFileTests.m b/Tests/KSCrashTests/BSG_KSFileTests.m index 622563519..f4ad55f71 100644 --- a/Tests/KSCrashTests/BSG_KSFileTests.m +++ b/Tests/KSCrashTests/BSG_KSFileTests.m @@ -20,6 +20,7 @@ @interface BSG_KSFileTests : XCTestCase @implementation BSG_KSFileTests - (void)setUp { + [super setUp]; self.filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:[self description]]; self.fileDescriptor = open(self.filePath.fileSystemRepresentation, O_RDWR | O_CREAT | O_EXCL, 0644); } diff --git a/Tests/KSCrashTests/BSG_KSMachHeadersTests.m b/Tests/KSCrashTests/BSG_KSMachHeadersTests.m index 3d5370417..a41c082bd 100644 --- a/Tests/KSCrashTests/BSG_KSMachHeadersTests.m +++ b/Tests/KSCrashTests/BSG_KSMachHeadersTests.m @@ -53,6 +53,7 @@ @interface BSG_KSMachHeadersTests : XCTestCase @implementation BSG_KSMachHeadersTests - (void)setUp { + [super setUp]; bsg_mach_headers_initialize(); } diff --git a/Tests/KSCrashTests/KSCrashNames_Test.m b/Tests/KSCrashTests/KSCrashNames_Test.m index 01f1f17f2..77947e9fc 100644 --- a/Tests/KSCrashTests/KSCrashNames_Test.m +++ b/Tests/KSCrashTests/KSCrashNames_Test.m @@ -16,14 +16,6 @@ @interface KSCrashNames_Test : XCTestCase @implementation KSCrashNames_Test -- (void)setUp { - // Put setup code here. This method is called before the invocation of each test method in the class. -} - -- (void)tearDown { - // Put teardown code here. This method is called after the invocation of each test method in the class. -} - - (void)testValidStates { XCTAssertTrue(strcmp(bsg_kscrashthread_state_name(TH_STATE_RUNNING), "TH_STATE_RUNNING") == 0); XCTAssertTrue(strcmp(bsg_kscrashthread_state_name(TH_STATE_STOPPED), "TH_STATE_STOPPED") == 0); diff --git a/Tests/KSCrashTests/KSCrashSentry_Tests.m b/Tests/KSCrashTests/KSCrashSentry_Tests.m index c744d2370..4f6fa5365 100755 --- a/Tests/KSCrashTests/KSCrashSentry_Tests.m +++ b/Tests/KSCrashTests/KSCrashSentry_Tests.m @@ -44,6 +44,7 @@ @interface KSCrashSentry_Tests : XCTestCase @end @implementation KSCrashSentry_Tests - (void) setUp { + [super setUp]; bsg_kscrashsentry_installWithContext(&context, BSG_KSCrashTypeAll, onCrash); }