Skip to content

Migrate to Firebase common executors #6128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions firebase-crashlytics/firebase-crashlytics.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ dependencies {
testImplementation(libs.mockito.core)
testImplementation(libs.robolectric)
testImplementation(libs.truth)
testImplementation(project(":integ-testing"))

androidTestImplementation(libs.androidx.test.core)
androidTestImplementation(libs.androidx.test.runner)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@
import com.google.android.gms.tasks.TaskCompletionSource;
import com.google.android.gms.tasks.Tasks;
import com.google.firebase.FirebaseApp;
import com.google.firebase.concurrent.TestOnlyExecutors;
import com.google.firebase.crashlytics.internal.CrashlyticsNativeComponent;
import com.google.firebase.crashlytics.internal.CrashlyticsTestCase;
import com.google.firebase.crashlytics.internal.CrashlyticsWorker;
import com.google.firebase.crashlytics.internal.DevelopmentPlatformProvider;
import com.google.firebase.crashlytics.internal.NativeSessionFileProvider;
import com.google.firebase.crashlytics.internal.analytics.AnalyticsEventLogger;
Expand All @@ -55,13 +57,15 @@
import java.util.TreeSet;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.mockito.ArgumentCaptor;

public class CrashlyticsControllerTest extends CrashlyticsTestCase {
private static final String GOOGLE_APP_ID = "google:app:id";
private static final String SESSION_ID = "session_id";

private final CrashlyticsWorker commonWorker =
new CrashlyticsWorker(TestOnlyExecutors.background());

private Context testContext;
private IdManager idManager;
private SettingsProvider testSettingsProvider;
Expand Down Expand Up @@ -99,14 +103,19 @@ protected void setUp() throws Exception {
when(testSettingsProvider.getSettingsAsync()).thenReturn(Tasks.forResult(testSettings));
}

@Override
protected void tearDown() throws Exception {
super.tearDown();
commonWorker.await();
}

/** A convenience class for building CrashlyticsController instances for testing. */
private class ControllerBuilder {
private DataCollectionArbiter dataCollectionArbiter;
private CrashlyticsNativeComponent nativeComponent = null;
private AnalyticsEventLogger analyticsEventLogger;
private SessionReportingCoordinator sessionReportingCoordinator;

private CrashlyticsBackgroundWorker backgroundWorker;
private LogFileManager logFileManager = null;

private UserMetadata userMetadata = null;
Expand All @@ -118,8 +127,6 @@ private class ControllerBuilder {
analyticsEventLogger = mock(AnalyticsEventLogger.class);

sessionReportingCoordinator = mockSessionReportingCoordinator;

backgroundWorker = new CrashlyticsBackgroundWorker(new SameThreadExecutorService());
}

ControllerBuilder setDataCollectionArbiter(DataCollectionArbiter arbiter) {
Expand Down Expand Up @@ -168,7 +175,7 @@ public CrashlyticsController build() {
final CrashlyticsController controller =
new CrashlyticsController(
testContext.getApplicationContext(),
backgroundWorker,
commonWorker,
idManager,
dataCollectionArbiter,
testFileStore,
Expand Down Expand Up @@ -208,6 +215,8 @@ public void testWriteNonFatal_callsSessionReportingCoordinatorPersistNonFatal()
controller.writeNonFatalException(thread, nonFatal);
controller.doCloseSessions(testSettingsProvider);

commonWorker.await();

verify(mockSessionReportingCoordinator)
.persistNonFatalEvent(eq(nonFatal), eq(thread), eq(sessionId), anyLong());
}
Expand All @@ -228,9 +237,8 @@ public void testFatalException_callsSessionReportingCoordinatorPersistFatal() th
.persistFatalEvent(eq(fatal), eq(thread), eq(sessionId), anyLong());
}

@Test
@SdkSuppress(minSdkVersion = 30) // ApplicationExitInfo
public void testOnDemandFatal_callLogFatalException() {
public void testOnDemandFatal_callLogFatalException() throws Exception {
Thread thread = Thread.currentThread();
Exception fatal = new RuntimeException("Fatal");
Thread.UncaughtExceptionHandler exceptionHandler = mock(Thread.UncaughtExceptionHandler.class);
Expand All @@ -246,6 +254,8 @@ public void testOnDemandFatal_callLogFatalException() {
controller.enableExceptionHandling(SESSION_ID, exceptionHandler, testSettingsProvider);
controller.logFatalException(thread, fatal);

commonWorker.await();

verify(mockUserMetadata).setNewSession(not(eq(SESSION_ID)));
}

Expand Down Expand Up @@ -323,17 +333,20 @@ public File getOsFile() {
final CrashlyticsController controller =
builder().setNativeComponent(mockNativeComponent).setLogFileManager(logFileManager).build();

controller.finalizeSessions(testSettingsProvider);
commonWorker.submit(() -> controller.finalizeSessions(testSettingsProvider));
commonWorker.await();

verify(mockSessionReportingCoordinator)
.finalizeSessionWithNativeEvent(eq(previousSessionId), any(), any());
verify(mockSessionReportingCoordinator, never())
.finalizeSessionWithNativeEvent(eq(sessionId), any(), any());
}

@SdkSuppress(minSdkVersion = 30) // ApplicationExitInfo
public void testMissingNativeComponentCausesNoReports() {
public void testMissingNativeComponentCausesNoReports() throws Exception {
final CrashlyticsController controller = createController();
controller.finalizeSessions(testSettingsProvider);
commonWorker.submit(() -> controller.finalizeSessions(testSettingsProvider));
commonWorker.await();

List<String> sessions = testFileStore.getAllOpenSessionIds();
for (String sessionId : sessions) {
Expand Down Expand Up @@ -384,7 +397,8 @@ public void testFinalizeSessionAfterCrashOk() throws Exception {
testSettingsProvider, Thread.currentThread(), new RuntimeException());

// This should not throw.
controller.finalizeSessions(testSettingsProvider);
commonWorker.submit(() -> controller.finalizeSessions(testSettingsProvider));
commonWorker.await();
}

@SdkSuppress(minSdkVersion = 30) // ApplicationExitInfo
Expand Down Expand Up @@ -535,7 +549,7 @@ public void testUploadDisabledThenEnabled() throws Exception {
}

@SdkSuppress(minSdkVersion = 30) // ApplicationExitInfo
public void testFatalEvent_sendsAppExceptionEvent() {
public void testFatalEvent_sendsAppExceptionEvent() throws Exception {
final String sessionId = "sessionId";
final LogFileManager logFileManager = new LogFileManager(testFileStore);
final AnalyticsEventLogger mockFirebaseAnalyticsLogger = mock(AnalyticsEventLogger.class);
Expand All @@ -548,10 +562,14 @@ public void testFatalEvent_sendsAppExceptionEvent() {
when(mockSessionReportingCoordinator.listSortedOpenSessionIds())
.thenReturn(new TreeSet<>(Collections.singleton(sessionId)));

controller.openSession(SESSION_ID);
controller.handleUncaughtException(
testSettingsProvider, Thread.currentThread(), new RuntimeException("Fatal"));
controller.finalizeSessions(testSettingsProvider);
commonWorker.submit(
() -> {
controller.openSession(SESSION_ID);
controller.handleUncaughtException(
testSettingsProvider, Thread.currentThread(), new RuntimeException("Fatal"));
controller.finalizeSessions(testSettingsProvider);
});
commonWorker.await();

assertFirebaseAnalyticsCrashEvent(mockFirebaseAnalyticsLogger);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@
import com.google.android.gms.tasks.Tasks;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.concurrent.TestOnlyExecutors;
import com.google.firebase.crashlytics.internal.CrashlyticsNativeComponent;
import com.google.firebase.crashlytics.internal.CrashlyticsNativeComponentDeferredProxy;
import com.google.firebase.crashlytics.internal.CrashlyticsTestCase;
import com.google.firebase.crashlytics.internal.CrashlyticsWorker;
import com.google.firebase.crashlytics.internal.DevelopmentPlatformProvider;
import com.google.firebase.crashlytics.internal.RemoteConfigDeferredProxy;
import com.google.firebase.crashlytics.internal.analytics.UnavailableAnalyticsEventLogger;
Expand All @@ -44,7 +46,6 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;

public class CrashlyticsCoreInitializationTest extends CrashlyticsTestCase {

Expand Down Expand Up @@ -89,8 +90,9 @@ private static final class CoreBuilder {
private IdManager idManager;
private CrashlyticsNativeComponent nativeComponent;
private DataCollectionArbiter arbiter;
private ExecutorService crashHandlerExecutor;
private FileStore fileStore;
private CrashlyticsWorker commonWorker;
private CrashlyticsWorker diskWriteWorker;

public CoreBuilder(Context context, FirebaseOptions firebaseOptions) {
app = mock(FirebaseApp.class);
Expand Down Expand Up @@ -119,7 +121,8 @@ public void whenAvailable(
arbiter = mock(DataCollectionArbiter.class);
when(arbiter.isAutomaticDataCollectionEnabled()).thenReturn(true);

crashHandlerExecutor = new SameThreadExecutorService();
commonWorker = new CrashlyticsWorker(TestOnlyExecutors.background());
diskWriteWorker = new CrashlyticsWorker(TestOnlyExecutors.background());
fileStore = new FileStore(context);
}

Expand All @@ -142,9 +145,10 @@ public CrashlyticsCore build() {
new DisabledBreadcrumbSource(),
new UnavailableAnalyticsEventLogger(),
fileStore,
crashHandlerExecutor,
mock(CrashlyticsAppQualitySessionsSubscriber.class),
mock(RemoteConfigDeferredProxy.class));
mock(RemoteConfigDeferredProxy.class),
commonWorker,
diskWriteWorker);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@
import com.google.android.gms.tasks.Tasks;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.concurrent.TestOnlyExecutors;
import com.google.firebase.crashlytics.BuildConfig;
import com.google.firebase.crashlytics.internal.CrashlyticsNativeComponent;
import com.google.firebase.crashlytics.internal.CrashlyticsNativeComponentDeferredProxy;
import com.google.firebase.crashlytics.internal.CrashlyticsTestCase;
import com.google.firebase.crashlytics.internal.CrashlyticsWorker;
import com.google.firebase.crashlytics.internal.DevelopmentPlatformProvider;
import com.google.firebase.crashlytics.internal.RemoteConfigDeferredProxy;
import com.google.firebase.crashlytics.internal.analytics.UnavailableAnalyticsEventLogger;
Expand Down Expand Up @@ -427,9 +429,10 @@ CrashlyticsCore build(Context context) {
breadcrumbSource,
new UnavailableAnalyticsEventLogger(),
new FileStore(context),
new SameThreadExecutorService(),
mock(CrashlyticsAppQualitySessionsSubscriber.class),
mock(RemoteConfigDeferredProxy.class));
mock(RemoteConfigDeferredProxy.class),
new CrashlyticsWorker(TestOnlyExecutors.background()),
new CrashlyticsWorker(TestOnlyExecutors.background()));
return crashlyticsCore;
}
}
Expand Down
Loading
Loading