Skip to content

chore: [SDK-5022] add demo test crash flow - #1715

Open
fadi-george wants to merge 5 commits into
mainfrom
fadi/sdk-5022
Open

chore: [SDK-5022] add demo test crash flow#1715
fadi-george wants to merge 5 commits into
mainfrom
fadi/sdk-5022

Conversation

@fadi-george

Copy link
Copy Markdown
Collaborator

Description

One Line Summary

Adds a marked test-crash flow to the SwiftUI demo app.

Details

Motivation

The demo needs a deterministic way to exercise the SDK's uncaught Objective-C exception capture without treating unrelated host-app crashes as OneSignal failures.

Scope

Adds a secondary demo screen and crash action, plus an explicit userInfo marker recognized by the crash handler. Unmarked host-app exceptions remain ignored.

Other

Stacked on #1714.

Testing

Unit testing

Added crash-handler coverage for marked and unmarked host-app exceptions.

Manual testing

Triggered the demo crash and confirmed it is persisted and uploaded after relaunch.

Affected code checklist

  • Notifications
  • Outcomes
  • Sessions
  • In-App Messaging
  • REST API requests
  • Public API changes

Checklist

Overview

  • I have filled out all required sections above
  • PR does one thing
  • Any public API changes are explained above

Testing

  • I have included test coverage for these changes
  • Applicable automated tests pass
  • I have manually tested the demo flow

Final pass

  • Code is as readable as possible
  • I have reviewed this PR

Made with Cursor

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multi-model adversarial review (interrogate)

Intent

Add a deterministic demo test-crash flow that exercises the SDK's uncaught Objective-C exception capture without treating unrelated host-app crashes as OneSignal failures — via a SecondaryView crash action and a userInfo marker (OSCrashTestMarker) that lets OSLogCrashHandler persist marked host-stack exceptions. Unmarked host exceptions stay ignored. Stacked on #1714.

Reviewers

  • A: claude-fable-5-thinking-xhigh (6)
  • B: gpt-5.6-sol-xhigh (4)
  • C: cursor-grok-4.5-high-fast (7)
  • D: claude-opus-5-thinking-high (11)

Act On

  1. Undeclared public API ships a permanent attribution bypass (A/B/C/D) — public enum OSCrashTestMarker is new supported surface on distributed OneSignalOSCore, while the PR checklist leaves Public API changes unchecked. Commit 7f205d3a already did the same gate with a private static let exception name and zero public API; a0f0e53f traded that away. Prefer: (a) OSCore-owned raise helper so isOneSignalAtFault accepts the frame with no bypass, (b) restore private name-based marker + string literal in the demo, or (c) @_spi + document if a symbol is truly required.
  2. Marked crashes are unlabeled in telemetry (A/C/D) — marker is gate-only then discarded; CrashData gets RuntimeException + host stack + caller reason. Ops cannot filter demo pollution except brittle string match. Name-based predecessor self-labeled via exceptionType. Stamp a deterministic type/prefix when the marker branch admits the crash, or delete the bypass via the OSCore raise helper.
  3. Wrong-layer OR on the shared fatal path (A/C/D) — isMarkedTestCrash || isOneSignalAtFault encodes a demo concern into every uncaught-exception path. Code judo: raise from OneSignalOSCore so attribution already works; keep handle attribution-only.

Consider

  • Demo is the only app file importing OneSignalOSCore (C/D) — teaches sub-framework coupling for a string constant.
  • Unit tests call handle(...) directly; no raise→handler→persist→relaunch coverage (B/D). Thin cases: no NSNumber bridging, no previous-handler forward assert, reason: nil unlike demo.
  • TEMP_* pbxproj UUID churn vs documented xcodegen generate (A/B/C/D).
  • Crash button can fire before remote-logging arms the handler (B) — not unique to this PR, but weakens “deterministic.”
  • #if DEBUG alone is insufficient — e2e archives Release (D).

Noted

Copyright 2024 on new 2026 file; DateFormatter without en_US_POSIX; RuntimeException Java-ism; bare ActionButton vs SectionCard pattern; build.md / shared Appium ID parity not updated.

