Merge "Add more test coverage to ConnectivityManagerTest." into nyc-dev

This commit is contained in:
TreeHugger Robot
2016-04-27 10:21:47 +00:00
committed by Android (Google) Code Review

View File

@@ -38,9 +38,16 @@ import android.net.wifi.WifiManager;
import android.test.AndroidTestCase; import android.test.AndroidTestCase;
import android.util.Log; import android.util.Log;
import android.os.SystemProperties; import android.os.SystemProperties;
import android.system.Os;
import android.system.OsConstants;
import com.android.internal.telephony.PhoneConstants; 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.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; 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_MOBILE = ConnectivityManager.TYPE_MOBILE;
public static final int TYPE_WIFI = ConnectivityManager.TYPE_WIFI; 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 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. // Action sent to ConnectivityActionReceiver when a network callback is sent via PendingIntent.
private static final String NETWORK_CALLBACK_ACTION = private static final String NETWORK_CALLBACK_ACTION =
@@ -249,6 +264,12 @@ public class ConnectivityManagerTest extends AndroidTestCase {
mCm.getBackgroundDataSetting(); mCm.getBackgroundDataSetting();
} }
private NetworkRequest makeWifiNetworkRequest() {
return new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.build();
}
/** /**
* Exercises both registerNetworkCallback and unregisterNetworkCallback. This checks to * Exercises both registerNetworkCallback and unregisterNetworkCallback. This checks to
* see if we get a callback for the TRANSPORT_WIFI transport type being available. * 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. // 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(); final TestNetworkCallback callback = new TestNetworkCallback();
mCm.registerNetworkCallback(request, callback); mCm.registerNetworkCallback(makeWifiNetworkRequest(), callback);
final TestNetworkCallback defaultTrackingCallback = new TestNetworkCallback(); final TestNetworkCallback defaultTrackingCallback = new TestNetworkCallback();
mCm.registerDefaultNetworkCallback(defaultTrackingCallback); mCm.registerDefaultNetworkCallback(defaultTrackingCallback);
final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled(); final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled();
Network wifiNetwork = null;
try { try {
// Make sure WiFi is connected to an access point to start with. // 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 // 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 // network even if it was already connected as a state-based action when the callback
// is registered. // is registered.
assertTrue("Did not receive NetworkCallback.onAvailable for TRANSPORT_WIFI", wifiNetwork = callback.waitForAvailable();
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()); defaultTrackingCallback.waitForAvailable());
} catch (InterruptedException e) { } catch (InterruptedException e) {
fail("Broadcast receiver or NetworkCallback wait was interrupted."); 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. // Return WiFi to its original enabled/disabled state.
if (!previousWifiEnabledState) { if (!previousWifiEnabledState) {
disconnectFromWifi(); disconnectFromWifi(wifiNetwork);
} }
} }
} }
@@ -329,10 +349,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
// We will register for a WIFI network being available or lost. // We will register for a WIFI network being available or lost.
NetworkRequest request = new NetworkRequest.Builder() mCm.registerNetworkCallback(makeWifiNetworkRequest(), pendingIntent);
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.build();
mCm.registerNetworkCallback(request, pendingIntent);
final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled(); final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled();
@@ -356,7 +373,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
// Return WiFi to its original enabled/disabled state. // Return WiFi to its original enabled/disabled state.
if (!previousWifiEnabledState) { 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. // We will toggle the state of wifi to generate a connectivity change.
final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled(); final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled();
if (previousWifiEnabledState) { if (previousWifiEnabledState) {
disconnectFromWifi(); Network wifiNetwork = getWifiNetwork();
disconnectFromWifi(wifiNetwork);
} else { } else {
connectToWifi(); connectToWifi();
} }
@@ -387,12 +406,16 @@ public class ConnectivityManagerTest extends AndroidTestCase {
if (previousWifiEnabledState) { if (previousWifiEnabledState) {
connectToWifi(); connectToWifi();
} else { } else {
disconnectFromWifi(); disconnectFromWifi(null);
} }
} }
/** Enable WiFi and wait for it to become connected to a network. */ /** 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( ConnectivityActionReceiver receiver = new ConnectivityActionReceiver(
ConnectivityManager.TYPE_WIFI, NetworkInfo.State.CONNECTED); ConnectivityManager.TYPE_WIFI, NetworkInfo.State.CONNECTED);
IntentFilter filter = new IntentFilter(); IntentFilter filter = new IntentFilter();
@@ -402,36 +425,94 @@ public class ConnectivityManagerTest extends AndroidTestCase {
boolean connected = false; boolean connected = false;
try { try {
assertTrue(mWifiManager.setWifiEnabled(true)); assertTrue(mWifiManager.setWifiEnabled(true));
// Ensure we get both an onAvailable callback and a CONNECTIVITY_ACTION.
wifiNetwork = callback.waitForAvailable();
assertNotNull(wifiNetwork);
connected = receiver.waitForState(); connected = receiver.waitForState();
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
fail("connectToWifi was interrupted"); fail("connectToWifi was interrupted");
} finally { } finally {
mCm.unregisterNetworkCallback(callback);
mContext.unregisterReceiver(receiver); mContext.unregisterReceiver(receiver);
} }
assertTrue("Wifi must be configured to connect to an access point for this test.", assertTrue("Wifi must be configured to connect to an access point for this test.",
connected); 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. */ /** 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( ConnectivityActionReceiver receiver = new ConnectivityActionReceiver(
ConnectivityManager.TYPE_WIFI, NetworkInfo.State.DISCONNECTED); ConnectivityManager.TYPE_WIFI, NetworkInfo.State.DISCONNECTED);
IntentFilter filter = new IntentFilter(); IntentFilter filter = new IntentFilter();
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
mContext.registerReceiver(receiver, filter); 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; boolean disconnected = false;
try { try {
assertTrue(mWifiManager.setWifiEnabled(false)); assertTrue(mWifiManager.setWifiEnabled(false));
// Ensure we get both an onLost callback and a CONNECTIVITY_ACTION.
lostWifiNetwork = callback.waitForLost();
assertNotNull(lostWifiNetwork);
disconnected = receiver.waitForState(); disconnected = receiver.waitForState();
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
fail("disconnectFromWifi was interrupted"); fail("disconnectFromWifi was interrupted");
} finally { } finally {
mCm.unregisterNetworkCallback(callback);
mContext.unregisterReceiver(receiver); mContext.unregisterReceiver(receiver);
} }
assertTrue("Wifi failed to reach DISCONNECTED state.", disconnected); 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 static class TestNetworkCallback extends ConnectivityManager.NetworkCallback {
private final CountDownLatch mAvailableLatch = new CountDownLatch(1); private final CountDownLatch mAvailableLatch = new CountDownLatch(1);
private final CountDownLatch mLostLatch = new CountDownLatch(1);
public boolean waitForAvailable() throws InterruptedException { public Network currentNetwork;
return mAvailableLatch.await(30, TimeUnit.SECONDS); 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 @Override
public void onAvailable(Network network) { public void onAvailable(Network network) {
currentNetwork = network;
mAvailableLatch.countDown(); 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. */ /** Verify restricted networks cannot be requested. */
@@ -523,8 +637,6 @@ public class ConnectivityManagerTest extends AndroidTestCase {
try { try {
mCm.requestNetwork(request, callback); mCm.requestNetwork(request, callback);
fail("No exception thrown when restricted network requested."); fail("No exception thrown when restricted network requested.");
} catch (SecurityException e) { } catch (SecurityException expected) {}
// Expected.
}
} }
} }