1+ <<<<<<< HEAD
12@testable import Sentry
23import SentrySampleShared
4+ =======
5+ >>>>>>> parent of 2 a36 c3 f8 ( impr ( profiling) : always remove launch profile config after starting ( #5318 ) )
36import XCTest
47
58//swiftlint:disable function_body_length todo
69
710class ProfilingUITests : BaseUITest {
811 override var automaticallyLaunchAndTerminateApp : Bool { false }
9-
12+
1013 func testAppLaunchesWithTraceProfiler( ) throws {
1114 guard #available( iOS 16 , * ) else {
1215 throw XCTSkip ( " Only run for latest iOS version we test; we've had issues with prior versions in SauceLabs " )
1316 }
1417
15- try performTest ( profileType: . trace)
18+ // by default, launch profiling is not enabled
19+ try launchAndConfigureSubsequentLaunches ( shouldProfileThisLaunch: false )
20+
21+ // after configuring for launch profiling, check the marker file exists, and that the profile happens
22+ try launchAndConfigureSubsequentLaunches ( terminatePriorSession: true , shouldProfileThisLaunch: true )
1623 }
1724
1825 func testAppLaunchesWithContinuousProfilerV1( ) throws {
1926 guard #available( iOS 16 , * ) else {
2027 throw XCTSkip ( " Only run for latest iOS version we test; we've had issues with prior versions in SauceLabs " )
2128 }
2229
23- try performTest ( profileType: . continuous)
30+ // by default, launch profiling is not enabled
31+ try launchAndConfigureSubsequentLaunches ( shouldProfileThisLaunch: false , continuousProfiling: true )
32+
33+ // after configuring for launch profiling, check the marker file exists, and that the profile happens
34+ try launchAndConfigureSubsequentLaunches ( terminatePriorSession: true , shouldProfileThisLaunch: true , continuousProfiling: true )
2435 }
2536
2637 func testAppLaunchesWithContinuousProfilerV2TraceLifecycle( ) throws {
2738 guard #available( iOS 16 , * ) else {
2839 throw XCTSkip ( " Only run for latest iOS version we test; we've had issues with prior versions in SauceLabs " )
2940 }
3041
31- try performTest ( profileType: . ui, lifecycle: . trace)
42+ // by default, launch profiling is not enabled
43+ try launchAndConfigureSubsequentLaunches ( shouldProfileThisLaunch: false , continuousProfiling: true , v2TraceLifecycle: true )
44+
45+ // after configuring for launch profiling, check the marker file exists, and that the profile happens
46+ try launchAndConfigureSubsequentLaunches ( terminatePriorSession: true , shouldProfileThisLaunch: true , continuousProfiling: true , v2TraceLifecycle: true )
3247 }
3348
3449 func testAppLaunchesWithContinuousProfilerV2ManualLifeCycle( ) throws {
3550 guard #available( iOS 16 , * ) else {
3651 throw XCTSkip ( " Only run for latest iOS version we test; we've had issues with prior versions in SauceLabs " )
3752 }
3853
39- try performTest ( profileType: . ui, lifecycle: . manual)
54+ // by default, launch profiling is not enabled
55+ try launchAndConfigureSubsequentLaunches ( shouldProfileThisLaunch: false , continuousProfiling: true , v2ManualLifecycle: true )
56+
57+ // after configuring for launch profiling, check the marker file exists, and that the profile happens
58+ try launchAndConfigureSubsequentLaunches ( terminatePriorSession: true , shouldProfileThisLaunch: true , continuousProfiling: true , v2ManualLifecycle: true )
4059 }
4160
4261 /**
@@ -130,6 +149,7 @@ extension ProfilingUITests {
130149 func stopContinuousProfiler( ) {
131150 app. buttons [ " io.sentry.ios-swift.ui-test.button.stop-continuous-profiler " ] . afterWaitingForExistence ( " Couldn't find button to stop continuous profiler " ) . tap ( )
132151 }
152+ < <<<<<< HEAD
133153
134154 enum ProfilingType {
135155 case trace
@@ -180,56 +200,74 @@ extension ProfilingUITests {
180200 }
181201 }
182202
203+ =======
204+
205+ >>>>>>> parent of 2 a36 c3 f8 ( impr( profiling) : always remove launch profile config after starting ( #5318 ) )
183206 /**
184207 * Performs the various operations for the launch profiler test case:
185208 * - terminates an existing app session
186- * - starts a new app session
209+ * - creates a new one
187210 * - sets launch args and env vars to set the appropriate `SentryOption` values for the desired behavior
188- * - launches the new configured app session, which will optionally start a launch profiler and then call SentrySDK.startWithOptions configured based on the launch args and env vars
211+ * - launches the new configured app session
189212 * - asserts the expected outcomes of the config file and launch profiler
190213 */
191214 func launchAndConfigureSubsequentLaunches(
192215 terminatePriorSession: Bool = false ,
193216 shouldProfileThisLaunch: Bool ,
194- shouldProfileNextLaunch : Bool ,
195- profileType : ProfilingType ,
196- lifecycle : SentryProfileOptions . SentryProfileLifecycle ?
217+ continuousProfiling : Bool = false ,
218+ v2TraceLifecycle : Bool = false ,
219+ v2ManualLifecycle : Bool = false
197220 ) throws {
198221 if terminatePriorSession {
199222 app. terminate ( )
200223 app = newAppSession ( )
201224 }
202225
203- setAppLaunchParameters ( profileType, lifecycle, shouldProfileNextLaunch)
226+ app. launchArguments. append ( contentsOf: [
227+ // these help avoid other profiles that'd be taken automatically, that interfere with the checking we do for the assertions later in the tests
228+ " --disable-swizzling " ,
229+ " --disable-auto-performance-tracing " ,
230+ " --disable-uiviewcontroller-tracing " ,
204231
205- launchApp ( activateBeforeLaunch : false )
206- goToProfiling ( )
232+ // sets a marker function to run in a load command that the launch profile should detect
233+ " --io.sentry.slow-load-method " ,
207234
208- let configFileExists = try checkLaunchProfileMarkerFileExistence ( )
235+ // override full chunk completion before stoppage introduced in https://github.com/getsentry/sentry-cocoa/pull/4214
236+ " --io.sentry.continuous-profiler-immediate-stop "
237+ ] )
209238
210- if shouldProfileNextLaunch {
211- XCTAssert ( configFileExists, " A launch profile config file should be present on disk if SentrySDK.startWithOptions configured launch profiling for the next launch. " )
239+ if continuousProfiling {
240+ if v2TraceLifecycle {
241+ app. launchEnvironment [ " --io.sentry.profile-session-sample-rate " ] = " 1 "
242+ } else if v2ManualLifecycle {
243+ app. launchArguments. append ( contentsOf: [
244+ " --io.sentry.profile-lifecycle-manual "
245+ ] )
246+ app. launchEnvironment [ " --io.sentry.profile-session-sample-rate " ] = " 1 "
247+ } else {
248+ app. launchArguments. append ( " --io.sentry.disable-ui-profiling " )
249+ }
212250 } else {
213- XCTAssertFalse ( configFileExists , " Launch profile config files should be removed upon starting launch profiles. If SentrySDK.startWithOptions doesn't reconfigure launch profiling, the config file should not be present. " )
251+ app . launchEnvironment [ " --io.sentry.profilesSampleRate " ] = " 1 "
214252 }
215253
254+ launchApp ( )
255+ goToProfiling ( )
256+ XCTAssert ( try checkLaunchProfileMarkerFileExistence ( ) )
257+
216258 guard shouldProfileThisLaunch else {
217259 return
218260 }
219-
220- if profileType == . trace {
221- retrieveLastProfileData ( )
222- } else {
223- if profileType == . continuous || ( profileType == . ui && lifecycle == . manual) {
261+
262+ if continuousProfiling {
263+ if !v2TraceLifecycle {
224264 stopContinuousProfiler ( )
225265 }
226266 retrieveFirstProfileChunkData ( )
267+ } else {
268+ retrieveLastProfileData ( )
227269 }
228-
229- try assertProfileContents ( )
230- }
231-
232- func assertProfileContents( ) throws {
270+
233271 let lastProfile = try marshalJSONDictionaryFromApp ( )
234272 let sampledProfile = try XCTUnwrap ( lastProfile [ " profile " ] as? [ String : Any ] )
235273 let stacks = try XCTUnwrap ( sampledProfile [ " stacks " ] as? [ [ Int ] ] )
@@ -239,7 +277,7 @@ extension ProfilingUITests {
239277 frames [ stackFrame] [ " function " ]
240278 }
241279 } )
242-
280+
243281 // grab the first stack that contained frames from the fixture code that simulates a slow +[load] method
244282 var stackID : Int ?
245283 let stack = try XCTUnwrap ( stackFunctions. enumerated ( ) . first { nextStack in
@@ -258,12 +296,12 @@ extension ProfilingUITests {
258296 XCTFail ( " Didn't find the ID of the stack containing the target function " )
259297 return
260298 }
261-
299+
262300 // ensure that the stack doesn't contain any calls to main functions; this ensures we actually captured pre-main stacks
263301 XCTAssertFalse ( stack. contains ( " main " ) )
264302 XCTAssertFalse ( stack. contains ( " UIApplicationMain " ) )
265303 XCTAssertFalse ( stack. contains ( " -[UIApplication _run] " ) )
266-
304+
267305 // ensure that the stack happened on the main thread; this is a cross-check to make sure we didn't accidentally grab a stack from a different thread that wouldn't have had a call to main() anyways, thereby possibly missing the real stack that may have contained main() calls (but shouldn't for this test)
268306 let samples = try XCTUnwrap ( sampledProfile [ " samples " ] as? [ [ String : Any ] ] )
269307 let sample = try XCTUnwrap ( samples. first { nextSample in
0 commit comments