Skip to content

Commit d8cc6ae

Browse files
test: Improve trigger non fully blocking AppHang (#4265)
Make triggering a non-fully blocking app hang where some frames are rendered, but the UI still seems stuck to the user more realistic by continuously blocking the main thread for 0.5 seconds and then quickly rendering a few frames and then blocking it again. Co-authored-by: Andrew McKnight <[email protected]>
1 parent 706c41f commit d8cc6ae

File tree

7 files changed

+50
-53
lines changed

7 files changed

+50
-53
lines changed

Samples/iOS-Swift/iOS-Swift-UITests/ProfilingUITests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class ProfilingUITests: BaseUITest {
4848
goToTransactions()
4949
startTransaction()
5050

51-
app.buttons["anrFillingRunLoop"].afterWaitingForExistence("Couldn't find button to ANR").tap()
51+
app.buttons["appHangFullyBlocking"].afterWaitingForExistence("Couldn't find button to trigger fully blocking AppHang.").tap()
5252
stopTransaction()
5353

5454
goToProfiling()

Samples/iOS-Swift/iOS-Swift.xcodeproj/project.pbxproj

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
/* Begin PBXBuildFile section */
1010
0AAAB8572887F7C60011845C /* PermissionsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AABE2E928855FF80057ED69 /* PermissionsViewController.swift */; };
1111
0AABE2EA28855FF80057ED69 /* PermissionsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AABE2E928855FF80057ED69 /* PermissionsViewController.swift */; };
12-
629EC8AD2B0B537400858855 /* ANRs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 629EC8AC2B0B537400858855 /* ANRs.swift */; };
13-
629EC8BB2B0B5BAE00858855 /* ANRs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 629EC8AC2B0B537400858855 /* ANRs.swift */; };
12+
629EC8AD2B0B537400858855 /* TriggerAppHang.swift in Sources */ = {isa = PBXBuildFile; fileRef = 629EC8AC2B0B537400858855 /* TriggerAppHang.swift */; };
13+
629EC8BB2B0B5BAE00858855 /* TriggerAppHang.swift in Sources */ = {isa = PBXBuildFile; fileRef = 629EC8AC2B0B537400858855 /* TriggerAppHang.swift */; };
1414
62C07D5C2AF3E3F500894688 /* BaseUITest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C07D5B2AF3E3F500894688 /* BaseUITest.swift */; };
1515
630853532440C60F00DDE4CE /* Sentry.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 630853322440C44F00DDE4CE /* Sentry.framework */; };
1616
637AFDAA243B02760034958B /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 637AFDA9243B02760034958B /* AppDelegate.swift */; };
@@ -279,7 +279,7 @@
279279

280280
/* Begin PBXFileReference section */
281281
0AABE2E928855FF80057ED69 /* PermissionsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionsViewController.swift; sourceTree = "<group>"; };
282-
629EC8AC2B0B537400858855 /* ANRs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ANRs.swift; sourceTree = "<group>"; };
282+
629EC8AC2B0B537400858855 /* TriggerAppHang.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TriggerAppHang.swift; sourceTree = "<group>"; };
283283
62C07D5B2AF3E3F500894688 /* BaseUITest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseUITest.swift; sourceTree = "<group>"; };
284284
6308532C2440C44F00DDE4CE /* Sentry.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Sentry.xcodeproj; path = ../../Sentry.xcodeproj; sourceTree = "<group>"; };
285285
637AFDA6243B02760034958B /* iOS-Swift.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "iOS-Swift.app"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -607,7 +607,7 @@
607607
7B5525B22938B5B5006A2932 /* DiskWriteException.swift */,
608608
D8F01DF02A1377D0008F4996 /* SentryExposure.h */,
609609
D8832B192AF4FE2000C522B0 /* SentryUIApplication.h */,
610-
629EC8AC2B0B537400858855 /* ANRs.swift */,
610+
629EC8AC2B0B537400858855 /* TriggerAppHang.swift */,
611611
);
612612
path = Tools;
613613
sourceTree = "<group>";
@@ -954,7 +954,7 @@
954954
7B79000429028C7300A7F467 /* MetricKitManager.swift in Sources */,
955955
D8D7BB4A2750067900044146 /* UIAssert.swift in Sources */,
956956
D8F3D057274E574200B56F8C /* LoremIpsumViewController.swift in Sources */,
957-
629EC8AD2B0B537400858855 /* ANRs.swift in Sources */,
957+
629EC8AD2B0B537400858855 /* TriggerAppHang.swift in Sources */,
958958
D8AE48C92C57DC2F0092A2A6 /* WebViewController.swift in Sources */,
959959
D8DBDA78274D5FC400007380 /* SplitViewController.swift in Sources */,
960960
84ACC43C2A73CB5900932A18 /* ProfilingNetworkScanner.swift in Sources */,
@@ -1011,7 +1011,7 @@
10111011
D8F3D055274E572F00B56F8C /* RandomErrors.swift in Sources */,
10121012
0AAAB8572887F7C60011845C /* PermissionsViewController.swift in Sources */,
10131013
D8269A3C274C095E00BD5BD5 /* AppDelegate.swift in Sources */,
1014-
629EC8BB2B0B5BAE00858855 /* ANRs.swift in Sources */,
1014+
629EC8BB2B0B5BAE00858855 /* TriggerAppHang.swift in Sources */,
10151015
D80D021B29EE9E3D0084393D /* ErrorsViewController.swift in Sources */,
10161016
D8444E53275F792A0042F4DE /* UIAssert.swift in Sources */,
10171017
D8269A3E274C095E00BD5BD5 /* SceneDelegate.swift in Sources */,

