Merge changes I54451c4a,Ib0a2518b into main
* changes:
Inline runUdp4Test
Create a tethered interface request in setUp
diff --git a/Tethering/tests/integration/base/android/net/EthernetTetheringTestBase.java b/Tethering/tests/integration/base/android/net/EthernetTetheringTestBase.java
index 120b871..9ab39bf 100644
--- a/Tethering/tests/integration/base/android/net/EthernetTetheringTestBase.java
+++ b/Tethering/tests/integration/base/android/net/EthernetTetheringTestBase.java
@@ -42,7 +42,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeFalse;
@@ -105,7 +104,7 @@
// Used to check if any tethering interface is available. Choose 200ms to be request timeout
// because the average interface requested time on cuttlefish@acloud is around 10ms.
// See TetheredInterfaceRequester.getInterface, isInterfaceForTetheringAvailable.
- private static final int AVAILABLE_TETHER_IFACE_REQUEST_TIMEOUT_MS = 200;
+ private static final int SHORT_TIMEOUT_MS = 200;
private static final int TETHER_REACHABILITY_ATTEMPTS = 20;
protected static final long WAIT_RA_TIMEOUT_MS = 2000;
@@ -154,7 +153,7 @@
private boolean mRunTests;
private HandlerThread mHandlerThread;
private Handler mHandler;
- private TetheredInterfaceRequester mTetheredInterfaceRequester;
+ protected TetheredInterfaceRequester mTetheredInterfaceRequester;
// Late initialization in initTetheringTester().
private TapPacketReader mUpstreamReader;
@@ -245,12 +244,14 @@
maybeUnregisterTetheringEventCallback(mTetheringEventCallback);
mTetheringEventCallback = null;
- runAsShell(NETWORK_SETTINGS, () -> mTetheredInterfaceRequester.release());
setIncludeTestInterfaces(false);
}
@After
public void tearDown() throws Exception {
+ if (mTetheredInterfaceRequester != null) {
+ mTetheredInterfaceRequester.release();
+ }
try {
if (mRunTests) cleanUp();
} finally {
@@ -263,33 +264,17 @@
}
}
- protected static boolean isInterfaceForTetheringAvailable() throws Exception {
- // Before T, all ethernet interfaces could be used for server mode. Instead of
- // waiting timeout, just checking whether the system currently has any
- // ethernet interface is more reliable.
- if (!SdkLevel.isAtLeastT()) {
- return runAsShell(CONNECTIVITY_USE_RESTRICTED_NETWORKS, () -> sEm.isAvailable());
- }
-
+ protected boolean isInterfaceForTetheringAvailable() throws Exception {
// If previous test case doesn't release tethering interface successfully, the other tests
// after that test may be skipped as unexcepted.
// TODO: figure out a better way to check default tethering interface existenion.
- final TetheredInterfaceRequester requester = new TetheredInterfaceRequester();
- try {
- // Use short timeout (200ms) for requesting an existing interface, if any, because
- // it should reurn faster than requesting a new tethering interface. Using default
- // timeout (5000ms, TIMEOUT_MS) may make that total testing time is over 1 minute
- // test module timeout on internal testing.
- // TODO: if this becomes flaky, consider using default timeout (5000ms) and moving
- // this check into #setUpOnce.
- return requester.getInterface(AVAILABLE_TETHER_IFACE_REQUEST_TIMEOUT_MS) != null;
- } catch (TimeoutException e) {
- return false;
- } finally {
- runAsShell(NETWORK_SETTINGS, () -> {
- requester.release();
- });
- }
+ // Use short timeout (200ms) for requesting an existing interface, if any, because
+ // it should reurn faster than requesting a new tethering interface. Using default
+ // timeout (5000ms, TIMEOUT_MS) may make that total testing time is over 1 minute
+ // test module timeout on internal testing.
+ // TODO: if this becomes flaky, consider using default timeout (5000ms) and moving
+ // this check into #setUpOnce.
+ return mTetheredInterfaceRequester.isPhysicalInterfaceAvailable(SHORT_TIMEOUT_MS);
}
protected static void setIncludeTestInterfaces(boolean include) {
@@ -304,14 +289,6 @@
});
}
- protected String getTetheredInterface() throws Exception {
- return mTetheredInterfaceRequester.getInterface();
- }
-
- protected CompletableFuture<String> requestTetheredInterface() throws Exception {
- return mTetheredInterfaceRequester.requestInterface();
- }
-
protected static void waitForRouterAdvertisement(TapPacketReader reader, String iface,
long timeoutMs) {
final long deadline = SystemClock.uptimeMillis() + timeoutMs;
@@ -605,6 +582,11 @@
private TetheredInterfaceRequest mRequest;
private final CompletableFuture<String> mFuture = new CompletableFuture<>();
+ TetheredInterfaceRequester() {
+ mRequest = runAsShell(NETWORK_SETTINGS, () ->
+ sEm.requestTetheredInterface(c -> c.run() /* executor */, this));
+ }
+
@Override
public void onAvailable(String iface) {
Log.d(TAG, "Ethernet interface available: " + iface);
@@ -616,28 +598,21 @@
mFuture.completeExceptionally(new IllegalStateException("onUnavailable received"));
}
- public CompletableFuture<String> requestInterface() {
- assertNull("BUG: more than one tethered interface request", mRequest);
- Log.d(TAG, "Requesting tethered interface");
- mRequest = runAsShell(NETWORK_SETTINGS, () ->
- sEm.requestTetheredInterface(c -> c.run() /* executor */, this));
- return mFuture;
- }
-
- public String getInterface(int timeout) throws Exception {
- return requestInterface().get(timeout, TimeUnit.MILLISECONDS);
+ public boolean isPhysicalInterfaceAvailable(int timeout) {
+ try {
+ final String iface = mFuture.get(timeout, TimeUnit.MILLISECONDS);
+ return !iface.startsWith("testtap");
+ } catch (Exception e) {
+ return false;
+ }
}
public String getInterface() throws Exception {
- return getInterface(TIMEOUT_MS);
+ return mFuture.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
}
public void release() {
- if (mRequest != null) {
- mFuture.obtrudeException(new IllegalStateException("Request already released"));
- mRequest.release();
- mRequest = null;
- }
+ runAsShell(NETWORK_SETTINGS, () -> mRequest.release());
}
}
@@ -658,7 +633,10 @@
lp.setLinkAddresses(addresses);
lp.setDnsServers(dnses);
- return runAsShell(MANAGE_TEST_NETWORKS, () -> initTestNetwork(sContext, lp, TIMEOUT_MS));
+ // TODO: initTestNetwork can take up to 15 seconds on a workstation. Investigate when and
+ // why this is the case. It is unclear whether a 30 second timeout is enough when running
+ // these tests in the much slower test infra.
+ return runAsShell(MANAGE_TEST_NETWORKS, () -> initTestNetwork(sContext, lp, 30_000));
}
protected void sendDownloadPacketUdp(@NonNull final InetAddress srcIp,
diff --git a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
index c54d1b4..5c258b2 100644
--- a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
+++ b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
@@ -59,7 +59,7 @@
import com.android.testutils.NetworkStackModuleTest;
import com.android.testutils.TapPacketReader;
-import org.junit.BeforeClass;
+import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -75,8 +75,6 @@
import java.util.Collection;
import java.util.List;
import java.util.Random;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@RunWith(AndroidJUnit4.class)
@@ -151,33 +149,14 @@
(byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04 /* Address: 1.2.3.4 */
};
- /** Enable/disable tethering once before running the tests. */
- @BeforeClass
- public static void setUpOnce() throws Exception {
- // The first test case may experience tethering restart with IP conflict handling.
- // Tethering would cache the last upstreams so that the next enabled tethering avoids
- // picking up the address that is in conflict with the upstreams. To protect subsequent
- // tests, turn tethering on and off before running them.
- MyTetheringEventCallback callback = null;
- TestNetworkInterface testIface = null;
- assumeTrue(sEm != null);
- try {
- // If the physical ethernet interface is available, do nothing.
- if (isInterfaceForTetheringAvailable()) return;
-
- testIface = createTestInterface();
- setIncludeTestInterfaces(true);
-
- callback = enableEthernetTethering(testIface.getInterfaceName(), null);
- callback.awaitUpstreamChanged(true /* throwTimeoutException */);
- } catch (TimeoutException e) {
- Log.d(TAG, "WARNNING " + e);
- } finally {
- maybeCloseTestInterface(testIface);
- maybeUnregisterTetheringEventCallback(callback);
-
- setIncludeTestInterfaces(false);
- }
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ // TODO: See b/318121782#comment4. Register an ethernet InterfaceStateListener, and wait for
+ // the callback to report client mode. This happens as soon as both
+ // TetheredInterfaceRequester and the tethering code itself have released the interface,
+ // i.e. after stopTethering() has completed.
+ Thread.sleep(3000);
}
@Test
@@ -201,7 +180,7 @@
Log.d(TAG, "Including test interfaces");
setIncludeTestInterfaces(true);
- final String iface = getTetheredInterface();
+ final String iface = mTetheredInterfaceRequester.getInterface();
assertEquals("TetheredInterfaceCallback for unexpected interface",
downstreamIface.getInterfaceName(), iface);
@@ -223,8 +202,6 @@
// This test requires manipulating packets. Skip if there is a physical Ethernet connected.
assumeFalse(isInterfaceForTetheringAvailable());
- CompletableFuture<String> futureIface = requestTetheredInterface();
-
setIncludeTestInterfaces(true);
TestNetworkInterface downstreamIface = null;
@@ -234,7 +211,7 @@
try {
downstreamIface = createTestInterface();
- final String iface = futureIface.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ final String iface = mTetheredInterfaceRequester.getInterface();
assertEquals("TetheredInterfaceCallback for unexpected interface",
downstreamIface.getInterfaceName(), iface);
@@ -264,7 +241,7 @@
try {
downstreamIface = createTestInterface();
- final String iface = getTetheredInterface();
+ final String iface = mTetheredInterfaceRequester.getInterface();
assertEquals("TetheredInterfaceCallback for unexpected interface",
downstreamIface.getInterfaceName(), iface);
@@ -338,7 +315,7 @@
try {
downstreamIface = createTestInterface();
- final String iface = getTetheredInterface();
+ final String iface = mTetheredInterfaceRequester.getInterface();
assertEquals("TetheredInterfaceCallback for unexpected interface",
downstreamIface.getInterfaceName(), iface);
@@ -388,7 +365,7 @@
MyTetheringEventCallback tetheringEventCallback = null;
try {
// Get an interface to use.
- final String iface = getTetheredInterface();
+ final String iface = mTetheredInterfaceRequester.getInterface();
// Enable Ethernet tethering and check that it starts.
tetheringEventCallback = enableEthernetTethering(iface, null /* any upstream */);
@@ -509,17 +486,23 @@
// TODO: test BPF offload maps {rule, stats}.
}
- // Test network topology:
- //
- // public network (rawip) private network
- // | UE |
- // +------------+ V +------------+------------+ V +------------+
- // | Sever +---------+ Upstream | Downstream +---------+ Client |
- // +------------+ +------------+------------+ +------------+
- // remote ip public ip private ip
- // 8.8.8.8:443 <Upstream ip>:9876 <TetheredDevice ip>:9876
- //
- private void runUdp4Test() throws Exception {
+
+ /**
+ * Basic IPv4 UDP tethering test. Verify that UDP tethered packets are transferred no matter
+ * using which data path.
+ */
+ @Test
+ public void testTetherUdpV4() throws Exception {
+ // Test network topology:
+ //
+ // public network (rawip) private network
+ // | UE |
+ // +------------+ V +------------+------------+ V +------------+
+ // | Sever +---------+ Upstream | Downstream +---------+ Client |
+ // +------------+ +------------+------------+ +------------+
+ // remote ip public ip private ip
+ // 8.8.8.8:443 <Upstream ip>:9876 <TetheredDevice ip>:9876
+ //
final TetheringTester tester = initTetheringTester(toList(TEST_IP4_ADDR),
toList(TEST_IP4_DNS));
final TetheredDevice tethered = tester.createTetheredDevice(TEST_MAC, false /* hasIpv6 */);
@@ -541,15 +524,6 @@
sendDownloadPacketUdp(remoteIp, tetheringUpstreamIp, tester, false /* is6To4 */);
}
- /**
- * Basic IPv4 UDP tethering test. Verify that UDP tethered packets are transferred no matter
- * using which data path.
- */
- @Test
- public void testTetherUdpV4() throws Exception {
- runUdp4Test();
- }
-
// Test network topology:
//
// public network (rawip) private network
@@ -599,7 +573,7 @@
final TetheredDevice tethered = tester.createTetheredDevice(TEST_MAC, false /* hasIpv6 */);
// TODO: remove the connectivity verification for upstream connected notification race.
- // See the same reason in runUdp4Test().
+ // See the same reason in testTetherUdp4().
probeV4TetheringConnectivity(tester, tethered, false /* is4To6 */);
final ByteBuffer request = buildIcmpEchoPacketV4(tethered.macAddr /* srcMac */,
@@ -707,7 +681,7 @@
final TetheredDevice tethered = tester.createTetheredDevice(TEST_MAC, false /* hasIpv6 */);
// TODO: remove the connectivity verification for upstream connected notification race.
- // See the same reason in runUdp4Test().
+ // See the same reason in testTetherUdp4().
probeV4TetheringConnectivity(tester, tethered, false /* is4To6 */);
// [1] Send DNS query.
@@ -751,7 +725,7 @@
final TetheredDevice tethered = tester.createTetheredDevice(TEST_MAC, false /* hasIpv6 */);
// TODO: remove the connectivity verification for upstream connected notification race.
- // See the same reason in runUdp4Test().
+ // See the same reason in testTetherUdp4().
probeV4TetheringConnectivity(tester, tethered, false /* is4To6 */);
runTcpTest(tethered.macAddr /* uploadSrcMac */, tethered.routerMacAddr /* uploadDstMac */,
diff --git a/tests/cts/net/src/android/net/cts/NsdManagerDownstreamTetheringTest.kt b/tests/cts/net/src/android/net/cts/NsdManagerDownstreamTetheringTest.kt
index 1b1f367..a3c3f45 100644
--- a/tests/cts/net/src/android/net/cts/NsdManagerDownstreamTetheringTest.kt
+++ b/tests/cts/net/src/android/net/cts/NsdManagerDownstreamTetheringTest.kt
@@ -72,7 +72,7 @@
tryTest {
downstreamIface = createTestInterface()
- val iface = tetheredInterface
+ val iface = mTetheredInterfaceRequester.getInterface()
assertEquals(iface, downstreamIface?.interfaceName)
val request = TetheringRequest.Builder(TETHERING_ETHERNET)
.setConnectivityScope(CONNECTIVITY_SCOPE_LOCAL).build()
@@ -115,7 +115,7 @@
tryTest {
downstreamIface = createTestInterface()
- val iface = tetheredInterface
+ val iface = mTetheredInterfaceRequester.getInterface()
assertEquals(iface, downstreamIface?.interfaceName)
val localAddr = LinkAddress("192.0.2.3/28")