34
34
import com .google .android .gms .tasks .TaskCompletionSource ;
35
35
import com .google .android .gms .tasks .Tasks ;
36
36
import com .google .firebase .FirebaseApp ;
37
+ import com .google .firebase .concurrent .TestOnlyExecutors ;
37
38
import com .google .firebase .crashlytics .internal .CrashlyticsNativeComponent ;
38
39
import com .google .firebase .crashlytics .internal .CrashlyticsTestCase ;
39
40
import com .google .firebase .crashlytics .internal .DevelopmentPlatformProvider ;
40
41
import com .google .firebase .crashlytics .internal .NativeSessionFileProvider ;
41
42
import com .google .firebase .crashlytics .internal .analytics .AnalyticsEventLogger ;
43
+ import com .google .firebase .crashlytics .internal .concurrency .CrashlyticsWorker ;
42
44
import com .google .firebase .crashlytics .internal .metadata .LogFileManager ;
43
45
import com .google .firebase .crashlytics .internal .metadata .UserMetadata ;
44
46
import com .google .firebase .crashlytics .internal .model .CrashlyticsReport ;
55
57
import java .util .TreeSet ;
56
58
import java .util .concurrent .Executor ;
57
59
import java .util .concurrent .TimeUnit ;
58
- import org .junit .Test ;
59
60
import org .mockito .ArgumentCaptor ;
60
61
61
62
public class CrashlyticsControllerTest extends CrashlyticsTestCase {
62
63
private static final String GOOGLE_APP_ID = "google:app:id" ;
63
64
private static final String SESSION_ID = "session_id" ;
64
65
66
+ private final CrashlyticsWorker commonWorker =
67
+ new CrashlyticsWorker (TestOnlyExecutors .background ());
68
+
65
69
private Context testContext ;
66
70
private IdManager idManager ;
67
71
private SettingsProvider testSettingsProvider ;
@@ -70,6 +74,8 @@ public class CrashlyticsControllerTest extends CrashlyticsTestCase {
70
74
private DataCollectionArbiter mockDataCollectionArbiter ;
71
75
private CrashlyticsNativeComponent mockNativeComponent = mock (CrashlyticsNativeComponent .class );
72
76
77
+ private CrashlyticsWorker diskWriteWorker = new CrashlyticsWorker (TestOnlyExecutors .background ());
78
+
73
79
@ Override
74
80
protected void setUp () throws Exception {
75
81
super .setUp ();
@@ -99,14 +105,19 @@ protected void setUp() throws Exception {
99
105
when (testSettingsProvider .getSettingsAsync ()).thenReturn (Tasks .forResult (testSettings ));
100
106
}
101
107
108
+ @ Override
109
+ protected void tearDown () throws Exception {
110
+ super .tearDown ();
111
+ commonWorker .await ();
112
+ }
113
+
102
114
/** A convenience class for building CrashlyticsController instances for testing. */
103
115
private class ControllerBuilder {
104
116
private DataCollectionArbiter dataCollectionArbiter ;
105
117
private CrashlyticsNativeComponent nativeComponent = null ;
106
118
private AnalyticsEventLogger analyticsEventLogger ;
107
119
private SessionReportingCoordinator sessionReportingCoordinator ;
108
120
109
- private CrashlyticsBackgroundWorker backgroundWorker ;
110
121
private LogFileManager logFileManager = null ;
111
122
112
123
private UserMetadata userMetadata = null ;
@@ -118,8 +129,6 @@ private class ControllerBuilder {
118
129
analyticsEventLogger = mock (AnalyticsEventLogger .class );
119
130
120
131
sessionReportingCoordinator = mockSessionReportingCoordinator ;
121
-
122
- backgroundWorker = new CrashlyticsBackgroundWorker (new SameThreadExecutorService ());
123
132
}
124
133
125
134
ControllerBuilder setDataCollectionArbiter (DataCollectionArbiter arbiter ) {
@@ -168,7 +177,7 @@ public CrashlyticsController build() {
168
177
final CrashlyticsController controller =
169
178
new CrashlyticsController (
170
179
testContext .getApplicationContext (),
171
- backgroundWorker ,
180
+ commonWorker ,
172
181
idManager ,
173
182
dataCollectionArbiter ,
174
183
testFileStore ,
@@ -179,7 +188,8 @@ public CrashlyticsController build() {
179
188
sessionReportingCoordinator ,
180
189
nativeComponent ,
181
190
analyticsEventLogger ,
182
- mock (CrashlyticsAppQualitySessionsSubscriber .class ));
191
+ mock (CrashlyticsAppQualitySessionsSubscriber .class ),
192
+ diskWriteWorker );
183
193
return controller ;
184
194
}
185
195
}
@@ -208,6 +218,8 @@ public void testWriteNonFatal_callsSessionReportingCoordinatorPersistNonFatal()
208
218
controller .writeNonFatalException (thread , nonFatal );
209
219
controller .doCloseSessions (testSettingsProvider );
210
220
221
+ commonWorker .await ();
222
+
211
223
verify (mockSessionReportingCoordinator )
212
224
.persistNonFatalEvent (eq (nonFatal ), eq (thread ), eq (sessionId ), anyLong ());
213
225
}
@@ -228,9 +240,8 @@ public void testFatalException_callsSessionReportingCoordinatorPersistFatal() th
228
240
.persistFatalEvent (eq (fatal ), eq (thread ), eq (sessionId ), anyLong ());
229
241
}
230
242
231
- @ Test
232
243
@ SdkSuppress (minSdkVersion = 30 ) // ApplicationExitInfo
233
- public void testOnDemandFatal_callLogFatalException () {
244
+ public void testOnDemandFatal_callLogFatalException () throws Exception {
234
245
Thread thread = Thread .currentThread ();
235
246
Exception fatal = new RuntimeException ("Fatal" );
236
247
Thread .UncaughtExceptionHandler exceptionHandler = mock (Thread .UncaughtExceptionHandler .class );
@@ -246,6 +257,8 @@ public void testOnDemandFatal_callLogFatalException() {
246
257
controller .enableExceptionHandling (SESSION_ID , exceptionHandler , testSettingsProvider );
247
258
controller .logFatalException (thread , fatal );
248
259
260
+ commonWorker .await ();
261
+
249
262
verify (mockUserMetadata ).setNewSession (not (eq (SESSION_ID )));
250
263
}
251
264
@@ -323,17 +336,20 @@ public File getOsFile() {
323
336
final CrashlyticsController controller =
324
337
builder ().setNativeComponent (mockNativeComponent ).setLogFileManager (logFileManager ).build ();
325
338
326
- controller .finalizeSessions (testSettingsProvider );
339
+ commonWorker .submit (() -> controller .finalizeSessions (testSettingsProvider ));
340
+ commonWorker .await ();
341
+
327
342
verify (mockSessionReportingCoordinator )
328
343
.finalizeSessionWithNativeEvent (eq (previousSessionId ), any (), any ());
329
344
verify (mockSessionReportingCoordinator , never ())
330
345
.finalizeSessionWithNativeEvent (eq (sessionId ), any (), any ());
331
346
}
332
347
333
348
@ SdkSuppress (minSdkVersion = 30 ) // ApplicationExitInfo
334
- public void testMissingNativeComponentCausesNoReports () {
349
+ public void testMissingNativeComponentCausesNoReports () throws Exception {
335
350
final CrashlyticsController controller = createController ();
336
- controller .finalizeSessions (testSettingsProvider );
351
+ commonWorker .submit (() -> controller .finalizeSessions (testSettingsProvider ));
352
+ commonWorker .await ();
337
353
338
354
List <String > sessions = testFileStore .getAllOpenSessionIds ();
339
355
for (String sessionId : sessions ) {
@@ -363,13 +379,14 @@ public void testLoggedExceptionsAfterCrashOk() {
363
379
*/
364
380
// FIXME: Validate this test works as intended
365
381
@ SdkSuppress (minSdkVersion = 30 ) // ApplicationExitInfo
366
- public void testLogStringAfterCrashOk () {
382
+ public void testLogStringAfterCrashOk () throws Exception {
367
383
final CrashlyticsController controller = builder ().build ();
368
384
controller .handleUncaughtException (
369
385
testSettingsProvider , Thread .currentThread (), new RuntimeException ());
370
386
371
387
// This should not throw.
372
- controller .writeToLog (System .currentTimeMillis (), "Hi" );
388
+ diskWriteWorker .submit (() -> controller .writeToLog (System .currentTimeMillis (), "Hi" ));
389
+ diskWriteWorker .await ();
373
390
}
374
391
375
392
/**
@@ -384,7 +401,8 @@ public void testFinalizeSessionAfterCrashOk() throws Exception {
384
401
testSettingsProvider , Thread .currentThread (), new RuntimeException ());
385
402
386
403
// This should not throw.
387
- controller .finalizeSessions (testSettingsProvider );
404
+ commonWorker .submit (() -> controller .finalizeSessions (testSettingsProvider ));
405
+ commonWorker .await ();
388
406
}
389
407
390
408
@ SdkSuppress (minSdkVersion = 30 ) // ApplicationExitInfo
@@ -535,7 +553,7 @@ public void testUploadDisabledThenEnabled() throws Exception {
535
553
}
536
554
537
555
@ SdkSuppress (minSdkVersion = 30 ) // ApplicationExitInfo
538
- public void testFatalEvent_sendsAppExceptionEvent () {
556
+ public void testFatalEvent_sendsAppExceptionEvent () throws Exception {
539
557
final String sessionId = "sessionId" ;
540
558
final LogFileManager logFileManager = new LogFileManager (testFileStore );
541
559
final AnalyticsEventLogger mockFirebaseAnalyticsLogger = mock (AnalyticsEventLogger .class );
@@ -548,10 +566,14 @@ public void testFatalEvent_sendsAppExceptionEvent() {
548
566
when (mockSessionReportingCoordinator .listSortedOpenSessionIds ())
549
567
.thenReturn (new TreeSet <>(Collections .singleton (sessionId )));
550
568
551
- controller .openSession (SESSION_ID );
552
- controller .handleUncaughtException (
553
- testSettingsProvider , Thread .currentThread (), new RuntimeException ("Fatal" ));
554
- controller .finalizeSessions (testSettingsProvider );
569
+ commonWorker .submit (
570
+ () -> {
571
+ controller .openSession (SESSION_ID );
572
+ controller .handleUncaughtException (
573
+ testSettingsProvider , Thread .currentThread (), new RuntimeException ("Fatal" ));
574
+ controller .finalizeSessions (testSettingsProvider );
575
+ });
576
+ commonWorker .await ();
555
577
556
578
assertFirebaseAnalyticsCrashEvent (mockFirebaseAnalyticsLogger );
557
579
}
0 commit comments