Samples/iOS-Swift/iOS-Swift/Base.lproj/Main.storyboard

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,13 @@
6363
<action selector="stopTransaction:" destination="BYZ-38-t0r" eventType="touchUpInside" id="r2S-U5-Af9"/>
6464
</connections>
6565
</button>
66-
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="LvU-yx-01i" userLabel="triggerANRRunLoop">
66+
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="LvU-yx-01i">
6767
<rect key="frame" x="0.0" y="84" width="259" height="28"/>
68-
<accessibility key="accessibilityConfiguration" identifier="anrFillingRunLoop"/>
68+
<accessibility key="accessibilityConfiguration" identifier="appHangFullyBlocking"/>
6969
<fontDescription key="fontDescription" type="system" pointSize="13"/>
70-
<state key="normal" title="ANR filling run loop"/>
70+
<state key="normal" title="AppHangFullyBlocking"/>
7171
<connections>
72-
<action selector="anrFillingRunLoop:" destination="BYZ-38-t0r" eventType="touchUpInside" id="uqP-sv-C4a"/>
72+
<action selector="appHangFullyBlocking:" destination="BYZ-38-t0r" eventType="touchUpInside" id="uqP-sv-C4a"/>
7373
</connections>
7474
</button>
7575
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="5IM-MG-9GW">
@@ -167,7 +167,7 @@
167167
<tabBarItem key="tabBarItem" title="Transactions" image="clock.fill" catalog="system" selectedImage="clock.fill" id="ypv-KA-BBe"/>
168168
<navigationItem key="navigationItem" title="Sentry Test App (Swift)" id="Ddh-Ww-vzM"/>
169169
<connections>
170-
<outlet property="anrFillingRunLoopButton" destination="LvU-yx-01i" id="Epa-mo-uMP"/>
170+
<outlet property="appHangFullyBlockingButton" destination="LvU-yx-01i" id="Epa-mo-uMP"/>
171171
</connections>
172172
</viewController>
173173
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>

Samples/iOS-Swift/iOS-Swift/ExtraViewController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ class ExtraViewController: UIViewController {
102102

103103
@IBAction func anrFillingRunLoop(_ sender: UIButton) {
104104
highlightButton(sender)
105-
triggerANRFillingRunLoop(button: self.anrFillingRunLoopButton)
105+
triggerNonFullyBlockingAppHang()
106106
}
107107

108108
@IBAction func getPasteBoardString(_ sender: Any) {

Samples/iOS-Swift/iOS-Swift/Tools/ANRs.swift

Lines changed: 0 additions & 37 deletions
This file was deleted.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import Foundation
2+
import UIKit
3+
4+
/// Triggers a non-fully blocking app hang by blocking the app for 0.5 seconds,
5+
/// then allowing it to draw a couple of frames, and blocking it again. While the app
6+
/// is not fully blocked because it renders a few frames, it still seems blocked to the
7+
/// user and should be considered an app hang.
8+
func triggerNonFullyBlockingAppHang() {
9+
10+
DispatchQueue.global().async {
11+
for _ in 0...10 {
12+
Thread.sleep(forTimeInterval: 0.001)
13+
DispatchQueue.main.sync {
14+
Thread.sleep(forTimeInterval: 0.5)
15+
}
16+
}
17+
}
18+
}
19+
20+
/// Schedules heavy UI rendering work on the main thread in a tight loop, which causes
21+
/// a fully blocking app hang without frames being rendered.
22+
func triggerFullyBlockingAppHang(button: UIButton) {
23+
let buttonTitle = button.currentTitle
24+
var i = 0
25+
26+
for _ in 0...5_000_000 {
27+
i += Int.random(in: 0...10)
28+
i -= 1
29+
30+
button.setTitle("\(i)", for: .normal)
31+
}
32+
33+
button.setTitle(buttonTitle, for: .normal)
34+
}

Samples/iOS-Swift/iOS-Swift/TransactionsViewController.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import UIKit
33

44
class TransactionsViewController: UIViewController {
55

6-
@IBOutlet weak var anrFillingRunLoopButton: UIButton!
6+
@IBOutlet weak var appHangFullyBlockingButton: UIButton!
77

88
private let dispatchQueue = DispatchQueue(label: "ViewController", attributes: .concurrent)
99
private var timer: Timer?
@@ -127,8 +127,8 @@ class TransactionsViewController: UIViewController {
127127
present(alert, animated: true)
128128
}
129129

130-
@IBAction func anrFillingRunLoop(_ sender: Any) {
131-
triggerANRFillingRunLoop(button: self.anrFillingRunLoopButton)
130+
@IBAction func appHangFullyBlocking(_ sender: Any) {
131+
triggerFullyBlockingAppHang(button: self.appHangFullyBlockingButton)
132132
}
133133

134134
@IBAction func captureTransaction(_ sender: UIButton) {

0 commit comments

Comments
 (0)