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 3// found in the LICENSE file. 4 5package org.chromium.content.browser; 6 7import android.content.Context; 8import android.os.RemoteException; 9import android.test.InstrumentationTestCase; 10import android.test.suitebuilder.annotation.MediumTest; 11 12import org.chromium.base.library_loader.LibraryLoader; 13import org.chromium.base.test.util.Feature; 14import org.chromium.content.browser.test.util.Criteria; 15import org.chromium.content.browser.test.util.CriteriaHelper; 16 17/** 18 * Instrumentation tests for ChildProcessLauncher. 19 */ 20public class ChildProcessLauncherTest extends InstrumentationTestCase { 21 /** 22 * Tests cleanup for a connection that fails to connect in the first place. 23 */ 24 @MediumTest 25 @Feature({"ProcessManagement"}) 26 public void testServiceFailedToBind() throws InterruptedException, RemoteException { 27 assertEquals(0, ChildProcessLauncher.allocatedConnectionsCountForTesting()); 28 assertEquals(0, ChildProcessLauncher.connectedServicesCountForTesting()); 29 30 // Try to allocate a connection to service class in incorrect package. We can do that by 31 // using the instrumentation context (getContext()) instead of the app context 32 // (getTargetContext()). 33 Context context = getInstrumentation().getContext(); 34 ChildProcessLauncher.allocateBoundConnectionForTesting(context); 35 36 // Verify that the connection is not considered as allocated. 37 assertEquals(0, ChildProcessLauncher.allocatedConnectionsCountForTesting()); 38 assertEquals(0, ChildProcessLauncher.connectedServicesCountForTesting()); 39 } 40 41 /** 42 * Tests cleanup for a connection that terminates before setup. 43 */ 44 @MediumTest 45 @Feature({"ProcessManagement"}) 46 public void testServiceCrashedBeforeSetup() throws InterruptedException, RemoteException { 47 assertEquals(0, ChildProcessLauncher.allocatedConnectionsCountForTesting()); 48 assertEquals(0, ChildProcessLauncher.connectedServicesCountForTesting()); 49 50 // Start and connect to a new service. 51 final ChildProcessConnectionImpl connection = startConnection(); 52 assertEquals(1, ChildProcessLauncher.allocatedConnectionsCountForTesting()); 53 54 // Verify that the service is not yet set up. 55 assertEquals(0, connection.getPid()); 56 assertEquals(0, ChildProcessLauncher.connectedServicesCountForTesting()); 57 58 // Crash the service. 59 assertTrue(connection.crashServiceForTesting()); 60 61 // Verify that the connection gets cleaned-up. 62 assertTrue("Crashed connection wasn't released from the allocator.", 63 CriteriaHelper.pollForCriteria(new Criteria() { 64 @Override 65 public boolean isSatisfied() { 66 return ChildProcessLauncher.allocatedConnectionsCountForTesting() == 0; 67 } 68 })); 69 70 assertTrue("Crashed connection wasn't released from ChildProcessLauncher.", 71 CriteriaHelper.pollForCriteria(new Criteria() { 72 @Override 73 public boolean isSatisfied() { 74 return ChildProcessLauncher.connectedServicesCountForTesting() == 0; 75 } 76 })); 77 } 78 79 /** 80 * Tests cleanup for a connection that terminates after setup. 81 */ 82 @MediumTest 83 @Feature({"ProcessManagement"}) 84 public void testServiceCrashedAfterSetup() throws InterruptedException, RemoteException { 85 assertEquals(0, ChildProcessLauncher.allocatedConnectionsCountForTesting()); 86 87 // Start and connect to a new service. 88 final ChildProcessConnectionImpl connection = startConnection(); 89 assertEquals(1, ChildProcessLauncher.allocatedConnectionsCountForTesting()); 90 91 // Initiate the connection setup. 92 ChildProcessLauncher.triggerConnectionSetup(connection, new String[0], 1, 93 new FileDescriptorInfo[0], ChildProcessLauncher.CALLBACK_FOR_RENDERER_PROCESS, 0); 94 95 // Verify that the connection completes the setup. 96 assertTrue("The connection wasn't registered in ChildProcessLauncher after setup.", 97 CriteriaHelper.pollForCriteria(new Criteria() { 98 @Override 99 public boolean isSatisfied() { 100 return ChildProcessLauncher.connectedServicesCountForTesting() == 1; 101 } 102 })); 103 104 assertTrue("The connection failed to get a pid in setup.", 105 CriteriaHelper.pollForCriteria(new Criteria() { 106 @Override 107 public boolean isSatisfied() { 108 return connection.getPid() != 0; 109 } 110 })); 111 112 // Crash the service. 113 assertTrue(connection.crashServiceForTesting()); 114 115 // Verify that the connection gets cleaned-up. 116 assertTrue("Crashed connection wasn't released from the allocator.", 117 CriteriaHelper.pollForCriteria(new Criteria() { 118 @Override 119 public boolean isSatisfied() { 120 return ChildProcessLauncher.allocatedConnectionsCountForTesting() == 0; 121 } 122 })); 123 124 assertTrue("Crashed connection wasn't released from ChildProcessLauncher.", 125 CriteriaHelper.pollForCriteria(new Criteria() { 126 @Override 127 public boolean isSatisfied() { 128 return ChildProcessLauncher.connectedServicesCountForTesting() == 0; 129 } 130 })); 131 132 // Verify that the connection pid remains set after termination. 133 assertTrue(connection.getPid() != 0); 134 } 135 136 private ChildProcessConnectionImpl startConnection() throws InterruptedException { 137 // Allocate a new connection. 138 Context context = getInstrumentation().getTargetContext(); 139 final ChildProcessConnectionImpl connection = (ChildProcessConnectionImpl) 140 ChildProcessLauncher.allocateBoundConnectionForTesting(context); 141 142 // Wait for the service to connect. 143 assertTrue("The connection wasn't established.", 144 CriteriaHelper.pollForCriteria(new Criteria() { 145 @Override 146 public boolean isSatisfied() { 147 return connection.isConnected(); 148 } 149 })); 150 return connection; 151 } 152 153 @Override 154 protected void setUp() throws Exception { 155 super.setUp(); 156 LibraryLoader.ensureInitialized(); 157 } 158} 159