Skip to content

Commit

Permalink
Split functionality out of MinidumpUploaderTest into smaller components.
Browse files Browse the repository at this point in the history
Prepare to split MinidumpUploaderTest into WebView-specific tests, and
tests shared between WebView and Chrome, by splitting some
test-functionality out into smaller components and removing unnecessary
dependencies on AwMinidumpUploaderDelegate.

BUG=692448

Review-Url: https://codereview.chromium.org/2820683002
Cr-Commit-Position: refs/heads/master@{#465597}
  • Loading branch information
gsennton authored and Commit bot committed Apr 19, 2017
1 parent c8717b5 commit 2be4a32
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

package org.chromium.android_webview.test.crash;

import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout;

import android.os.ParcelFileDescriptor;
import android.support.test.filters.MediumTest;
import android.webkit.ValueCallback;
Expand All @@ -19,9 +17,11 @@
import org.chromium.components.minidump_uploader.CrashTestCase;
import org.chromium.components.minidump_uploader.MinidumpUploadCallable;
import org.chromium.components.minidump_uploader.MinidumpUploadCallableTest;
import org.chromium.components.minidump_uploader.MinidumpUploadTestUtility;
import org.chromium.components.minidump_uploader.MinidumpUploader;
import org.chromium.components.minidump_uploader.MinidumpUploaderDelegate;
import org.chromium.components.minidump_uploader.MinidumpUploaderImpl;
import org.chromium.components.minidump_uploader.TestMinidumpUploaderImpl;
import org.chromium.components.minidump_uploader.util.CrashReportingPermissionManager;
import org.chromium.components.minidump_uploader.util.HttpURLConnectionFactory;

Expand All @@ -37,7 +37,6 @@
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
* Instrumentation tests for MinidumpUploader.
Expand All @@ -46,8 +45,6 @@ public class MinidumpUploaderTest extends CrashTestCase {
private static final String TAG = "MinidumpUploaderTest";
private static final String BOUNDARY = "TESTBOUNDARY";

private static final long TIME_OUT_MILLIS = 3000;

@Override
protected File getExistingCacheDir() {
return CrashReceiverService.getOrCreateWebViewCrashDir();
Expand All @@ -72,44 +69,12 @@ public void queryMetricsSetting(ValueCallback<Boolean> callback) {
}
}

private class TestMinidumpUploaderImpl extends MinidumpUploaderImpl {
private final CrashReportingPermissionManager mPermissionManager;

TestMinidumpUploaderImpl(CrashReportingPermissionManager permissionManager) {
super(new AwMinidumpUploaderDelegate());
mPermissionManager = permissionManager;
}

TestMinidumpUploaderImpl(MinidumpUploaderDelegate delegate,
CrashReportingPermissionManager permissionManager) {
super(delegate);
mPermissionManager = permissionManager;
}

@Override
public CrashFileManager createCrashFileManager(File crashDir) {
return new CrashFileManager(crashDir) {
@Override
public void cleanOutAllNonFreshMinidumpFiles() {}
};
}

@Override
public MinidumpUploadCallable createMinidumpUploadCallable(
File minidumpFile, File logfile) {
return new MinidumpUploadCallable(minidumpFile, logfile,
new MinidumpUploadCallableTest.TestHttpURLConnectionFactory(),
mPermissionManager);
}
}

/**
* Test to ensure the minidump uploading mechanism behaves as expected when we fail to upload
* minidumps.
*/
@MediumTest
public void testFailUploadingMinidumps() throws IOException {
PlatformServiceBridge.injectInstance(new TestPlatformServiceBridge(true));
final CrashReportingPermissionManager permManager =
new MockCrashReportingPermissionManager() {
{
Expand All @@ -119,7 +84,8 @@ public void testFailUploadingMinidumps() throws IOException {
mIsEnabledForTests = false;
}
};
MinidumpUploader minidumpUploader = new TestMinidumpUploaderImpl(permManager);
MinidumpUploader minidumpUploader =
new TestMinidumpUploaderImpl(getExistingCacheDir(), permManager);

File firstFile = createMinidumpFileInCrashDir("1_abc.dmp0");
File secondFile = createMinidumpFileInCrashDir("12_abc.dmp0");
Expand All @@ -134,7 +100,8 @@ public void testFailUploadingMinidumps() throws IOException {
File expectedJustBelowMaxTriesFile = new File(mCrashDir,
justBelowMaxTriesFile.getName().replace(triesBelowMaxString, maxTriesString));

uploadMinidumpsSync(minidumpUploader, true /* expectReschedule */);
MinidumpUploadTestUtility.uploadMinidumpsSync(
minidumpUploader, true /* expectReschedule */);
assertFalse(firstFile.exists());
assertFalse(secondFile.exists());
assertFalse(justBelowMaxTriesFile.exists());
Expand All @@ -145,55 +112,6 @@ public void testFailUploadingMinidumps() throws IOException {
assertTrue(maxTriesFile.exists());
}

/**
* Utility method for running {@param minidumpUploader}.uploadAllMinidumps on the UI thread to
* avoid breaking any assertions about running on the UI thread.
*/
private static void uploadAllMinidumpsOnUiThread(final MinidumpUploader minidumpUploader,
final MinidumpUploader.UploadsFinishedCallback uploadsFinishedCallback) {
uploadAllMinidumpsOnUiThread(
minidumpUploader, uploadsFinishedCallback, false /* blockUntilJobPosted */);
}

private static void uploadAllMinidumpsOnUiThread(final MinidumpUploader minidumpUploader,
final MinidumpUploader.UploadsFinishedCallback uploadsFinishedCallback,
boolean blockUntilJobPosted) {
final CountDownLatch jobPostedLatch = new CountDownLatch(1);
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
minidumpUploader.uploadAllMinidumps(uploadsFinishedCallback);
jobPostedLatch.countDown();
}
});
if (blockUntilJobPosted) {
try {
jobPostedLatch.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}

private static void uploadMinidumpsSync(
MinidumpUploader minidumpUploader, final boolean expectReschedule) {
final CountDownLatch uploadsFinishedLatch = new CountDownLatch(1);
uploadAllMinidumpsOnUiThread(
minidumpUploader, new MinidumpUploader.UploadsFinishedCallback() {
@Override
public void uploadsFinished(boolean reschedule) {
assertEquals(expectReschedule, reschedule);
uploadsFinishedLatch.countDown();
}
});
try {
assertTrue(uploadsFinishedLatch.await(
scaleTimeout(TIME_OUT_MILLIS), TimeUnit.MILLISECONDS));
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}

/**
* Ensure MinidumpUploaderImpl doesn't crash even if the WebView Crash dir doesn't exist (could
* happen e.g. if a Job persists across WebView-updates?
Expand All @@ -212,7 +130,15 @@ public void testUploadingWithoutCrashDir() throws IOException {
new MockCrashReportingPermissionManager() {
{ mIsEnabledForTests = true; }
};
MinidumpUploader minidumpUploader = new TestMinidumpUploaderImpl(permManager);
MinidumpUploader minidumpUploader =
// Use AwMinidumpUploaderDelegate instead of TestMinidumpUploaderDelegate here
// since AwMinidumpUploaderDelegate defines the WebView crash directory.
new TestMinidumpUploaderImpl(new AwMinidumpUploaderDelegate() {
@Override
public CrashReportingPermissionManager createCrashReportingPermissionManager() {
return permManager;
}
});

File firstFile = createMinidumpFileInCrashDir("1_abc.dmp0");
File secondFile = createMinidumpFileInCrashDir("12_abcd.dmp0");
Expand All @@ -221,7 +147,8 @@ public void testUploadingWithoutCrashDir() throws IOException {
File expectedSecondUploadFile =
new File(mCrashDir, secondFile.getName().replace(".dmp", ".up"));

uploadMinidumpsSync(minidumpUploader, false /* expectReschedule */);
MinidumpUploadTestUtility.uploadMinidumpsSync(
minidumpUploader, false /* expectReschedule */);

assertFalse(firstFile.exists());
assertTrue(expectedFirstUploadFile.exists());
Expand All @@ -235,8 +162,7 @@ private interface MinidumpUploadCallableCreator {

private MinidumpUploaderImpl createCallableListMinidumpUploader(
final List<MinidumpUploadCallableCreator> callables, final boolean userPermitted) {
PlatformServiceBridge.injectInstance(new TestPlatformServiceBridge(userPermitted));
return new TestMinidumpUploaderImpl(null) {
return new TestMinidumpUploaderImpl(getExistingCacheDir(), null) {
private int mIndex = 0;

@Override
Expand Down Expand Up @@ -277,7 +203,8 @@ public MinidumpUploadCallable createCallable(File minidumpFile, File logfile) {
File firstFile = createMinidumpFileInCrashDir("firstFile.dmp0");
File secondFile = createMinidumpFileInCrashDir("secondFile.dmp0");

uploadMinidumpsSync(minidumpUploader, true /* expectReschedule */);
MinidumpUploadTestUtility.uploadMinidumpsSync(
minidumpUploader, true /* expectReschedule */);
assertFalse(firstFile.exists());
assertFalse(secondFile.exists());
File expectedSecondFile;
Expand Down Expand Up @@ -354,13 +281,13 @@ public void testCancelingWontCancelFirstUpload() throws IOException {
}

private void testCancellation(final boolean successfulUpload) throws IOException {
PlatformServiceBridge.injectInstance(new TestPlatformServiceBridge(true));
final CrashReportingPermissionManager permManager =
new MockCrashReportingPermissionManager() {
{ mIsEnabledForTests = true; }
};
final CountDownLatch stopStallingLatch = new CountDownLatch(1);
MinidumpUploaderImpl minidumpUploader = new TestMinidumpUploaderImpl(permManager) {
MinidumpUploaderImpl minidumpUploader = new TestMinidumpUploaderImpl(
getExistingCacheDir(), permManager) {
@Override
public MinidumpUploadCallable createMinidumpUploadCallable(
File minidumpFile, File logfile) {
Expand All @@ -376,7 +303,7 @@ public MinidumpUploadCallable createMinidumpUploadCallable(
File expectedFirstRetryFile = new File(mCrashDir, firstFile.getName() + ".try1");

// This is run on the UI thread to avoid failing any assertOnUiThread assertions.
uploadAllMinidumpsOnUiThread(minidumpUploader,
MinidumpUploadTestUtility.uploadAllMinidumpsOnUiThread(minidumpUploader,
new MinidumpUploader.UploadsFinishedCallback() {
@Override
public void uploadsFinished(boolean reschedule) {
Expand Down Expand Up @@ -497,8 +424,7 @@ private void testPlatformServicesBridgeIsUsed(final boolean userConsent) throws
PlatformServiceBridge.injectInstance(new TestPlatformServiceBridge(userConsent));
MinidumpUploaderDelegate delegate =
new WebViewUserConsentMinidumpUploaderDelegate(userConsent);
MinidumpUploader minidumpUploader = new TestMinidumpUploaderImpl(
delegate, delegate.createCrashReportingPermissionManager());
MinidumpUploader minidumpUploader = new TestMinidumpUploaderImpl(delegate);

File firstFile = createMinidumpFileInCrashDir("1_abc.dmp0");
File secondFile = createMinidumpFileInCrashDir("12_abcd.dmp0");
Expand All @@ -507,7 +433,8 @@ private void testPlatformServicesBridgeIsUsed(final boolean userConsent) throws
File expectedSecondFile = new File(
mCrashDir, secondFile.getName().replace(".dmp", userConsent ? ".up" : ".skipped"));

uploadMinidumpsSync(minidumpUploader, false /* expectReschedule */);
MinidumpUploadTestUtility.uploadMinidumpsSync(
minidumpUploader, false /* expectReschedule */);

assertFalse(firstFile.exists());
assertTrue(expectedFirstFile.exists());
Expand Down Expand Up @@ -595,14 +522,23 @@ private File[] copyAndUploadMinidumpsSync(CrashFileManager fileManager, File[][]
uids[n] /* uid */, fileDescriptors[n], false /* scheduleUploads */);
}

PlatformServiceBridge.injectInstance(new TestPlatformServiceBridge(true));
final CrashReportingPermissionManager permManager =
new MockCrashReportingPermissionManager() {
{ mIsEnabledForTests = true; }
};
MinidumpUploader minidumpUploader = new TestMinidumpUploaderImpl(permManager);
MinidumpUploader minidumpUploader =
// Use AwMinidumpUploaderDelegate instead of TestMinidumpUploaderDelegate to ensure
// AwMinidumpUploaderDelegate works well together with the minidump-copying methods
// of CrashReceiverService.
new TestMinidumpUploaderImpl(new AwMinidumpUploaderDelegate() {
@Override
public CrashReportingPermissionManager createCrashReportingPermissionManager() {
return permManager;
}
});

uploadMinidumpsSync(minidumpUploader, false /* expectReschedule */);
MinidumpUploadTestUtility.uploadMinidumpsSync(
minidumpUploader, false /* expectReschedule */);
// Ensure there are no minidumps left to upload.
File[] nonUploadedMinidumps =
fileManager.getAllMinidumpFiles(MinidumpUploaderImpl.MAX_UPLOAD_TRIES_ALLOWED);
Expand Down
3 changes: 3 additions & 0 deletions components/minidump_uploader/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,8 @@ android_library("minidump_uploader_javatests") {
"android/javatests/src/org/chromium/components/minidump_uploader/CrashFileManagerTest.java",
"android/javatests/src/org/chromium/components/minidump_uploader/CrashTestCase.java",
"android/javatests/src/org/chromium/components/minidump_uploader/MinidumpUploadCallableTest.java",
"android/javatests/src/org/chromium/components/minidump_uploader/MinidumpUploadTestUtility.java",
"android/javatests/src/org/chromium/components/minidump_uploader/TestMinidumpUploaderDelegate.java",
"android/javatests/src/org/chromium/components/minidump_uploader/TestMinidumpUploaderImpl.java",
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ public class MinidumpUploaderImpl implements MinidumpUploader {
/**
* The delegate that performs embedder-specific behavior.
*/
private final MinidumpUploaderDelegate mDelegate;
@VisibleForTesting
protected final MinidumpUploaderDelegate mDelegate;

/**
* Manages the set of pending and failed local minidump files.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.components.minidump_uploader;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout;

import org.chromium.base.ThreadUtils;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
* Utility class for testing the minidump-uploading mechanism.
*/
public class MinidumpUploadTestUtility {
private static final long TIME_OUT_MILLIS = 3000;

/**
* Utility method for running {@param minidumpUploader}.uploadAllMinidumps on the UI thread to
* avoid breaking any assertions about running on the UI thread.
*/
public static void uploadAllMinidumpsOnUiThread(final MinidumpUploader minidumpUploader,
final MinidumpUploader.UploadsFinishedCallback uploadsFinishedCallback) {
uploadAllMinidumpsOnUiThread(
minidumpUploader, uploadsFinishedCallback, false /* blockUntilJobPosted */);
}

/**
* Utility method for running {@param minidumpUploader}.uploadAllMinidumps on the UI thread to
* avoid breaking any assertions about running on the UI thread.
* @param blockUntilJobPosted whether to block the current thread until the minidump-uploading
* job has been posted to the UI thread. This can be used to avoid
* some race-conditions (e.g. when waiting for variables that are
* initialized in the uploadAllMinidumps call).
*/
public static void uploadAllMinidumpsOnUiThread(final MinidumpUploader minidumpUploader,
final MinidumpUploader.UploadsFinishedCallback uploadsFinishedCallback,
boolean blockUntilJobPosted) {
final CountDownLatch jobPostedLatch = new CountDownLatch(1);
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
minidumpUploader.uploadAllMinidumps(uploadsFinishedCallback);
jobPostedLatch.countDown();
}
});
if (blockUntilJobPosted) {
try {
assertTrue(
jobPostedLatch.await(scaleTimeout(TIME_OUT_MILLIS), TimeUnit.MILLISECONDS));
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}

/**
* Utility method for uploading minidumps, and waiting for the uploads to finish.
* @param minidumpUploader the implementation to use to upload minidumps.
* @param expectReschedule value used to assert whether the uploads should be rescheduled,
* e.g. when uploading succeeds we should normally not expect to
* reschedule.
*/
public static void uploadMinidumpsSync(
MinidumpUploader minidumpUploader, final boolean expectReschedule) {
final CountDownLatch uploadsFinishedLatch = new CountDownLatch(1);
uploadAllMinidumpsOnUiThread(
minidumpUploader, new MinidumpUploader.UploadsFinishedCallback() {
@Override
public void uploadsFinished(boolean reschedule) {
assertEquals(expectReschedule, reschedule);
uploadsFinishedLatch.countDown();
}
});
try {
assertTrue(uploadsFinishedLatch.await(
scaleTimeout(TIME_OUT_MILLIS), TimeUnit.MILLISECONDS));
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
Loading

0 comments on commit 2be4a32

Please sign in to comment.