@@ -26,8 +26,14 @@ import org.junit.Test
26
26
import org.junit.runner.RunWith
27
27
import org.robolectric.RobolectricTestRunner
28
28
import org.robolectric.annotation.Config
29
+ import java.io.InputStream
29
30
import java.nio.ByteBuffer
31
+ import java.nio.file.Paths
30
32
33
+ /* *
34
+ * WARNING: For now these test only run on bazel given the difference between accessing
35
+ * test resources on gradle vs Bazel
36
+ */
31
37
@RunWith(RobolectricTestRunner ::class )
32
38
@Config(sdk = [31 ])
33
39
class FatalIssueReporterProcessorTest {
@@ -77,14 +83,14 @@ class FatalIssueReporterProcessorTest {
77
83
" persistJvmCrash_withFakeException_shouldCreateNonEmptyErrorModel" ,
78
84
)
79
85
assertThat(error.stackTrace(0 )!! .sourceFile!! .path).isEqualTo(" FatalIssueReporterProcessorTest.kt" )
80
- assertThat(error.stackTrace(0 )!! .sourceFile!! .line).isEqualTo(50 )
86
+ assertThat(error.stackTrace(0 )!! .sourceFile!! .line).isEqualTo(56 )
81
87
assertThat(error.stackTrace(0 )!! .sourceFile!! .column).isEqualTo(0 )
82
88
}
83
89
84
90
@Test
85
91
fun persistAppExitReport_whenAnr_shouldCreateNonEmptyErrorModel () {
86
92
val description = APP_EXIT_DESCRIPTION_ANR
87
- val traceInputStream = createTraceInputStream( APP_EXIT_VALID_ANR_TRACE )
93
+ val traceInputStream = buildTraceInputStringFromFile( " app_exit_anr_deadlock_anr.txt " )
88
94
89
95
fatalIssueReporterProcessor.persistAppExitReport(
90
96
fatalIssueType = ReportType .AppNotResponding ,
@@ -101,8 +107,8 @@ class FatalIssueReporterProcessorTest {
101
107
val buffer = ByteBuffer .wrap(fatalIssueReportCaptor.firstValue)
102
108
val report = Report .getRootAsReport(buffer)
103
109
val error = report.errors(0 )!!
104
- assertThat(error.name).isEqualTo(APP_EXIT_DESCRIPTION_ANR )
105
- assertThat(error.reason).isEqualTo(" User Perceived ANR " )
110
+ assertThat(error.name).isEqualTo(" User Perceived ANR " )
111
+ assertThat(error.reason).isEqualTo(APP_EXIT_DESCRIPTION_ANR )
106
112
assertThat(error.stackTrace(0 )!! .type).isEqualTo(1 )
107
113
assertThat(error.stackTrace(0 )!! .stateLength).isEqualTo(0 )
108
114
assertThat(error.stackTrace(0 )!! .className).isEqualTo(" io.bitdrift.capture.FatalIssueGenerator" )
@@ -116,7 +122,7 @@ class FatalIssueReporterProcessorTest {
116
122
fun persistAppExitReport_whenUserPerceivedAnr_shouldMatchAnrReason () {
117
123
assertAnrReason(
118
124
descriptionFromAppExit = " Input Dispatching Timed Out" ,
119
- expectedReasonMessage = " User Perceived ANR" ,
125
+ expectedMessage = " User Perceived ANR" ,
120
126
)
121
127
}
122
128
@@ -126,7 +132,7 @@ class FatalIssueReporterProcessorTest {
126
132
descriptionFromAppExit =
127
133
" Broadcast of Intent { act=android.intent.action.MAIN " +
128
134
" cmp=com.example.app/.MainActivity}" ,
129
- expectedReasonMessage = " Broadcast Receiver ANR" ,
135
+ expectedMessage = " Broadcast Receiver ANR" ,
130
136
)
131
137
}
132
138
@@ -136,71 +142,71 @@ class FatalIssueReporterProcessorTest {
136
142
descriptionFromAppExit =
137
143
" Executing service. { act=android.intent.action.MAIN \" +\n " +
138
144
" \" cmp=com.example.app/.MainActivity}" ,
139
- expectedReasonMessage = " Executing Service ANR" ,
145
+ expectedMessage = " Executing Service ANR" ,
140
146
)
141
147
}
142
148
143
149
@Test
144
150
fun persistAppExitReport_whenStartServiceForegroundAnr_shouldMatchAnrReason () {
145
151
assertAnrReason(
146
152
descriptionFromAppExit = " Service.StartForeground() not called.{ act=android.intent.action.MAIN}" ,
147
- expectedReasonMessage = " Service.startForeground() Not Called ANR" ,
153
+ expectedMessage = " Service.startForeground() Not Called ANR" ,
148
154
)
149
155
}
150
156
151
157
@Test
152
158
fun persistAppExitReport_whenContentProviderTimeoutAnr_shouldMatchAnrReason () {
153
159
assertAnrReason(
154
160
descriptionFromAppExit = " My Application. Content Provider Timeout" ,
155
- expectedReasonMessage = " Content Provider ANR" ,
161
+ expectedMessage = " Content Provider ANR" ,
156
162
)
157
163
}
158
164
159
165
@Test
160
166
fun persistAppExitReport_whenAppRegisteredTimeoutAnr_shouldMatchAnrReason () {
161
167
assertAnrReason(
162
168
descriptionFromAppExit = " My Application. App Registered Timeout" ,
163
- expectedReasonMessage = " App Registered ANR" ,
169
+ expectedMessage = " App Registered ANR" ,
164
170
)
165
171
}
166
172
167
173
@Test
168
174
fun persistAppExitReport_whenShortFgsTimeoutAnr_shouldMatchAnrReason () {
169
175
assertAnrReason(
170
176
descriptionFromAppExit = " Foreground service ANR. Short FGS Timeout. Duration=5000ms" ,
171
- expectedReasonMessage = " Short Foreground Service Timeout ANR" ,
177
+ expectedMessage = " Short Foreground Service Timeout ANR" ,
172
178
)
173
179
}
174
180
175
181
@Test
176
182
fun persistAppExitReport_whenSystemJobServiceTimeoutAnr_shouldMatchAnrReason () {
177
183
assertAnrReason(
178
184
descriptionFromAppExit = " SystemJobService. Job Service Timeout" ,
179
- expectedReasonMessage = " Job Service ANR" ,
185
+ expectedMessage = " Job Service ANR" ,
180
186
)
181
187
}
182
188
183
189
@Test
184
190
fun persistAppExitReport_whenAppStartupTimeOut_shouldMatchAnrReason () {
185
191
assertAnrReason(
186
192
descriptionFromAppExit = " App start timeout. Timeout=5000ms" ,
187
- expectedReasonMessage = " App Start ANR" ,
193
+ expectedMessage = " App Start ANR" ,
188
194
)
189
195
}
190
196
191
197
@Test
192
198
fun persistAppExitReport_whenServiceStartTimeout_shouldMatchAnrReason () {
193
199
assertAnrReason(
194
200
descriptionFromAppExit = " Service start timeout. Timeout=5000ms" ,
195
- expectedReasonMessage = " Service Start ANR" ,
201
+ expectedMessage = " Service Start ANR" ,
196
202
)
197
203
}
198
204
199
205
@Test
200
206
fun persistAppExitReport_whenBackgroundAnr_shouldMatchAnrReason () {
201
207
assertAnrReason(
202
208
descriptionFromAppExit = " It's full moon ANR" ,
203
- expectedReasonMessage = " Undetermined ANR" ,
209
+ expectedMessage = " Undetermined ANR" ,
204
210
)
205
211
}
206
212
@@ -211,14 +217,14 @@ class FatalIssueReporterProcessorTest {
211
217
" bg anr: Process " +
212
218
" ProcessRecord{9707291 4609:io.bitdrift.gradletestapp/u0a207} " +
213
219
" failed to complete startup\n " ,
214
- expectedReasonMessage = " Background ANR" ,
220
+ expectedMessage = " Background ANR" ,
215
221
)
216
222
}
217
223
218
224
@Test
219
225
fun persistAppExitReport_whenNativeCrash_shouldCreateEmptyErrorModel () {
220
226
val description = " Native crash"
221
- val traceInputStream = createTraceInputStream( " sample native crash trace " )
227
+ val traceInputStream = buildTraceInputStringFromFile( " app_exit_native_crash.txt " )
222
228
223
229
fatalIssueReporterProcessor.persistAppExitReport(
224
230
ReportType .NativeCrash ,
@@ -255,15 +261,13 @@ class FatalIssueReporterProcessorTest {
255
261
256
262
private fun assertAnrReason (
257
263
descriptionFromAppExit : String ,
258
- expectedReasonMessage : String ,
264
+ expectedMessage : String ,
259
265
) {
260
- val traceInputStream = createTraceInputStream(APP_EXIT_VALID_ANR_TRACE )
261
-
262
266
fatalIssueReporterProcessor.persistAppExitReport(
263
267
fatalIssueType = ReportType .AppNotResponding ,
264
268
FAKE_TIME_STAMP ,
265
269
descriptionFromAppExit,
266
- traceInputStream ,
270
+ buildTraceInputStringFromFile( " app_exit_anr_deadlock_anr.txt " ) ,
267
271
)
268
272
269
273
verify(fatalIssueReporterStorage).persistFatalIssue(
@@ -274,41 +278,29 @@ class FatalIssueReporterProcessorTest {
274
278
val report = Report .getRootAsReport(ByteBuffer .wrap(fatalIssueReportCaptor.firstValue))
275
279
assertThat(report.errors(0 )).isNotNull
276
280
report.errors(0 )?.let { error ->
277
- assertThat(error.reason ).isEqualTo(expectedReasonMessage )
281
+ assertThat(error.name ).isEqualTo(expectedMessage )
278
282
}
279
283
}
280
284
285
+ private fun buildTraceInputStringFromFile (rawFilePath : String ): InputStream {
286
+ val file =
287
+ Paths
288
+ .get(
289
+ System .getenv(" TEST_SRCDIR" ),
290
+ " _main" ,
291
+ " platform/jvm/capture/src/test/resources" ,
292
+ rawFilePath,
293
+ ).toFile()
294
+ val resourceStream = file.inputStream()
295
+ val anrRawTrace = resourceStream.bufferedReader().use { it.readText() }
296
+ return createTraceInputStream(anrRawTrace)
297
+ }
298
+
281
299
private companion object {
282
300
const val FAKE_TIME_STAMP = 1241515210914L
283
301
const val APP_EXIT_DESCRIPTION_ANR =
284
302
" Input dispatching timed out (219180 " +
285
303
" io.bitdrift.capture/io.bitdrift.capture.MainActivity (server) " +
286
304
" is not responding. Waited 5004ms for MotionEvent"
287
-
288
- // TODO(FranAguilera): BIT-5142 use raw files
289
- const val APP_EXIT_VALID_ANR_TRACE =
290
- " \" main\" prio=5 tid=1 Blocked\n " +
291
- " | group=\" main\" sCount=1 ucsCount=0 flags=1 obj=0x721b0f98 self=0xb400007d136a27b0\n " +
292
- " | sysTid=3994 nice=-10 cgrp=top-app sched=0/0 handle=0x7f053014f8\n " +
293
- " | state=S schedstat=( 979645230 62026944 1016 ) utm=91 stm=6 core=0 HZ=100\n " +
294
- " | stack=0x7ffccb0000-0x7ffccb2000 stackSize=8188KB\n " +
295
- " | held mutexes=\n " +
296
- " at io.bitdrift.capture.FatalIssueGenerator.startProcessing(FatalIssueGenerator.kt:106)\n " +
297
- " - waiting to lock <0x0481d03d> (a java.lang.String) held by thread 4\n " +
298
- " - locked <0x04e67032> (a java.lang.String)\n " +
299
- " at io.bitdrift.capture.FatalIssueGenerator.forceDeadlockAnr$(FatalIssueGenerator.kt:35)\n " +
300
- " at io.bitdrift.capture.FatalIssueGenerator(unavailable:0)\n " +
301
- " at io.bitdrift.capture.FatalIssueGenerator\n " +
302
- " at io.bitdrift.capture.FatalIssueGenerator.callOnMainThread\n " +
303
- " at io.bitdrift.capture.FatalIssueGenerator\n " +
304
- " at io.bitdrift.capture.FatalIssueGenerator\n " +
305
- " at android.os.Handler.handleCallback(Handler.java:958)\n " +
306
- " at android.os.Handler.dispatchMessage(Handler.java:99)\n " +
307
- " at android.os.Looper.loopOnce(Looper.java:205)\n " +
308
- " at android.os.Looper.loop(Looper.java:294)\n " +
309
- " at android.app.ActivityThread.main(ActivityThread.java:8177)\n " +
310
- " at java.lang.reflect.Method.invoke(Native method)\n " +
311
- " at com.android.internal.os.RuntimeInit.run(RuntimeInit.java:552)\n " +
312
- " at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)\n "
313
305
}
314
306
}
0 commit comments