Add a test to identify memory leak in ConnectivityManager
The sInstance static instance which self reference to ConnectivityManager which holds a reference to a ConnectivityManager instance causes the Context referenced by that instance to never be GCed. Bug: 202978965 Test: atest ConnectivityManagerTest Change-Id: I0227f63dbc27688ea5f4ef9275fd0f9c247ad14c
This commit is contained in:
@@ -72,6 +72,7 @@ import android.os.Process;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.internal.util.test.BroadcastInterceptingContext;
|
||||
import com.android.testutils.DevSdkIgnoreRule;
|
||||
import com.android.testutils.DevSdkIgnoreRunner;
|
||||
|
||||
@@ -82,6 +83,8 @@ import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
@RunWith(DevSdkIgnoreRunner.class)
|
||||
@SmallTest
|
||||
@DevSdkIgnoreRule.IgnoreUpTo(VERSION_CODES.R)
|
||||
@@ -461,4 +464,50 @@ public class ConnectivityManagerTest {
|
||||
}
|
||||
fail("expected exception of type " + throwableType);
|
||||
}
|
||||
|
||||
private static class MockContext extends BroadcastInterceptingContext {
|
||||
MockContext(Context base) {
|
||||
super(base);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context getApplicationContext() {
|
||||
return mock(Context.class);
|
||||
}
|
||||
}
|
||||
|
||||
private WeakReference<Context> makeConnectivityManagerAndReturnContext() {
|
||||
// Mockito may have an internal reference to the mock, creating MockContext for testing.
|
||||
final Context c = new MockContext(mock(Context.class));
|
||||
|
||||
new ConnectivityManager(c, mService);
|
||||
|
||||
return new WeakReference<>(c);
|
||||
}
|
||||
|
||||
private void forceGC() {
|
||||
// First GC ensures that objects are collected for finalization, then second GC ensures
|
||||
// they're garbage-collected after being finalized.
|
||||
System.gc();
|
||||
System.runFinalization();
|
||||
System.gc();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectivityManagerDoesNotLeakContext() throws Exception {
|
||||
final WeakReference<Context> ref = makeConnectivityManagerAndReturnContext();
|
||||
|
||||
final int attempts = 100;
|
||||
final long waitIntervalMs = 50;
|
||||
for (int i = 0; i < attempts; i++) {
|
||||
forceGC();
|
||||
if (ref.get() == null) break;
|
||||
|
||||
Thread.sleep(waitIntervalMs);
|
||||
}
|
||||
|
||||
// TODO: fix memory leak then assertNull here.
|
||||
assertNotNull("Couldn't find the Context leak in ConnectivityManager after " + attempts
|
||||
+ " attempts", ref.get());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user