Dismissed

  • Treating the bypass as a critical third-party “poison” exploit — intentional opt-in for integration apps; the real defect is shipping it as undeclared public supported API with unlabeled payloads.
  • Demanding a full Catalyst UI path in this PR — nice-to-have on the #1714 stack, not required for the stated iOS demo flow.

Agreement Map

4/4: public API + checklist gap. 3/4 (A/C/D): unlabeled telemetry after marker discard; prefer deleting the shared-path OR via OSCore-framed raise or private name marker. B uniquely stressed handler-not-armed timing. Strongest judo (C): OSCore raise helper deletes findings 1–3 together.

Verdict: Intent is sound and the marked path works in unit tests, but the userInfo refactor regresses the private name-based design — shipping public API and unlabeled host crashes into the SDK fault pipeline. Prefer the OSCore raise helper or restore private self-labeling before merge.

Open in Web View Automation 

Sent by Cursor Automation: Automatic PR Review

Comment thread iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/Logging/OSLogCrashHandler.swift Outdated
Comment thread iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/Logging/OSLogCrashHandler.swift Outdated
Comment thread examples/demo/App/Views/SecondaryView.swift Outdated
Comment thread examples/demo/App/Views/SecondaryView.swift Outdated
@cursor

cursor Bot commented Aug 14, 2026

Copy link
Copy Markdown

Thanks for this — the demo crash flow looks solid. SecondaryView, the marked vs unmarked host-exception tests, and the manual persist-and-upload-after-relaunch check all make sense for exercising app-crash capture.

Two small requests, if you have a chance:

  1. Public API. I don’t think we need OSCrashTestMarker as public surface on OneSignalOSCore. Could we keep it internal / @_spi, or raise the demo crash from an OSCore helper so the existing attribution path covers it without a new public symbol?

  2. Uncaught-exception handler. The current tests call handle(...) directly, which is useful, but would it be possible to also simulate a real uncaught NSException going through the installed handler (raise → handler → persist)? Even one case like that would add a lot of confidence that the demo path matches production.

Everything else looks good to me — thank you!

@abdulraqeeb33

Copy link
Copy Markdown
Contributor

Also @fadi-george were you able to test a crash is captured in both KMP and iOS core code?

Base automatically changed from fadi/sdk-4998 to main August 18, 2026 16:34
fadi-george and others added 3 commits August 18, 2026 09:48
Allow demo-generated NSExceptions to bypass stack attribution through an explicit userInfo marker while preserving their runtime exception type.

Co-authored-by: Cursor <cursoragent@cursor.com>
@fadi-george fadi-george changed the title feat: [SDK-5022] add demo test crash flow chore: [SDK-5022] add demo test crash flow Aug 18, 2026
fadi-george and others added 2 commits August 18, 2026 10:03
Keep production crash attribution unchanged by moving the synthetic crash origin into an SPI helper instead of bypassing the host-crash filter.

Co-authored-by: Cursor <cursoragent@cursor.com>
Keep the demo on the standard framework boundary while retaining an SPI-only SDK-originated crash path.

Co-authored-by: Cursor <cursoragent@cursor.com>
@onesignal-deploy

Copy link
Copy Markdown
Collaborator

Addressed the review in 19d935e and 819ccec:

  • Removed the public marker and host-crash attribution bypass.
  • Added an SPI-only crash helper on OneSignalFramework, so the synthetic crash follows normal attribution.
  • Kept the demo on the standard framework boundary and made the timestamp locale-stable.

A truly uncaught NSException cannot run inside the XCTest host without terminating it. Existing tests cover handler registration, OneSignalCore/OneSignalKMP frame attribution, and KMP reporter persistence; the demo remains the end-to-end process-termination check. I have not separately induced a fatal exception originating inside KMP in this PR.

@abdulraqeeb33 abdulraqeeb33 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remember, this is not a true test of the crash, the Red app is crashing here and its not the OneSignal SDK (that includes KMP)

@nan-li nan-li left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remember, this is not a true test of the crash, the Red app is crashing here and its not the OneSignal SDK (that includes KMP)

The SDK is crashing here, because this PR added a trigger-able crash to the SDK itself in the swift interface. I am not sure we want to merge this PR by adding one-off test cases to the SDK codebase. I don't really see the need to make this case special than any other manual test we do, unless it's important for Appium testing? Can Appium tests validate this though?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants