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); |
| 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 |