blob: 985e313a925a738c11885223a927b315488b31ea [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.net.cts;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import android.content.Context;
import android.content.ContentResolver;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkUtils;
import android.net.cts.util.CtsNetUtils;
import android.platform.test.annotations.AppModeFull;
import android.provider.Settings;
import android.system.ErrnoException;
import android.system.OsConstants;
import android.test.AndroidTestCase;
import java.util.ArrayList;
public class MultinetworkApiTest extends AndroidTestCase {
static {
System.loadLibrary("nativemultinetwork_jni");
}
private static final String TAG = "MultinetworkNativeApiTest";
static final String GOOGLE_PRIVATE_DNS_SERVER = "dns.google";
/**
* @return 0 on success
*/
private static native int runGetaddrinfoCheck(long networkHandle);
private static native int runSetprocnetwork(long networkHandle);
private static native int runSetsocknetwork(long networkHandle);
private static native int runDatagramCheck(long networkHandle);
private static native void runResNapiMalformedCheck(long networkHandle);
private static native void runResNcancelCheck(long networkHandle);
private static native void runResNqueryCheck(long networkHandle);
private static native void runResNsendCheck(long networkHandle);
private static native void runResNnxDomainCheck(long networkHandle);
private ContentResolver mCR;
private ConnectivityManager mCM;
private CtsNetUtils mCtsNetUtils;
private String mOldMode;
private String mOldDnsSpecifier;
@Override
protected void setUp() throws Exception {
super.setUp();
mCM = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
mCR = getContext().getContentResolver();
mCtsNetUtils = new CtsNetUtils(getContext());
mCtsNetUtils.storePrivateDnsSetting();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
}
private Network[] getTestableNetworks() {
final ArrayList<Network> testableNetworks = new ArrayList<Network>();
for (Network network : mCM.getAllNetworks()) {
final NetworkCapabilities nc = mCM.getNetworkCapabilities(network);
if (nc != null
&& nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
&& nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
testableNetworks.add(network);
}
}
assertTrue(
"This test requires that at least one network be connected. " +
"Please ensure that the device is connected to a network.",
testableNetworks.size() >= 1);
return testableNetworks.toArray(new Network[0]);
}
public void testGetaddrinfo() throws ErrnoException {
for (Network network : getTestableNetworks()) {
int errno = runGetaddrinfoCheck(network.getNetworkHandle());
if (errno != 0) {
throw new ErrnoException(
"getaddrinfo on " + mCM.getNetworkInfo(network), -errno);
}
}
}
public void testSetprocnetwork() throws ErrnoException {
// Hopefully no prior test in this process space has set a default network.
assertNull(mCM.getProcessDefaultNetwork());
assertEquals(0, NetworkUtils.getBoundNetworkForProcess());
for (Network network : getTestableNetworks()) {
mCM.setProcessDefaultNetwork(null);
assertNull(mCM.getProcessDefaultNetwork());
int errno = runSetprocnetwork(network.getNetworkHandle());
if (errno != 0) {
throw new ErrnoException(
"setprocnetwork on " + mCM.getNetworkInfo(network), -errno);
}
Network processDefault = mCM.getProcessDefaultNetwork();
assertNotNull(processDefault);
assertEquals(network, processDefault);
// TODO: open DatagramSockets, connect them to 192.0.2.1 and 2001:db8::,
// and ensure that the source address is in fact on this network as
// determined by mCM.getLinkProperties(network).
mCM.setProcessDefaultNetwork(null);
}
for (Network network : getTestableNetworks()) {
NetworkUtils.bindProcessToNetwork(0);
assertNull(mCM.getBoundNetworkForProcess());
int errno = runSetprocnetwork(network.getNetworkHandle());
if (errno != 0) {
throw new ErrnoException(
"setprocnetwork on " + mCM.getNetworkInfo(network), -errno);
}
assertEquals(network, new Network(mCM.getBoundNetworkForProcess()));
// TODO: open DatagramSockets, connect them to 192.0.2.1 and 2001:db8::,
// and ensure that the source address is in fact on this network as
// determined by mCM.getLinkProperties(network).
NetworkUtils.bindProcessToNetwork(0);
}
}
public void testSetsocknetwork() throws ErrnoException {
for (Network network : getTestableNetworks()) {
int errno = runSetsocknetwork(network.getNetworkHandle());
if (errno != 0) {
throw new ErrnoException(
"setsocknetwork on " + mCM.getNetworkInfo(network), -errno);
}
}
}
public void testNativeDatagramTransmission() throws ErrnoException {
for (Network network : getTestableNetworks()) {
int errno = runDatagramCheck(network.getNetworkHandle());
if (errno != 0) {
throw new ErrnoException(
"DatagramCheck on " + mCM.getNetworkInfo(network), -errno);
}
}
}
public void testNoSuchNetwork() {
final Network eNoNet = new Network(54321);
assertNull(mCM.getNetworkInfo(eNoNet));
final long eNoNetHandle = eNoNet.getNetworkHandle();
assertEquals(-OsConstants.ENONET, runSetsocknetwork(eNoNetHandle));
assertEquals(-OsConstants.ENONET, runSetprocnetwork(eNoNetHandle));
// TODO: correct test permissions so this call is not silently re-mapped
// to query on the default network.
// assertEquals(-OsConstants.ENONET, runGetaddrinfoCheck(eNoNetHandle));
}
public void testNetworkHandle() {
// Test Network -> NetworkHandle -> Network results in the same Network.
for (Network network : getTestableNetworks()) {
long networkHandle = network.getNetworkHandle();
Network newNetwork = Network.fromNetworkHandle(networkHandle);
assertEquals(newNetwork, network);
}
// Test that only obfuscated handles are allowed.
try {
Network.fromNetworkHandle(100);
fail();
} catch (IllegalArgumentException e) {}
try {
Network.fromNetworkHandle(-1);
fail();
} catch (IllegalArgumentException e) {}
try {
Network.fromNetworkHandle(0);
fail();
} catch (IllegalArgumentException e) {}
}
public void testResNApi() throws Exception {
final Network[] testNetworks = getTestableNetworks();
for (Network network : testNetworks) {
// Throws AssertionError directly in jni function if test fail.
runResNqueryCheck(network.getNetworkHandle());
runResNsendCheck(network.getNetworkHandle());
runResNcancelCheck(network.getNetworkHandle());
runResNapiMalformedCheck(network.getNetworkHandle());
final NetworkCapabilities nc = mCM.getNetworkCapabilities(network);
// Some cellular networks configure their DNS servers never to return NXDOMAIN, so don't
// test NXDOMAIN on these DNS servers.
// b/144521720
if (nc != null && !nc.hasTransport(TRANSPORT_CELLULAR)) {
runResNnxDomainCheck(network.getNetworkHandle());
}
}
}
@AppModeFull(reason = "WRITE_SECURE_SETTINGS permission can't be granted to instant apps")
public void testResNApiNXDomainPrivateDns() throws InterruptedException {
// Enable private DNS strict mode and set server to dns.google before doing NxDomain test.
// b/144521720
try {
mCtsNetUtils.setPrivateDnsStrictMode(GOOGLE_PRIVATE_DNS_SERVER);
for (Network network : getTestableNetworks()) {
// Wait for private DNS setting to propagate.
mCtsNetUtils.awaitPrivateDnsSetting("NxDomain test wait private DNS setting timeout",
network, GOOGLE_PRIVATE_DNS_SERVER, true);
runResNnxDomainCheck(network.getNetworkHandle());
}
} finally {
mCtsNetUtils.restorePrivateDnsSetting();
}
}
}