Add more test coverage to ConnectivityManagerTest.
1. Test NetworkCallbacks as well as CONNECTIVITY_ACTION, since we are moving away from CONNECTIVITY_ACTION. 2. Use the Network objects we get back to test Network#getSocketFactory(). 3. Check that TCP connections are closed with ECONNABORTED when a network disconnects. Bug: 28251576 Change-Id: I41a438b82ef9251e52866332f3445f1bf876e04f
This commit is contained in:
@@ -38,9 +38,16 @@ import android.net.wifi.WifiManager;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.util.Log;
|
||||
import android.os.SystemProperties;
|
||||
import android.system.Os;
|
||||
import android.system.OsConstants;
|
||||
|
||||
import com.android.internal.telephony.PhoneConstants;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -57,7 +64,15 @@ public class ConnectivityManagerTest extends AndroidTestCase {
|
||||
|
||||
public static final int TYPE_MOBILE = ConnectivityManager.TYPE_MOBILE;
|
||||
public static final int TYPE_WIFI = ConnectivityManager.TYPE_WIFI;
|
||||
|
||||
private static final int HOST_ADDRESS = 0x7f000001;// represent ip 127.0.0.1
|
||||
private static final String TEST_HOST = "connectivitycheck.gstatic.com";
|
||||
private static final int SOCKET_TIMEOUT_MS = 2000;
|
||||
private static final int HTTP_PORT = 80;
|
||||
private static final String HTTP_REQUEST =
|
||||
"GET /generate_204 HTTP/1.0\r\n" +
|
||||
"Host: " + TEST_HOST + "\r\n" +
|
||||
"Connection: keep-alive\r\n\r\n";
|
||||
|
||||
// Action sent to ConnectivityActionReceiver when a network callback is sent via PendingIntent.
|
||||
private static final String NETWORK_CALLBACK_ACTION =
|
||||
@@ -249,6 +264,12 @@ public class ConnectivityManagerTest extends AndroidTestCase {
|
||||
mCm.getBackgroundDataSetting();
|
||||
}
|
||||
|
||||
private NetworkRequest makeWifiNetworkRequest() {
|
||||
return new NetworkRequest.Builder()
|
||||
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Exercises both registerNetworkCallback and unregisterNetworkCallback. This checks to
|
||||
* see if we get a callback for the TRANSPORT_WIFI transport type being available.
|
||||
@@ -265,16 +286,14 @@ public class ConnectivityManagerTest extends AndroidTestCase {
|
||||
}
|
||||
|
||||
// We will register for a WIFI network being available or lost.
|
||||
final NetworkRequest request = new NetworkRequest.Builder()
|
||||
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
|
||||
.build();
|
||||
final TestNetworkCallback callback = new TestNetworkCallback();
|
||||
mCm.registerNetworkCallback(request, callback);
|
||||
mCm.registerNetworkCallback(makeWifiNetworkRequest(), callback);
|
||||
|
||||
final TestNetworkCallback defaultTrackingCallback = new TestNetworkCallback();
|
||||
mCm.registerDefaultNetworkCallback(defaultTrackingCallback);
|
||||
|
||||
final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled();
|
||||
Network wifiNetwork = null;
|
||||
|
||||
try {
|
||||
// Make sure WiFi is connected to an access point to start with.
|
||||
@@ -285,10 +304,11 @@ public class ConnectivityManagerTest extends AndroidTestCase {
|
||||
// Now we should expect to get a network callback about availability of the wifi
|
||||
// network even if it was already connected as a state-based action when the callback
|
||||
// is registered.
|
||||
assertTrue("Did not receive NetworkCallback.onAvailable for TRANSPORT_WIFI",
|
||||
callback.waitForAvailable());
|
||||
wifiNetwork = callback.waitForAvailable();
|
||||
assertNotNull("Did not receive NetworkCallback.onAvailable for TRANSPORT_WIFI",
|
||||
wifiNetwork);
|
||||
|
||||
assertTrue("Did not receive NetworkCallback.onAvailable for any default network",
|
||||
assertNotNull("Did not receive NetworkCallback.onAvailable for any default network",
|
||||
defaultTrackingCallback.waitForAvailable());
|
||||
} catch (InterruptedException e) {
|
||||
fail("Broadcast receiver or NetworkCallback wait was interrupted.");
|
||||
@@ -298,7 +318,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
|
||||
|
||||
// Return WiFi to its original enabled/disabled state.
|
||||
if (!previousWifiEnabledState) {
|
||||
disconnectFromWifi();
|
||||
disconnectFromWifi(wifiNetwork);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -329,10 +349,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
|
||||
mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
|
||||
|
||||
// We will register for a WIFI network being available or lost.
|
||||
NetworkRequest request = new NetworkRequest.Builder()
|
||||
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
|
||||
.build();
|
||||
mCm.registerNetworkCallback(request, pendingIntent);
|
||||
mCm.registerNetworkCallback(makeWifiNetworkRequest(), pendingIntent);
|
||||
|
||||
final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled();
|
||||
|
||||
@@ -356,7 +373,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
|
||||
|
||||
// Return WiFi to its original enabled/disabled state.
|
||||
if (!previousWifiEnabledState) {
|
||||
disconnectFromWifi();
|
||||
disconnectFromWifi(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -370,8 +387,10 @@ public class ConnectivityManagerTest extends AndroidTestCase {
|
||||
|
||||
// We will toggle the state of wifi to generate a connectivity change.
|
||||
final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled();
|
||||
|
||||
if (previousWifiEnabledState) {
|
||||
disconnectFromWifi();
|
||||
Network wifiNetwork = getWifiNetwork();
|
||||
disconnectFromWifi(wifiNetwork);
|
||||
} else {
|
||||
connectToWifi();
|
||||
}
|
||||
@@ -387,12 +406,16 @@ public class ConnectivityManagerTest extends AndroidTestCase {
|
||||
if (previousWifiEnabledState) {
|
||||
connectToWifi();
|
||||
} else {
|
||||
disconnectFromWifi();
|
||||
disconnectFromWifi(null);
|
||||
}
|
||||
}
|
||||
|
||||
/** Enable WiFi and wait for it to become connected to a network. */
|
||||
private void connectToWifi() {
|
||||
private Network connectToWifi() {
|
||||
final TestNetworkCallback callback = new TestNetworkCallback();
|
||||
mCm.registerNetworkCallback(makeWifiNetworkRequest(), callback);
|
||||
Network wifiNetwork = null;
|
||||
|
||||
ConnectivityActionReceiver receiver = new ConnectivityActionReceiver(
|
||||
ConnectivityManager.TYPE_WIFI, NetworkInfo.State.CONNECTED);
|
||||
IntentFilter filter = new IntentFilter();
|
||||
@@ -402,36 +425,94 @@ public class ConnectivityManagerTest extends AndroidTestCase {
|
||||
boolean connected = false;
|
||||
try {
|
||||
assertTrue(mWifiManager.setWifiEnabled(true));
|
||||
// Ensure we get both an onAvailable callback and a CONNECTIVITY_ACTION.
|
||||
wifiNetwork = callback.waitForAvailable();
|
||||
assertNotNull(wifiNetwork);
|
||||
connected = receiver.waitForState();
|
||||
} catch (InterruptedException ex) {
|
||||
fail("connectToWifi was interrupted");
|
||||
} finally {
|
||||
mCm.unregisterNetworkCallback(callback);
|
||||
mContext.unregisterReceiver(receiver);
|
||||
}
|
||||
|
||||
assertTrue("Wifi must be configured to connect to an access point for this test.",
|
||||
connected);
|
||||
return wifiNetwork;
|
||||
}
|
||||
|
||||
private Socket getBoundSocket(Network network, String host, int port) throws IOException {
|
||||
InetSocketAddress addr = new InetSocketAddress(host, port);
|
||||
Socket s = network.getSocketFactory().createSocket();
|
||||
try {
|
||||
s.setSoTimeout(SOCKET_TIMEOUT_MS);
|
||||
s.connect(addr, SOCKET_TIMEOUT_MS);
|
||||
} catch (IOException e) {
|
||||
s.close();
|
||||
throw e;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
private void testHttpRequest(Socket s) throws IOException {
|
||||
OutputStream out = s.getOutputStream();
|
||||
InputStream in = s.getInputStream();
|
||||
|
||||
final byte[] requestBytes = HTTP_REQUEST.getBytes("UTF-8");
|
||||
byte[] responseBytes = new byte[4096];
|
||||
out.write(requestBytes);
|
||||
in.read(responseBytes);
|
||||
assertTrue(new String(responseBytes, "UTF-8").startsWith("HTTP/1.0 204 No Content\r\n"));
|
||||
}
|
||||
|
||||
/** Disable WiFi and wait for it to become disconnected from the network. */
|
||||
private void disconnectFromWifi() {
|
||||
private void disconnectFromWifi(Network wifiNetworkToCheck) {
|
||||
final TestNetworkCallback callback = new TestNetworkCallback();
|
||||
mCm.registerNetworkCallback(makeWifiNetworkRequest(), callback);
|
||||
Network lostWifiNetwork = null;
|
||||
|
||||
ConnectivityActionReceiver receiver = new ConnectivityActionReceiver(
|
||||
ConnectivityManager.TYPE_WIFI, NetworkInfo.State.DISCONNECTED);
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
||||
mContext.registerReceiver(receiver, filter);
|
||||
|
||||
// Assert that we can establish a TCP connection on wifi.
|
||||
Socket wifiBoundSocket = null;
|
||||
if (wifiNetworkToCheck != null) {
|
||||
try {
|
||||
wifiBoundSocket = getBoundSocket(wifiNetworkToCheck, TEST_HOST, HTTP_PORT);
|
||||
testHttpRequest(wifiBoundSocket);
|
||||
} catch (IOException e) {
|
||||
fail("HTTP request before wifi disconnected failed with: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
boolean disconnected = false;
|
||||
try {
|
||||
assertTrue(mWifiManager.setWifiEnabled(false));
|
||||
// Ensure we get both an onLost callback and a CONNECTIVITY_ACTION.
|
||||
lostWifiNetwork = callback.waitForLost();
|
||||
assertNotNull(lostWifiNetwork);
|
||||
disconnected = receiver.waitForState();
|
||||
} catch (InterruptedException ex) {
|
||||
fail("disconnectFromWifi was interrupted");
|
||||
} finally {
|
||||
mCm.unregisterNetworkCallback(callback);
|
||||
mContext.unregisterReceiver(receiver);
|
||||
}
|
||||
|
||||
assertTrue("Wifi failed to reach DISCONNECTED state.", disconnected);
|
||||
|
||||
// Check that the socket is closed when wifi disconnects.
|
||||
if (wifiBoundSocket != null) {
|
||||
try {
|
||||
testHttpRequest(wifiBoundSocket);
|
||||
fail("HTTP request should not succeed after wifi disconnects");
|
||||
} catch (IOException expected) {
|
||||
assertEquals(Os.strerror(OsConstants.ECONNABORTED), expected.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -498,15 +579,48 @@ public class ConnectivityManagerTest extends AndroidTestCase {
|
||||
*/
|
||||
private static class TestNetworkCallback extends ConnectivityManager.NetworkCallback {
|
||||
private final CountDownLatch mAvailableLatch = new CountDownLatch(1);
|
||||
private final CountDownLatch mLostLatch = new CountDownLatch(1);
|
||||
|
||||
public boolean waitForAvailable() throws InterruptedException {
|
||||
return mAvailableLatch.await(30, TimeUnit.SECONDS);
|
||||
public Network currentNetwork;
|
||||
public Network lastLostNetwork;
|
||||
|
||||
public Network waitForAvailable() throws InterruptedException {
|
||||
return mAvailableLatch.await(30, TimeUnit.SECONDS) ? currentNetwork : null;
|
||||
}
|
||||
|
||||
public Network waitForLost() throws InterruptedException {
|
||||
return mLostLatch.await(30, TimeUnit.SECONDS) ? lastLostNetwork : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAvailable(Network network) {
|
||||
currentNetwork = network;
|
||||
mAvailableLatch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLost(Network network) {
|
||||
lastLostNetwork = network;
|
||||
if (network.equals(currentNetwork)) {
|
||||
currentNetwork = null;
|
||||
}
|
||||
mLostLatch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
private Network getWifiNetwork() {
|
||||
TestNetworkCallback callback = new TestNetworkCallback();
|
||||
mCm.registerNetworkCallback(makeWifiNetworkRequest(), callback);
|
||||
Network network = null;
|
||||
try {
|
||||
network = callback.waitForAvailable();
|
||||
} catch (InterruptedException e) {
|
||||
fail("NetworkCallback wait was interrupted.");
|
||||
} finally {
|
||||
mCm.unregisterNetworkCallback(callback);
|
||||
}
|
||||
assertNotNull("Cannot find Network for wifi. Is wifi connected?", network);
|
||||
return network;
|
||||
}
|
||||
|
||||
/** Verify restricted networks cannot be requested. */
|
||||
@@ -523,8 +637,6 @@ public class ConnectivityManagerTest extends AndroidTestCase {
|
||||
try {
|
||||
mCm.requestNetwork(request, callback);
|
||||
fail("No exception thrown when restricted network requested.");
|
||||
} catch (SecurityException e) {
|
||||
// Expected.
|
||||
}
|
||||
} catch (SecurityException expected) {}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user