diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index eadba7c2c9a..d9659a7766c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -326,38 +326,6 @@ jobs: ~/Library/Logs/scan/*.log ./fastlane/test_output/** - # macos-11 doesn't have a simulator for iOS 12 - ui-tests-swift-ios-12: - name: UI Tests on iOS 12 Simulator - runs-on: macos-11 - strategy: - matrix: - target: ['ios_swift', 'ios_objc', 'tvos_swift'] - - steps: - - uses: actions/checkout@v3 - - # GH action images don't have an iOS 12.4 simulator. Therefore we have to download and install the simulator manually. - - name: Install iOS 12.4 simulator - run: | - gem install xcode-install - xcversion simulators --install='iOS 12.4' - xcrun simctl create custom-test-device "iPhone 8" "com.apple.CoreSimulator.SimRuntime.iOS-12-4" - - # GitHub Actions sometimes fail to launch the UI tests. Therefore we retry - - name: Run Fastlane - run: for i in {1..2}; do fastlane ui_tests_${{matrix.target}} device:"iPhone 8 (12.4)" address_sanitizer:false && break ; done - shell: sh - - - name: Archiving Raw Test Logs - uses: actions/upload-artifact@v3 - if: ${{ failure() || cancelled() }} - with: - name: raw-uitest-output-${{matrix.target}}-ios-12 - path: | - ~/Library/Logs/scan/*.log - ./fastlane/test_output/** - ui-tests-address-sanitizer: name: UI Tests with Address Sanitizer runs-on: macos-12 diff --git a/Sources/Sentry/SentryAppStartTracker.m b/Sources/Sentry/SentryAppStartTracker.m index 801c067d188..3b351d1aabb 100644 --- a/Sources/Sentry/SentryAppStartTracker.m +++ b/Sources/Sentry/SentryAppStartTracker.m @@ -67,6 +67,7 @@ - (instancetype)initWithCurrentDateProvider:(id)curre self.wasInBackground = NO; self.didFinishLaunchingTimestamp = [currentDateProvider date]; self.enablePreWarmedAppStartTracing = enablePreWarmedAppStartTracing; + self.isRunning = NO; } return self; } @@ -116,6 +117,8 @@ - (void)start # if SENTRY_HAS_UIKIT [self.appStateManager start]; # endif + + self.isRunning = YES; } - (void)buildAppStartMeasurement @@ -208,8 +211,8 @@ - (void)buildAppStartMeasurement SentrySDK.appStartMeasurement = appStartMeasurement; }; - // With only running this once we know that the process is a new one when the following - // code is executed. +// With only running this once we know that the process is a new one when the following +// code is executed. // We need to make sure the block runs on each test instead of only once # if TEST block(); @@ -285,6 +288,10 @@ - (void)stop [NSNotificationCenter.defaultCenter removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil]; + +# if TEST + self.isRunning = NO; +# endif } - (void)dealloc diff --git a/Sources/Sentry/include/SentryAppStartTracker.h b/Sources/Sentry/include/SentryAppStartTracker.h index 82a4f1d802e..461fe5d58ec 100644 --- a/Sources/Sentry/include/SentryAppStartTracker.h +++ b/Sources/Sentry/include/SentryAppStartTracker.h @@ -16,6 +16,8 @@ NS_ASSUME_NONNULL_BEGIN @interface SentryAppStartTracker : NSObject SENTRY_NO_INIT +@property (nonatomic) BOOL isRunning; + - (instancetype)initWithCurrentDateProvider:(id)currentDateProvider dispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper appStateManager:(SentryAppStateManager *)appStateManager diff --git a/Tests/SentryTests/Integrations/Performance/AppStartTracking/SentryAppStartTrackingIntegrationTests.swift b/Tests/SentryTests/Integrations/Performance/AppStartTracking/SentryAppStartTrackingIntegrationTests.swift index 4a327ab40dc..04146f54c97 100644 --- a/Tests/SentryTests/Integrations/Performance/AppStartTracking/SentryAppStartTrackingIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/Performance/AppStartTracking/SentryAppStartTrackingIntegrationTests.swift @@ -40,26 +40,35 @@ class SentryAppStartTrackingIntegrationTests: NotificationCenterTestCase { sut.stop() } - func testAppStartMeasuringEnabledAndSampleRate_DoesUpdatesAppState() { + func testAppStartMeasuringEnabledAndSampleRate_properlySetupTracker() throws { sut.install(with: fixture.options) + + let tracker = try XCTUnwrap(Dynamic(sut).tracker.asObject as? SentryAppStartTracker, "SentryAppStartTrackingIntegration should have a tracker") + try assertTrackerSetupAndRunning(tracker) + } + + func testUnistall_stopsTracker() throws { + sut.install(with: fixture.options) + + let tracker = try XCTUnwrap(Dynamic(sut).tracker.asObject as? SentryAppStartTracker, "SentryAppStartTrackingIntegration should have a tracker") + try assertTrackerSetupAndRunning(tracker) + sut.uninstall() - uiWindowDidBecomeVisible() - - XCTAssertNotNil(SentrySDK.getAppStartMeasurement()) + let isRunning = Dynamic(tracker).isRunning.asBool ?? true + XCTAssertFalse(isRunning, "AppStartTracking should not be running") } - func testNoSampleRate_DoesNotUpdatesAppState() { + func testNoSampleRate_noTracker() { let options = fixture.options options.tracesSampleRate = 0.0 options.tracesSampler = nil sut.install(with: options) - - uiWindowDidBecomeVisible() - - XCTAssertNil(SentrySDK.getAppStartMeasurement()) + + let tracker = Dynamic(sut).tracker.asAnyObject as? SentryAppStartTracker + XCTAssertNil(tracker) } - func testHybridSDKModeEnabled_DoesUpdatesAppState() { + func testHybridSDKModeEnabled_properlySetupTracker() throws { PrivateSentrySDKOnly.appStartMeasurementHybridSDKMode = true let options = fixture.options @@ -67,30 +76,27 @@ class SentryAppStartTrackingIntegrationTests: NotificationCenterTestCase { options.tracesSampler = nil sut.install(with: options) - uiWindowDidBecomeVisible() - - XCTAssertNotNil(SentrySDK.getAppStartMeasurement()) + let tracker = try XCTUnwrap(Dynamic(sut).tracker.asObject as? SentryAppStartTracker, "SentryAppStartTrackingIntegration should have a tracker") + try assertTrackerSetupAndRunning(tracker) } - func testOnlyAppStartMeasuringEnabled_DoesNotUpdatesAppState() { + func testOnlyAppStartMeasuringEnabled_noTracker() { let options = fixture.options options.tracesSampleRate = 0.0 options.tracesSampler = nil sut.install(with: options) - uiWindowDidBecomeVisible() - - XCTAssertNil(SentrySDK.getAppStartMeasurement()) + let tracker = Dynamic(sut).tracker.asAnyObject as? SentryAppStartTracker + XCTAssertNil(tracker) } - func testAutoPerformanceTrackingDisabled_DoesNotUpdatesAppState() { + func testAutoPerformanceTrackingDisabled_noTracker() { let options = fixture.options options.enableAutoPerformanceTracing = false sut.install(with: options) - uiWindowDidBecomeVisible() - - XCTAssertNil(SentrySDK.getAppStartMeasurement()) + let tracker = Dynamic(sut).tracker.asAnyObject as? SentryAppStartTracker + XCTAssertNil(tracker) } func test_PerformanceTrackingDisabled() { @@ -100,6 +106,22 @@ class SentryAppStartTrackingIntegrationTests: NotificationCenterTestCase { XCTAssertFalse(result) } + + func assertTrackerSetupAndRunning(_ tracker: SentryAppStartTracker) throws { + let dateProvider = Dynamic(tracker).currentDate.asObject as? DefaultCurrentDateProvider + + XCTAssertEqual(dateProvider, DefaultCurrentDateProvider.sharedInstance()) + + _ = try XCTUnwrap(Dynamic(tracker).dispatchQueue.asAnyObject as? SentryDispatchQueueWrapper, "Tracker does not have a dispatch queue.") + + let appStateManager = Dynamic(tracker).appStateManager.asObject as? SentryAppStateManager + + XCTAssertEqual(appStateManager, SentryDependencyContainer.sharedInstance().appStateManager) + + _ = try XCTUnwrap(Dynamic(tracker).sysctl.asObject as? SentrySysctl, "Tracker does not have a Sysctl") + + XCTAssertTrue(tracker.isRunning, "AppStartTracking should be running") + } } #endif diff --git a/Tests/SentryTests/SentryViewHierarchyTests.swift b/Tests/SentryTests/SentryViewHierarchyTests.swift index f55f1318ce9..8dfef6bb3b6 100644 --- a/Tests/SentryTests/SentryViewHierarchyTests.swift +++ b/Tests/SentryTests/SentryViewHierarchyTests.swift @@ -4,7 +4,6 @@ import XCTest #if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) class SentryViewHierarchyTests: XCTestCase { private class Fixture { - let uiApplication = TestSentryUIApplication() var sut: SentryViewHierarchy { @@ -16,10 +15,26 @@ class SentryViewHierarchyTests: XCTestCase { override func setUp() { super.setUp() + fixture = Fixture() SentryDependencyContainer.sharedInstance().application = fixture.uiApplication } + override func setUpWithError() throws { + try super.setUpWithError() + + /** + * This test is making iOS 13 simulator hang in GH workflow, + * thats why we need to check for iOS 13 or later. + * By testing this in the other versions of iOS we guarantee the behavior + * mean while, running an iOS 12 sample with Saucelabs ensures this feature + * is not crashing the app. + */ + guard #available(iOS 13, *) else { + throw XCTSkip("Skipping for iOS < 13") + } + } + override func tearDown() { super.tearDown() clearTestState() @@ -164,7 +179,7 @@ class SentryViewHierarchyTests: XCTestCase { ex.fulfill() XCTAssertTrue(Thread.isMainThread) } - + let dispatch = DispatchQueue(label: "background") dispatch.async { let _ = sut.fetch()