| Index: chrome/android/javatests/src/org/chromium/chrome/browser/crash/LogcatExtractionRunnableTest.java
|
| diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/crash/LogcatExtractionRunnableTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/crash/LogcatExtractionRunnableTest.java
|
| index cd851953dff3bf5634e50b2c5a3716357c21a30d..727ce4987d8df4a53d460539b8fcf7dea50a402d 100644
|
| --- a/chrome/android/javatests/src/org/chromium/chrome/browser/crash/LogcatExtractionRunnableTest.java
|
| +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/crash/LogcatExtractionRunnableTest.java
|
| @@ -4,13 +4,19 @@
|
|
|
| package org.chromium.chrome.browser.crash;
|
|
|
| +import android.annotation.TargetApi;
|
| +import android.app.job.JobInfo;
|
| +import android.app.job.JobScheduler;
|
| import android.content.ComponentName;
|
| import android.content.Context;
|
| import android.content.Intent;
|
| +import android.os.Build;
|
| import android.support.test.filters.MediumTest;
|
|
|
| import org.chromium.base.StreamUtil;
|
| import org.chromium.base.test.util.AdvancedMockContext;
|
| +import org.chromium.chrome.browser.ChromeFeatureList;
|
| +import org.chromium.components.background_task_scheduler.TaskIds;
|
| import org.chromium.components.minidump_uploader.CrashFileManager;
|
| import org.chromium.components.minidump_uploader.CrashTestCase;
|
|
|
| @@ -19,9 +25,10 @@ import java.io.File;
|
| import java.io.FileReader;
|
| import java.io.FileWriter;
|
| import java.io.IOException;
|
| -import java.util.ArrayList;
|
| +import java.util.Arrays;
|
| +import java.util.HashMap;
|
| import java.util.List;
|
| -import java.util.concurrent.atomic.AtomicInteger;
|
| +import java.util.Map;
|
|
|
| /**
|
| * Unittests for {@link LogcatExtractionRunnable}.
|
| @@ -29,83 +36,182 @@ import java.util.concurrent.atomic.AtomicInteger;
|
| public class LogcatExtractionRunnableTest extends CrashTestCase {
|
| private File mCrashDir;
|
|
|
| + private static final String BOUNDARY = "boundary";
|
| + private static final String MINIDUMP_CONTENTS = "important minidump contents";
|
| + private static final List<String> LOGCAT =
|
| + Arrays.asList("some random log content", "some more deterministic log content");
|
| +
|
| + private static class TestLogcatExtractionRunnable extends LogcatExtractionRunnable {
|
| + TestLogcatExtractionRunnable(Context context, File minidump) {
|
| + super(context, minidump);
|
| + }
|
| +
|
| + @Override
|
| + protected List<String> getLogcat() {
|
| + return LOGCAT;
|
| + }
|
| + };
|
| +
|
| + @TargetApi(Build.VERSION_CODES.M)
|
| + private static class TestJobScheduler extends JobScheduler {
|
| + TestJobScheduler() {}
|
| +
|
| + @Override
|
| + public void cancel(int jobId) {}
|
| +
|
| + @Override
|
| + public void cancelAll() {}
|
| +
|
| + @Override
|
| + public List<JobInfo> getAllPendingJobs() {
|
| + return null;
|
| + }
|
| +
|
| + @Override
|
| + public JobInfo getPendingJob(int jobId) {
|
| + return null;
|
| + }
|
| +
|
| + @Override
|
| + public int schedule(JobInfo job) {
|
| + assertEquals(TaskIds.CHROME_MINIDUMP_UPLOADING_JOB_ID, job.getId());
|
| + assertEquals(ChromeMinidumpUploadJobService.class.getName(),
|
| + job.getService().getClassName());
|
| + return 0;
|
| + }
|
| + };
|
| +
|
| + // Responsible for verifying that the correct intent is fired after the logcat is extracted.
|
| + private class TestContext extends AdvancedMockContext {
|
| + int mNumServiceStarts;
|
| +
|
| + TestContext(Context realContext) {
|
| + super(realContext);
|
| + }
|
| +
|
| + @Override
|
| + public ComponentName startService(Intent intent) {
|
| + assertFalse("Should only start a service directly when the job scheduler is disabled.",
|
| + ChromeFeatureList.isEnabled(
|
| + ChromeFeatureList.UPLOAD_CRASH_REPORTS_USING_JOB_SCHEDULER));
|
| + ++mNumServiceStarts;
|
| + assertEquals(1, mNumServiceStarts);
|
| + assertEquals(
|
| + MinidumpUploadService.class.getName(), intent.getComponent().getClassName());
|
| + assertEquals(MinidumpUploadService.ACTION_UPLOAD, intent.getAction());
|
| + assertEquals(new File(mCrashDir, "test.dmp.try0").getAbsolutePath(),
|
| + intent.getStringExtra(MinidumpUploadService.FILE_TO_UPLOAD_KEY));
|
| + return super.startService(intent);
|
| + }
|
| +
|
| + @Override
|
| + public Object getSystemService(String name) {
|
| + if (Context.JOB_SCHEDULER_SERVICE.equals(name)) {
|
| + assertTrue("Should only access the JobScheduler when it is enabled.",
|
| + ChromeFeatureList.isEnabled(
|
| + ChromeFeatureList.UPLOAD_CRASH_REPORTS_USING_JOB_SCHEDULER));
|
| + return new TestJobScheduler();
|
| + }
|
| +
|
| + return super.getSystemService(name);
|
| + }
|
| + };
|
| +
|
| @Override
|
| protected void setUp() throws Exception {
|
| super.setUp();
|
| mCrashDir = new CrashFileManager(mCacheDir).getCrashDirectory();
|
| }
|
|
|
| - @MediumTest
|
| - public void testSimpleExtraction() {
|
| - // Set up the test.
|
| - final List<String> logcat = new ArrayList<String>();
|
| - logcat.add("some random log content");
|
| - logcat.add("some more deterministic log content");
|
| -
|
| - final File minidump = new File(mCrashDir, "test.dmp");
|
| - final String boundary = "boundary";
|
| - final String minidumpContents = "important minidump contents";
|
| + @Override
|
| + protected void tearDown() throws Exception {
|
| + ChromeFeatureList.setTestFeatures(null);
|
| + super.tearDown();
|
| + }
|
| +
|
| + /**
|
| + * Sets whether to upload minidumps using the JobScheduler API. Minidumps can either be uploaded
|
| + * via a JobScheduler, or via a direct Intent service.
|
| + * @param enable Whether to enable the JobScheduler API.
|
| + */
|
| + private void setJobSchedulerEnabled(boolean enable) {
|
| + Map<String, Boolean> features = new HashMap<>();
|
| + features.put(ChromeFeatureList.UPLOAD_CRASH_REPORTS_USING_JOB_SCHEDULER, enable);
|
| + ChromeFeatureList.setTestFeatures(features);
|
| + }
|
| +
|
| + /**
|
| + * Creates a simple fake minidump file for testing.
|
| + * @param filename The name of the file to create.
|
| + */
|
| + private File createMinidump(String filename) throws IOException {
|
| + File minidump = new File(mCrashDir, filename);
|
| FileWriter writer = null;
|
| try {
|
| writer = new FileWriter(minidump);
|
| - writer.write(boundary + "\n");
|
| - writer.write(minidumpContents + "\n");
|
| - } catch (IOException e) {
|
| - fail(e.toString());
|
| + writer.write(BOUNDARY + "\n");
|
| + writer.write(MINIDUMP_CONTENTS + "\n");
|
| } finally {
|
| StreamUtil.closeQuietly(writer);
|
| }
|
| + return minidump;
|
| + }
|
|
|
| - // The testContext is responsible for verifying that the correct intent is fired after the
|
| - // logcat is extracted.
|
| - final AtomicInteger numServiceStarts = new AtomicInteger(0);
|
| - Context testContext = new AdvancedMockContext(getInstrumentation().getTargetContext()) {
|
| - @Override
|
| - public ComponentName startService(Intent intent) {
|
| - assertEquals(1, numServiceStarts.incrementAndGet());
|
| - assertEquals(MinidumpUploadService.class.getName(),
|
| - intent.getComponent().getClassName());
|
| - assertEquals(MinidumpUploadService.ACTION_UPLOAD, intent.getAction());
|
| - assertEquals(new File(mCrashDir, "test.dmp.try0").getAbsolutePath(),
|
| - intent.getStringExtra(MinidumpUploadService.FILE_TO_UPLOAD_KEY));
|
| - return super.startService(intent);
|
| - }
|
| - };
|
| -
|
| - // Extract the logcat!
|
| - LogcatExtractionRunnable runnable = new LogcatExtractionRunnable(testContext, minidump) {
|
| - @Override
|
| - protected List<String> getLogcat() {
|
| - return logcat;
|
| - }
|
| - };
|
| - runnable.run();
|
| -
|
| - // Verify the file contents.
|
| + /**
|
| + * Verifies that the contents of the {@param filename} are the expected ones.
|
| + * @param filename The name of the file containing the concatenated logcat and minidump output.
|
| + */
|
| + private void verifyMinidumpWithLogcat(String filename) throws IOException {
|
| BufferedReader input = null;
|
| try {
|
| - File logfile = new File(mCrashDir, "test.dmp.try0");
|
| - assertTrue("Logfile should exist!", logfile.exists());
|
| + File minidumpWithLogcat = new File(mCrashDir, filename);
|
| + assertTrue("Should have created a file containing the logcat and minidump contents",
|
| + minidumpWithLogcat.exists());
|
|
|
| - input = new BufferedReader(new FileReader(logfile));
|
| - assertEquals("The first line should be the boundary line.", boundary, input.readLine());
|
| + input = new BufferedReader(new FileReader(minidumpWithLogcat));
|
| + assertEquals("The first line should be the boundary line.", BOUNDARY, input.readLine());
|
| assertEquals("The second line should be the content dispoistion.",
|
| MinidumpLogcatPrepender.LOGCAT_CONTENT_DISPOSITION, input.readLine());
|
| assertEquals("The third line should be the content type.",
|
| MinidumpLogcatPrepender.LOGCAT_CONTENT_TYPE, input.readLine());
|
| assertEquals("The fourth line should be blank, for padding.", "", input.readLine());
|
| - for (String expected : logcat) {
|
| - assertEquals(expected, input.readLine());
|
| + for (String expected : LOGCAT) {
|
| + assertEquals("The logcat contents should match", expected, input.readLine());
|
| }
|
| - assertEquals("The logcat should be followed by the boundary line.", boundary,
|
| + assertEquals("The logcat should be followed by the boundary line.", BOUNDARY,
|
| input.readLine());
|
| assertEquals(
|
| - "The minidump contents should follow.", minidumpContents, input.readLine());
|
| + "The minidump contents should follow.", MINIDUMP_CONTENTS, input.readLine());
|
| assertNull("There should be nothing else in the file", input.readLine());
|
| - } catch (IOException e) {
|
| - fail(e.toString());
|
| } finally {
|
| StreamUtil.closeQuietly(input);
|
| }
|
| }
|
| +
|
| + @MediumTest
|
| + public void testSimpleExtraction_SansJobScheduler() throws IOException {
|
| + setJobSchedulerEnabled(false);
|
| + final File minidump = createMinidump("test.dmp");
|
| + Context testContext = new TestContext(getInstrumentation().getTargetContext());
|
| +
|
| + LogcatExtractionRunnable runnable = new TestLogcatExtractionRunnable(testContext, minidump);
|
| + runnable.run();
|
| +
|
| + verifyMinidumpWithLogcat("test.dmp.try0");
|
| + }
|
| +
|
| + @MediumTest
|
| + public void testSimpleExtraction_WithJobScheduler() throws IOException {
|
| + // The JobScheduler API is only available as of Android M.
|
| + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return;
|
| +
|
| + setJobSchedulerEnabled(true);
|
| + final File minidump = createMinidump("test.dmp");
|
| + Context testContext = new TestContext(getInstrumentation().getTargetContext());
|
| +
|
| + LogcatExtractionRunnable runnable = new TestLogcatExtractionRunnable(testContext, minidump);
|
| + runnable.run();
|
| +
|
| + verifyMinidumpWithLogcat("test.dmp.try0");
|
| + }
|
| }
|
|
|