Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(42)

Side by Side Diff: chrome/android/javatests/src/org/chromium/chrome/browser/crash/MinidumpUploadServiceTest.java

Issue 1141283003: Upstream oodles of Chrome for Android code into Chromium. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: final patch? Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.chrome.browser.crash;
6
7 import android.content.ComponentName;
8 import android.content.Context;
9 import android.content.Intent;
10 import android.os.Handler;
11 import android.os.HandlerThread;
12 import android.test.suitebuilder.annotation.SmallTest;
13
14 import org.chromium.base.annotations.SuppressFBWarnings;
15 import org.chromium.base.test.util.AdvancedMockContext;
16 import org.chromium.base.test.util.Feature;
17 import org.chromium.content.browser.test.util.Criteria;
18 import org.chromium.content.browser.test.util.CriteriaHelper;
19 import org.chromium.net.NetworkChangeNotifier;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.concurrent.atomic.AtomicInteger;
26
27 /**
28 * Testcase for {@link MinidumpUploadService}.
29 */
30 public class MinidumpUploadServiceTest extends CrashTestCase {
31
32 private static final int CHECK_INTERVAL_MS = 250;
33 private static final int MAX_TIMEOUT_MS = 20000;
34 private static final String BOUNDARY = "TESTBOUNDARY";
35
36 @SmallTest
37 @Feature({"Android-AppBase"})
38 public void testFindAndUploadLastCrash() throws IOException {
39 // Setup prerequisites.
40 final AtomicInteger numServiceStarts = new AtomicInteger(0);
41 final File minidumpFile = new File(mCrashDir, "chromium_renderer-123.dmp ");
42 MinidumpPreparationContext context = new MinidumpPreparationContext(
43 getInstrumentation().getTargetContext()) {
44 @Override
45 public ComponentName startService(Intent intentToCheck) {
46 String filePath =
47 intentToCheck.getStringExtra(MinidumpUploadService.FILE_ TO_UPLOAD_KEY);
48 assertEquals("Minidump path should be the absolute path",
49 minidumpFile.getAbsolutePath(), filePath);
50 assertEquals("Should only call service once", 1,
51 numServiceStarts.incrementAndGet());
52 assertEquals("Action should be correct",
53 MinidumpUploadService.ACTION_UPLOAD, intentToCheck.getAc tion());
54 return new ComponentName(getPackageName(), MinidumpUploadService .class.getName());
55 }
56
57 };
58 MinidumpUploadService service = new TestMinidumpUploadService(context);
59 setUpMinidumpFile(minidumpFile, BOUNDARY);
60
61 // Run test.
62 Intent findAndUploadLastCrashIntent =
63 MinidumpUploadService.createFindAndUploadLastCrashIntent(context );
64 service.onCreate();
65 service.onHandleIntent(findAndUploadLastCrashIntent);
66
67 // Verify.
68 assertTrue("Minidump file should exist", minidumpFile.isFile());
69 assertEquals("Should have called startService() once", 1, numServiceStar ts.intValue());
70 }
71
72 private static class TestMinidumpUploadService extends MinidumpUploadService {
73 private TestMinidumpUploadService() {}
74 private TestMinidumpUploadService(Context context) {
75 attachBaseContext(context);
76 }
77
78 private void attachBaseContextLate(Context base) {
79 super.attachBaseContext(base);
80 }
81 }
82
83 @SmallTest
84 @Feature({"Android-AppBase"})
85 public void testFindAndUploadLastCrashNoFile() {
86 // Setup prerequisites.
87 MinidumpPreparationContext context = new MinidumpPreparationContext(
88 getInstrumentation().getTargetContext()) {
89 @Override
90 public ComponentName startService(Intent intentToCheck) {
91 fail("Should not start service");
92 return new ComponentName(getPackageName(), MinidumpUploadService .class.getName());
93 }
94
95 };
96 MinidumpUploadService service = new TestMinidumpUploadService(context);
97
98 // Run test.
99 Intent findAndUploadLastCrashIntent =
100 MinidumpUploadService.createFindAndUploadLastCrashIntent(context );
101 service.onCreate();
102 service.onHandleIntent(findAndUploadLastCrashIntent);
103
104 // Verification is done by the test NOT failing with fail(...) in the
105 // MinidumpPreparationContext startService(...) method.
106 }
107
108 @SmallTest
109 @Feature({"Android-AppBase"})
110 public void testFindAndUploadAllCrashes() throws IOException {
111 // Setup prerequisites.
112 final AtomicInteger numServiceStarts = new AtomicInteger(0);
113 final File[] minidumpFiles = {
114 new File(mCrashDir, "chromium_renderer-111.dmp1"),
115 new File(mCrashDir, "chromium_renderer-222.dmp2"),
116 new File(mCrashDir, "chromium_renderer-333.dmp3"),
117 };
118 MinidumpPreparationContext context = new MinidumpPreparationContext(
119 getInstrumentation().getTargetContext()) {
120 @Override
121 public ComponentName startService(Intent intentToCheck) {
122 String filePath =
123 intentToCheck.getStringExtra(MinidumpUploadService.FILE_ TO_UPLOAD_KEY);
124 // Assuming numServicesStart value corresponds to minidumpFiles index.
125 assertEquals("Minidump path should be the absolute path",
126 minidumpFiles[numServiceStarts.intValue()].getAbsolutePa th(), filePath);
127 assertTrue("Should not call service more than number of files",
128 numServiceStarts.incrementAndGet() <= minidumpFiles.leng th);
129 assertEquals("Action should be correct",
130 MinidumpUploadService.ACTION_UPLOAD, intentToCheck.getAc tion());
131 return new ComponentName(getPackageName(), MinidumpUploadService .class.getName());
132 }
133
134 };
135 MinidumpUploadService service = new TestMinidumpUploadService(context);
136 for (File minidumpFile : minidumpFiles) {
137 setUpMinidumpFile(minidumpFile, BOUNDARY);
138 }
139
140 // Run test.
141 Intent findAndUploadAllCrashesIntent =
142 MinidumpUploadService.createFindAndUploadAllCrashesIntent(contex t);
143 service.onCreate();
144 service.onHandleIntent(findAndUploadAllCrashesIntent);
145
146 // Verify.
147 for (File minidumpFile : minidumpFiles) {
148 assertTrue("Minidump file should exist: " + minidumpFile, minidumpFi le.isFile());
149 }
150 assertEquals("Should have called startService() same number of times as there are files",
151 minidumpFiles.length, numServiceStarts.intValue());
152 }
153
154 @SmallTest
155 @Feature({"Android-AppBase"})
156 public void testUploadCrash() throws IOException, InterruptedException {
157 List<CountedMinidumpUploadCallable> callables =
158 new ArrayList<CountedMinidumpUploadCallable>();
159 callables.add(new CountedMinidumpUploadCallable(
160 "chromium_renderer-111.dmp1", true, false));
161 runUploadCrashTest(callables);
162 }
163
164 @SmallTest
165 @Feature({"Android-AppBase"})
166 public void testUploadCrashWithThreeFails() throws IOException, InterruptedE xception {
167 // Create |MAX_TRIES_ALLOWED| callables.
168 final List<CountedMinidumpUploadCallable> callables =
169 new ArrayList<CountedMinidumpUploadCallable>();
170 for (int i = 0; i < MinidumpUploadService.MAX_TRIES_ALLOWED; i++) {
171 callables.add(new CountedMinidumpUploadCallable(
172 "chromium_renderer-111.dmp1" + (i > 0 ? ".try" + i : "") , f alse, true));
173 }
174 runUploadCrashTest(callables);
175 }
176
177 @SmallTest
178 @Feature({"Android-AppBase"})
179 public void testUploadCrashWithOneFailWithNetwork() throws IOException, Inte rruptedException {
180 List<CountedMinidumpUploadCallable> callables =
181 new ArrayList<CountedMinidumpUploadCallable>();
182 callables.add(new CountedMinidumpUploadCallable(
183 "chromium_renderer-111.dmp1", false, true));
184 callables.add(new CountedMinidumpUploadCallable(
185 "chromium_renderer-111.dmp1.try1", true, true));
186 runUploadCrashTest(callables);
187 }
188
189 @SmallTest
190 @Feature({"Android-AppBase"})
191 public void testUploadCrashWithOneFailNoNetwork() throws IOException, Interr uptedException {
192 List<CountedMinidumpUploadCallable> callables =
193 new ArrayList<CountedMinidumpUploadCallable>();
194 callables.add(new CountedMinidumpUploadCallable(
195 "chromium_renderer-111.dmp1", false, false));
196 runUploadCrashTest(callables);
197 }
198
199 @SuppressFBWarnings("RV_RETURN_VALUE_IGNORED_BAD_PRACTICE")
200 private void runUploadCrashTest(final List<CountedMinidumpUploadCallable> ca llables)
201 throws IOException, InterruptedException {
202 // Setup prerequisites.
203 // This version of the service overrides the createMinidumpUploadCallabl e(...) to be able
204 // to return fake ones. It also ensures that the service never tries to create a callable
205 // too many times.
206 TestMinidumpUploadService service = new TestMinidumpUploadService() {
207 int mIndex = 0;
208 boolean mTriggerNetworkChange = false;
209
210 @Override
211 MinidumpUploadCallable createMinidumpUploadCallable(File minidumpFil e, File logfile) {
212 if (mIndex >= callables.size()) {
213 fail("Should not create callable number " + mIndex);
214 }
215 CountedMinidumpUploadCallable callable = callables.get(mIndex++) ;
216 if (callable.mTriggerNetworkChange) {
217 mTriggerNetworkChange = true;
218 }
219 return callable;
220 }
221
222 @Override
223 protected void onHandleIntent(Intent intent) {
224 try {
225 runTestOnUiThread(new Runnable() {
226 @Override
227 public void run() {
228 // Set up basically a fake.
229 if (!NetworkChangeNotifier.isInitialized()) {
230 NetworkChangeNotifier.init(getApplicationContext ());
231 }
232 }
233 });
234 } catch (Throwable t) {
235 t.printStackTrace();
236 fail("Failed to set up NetworkChangeNotifier");
237 }
238
239 super.onHandleIntent(intent);
240
241 if (mTriggerNetworkChange) {
242 mTriggerNetworkChange = false;
243 try {
244 runTestOnUiThread(new Runnable() {
245 @Override
246 public void run() {
247 NetworkChangeNotifier.setAutoDetectConnectivityS tate(false);
248 // Quickly force the state to be connected and b ack to disconnected.
249 // An event should be triggered for retry logics .
250 NetworkChangeNotifier.forceConnectivityState(fal se);
251 NetworkChangeNotifier.forceConnectivityState(tru e);
252 }
253 });
254 } catch (Throwable t) {
255 t.printStackTrace();
256 fail("Failed to trigger NetworkChangeNotifier");
257 }
258 }
259 }
260 };
261 // Create a context that supports call to startService(...), where it ru ns the new service
262 // calls on a handler thread. We pass in the MinidumpUploadService as an argument so we
263 // can call it directly without going through the Android framework.
264 final MinidumpPreparationContext context = new MinidumpPreparationContex t(
265 getInstrumentation().getTargetContext(), service) {
266 Handler mHandler;
267 {
268 HandlerThread handlerThread =
269 new HandlerThread("MinidumpUploadServiceTest Handler Thr ead");
270 handlerThread.start();
271 mHandler = new Handler(handlerThread.getLooper());
272 }
273
274 @Override
275 public ComponentName startService(final Intent intentToCheck) {
276 assertTrue(MinidumpUploadService.ACTION_UPLOAD.equals(intentToCh eck.getAction())
277 || MinidumpUploadService.ACTION_FIND_ALL.equals(intentTo Check.getAction()));
278 // Post to the handler thread to run the retry intent.
279 mHandler.post(new Runnable() {
280 @Override
281 public void run() {
282 mService.onHandleIntent(intentToCheck);
283 }
284 });
285 return new ComponentName(getPackageName(), MinidumpUploadService .class.getName());
286 }
287
288 };
289 // We need the context before we can attach it to the service, so since Context is
290 // dependent on the service, we do this after context creation.
291 service.attachBaseContextLate(context);
292 // Create the file used for uploading.
293 File minidumpFile = new File(mCrashDir, "chromium_renderer-111.dmp1");
294 minidumpFile.createNewFile();
295 File logfile = new File(mCacheDir, CrashFileManager.CRASH_DUMP_LOGFILE);
296 setUpMinidumpFile(minidumpFile, BOUNDARY);
297
298 // Run test.
299 Intent uploadIntent =
300 MinidumpUploadService.createUploadIntent(context, minidumpFile, logfile);
301 service.onCreate();
302 service.onHandleIntent(uploadIntent);
303
304 // Verify asynchronously.
305 assertTrue("All callables should have a call-count of 1",
306 CriteriaHelper.pollForCriteria(new Criteria() {
307 @Override
308 public boolean isSatisfied() {
309 for (CountedMinidumpUploadCallable callable : callables) {
310 if (callable.mCalledCount != 1) {
311 return false;
312 }
313 }
314 return true;
315 }
316 }, MAX_TIMEOUT_MS, CHECK_INTERVAL_MS));
317 }
318
319 /**
320 * This tests how we instantiate crash uploading from Main, so it is just a sanity check.
321 */
322 @SmallTest
323 @Feature({"Android-AppBase"})
324 public void testTryUploadAllCrashDumpsHelperMethod() {
325 // Setup prerequisites.
326 final String startServiceFlag = "startServiceFlag";
327 MinidumpPreparationContext context = new MinidumpPreparationContext(
328 getInstrumentation().getTargetContext()) {
329 @Override
330 public ComponentName startService(Intent intentToCheck) {
331 assertEquals(MinidumpUploadService.ACTION_FIND_ALL, intentToChec k.getAction());
332 setFlag(startServiceFlag);
333 return new ComponentName(getPackageName(), MinidumpUploadService .class.getName());
334 }
335 };
336
337 // Run test.
338 MinidumpUploadService.tryUploadAllCrashDumps(context);
339
340 // Verify.
341 assertTrue("Should have called startService(...)", context.isFlagSet(sta rtServiceFlag));
342 }
343
344 private class MinidumpPreparationContext extends AdvancedMockContext {
345 /**
346 * Field used in overridden versions of startService() so we can support retries.
347 */
348 protected MinidumpUploadService mService;
349
350 public MinidumpPreparationContext(Context targetContext) {
351 this(targetContext, null);
352 }
353
354 public MinidumpPreparationContext(Context targetContext, MinidumpUploadS ervice service) {
355 super(targetContext);
356 mService = service;
357 }
358
359 @Override
360 public File getCacheDir() {
361 return mCacheDir;
362 }
363 }
364
365 /**
366 * A fake callable, that just counts the number of times it is called.
367 *
368 * It can be constructed with the wanted return-value of the call()-method.
369 */
370 private static class CountedMinidumpUploadCallable extends MinidumpUploadCal lable {
371 private int mCalledCount;
372 private final boolean mResult;
373 private final boolean mTriggerNetworkChange;
374
375 /**
376 * Creates a fake callable, that just counts the number of times it is c alled.
377 *
378 * @param result the value to return from the call()-method.
379 * @param networkChange Should trigger a network change after this calla ble is finished.
380 * This essentially triggers a retry if result is set to fail.
381 */
382 private CountedMinidumpUploadCallable(
383 String fileName, boolean result, boolean networkChange) {
384 super(new File(fileName), null, null, null, null);
385 this.mResult = result;
386 this.mTriggerNetworkChange = networkChange;
387 }
388
389 @Override
390 public Boolean call() {
391 ++mCalledCount;
392 return mResult;
393 }
394 }
395 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698