Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.android_webview.test.crash; | 5 package org.chromium.android_webview.test.crash; |
| 6 | 6 |
| 7 import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout; | 7 import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout; |
| 8 | 8 |
| 9 import android.content.Context; | 9 import android.content.Context; |
| 10 import android.os.ParcelFileDescriptor; | 10 import android.os.ParcelFileDescriptor; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 24 import org.chromium.components.minidump_uploader.util.CrashReportingPermissionMa nager; | 24 import org.chromium.components.minidump_uploader.util.CrashReportingPermissionMa nager; |
| 25 import org.chromium.components.minidump_uploader.util.HttpURLConnectionFactory; | 25 import org.chromium.components.minidump_uploader.util.HttpURLConnectionFactory; |
| 26 | 26 |
| 27 import java.io.File; | 27 import java.io.File; |
| 28 import java.io.FileInputStream; | 28 import java.io.FileInputStream; |
| 29 import java.io.FileNotFoundException; | 29 import java.io.FileNotFoundException; |
| 30 import java.io.IOException; | 30 import java.io.IOException; |
| 31 import java.io.InterruptedIOException; | 31 import java.io.InterruptedIOException; |
| 32 import java.io.OutputStream; | 32 import java.io.OutputStream; |
| 33 import java.net.HttpURLConnection; | 33 import java.net.HttpURLConnection; |
| 34 import java.net.MalformedURLException; | |
| 35 import java.net.URL; | |
| 34 import java.util.ArrayList; | 36 import java.util.ArrayList; |
| 35 import java.util.List; | 37 import java.util.List; |
| 36 import java.util.concurrent.CountDownLatch; | 38 import java.util.concurrent.CountDownLatch; |
| 37 import java.util.concurrent.TimeUnit; | 39 import java.util.concurrent.TimeUnit; |
| 38 | 40 |
| 39 /** | 41 /** |
| 40 * Instrumentation tests for MinidumpUploader. | 42 * Instrumentation tests for MinidumpUploader. |
| 41 */ | 43 */ |
| 42 public class MinidumpUploaderTest extends CrashTestCase { | 44 public class MinidumpUploaderTest extends CrashTestCase { |
| 43 private static final String TAG = "MinidumpUploaderTest"; | 45 private static final String TAG = "MinidumpUploaderTest"; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 139 // This file should have been left untouched. | 141 // This file should have been left untouched. |
| 140 assertTrue(maxTriesFile.exists()); | 142 assertTrue(maxTriesFile.exists()); |
| 141 } | 143 } |
| 142 | 144 |
| 143 /** | 145 /** |
| 144 * Utility method for running {@param minidumpUploader}.uploadAllMinidumps o n the UI thread to | 146 * Utility method for running {@param minidumpUploader}.uploadAllMinidumps o n the UI thread to |
| 145 * avoid breaking any assertions about running on the UI thread. | 147 * avoid breaking any assertions about running on the UI thread. |
| 146 */ | 148 */ |
| 147 private static void uploadAllMinidumpsOnUiThread(final MinidumpUploader mini dumpUploader, | 149 private static void uploadAllMinidumpsOnUiThread(final MinidumpUploader mini dumpUploader, |
| 148 final MinidumpUploader.UploadsFinishedCallback uploadsFinishedCallba ck) { | 150 final MinidumpUploader.UploadsFinishedCallback uploadsFinishedCallba ck) { |
| 151 uploadAllMinidumpsOnUiThread( | |
| 152 minidumpUploader, uploadsFinishedCallback, false /* blockUntilJo bPosted */); | |
| 153 } | |
| 154 | |
| 155 private static void uploadAllMinidumpsOnUiThread(final MinidumpUploader mini dumpUploader, | |
| 156 final MinidumpUploader.UploadsFinishedCallback uploadsFinishedCallba ck, | |
| 157 boolean blockUntilJobPosted) { | |
| 158 final CountDownLatch jobPostedLatch = new CountDownLatch(1); | |
| 149 ThreadUtils.runOnUiThread(new Runnable() { | 159 ThreadUtils.runOnUiThread(new Runnable() { |
| 150 @Override | 160 @Override |
| 151 public void run() { | 161 public void run() { |
| 152 minidumpUploader.uploadAllMinidumps(uploadsFinishedCallback); | 162 minidumpUploader.uploadAllMinidumps(uploadsFinishedCallback); |
| 163 jobPostedLatch.countDown(); | |
| 153 } | 164 } |
| 154 }); | 165 }); |
| 166 if (blockUntilJobPosted) { | |
| 167 try { | |
| 168 jobPostedLatch.await(); | |
| 169 } catch (InterruptedException e) { | |
| 170 throw new RuntimeException(e); | |
|
Ilya Sherman
2017/02/11 01:00:47
What's the reason to catch the exception just to r
gsennton
2017/02/13 10:46:55
Just to avoid having to declare the Exception type
| |
| 171 } | |
| 172 } | |
| 155 } | 173 } |
| 156 | 174 |
| 157 private static void uploadMinidumpsSync( | 175 private static void uploadMinidumpsSync( |
| 158 MinidumpUploader minidumpUploader, final boolean expectReschedule) { | 176 MinidumpUploader minidumpUploader, final boolean expectReschedule) { |
| 159 final CountDownLatch uploadsFinishedLatch = new CountDownLatch(1); | 177 final CountDownLatch uploadsFinishedLatch = new CountDownLatch(1); |
| 160 uploadAllMinidumpsOnUiThread( | 178 uploadAllMinidumpsOnUiThread( |
| 161 minidumpUploader, new MinidumpUploader.UploadsFinishedCallback() { | 179 minidumpUploader, new MinidumpUploader.UploadsFinishedCallback() { |
| 162 @Override | 180 @Override |
| 163 public void uploadsFinished(boolean reschedule) { | 181 public void uploadsFinished(boolean reschedule) { |
| 164 assertEquals(expectReschedule, reschedule); | 182 assertEquals(expectReschedule, reschedule); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 269 expectedSecondFile = new File(mCrashDir, secondFile.getName().replac e(".dmp", ".up")); | 287 expectedSecondFile = new File(mCrashDir, secondFile.getName().replac e(".dmp", ".up")); |
| 270 } else { | 288 } else { |
| 271 File uploadedFirstFile = | 289 File uploadedFirstFile = |
| 272 new File(mCrashDir, firstFile.getName().replace(".dmp", ".up ")); | 290 new File(mCrashDir, firstFile.getName().replace(".dmp", ".up ")); |
| 273 assertTrue(uploadedFirstFile.exists()); | 291 assertTrue(uploadedFirstFile.exists()); |
| 274 expectedSecondFile = new File(mCrashDir, secondFile.getName() + ".tr y1"); | 292 expectedSecondFile = new File(mCrashDir, secondFile.getName() + ".tr y1"); |
| 275 } | 293 } |
| 276 assertTrue(expectedSecondFile.exists()); | 294 assertTrue(expectedSecondFile.exists()); |
| 277 } | 295 } |
| 278 | 296 |
| 279 private static class StallingOutputStream extends OutputStream { | 297 private static class StallingHttpUrlConnectionFactory implements HttpURLConn ectionFactory { |
| 280 @Override | 298 private final CountDownLatch mStopStallingLatch; |
| 281 public void write(int b) throws IOException { | 299 private final boolean mSucceed; |
| 300 | |
| 301 private class StallingOutputStream extends OutputStream { | |
| 302 @Override | |
| 303 public void write(int b) throws IOException { | |
| 304 try { | |
| 305 mStopStallingLatch.await(); | |
| 306 } catch (InterruptedException e) { | |
| 307 throw new InterruptedIOException(e.toString()); | |
| 308 } | |
| 309 if (!mSucceed) { | |
| 310 throw new IOException(); | |
| 311 } | |
| 312 } | |
| 313 } | |
| 314 | |
| 315 public StallingHttpUrlConnectionFactory(CountDownLatch stopStallingLatch , boolean succeed) { | |
| 316 mStopStallingLatch = stopStallingLatch; | |
| 317 mSucceed = succeed; | |
| 318 } | |
| 319 | |
| 320 public HttpURLConnection createHttpURLConnection(String url) { | |
| 282 try { | 321 try { |
| 283 TimeUnit.MINUTES.sleep(100); | 322 return new MinidumpUploadCallableTest.TestHttpURLConnection(new URL(url)) { |
| 284 } catch (InterruptedException e) { | 323 @Override |
| 285 throw new InterruptedIOException(e.toString()); | 324 public OutputStream getOutputStream() { |
| 325 return new StallingOutputStream(); | |
| 326 } | |
| 327 }; | |
| 328 } catch (MalformedURLException e) { | |
| 329 return null; | |
| 286 } | 330 } |
| 287 } | 331 } |
| 288 } | 332 } |
| 289 | 333 |
| 290 private static class StallingHttpUrlConnectionFactory implements HttpURLConn ectionFactory { | |
| 291 public HttpURLConnection createHttpURLConnection(String url) { | |
| 292 return new HttpURLConnection(null) { | |
| 293 @Override | |
| 294 public OutputStream getOutputStream() throws IOException { | |
| 295 return new StallingOutputStream(); | |
| 296 } | |
| 297 | |
| 298 @Override | |
| 299 public void connect() {} | |
| 300 | |
| 301 @Override | |
| 302 public void disconnect() {} | |
| 303 | |
| 304 @Override | |
| 305 public boolean usingProxy() { | |
| 306 return false; | |
| 307 } | |
| 308 }; | |
| 309 } | |
| 310 } | |
| 311 | |
| 312 private static class FailingHttpUrlConnectionFactory implements HttpURLConne ctionFactory { | 334 private static class FailingHttpUrlConnectionFactory implements HttpURLConne ctionFactory { |
| 313 public HttpURLConnection createHttpURLConnection(String url) { | 335 public HttpURLConnection createHttpURLConnection(String url) { |
| 314 return null; | 336 return null; |
| 315 } | 337 } |
| 316 } | 338 } |
| 317 | 339 |
| 318 /** | 340 /** |
| 319 * Test that ensure we can interrupt the MinidumpUploader when uploading min idumps. | 341 * Test that ensures we can interrupt the MinidumpUploader when uploading mi nidumps. |
| 320 */ | 342 */ |
| 321 @MediumTest | 343 @MediumTest |
| 322 public void testCancelMinidumpUploads() throws IOException { | 344 public void testCancelMinidumpUploadsFailedUpload() throws IOException { |
| 345 testCancellation(false /* successfulUpload */); | |
| 346 } | |
| 347 | |
| 348 /** | |
| 349 * Test that ensures interrupting our upload-job will not interrupt the firs t upload. | |
| 350 */ | |
| 351 @MediumTest | |
| 352 public void testCancelingWontCancelFirstUpload() throws IOException { | |
| 353 testCancellation(true /* successfulUpload */); | |
| 354 } | |
| 355 | |
| 356 private void testCancellation(final boolean successfulUpload) throws IOExcep tion { | |
| 323 final CrashReportingPermissionManager permManager = | 357 final CrashReportingPermissionManager permManager = |
| 324 new MockCrashReportingPermissionManager() { | 358 new MockCrashReportingPermissionManager() { |
| 325 { mIsEnabledForTests = true; } | 359 { mIsEnabledForTests = true; } |
| 326 }; | 360 }; |
| 327 MinidumpUploader minidumpUploader = new MinidumpUploaderImpl( | 361 final CountDownLatch stopStallingLatch = new CountDownLatch(1); |
| 362 MinidumpUploaderImpl minidumpUploader = new MinidumpUploaderImpl( | |
| 328 getInstrumentation().getTargetContext(), false /* cleanOutMinidu mps */) { | 363 getInstrumentation().getTargetContext(), false /* cleanOutMinidu mps */) { |
| 329 @Override | 364 @Override |
| 330 public MinidumpUploadCallable createMinidumpUploadCallable( | 365 public MinidumpUploadCallable createMinidumpUploadCallable( |
| 331 File minidumpFile, File logfile) { | 366 File minidumpFile, File logfile) { |
| 332 return new MinidumpUploadCallable( | 367 return new MinidumpUploadCallable(minidumpFile, logfile, |
| 333 minidumpFile, logfile, new StallingHttpUrlConnectionFact ory(), permManager); | 368 new StallingHttpUrlConnectionFactory(stopStallingLatch, successfulUpload), |
| 369 permManager); | |
| 334 } | 370 } |
| 335 @Override | 371 @Override |
| 336 public PlatformServiceBridge createPlatformServiceBridge() { | 372 public PlatformServiceBridge createPlatformServiceBridge() { |
| 337 return new TestPlatformServiceBridge( | 373 return new TestPlatformServiceBridge( |
| 338 true /* canUseGms*/, permManager.isUsageAndCrashReportin gPermittedByUser()); | 374 true /* canUseGms*/, permManager.isUsageAndCrashReportin gPermittedByUser()); |
| 339 } | 375 } |
| 340 }; | 376 }; |
| 341 | 377 |
| 342 File firstFile = createMinidumpFileInCrashDir("123_abc.dmp0"); | 378 File firstFile = createMinidumpFileInCrashDir("123_abc.dmp0"); |
| 343 File nonExpectedFirstUploadFile = new File(mCrashDir, firstFile.getName( ) + ".up"); | 379 File expectedFirstUploadFile = |
| 344 File nonExpectedFirstRetryFile = new File(mCrashDir, firstFile.getName() + ".try1"); | 380 new File(mCrashDir, firstFile.getName().replace(".dmp", ".up")); |
| 381 File expectedFirstRetryFile = new File(mCrashDir, firstFile.getName() + ".try1"); | |
| 345 | 382 |
| 346 // This is run on the UI thread to avoid failing any assertOnUiThread as sertions. | 383 // This is run on the UI thread to avoid failing any assertOnUiThread as sertions. |
| 347 uploadAllMinidumpsOnUiThread( | 384 uploadAllMinidumpsOnUiThread(minidumpUploader, |
| 348 minidumpUploader, new MinidumpUploader.UploadsFinishedCallback() { | 385 new MinidumpUploader.UploadsFinishedCallback() { |
| 349 @Override | 386 @Override |
| 350 public void uploadsFinished(boolean reschedule) { | 387 public void uploadsFinished(boolean reschedule) { |
| 351 fail("This method shouldn't be called when we interrupt uploads."); | 388 if (successfulUpload) { |
| 389 assertFalse(reschedule); | |
| 390 } else { | |
| 391 fail("This method shouldn't be called when a cancele d upload fails."); | |
| 392 } | |
| 352 } | 393 } |
| 353 }); | 394 }, |
| 395 // Block until job posted - otherwise the worker thread might no t have been created | |
| 396 // before we try to join it. | |
| 397 true /* blockUntilJobPosted */); | |
| 354 minidumpUploader.cancelUploads(); | 398 minidumpUploader.cancelUploads(); |
| 399 stopStallingLatch.countDown(); | |
| 400 // Wait until our job finished. | |
| 401 try { | |
| 402 minidumpUploader.joinWorkerThreadForTesting(); | |
| 403 } catch (InterruptedException e) { | |
| 404 throw new RuntimeException(e); | |
| 405 } | |
| 355 | 406 |
| 356 assertTrue(firstFile.exists()); | 407 if (successfulUpload) { |
| 357 assertFalse(nonExpectedFirstUploadFile.exists()); | 408 // When the upload succeeds we expect the file to be renamed. |
| 358 assertFalse(nonExpectedFirstRetryFile.exists()); | 409 assertFalse(firstFile.exists()); |
| 410 assertTrue(expectedFirstUploadFile.exists()); | |
| 411 assertFalse(expectedFirstRetryFile.exists()); | |
| 412 } else { | |
| 413 // When the upload fails we won't change the minidump at all. | |
| 414 assertTrue(firstFile.exists()); | |
| 415 assertFalse(expectedFirstUploadFile.exists()); | |
| 416 assertFalse(expectedFirstRetryFile.exists()); | |
| 417 } | |
| 359 } | 418 } |
| 360 | 419 |
| 361 /** | 420 /** |
| 362 * Ensures that the minidump copying works together with the minidump upload ing. | 421 * Ensures that the minidump copying works together with the minidump upload ing. |
| 363 */ | 422 */ |
| 364 @MediumTest | 423 @MediumTest |
| 365 public void testCopyAndUploadWebViewMinidump() throws FileNotFoundException, IOException { | 424 public void testCopyAndUploadWebViewMinidump() throws FileNotFoundException, IOException { |
| 366 final CrashFileManager fileManager = new CrashFileManager( | 425 final CrashFileManager fileManager = new CrashFileManager( |
| 367 CrashReceiverService.getWebViewCrashDir(getInstrumentation().get TargetContext())); | 426 CrashReceiverService.getWebViewCrashDir(getInstrumentation().get TargetContext())); |
| 368 // Note that these minidump files are set up directly in the cache dir - not in the WebView | 427 // Note that these minidump files are set up directly in the cache dir - not in the WebView |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 612 assertEquals(numMinidumps, uploadedFiles.length); | 671 assertEquals(numMinidumps, uploadedFiles.length); |
| 613 return uploadedFiles; | 672 return uploadedFiles; |
| 614 } | 673 } |
| 615 | 674 |
| 616 private File createMinidumpFileInCrashDir(String name) throws IOException { | 675 private File createMinidumpFileInCrashDir(String name) throws IOException { |
| 617 File minidumpFile = new File(mCrashDir, name); | 676 File minidumpFile = new File(mCrashDir, name); |
| 618 setUpMinidumpFile(minidumpFile, BOUNDARY); | 677 setUpMinidumpFile(minidumpFile, BOUNDARY); |
| 619 return minidumpFile; | 678 return minidumpFile; |
| 620 } | 679 } |
| 621 } | 680 } |
| OLD | NEW |