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

Side by Side Diff: content/public/android/javatests/src/org/chromium/content/browser/BindingManagerImplTest.java

Issue 1146813010: Introduce moderate binding (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Use a histogram instead of an action Created 5 years, 6 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
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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.content.browser; 5 package org.chromium.content.browser;
6 6
7 import static android.content.ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
8 import static android.content.ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
9 import static android.content.ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
10
11 import android.app.Application;
7 import android.os.Bundle; 12 import android.os.Bundle;
8 import android.test.InstrumentationTestCase; 13 import android.test.InstrumentationTestCase;
9 import android.test.suitebuilder.annotation.SmallTest; 14 import android.test.suitebuilder.annotation.SmallTest;
15 import android.util.Pair;
10 16
11 import org.chromium.base.test.util.Feature; 17 import org.chromium.base.test.util.Feature;
12 import org.chromium.content.common.IChildProcessCallback; 18 import org.chromium.content.common.IChildProcessCallback;
13 import org.chromium.content.common.IChildProcessService; 19 import org.chromium.content.common.IChildProcessService;
14 20
21 import java.util.ArrayList;
22
15 /** 23 /**
16 * Unit tests for BindingManagerImpl. The tests run agains mock ChildProcessConn ection 24 * Unit tests for BindingManagerImpl. The tests run agains mock ChildProcessConn ection
17 * implementation, thus testing only the BindingManagerImpl itself. 25 * implementation, thus testing only the BindingManagerImpl itself.
18 * 26 *
19 * Default property of being low-end device is overriden, so that both low-end a nd high-end policies 27 * Default property of being low-end device is overriden, so that both low-end a nd high-end policies
20 * are tested. Unbinding delays are set to 0, so that we don't need to deal with waiting, but we 28 * are tested. Unbinding delays are set to 0, so that we don't need to deal with waiting, but we
21 * still can test if the unbinding tasks are posted or executed synchronously. 29 * still can test if the unbinding tasks are posted or executed synchronously.
22 */ 30 */
23 public class BindingManagerImplTest extends InstrumentationTestCase { 31 public class BindingManagerImplTest extends InstrumentationTestCase {
24 private static class MockChildProcessConnection implements ChildProcessConne ction { 32 private static class MockChildProcessConnection implements ChildProcessConne ction {
25 boolean mInitialBindingBound; 33 boolean mInitialBindingBound;
34 boolean mModerateBindingBound;
26 int mStrongBindingCount; 35 int mStrongBindingCount;
27 final int mPid; 36 final int mPid;
28 37
29 /** 38 /**
30 * Creates a mock binding corresponding to real ChildProcessConnectionIm pl after the 39 * Creates a mock binding corresponding to real ChildProcessConnectionIm pl after the
31 * connection is established: with initial binding bound and no strong b inding. 40 * connection is established: with initial binding bound and no strong b inding.
32 */ 41 */
33 MockChildProcessConnection(int pid) { 42 MockChildProcessConnection(int pid) {
34 mInitialBindingBound = true; 43 mInitialBindingBound = true;
35 mStrongBindingCount = 0; 44 mStrongBindingCount = 0;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 } 88 }
80 89
81 @Override 90 @Override
82 public void stop() { 91 public void stop() {
83 mInitialBindingBound = false; 92 mInitialBindingBound = false;
84 mStrongBindingCount = 0; 93 mStrongBindingCount = 0;
85 } 94 }
86 95
87 @Override 96 @Override
88 public int getServiceNumber() { 97 public int getServiceNumber() {
89 throw new UnsupportedOperationException(); 98 return mPid;
90 } 99 }
91 100
92 @Override 101 @Override
93 public boolean isInSandbox() { 102 public boolean isInSandbox() {
94 throw new UnsupportedOperationException(); 103 return true;
95 } 104 }
96 105
97 @Override 106 @Override
98 public IChildProcessService getService() { 107 public IChildProcessService getService() {
99 throw new UnsupportedOperationException(); 108 throw new UnsupportedOperationException();
100 } 109 }
101 110
102 @Override 111 @Override
103 public void start(String[] commandLine) { 112 public void start(String[] commandLine) {
104 throw new UnsupportedOperationException(); 113 throw new UnsupportedOperationException();
105 } 114 }
106 115
107 @Override 116 @Override
108 public void setupConnection(String[] commandLine, FileDescriptorInfo[] f ilesToBeMapped, 117 public void setupConnection(String[] commandLine, FileDescriptorInfo[] f ilesToBeMapped,
109 IChildProcessCallback processCallback, ConnectionCallback connec tionCallbacks, 118 IChildProcessCallback processCallback, ConnectionCallback connec tionCallbacks,
110 Bundle sharedRelros) { 119 Bundle sharedRelros) {
111 throw new UnsupportedOperationException(); 120 throw new UnsupportedOperationException();
112 } 121 }
122
123 @Override
124 public void addModerateBinding() {
125 mModerateBindingBound = true;
126 }
127
128 @Override
129 public void removeModerateBinding() {
130 mModerateBindingBound = false;
131 }
132
133 @Override
134 public boolean isModerateBindingBound() {
135 return mModerateBindingBound;
136 }
113 } 137 }
114 138
115 /** 139 /**
116 * Helper class that stores a manager along with its text label. This is use d for tests that 140 * Helper class that stores a manager along with its text label. This is use d for tests that
117 * iterate over all managers to indicate which manager was being tested when an assertion 141 * iterate over all managers to indicate which manager was being tested when an assertion
118 * failed. 142 * failed.
119 */ 143 */
120 private static class ManagerEntry { 144 private static class ManagerEntry {
121 BindingManagerImpl mManager; 145 BindingManagerImpl mManager;
122 String mLabel; // Name of the manager. 146 String mLabel; // Name of the manager.
123 147
124 ManagerEntry(BindingManagerImpl manager, String label) { 148 ManagerEntry(BindingManagerImpl manager, String label) {
125 mManager = manager; 149 mManager = manager;
126 mLabel = label; 150 mLabel = label;
127 } 151 }
128 152
129 String getErrorMessage() { 153 String getErrorMessage() {
130 return "Failed for the " + mLabel + " manager."; 154 return "Failed for the " + mLabel + " manager.";
131 } 155 }
132 } 156 }
133 157
134 // The managers are created in setUp() for convenience. 158 // The managers are created in setUp() for convenience.
135 BindingManagerImpl mLowEndManager; 159 BindingManagerImpl mLowEndManager;
136 BindingManagerImpl mHighEndManager; 160 BindingManagerImpl mHighEndManager;
161 BindingManagerImpl mModerateBindingManager;
137 ManagerEntry[] mAllManagers; 162 ManagerEntry[] mAllManagers;
138 163
139 @Override 164 @Override
140 protected void setUp() { 165 protected void setUp() {
141 mLowEndManager = BindingManagerImpl.createBindingManagerForTesting(true) ; 166 mLowEndManager = BindingManagerImpl.createBindingManagerForTesting(true) ;
142 mHighEndManager = BindingManagerImpl.createBindingManagerForTesting(fals e); 167 mHighEndManager = BindingManagerImpl.createBindingManagerForTesting(fals e);
168 mModerateBindingManager = BindingManagerImpl.createBindingManagerForTest ing(false);
169 mModerateBindingManager.startModerateBindingManagement(
170 getInstrumentation().getTargetContext(), 4, 0.25f, 0.5f);
143 mAllManagers = new ManagerEntry[] { 171 mAllManagers = new ManagerEntry[] {
144 new ManagerEntry(mLowEndManager, "low-end"), 172 new ManagerEntry(mLowEndManager, "low-end"),
145 new ManagerEntry(mHighEndManager, "high-end")}; 173 new ManagerEntry(mHighEndManager, "high-end"),
174 new ManagerEntry(mModerateBindingManager, "moderate-binding")};
146 } 175 }
147 176
148 /** 177 /**
149 * Verifies that when running on low-end, the binding manager drops the oom bindings for the 178 * Verifies that when running on low-end, the binding manager drops the oom bindings for the
150 * previously bound connection when a new connection is used in foreground. 179 * previously bound connection when a new connection is used in foreground.
151 */ 180 */
152 @SmallTest 181 @SmallTest
153 @Feature({"ProcessManagement"}) 182 @Feature({"ProcessManagement"})
154 public void testNewConnectionDropsPreviousOnLowEnd() { 183 public void testNewConnectionDropsPreviousOnLowEnd() {
155 // This test applies only to the low-end manager. 184 // This test applies only to the low-end manager.
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 276
248 // Wait until the posted unbinding tasks get executed and verify that th e strong binding was 277 // Wait until the posted unbinding tasks get executed and verify that th e strong binding was
249 // removed while the initial binding is not affected. Note that this wor ks only because the 278 // removed while the initial binding is not affected. Note that this wor ks only because the
250 // test binding manager has the unbinding delay set to 0. 279 // test binding manager has the unbinding delay set to 0.
251 getInstrumentation().waitForIdleSync(); 280 getInstrumentation().waitForIdleSync();
252 assertFalse(connection.isStrongBindingBound()); 281 assertFalse(connection.isStrongBindingBound());
253 assertTrue(connection.isInitialBindingBound()); 282 assertTrue(connection.isInitialBindingBound());
254 } 283 }
255 284
256 /** 285 /**
286 * Verifies the strong binding removal policies with moderate binding manage ment, where the
287 * moderate binding should be bound.
288 */
289 @SmallTest
290 @Feature({"ProcessManagement"})
291 public void testStrongBindingRemovalWithModerateBinding() throws Throwable {
292 // This test applies only to the moderate-binding manager.
293 final BindingManagerImpl manager = mModerateBindingManager;
294
295 // Add a connection to the manager.
296 final MockChildProcessConnection connection = new MockChildProcessConnec tion(1);
297 manager.addNewConnection(connection.getPid(), connection);
298 assertTrue(connection.isInitialBindingBound());
299 assertFalse(connection.isStrongBindingBound());
300 assertFalse(connection.isModerateBindingBound());
301 // This has to happen on the UI thread, so that we can check the binding status right after
302 // the call to remove it, before the any other task is executed on the m ain thread.
303 runTestOnUiThread(new Runnable() {
304 @Override
305 public void run() {
306 // Add a strong binding, verify that the initial binding is not removed.
307 manager.setInForeground(connection.getPid(), true);
308 assertTrue(connection.isStrongBindingBound());
309 assertTrue(connection.isInitialBindingBound());
310 assertFalse(connection.isModerateBindingBound());
311
312 // Remove the strong binding, verify that the strong binding is not removed
313 // immediately.
314 manager.setInForeground(connection.getPid(), false);
315 assertTrue(connection.isStrongBindingBound());
316 assertTrue(connection.isInitialBindingBound());
317 assertFalse(connection.isModerateBindingBound());
318 }
319 });
320
321 // Wait until the posted unbinding tasks get executed and verify that th e strong binding was
322 // removed while the initial binding is not affected, and the moderate b inding is bound.
323 getInstrumentation().waitForIdleSync();
324 assertFalse(connection.isStrongBindingBound());
325 assertTrue(connection.isInitialBindingBound());
326 assertTrue(connection.isModerateBindingBound());
327 }
328
329 /**
257 * Verifies that the initial binding is removed after determinedVisibility() is called. 330 * Verifies that the initial binding is removed after determinedVisibility() is called.
258 */ 331 */
259 @SmallTest 332 @SmallTest
260 @Feature({"ProcessManagement"}) 333 @Feature({"ProcessManagement"})
261 public void testInitialBindingRemoval() { 334 public void testInitialBindingRemoval() {
262 // This test applies to both low-end and high-end policies. 335 // This test applies to low-end, high-end and moderate-binding policies.
263 for (ManagerEntry managerEntry : mAllManagers) { 336 for (ManagerEntry managerEntry : mAllManagers) {
264 BindingManagerImpl manager = managerEntry.mManager; 337 BindingManagerImpl manager = managerEntry.mManager;
265 String message = managerEntry.getErrorMessage(); 338 String message = managerEntry.getErrorMessage();
266 339
267 // Add a connection to the manager. 340 // Add a connection to the manager.
268 MockChildProcessConnection connection = new MockChildProcessConnecti on(1); 341 MockChildProcessConnection connection = new MockChildProcessConnecti on(1);
269 manager.addNewConnection(connection.getPid(), connection); 342 manager.addNewConnection(connection.getPid(), connection);
270 343
271 // Verify that the initial binding is held. 344 // Verify that the initial binding is held.
272 assertTrue(connection.isInitialBindingBound()); 345 assertTrue(connection.isInitialBindingBound());
273 346
274 // Call determinedVisibility() and verify that the initial binding w as released. 347 // Call determinedVisibility() and verify that the initial binding w as released.
275 manager.determinedVisibility(connection.getPid()); 348 manager.determinedVisibility(connection.getPid());
276 assertFalse(connection.isInitialBindingBound()); 349 assertFalse(connection.isInitialBindingBound());
277 } 350 }
278 } 351 }
279 352
280 /** 353 /**
281 * Verifies that BindingManagerImpl correctly stashes the status of the conn ection oom bindings 354 * Verifies that BindingManagerImpl correctly stashes the status of the conn ection oom bindings
282 * when the connection is cleared. BindingManagerImpl should reply to isOomP rotected() queries 355 * when the connection is cleared. BindingManagerImpl should reply to isOomP rotected() queries
283 * with live status of the connection while it's still around and reply with stashed status 356 * with live status of the connection while it's still around and reply with stashed status
284 * after clearConnection() is called. 357 * after clearConnection() is called.
285 * 358 *
286 * This test corresponds to a process crash scenario: after a process dies a nd its connection is 359 * This test corresponds to a process crash scenario: after a process dies a nd its connection is
287 * cleared, isOomProtected() may be called to decide if it was a crash or ou t-of-memory kill. 360 * cleared, isOomProtected() may be called to decide if it was a crash or ou t-of-memory kill.
288 */ 361 */
289 @SmallTest 362 @SmallTest
290 @Feature({"ProcessManagement"}) 363 @Feature({"ProcessManagement"})
291 public void testIsOomProtected() { 364 public void testIsOomProtected() {
292 // This test applies to both low-end and high-end policies. 365 // This test applies to low-end, high-end and moderate-binding policies.
293 for (ManagerEntry managerEntry : mAllManagers) { 366 for (ManagerEntry managerEntry : mAllManagers) {
294 BindingManagerImpl manager = managerEntry.mManager; 367 BindingManagerImpl manager = managerEntry.mManager;
295 String message = managerEntry.getErrorMessage(); 368 String message = managerEntry.getErrorMessage();
296 369
297 // Add a connection to the manager. 370 // Add a connection to the manager.
298 MockChildProcessConnection connection = new MockChildProcessConnecti on(1); 371 MockChildProcessConnection connection = new MockChildProcessConnecti on(1);
299 manager.addNewConnection(connection.getPid(), connection); 372 manager.addNewConnection(connection.getPid(), connection);
300 373
301 // Initial binding is an oom binding. 374 // Initial binding is an oom binding.
302 assertTrue(message, manager.isOomProtected(connection.getPid())); 375 assertTrue(message, manager.isOomProtected(connection.getPid()));
(...skipping 29 matching lines...) Expand all
332 * period. 405 * period.
333 * 406 *
334 * The renderer that will be bound for the background period should be the o ne that was most 407 * The renderer that will be bound for the background period should be the o ne that was most
335 * recendly bound using .setInForeground(), even if there is one that was ad ded using 408 * recendly bound using .setInForeground(), even if there is one that was ad ded using
336 * .addNewConnection() after that. Otherwise we would bound a background ren derer when user 409 * .addNewConnection() after that. Otherwise we would bound a background ren derer when user
337 * loads a new tab in background and leaves the browser. 410 * loads a new tab in background and leaves the browser.
338 */ 411 */
339 @SmallTest 412 @SmallTest
340 @Feature({"ProcessManagement"}) 413 @Feature({"ProcessManagement"})
341 public void testBackgroundPeriodBinding() { 414 public void testBackgroundPeriodBinding() {
342 // This test applies to both low-end and high-end policies. 415 // This test applies to low-end, high-end and moderate-binding policies.
343 for (ManagerEntry managerEntry : mAllManagers) { 416 for (ManagerEntry managerEntry : mAllManagers) {
344 BindingManagerImpl manager = managerEntry.mManager; 417 BindingManagerImpl manager = managerEntry.mManager;
345 String message = managerEntry.getErrorMessage(); 418 String message = managerEntry.getErrorMessage();
346 419
347 // Add two connections, bind and release each. 420 // Add two connections, bind and release each.
348 MockChildProcessConnection firstConnection = new MockChildProcessCon nection(1); 421 MockChildProcessConnection firstConnection = new MockChildProcessCon nection(1);
349 manager.addNewConnection(firstConnection.getPid(), firstConnection); 422 manager.addNewConnection(firstConnection.getPid(), firstConnection);
350 manager.setInForeground(firstConnection.getPid(), true); 423 manager.setInForeground(firstConnection.getPid(), true);
351 manager.setInForeground(firstConnection.getPid(), false); 424 manager.setInForeground(firstConnection.getPid(), false);
352 425
(...skipping 23 matching lines...) Expand all
376 assertFalse(message, thirdConnection.isStrongBindingBound()); 449 assertFalse(message, thirdConnection.isStrongBindingBound());
377 450
378 // Call onBroughtToForeground() and verify that the strong binding w as removed. 451 // Call onBroughtToForeground() and verify that the strong binding w as removed.
379 manager.onBroughtToForeground(); 452 manager.onBroughtToForeground();
380 getInstrumentation().waitForIdleSync(); 453 getInstrumentation().waitForIdleSync();
381 assertFalse(message, firstConnection.isStrongBindingBound()); 454 assertFalse(message, firstConnection.isStrongBindingBound());
382 assertFalse(message, secondConnection.isStrongBindingBound()); 455 assertFalse(message, secondConnection.isStrongBindingBound());
383 assertFalse(message, thirdConnection.isStrongBindingBound()); 456 assertFalse(message, thirdConnection.isStrongBindingBound());
384 } 457 }
385 } 458 }
459
460 /**
461 * Verifies that onSentToBackground() drops all the moderate bindings, and
462 * onBroughtToForeground() doesn't recover them.
463 */
464 @SmallTest
465 @Feature({"ProcessManagement"})
466 public void testModerateBindingDropOnBackground() {
467 // This test applies only to the moderate-binding manager.
468 final BindingManagerImpl manager = mModerateBindingManager;
469
470 MockChildProcessConnection[] connections = new MockChildProcessConnectio n[4];
471 for (int i = 0; i < connections.length; i++) {
472 connections[i] = new MockChildProcessConnection(i + 1);
473 manager.addNewConnection(connections[i].getPid(), connections[i]);
474 }
475
476 // Verify that each connection has a moderate binding after binding and releasing a strong
477 // binding.
478 for (MockChildProcessConnection connection : connections) {
479 manager.setInForeground(connection.getPid(), true);
480 manager.setInForeground(connection.getPid(), false);
481 getInstrumentation().waitForIdleSync();
482 assertTrue(connection.isModerateBindingBound());
483 }
484
485 // Call onSentToBackground() and verify that all the moderate bindings d rop.
486 manager.onSentToBackground();
487 for (MockChildProcessConnection connection : connections) {
488 assertFalse(connection.isModerateBindingBound());
489 }
490
491 // Call onBroughtToForeground() and verify that the previous moderate bi ndings aren't
492 // recovered.
493 manager.onBroughtToForeground();
494 for (MockChildProcessConnection connection : connections) {
495 assertFalse(connection.isModerateBindingBound());
496 }
497 }
498
499 /**
500 * Verifies that onLowMemory() drops all the moderate bindings.
501 */
502 @SmallTest
503 @Feature({"ProcessManagement"})
504 public void testModerateBindingDropOnLowMemory() {
505 final Application app =
506 (Application) getInstrumentation().getTargetContext().getApplica tionContext();
507 // This test applies only to the moderate-binding manager.
508 final BindingManagerImpl manager = mModerateBindingManager;
509
510 MockChildProcessConnection[] connections = new MockChildProcessConnectio n[4];
511 for (int i = 0; i < connections.length; i++) {
512 connections[i] = new MockChildProcessConnection(i + 1);
513 manager.addNewConnection(connections[i].getPid(), connections[i]);
514 }
515
516 // Verify that each connection has a moderate binding after binding and releasing a strong
517 // binding.
518 for (MockChildProcessConnection connection : connections) {
519 manager.setInForeground(connection.getPid(), true);
520 manager.setInForeground(connection.getPid(), false);
521 getInstrumentation().waitForIdleSync();
522 assertTrue(connection.isModerateBindingBound());
523 }
524
525 // Call onLowMemory() and verify that all the moderate bindings drop.
526 app.onLowMemory();
527 for (MockChildProcessConnection connection : connections) {
528 assertFalse(connection.isModerateBindingBound());
529 }
530 }
531
532 /**
533 * Verifies that onTrimMemory() drops moderate bindings properly.
534 */
535 @SmallTest
536 @Feature({"ProcessManagement"})
537 public void testModerateBindingDropOnTrimMemory() {
538 final Application app =
539 (Application) getInstrumentation().getTargetContext().getApplica tionContext();
540 // This test applies only to the moderate-binding manager.
541 final BindingManagerImpl manager = mModerateBindingManager;
542
543 ArrayList<Pair<Integer, Integer>> levelAndExpectedVictimCountList =
544 new ArrayList<Pair<Integer, Integer>>();
545 levelAndExpectedVictimCountList.add(
546 new Pair<Integer, Integer>(TRIM_MEMORY_RUNNING_MODERATE, 1));
547 levelAndExpectedVictimCountList.add(new Pair<Integer, Integer>(TRIM_MEMO RY_RUNNING_LOW, 2));
548 levelAndExpectedVictimCountList.add(
549 new Pair<Integer, Integer>(TRIM_MEMORY_RUNNING_CRITICAL, 4));
550
551 MockChildProcessConnection[] connections = new MockChildProcessConnectio n[4];
552 for (int i = 0; i < connections.length; i++) {
553 connections[i] = new MockChildProcessConnection(i + 1);
554 manager.addNewConnection(connections[i].getPid(), connections[i]);
555 }
556
557 for (Pair<Integer, Integer> pair : levelAndExpectedVictimCountList) {
558 String message = String.format("Failed for the level=%d", pair.first );
559 // Verify that each connection has a moderate binding after binding and releasing a
560 // strong binding.
561 for (MockChildProcessConnection connection : connections) {
562 manager.setInForeground(connection.getPid(), true);
563 manager.setInForeground(connection.getPid(), false);
564 getInstrumentation().waitForIdleSync();
565 assertTrue(message, connection.isModerateBindingBound());
566 }
567
568 app.onTrimMemory(pair.first);
569 // Verify that some of moderate bindings drop.
570 for (int i = 0; i < connections.length; i++) {
571 assertEquals(message, i >= pair.second, connections[i].isModerat eBindingBound());
572 }
573 }
574 }
386 } 575 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698