Skip to content
Snippets Groups Projects
Commit 8f0e34be authored by Joseph Murphy's avatar Joseph Murphy Committed by Gerrit Code Review
Browse files

Revert "Use a TAP test network for MeshCoP service test cases"

This reverts commit 55648268.

Reason for revert: DroidMonitor revert

Change-Id: Idd86b0ceb18fc425c39fe3c75603a472568eabe1
parent 55648268
No related branches found
No related tags found
No related merge requests found
......@@ -42,7 +42,6 @@ android_test {
"guava",
"guava-android-testlib",
"net-tests-utils",
"ThreadNetworkTestUtils",
"truth",
],
libs: [
......
......@@ -17,6 +17,7 @@
package android.net.thread.cts;
import static android.Manifest.permission.ACCESS_NETWORK_STATE;
import static android.Manifest.permission.MANAGE_TEST_NETWORKS;
import static android.net.thread.ThreadNetworkController.DEVICE_ROLE_CHILD;
import static android.net.thread.ThreadNetworkController.DEVICE_ROLE_LEADER;
import static android.net.thread.ThreadNetworkController.DEVICE_ROLE_ROUTER;
......@@ -32,6 +33,7 @@ import static android.net.thread.ThreadNetworkException.ERROR_THREAD_DISABLED;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.android.testutils.TestNetworkTrackerKt.initTestNetwork;
import static com.android.testutils.TestPermissionUtil.runAsShell;
import static com.google.common.truth.Truth.assertThat;
......@@ -46,6 +48,7 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.LinkAddress;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
......@@ -59,9 +62,7 @@ import android.net.thread.ThreadNetworkController.OperationalDatasetCallback;
import android.net.thread.ThreadNetworkController.StateCallback;
import android.net.thread.ThreadNetworkException;
import android.net.thread.ThreadNetworkManager;
import android.net.thread.utils.TapTestNetworkTracker;
import android.os.Build;
import android.os.HandlerThread;
import android.os.OutcomeReceiver;
import androidx.annotation.NonNull;
......@@ -73,6 +74,7 @@ import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import com.android.testutils.DevSdkIgnoreRunner;
import com.android.testutils.FunctionalUtils.ThrowingRunnable;
import com.android.testutils.TestNetworkTracker;
import org.junit.After;
import org.junit.Before;
......@@ -108,7 +110,7 @@ public class ThreadNetworkControllerTest {
private static final int NETWORK_CALLBACK_TIMEOUT_MILLIS = 10 * 1000;
private static final int CALLBACK_TIMEOUT_MILLIS = 1_000;
private static final int ENABLED_TIMEOUT_MILLIS = 2_000;
private static final int SERVICE_DISCOVERY_TIMEOUT_MILLIS = 30_000;
private static final int SERVICE_DISCOVERY_TIMEOUT_MILLIS = 10 * 1000;
private static final String MESHCOP_SERVICE_TYPE = "_meshcop._udp";
private static final String THREAD_NETWORK_PRIVILEGED =
"android.permission.THREAD_NETWORK_PRIVILEGED";
......@@ -121,8 +123,6 @@ public class ThreadNetworkControllerTest {
private NsdManager mNsdManager;
private Set<String> mGrantedPermissions;
private HandlerThread mHandlerThread;
private TapTestNetworkTracker mTestNetworkTracker;
@Before
public void setUp() throws Exception {
......@@ -141,8 +141,6 @@ public class ThreadNetworkControllerTest {
setEnabledAndWait(mController, true);
mNsdManager = mContext.getSystemService(NsdManager.class);
mHandlerThread = new HandlerThread(this.getClass().getSimpleName());
mHandlerThread.start();
}
@After
......@@ -154,7 +152,6 @@ public class ThreadNetworkControllerTest {
future.get(LEAVE_TIMEOUT_MILLIS, MILLISECONDS);
}
dropAllPermissions();
tearDownTestNetwork();
}
@Test
......@@ -832,7 +829,7 @@ public class ThreadNetworkControllerTest {
@Test
public void meshcopService_threadEnabledButNotJoined_discoveredButNoNetwork() throws Exception {
setUpTestNetwork();
TestNetworkTracker testNetwork = setUpTestNetwork();
setEnabledAndWait(mController, true);
leaveAndWait(mController);
......@@ -848,11 +845,13 @@ public class ThreadNetworkControllerTest {
assertThat(txtMap.get("rv")).isNotNull();
assertThat(txtMap.get("tv")).isNotNull();
assertThat(txtMap.get("sb")).isNotNull();
tearDownTestNetwork(testNetwork);
}
@Test
public void meshcopService_joinedNetwork_discoveredHasNetwork() throws Exception {
setUpTestNetwork();
TestNetworkTracker testNetwork = setUpTestNetwork();
String networkName = "TestNet" + new Random().nextInt(10_000);
joinRandomizedDatasetAndWait(mController, networkName);
......@@ -873,26 +872,27 @@ public class ThreadNetworkControllerTest {
assertThat(txtMap.get("tv")).isNotNull();
assertThat(txtMap.get("sb")).isNotNull();
assertThat(txtMap.get("id").length).isEqualTo(16);
tearDownTestNetwork(testNetwork);
}
@Test
public void meshcopService_threadDisabled_notDiscovered() throws Exception {
setUpTestNetwork();
TestNetworkTracker testNetwork = setUpTestNetwork();
CompletableFuture<NsdServiceInfo> serviceLostFuture = new CompletableFuture<>();
NsdManager.DiscoveryListener listener =
discoverForServiceLost(MESHCOP_SERVICE_TYPE, serviceLostFuture);
setEnabledAndWait(mController, false);
try {
serviceLostFuture.get(SERVICE_DISCOVERY_TIMEOUT_MILLIS, MILLISECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException ignored) {
// It's fine if the service lost event didn't show up. The service may not ever be
// advertised.
serviceLostFuture.get(10_000, MILLISECONDS);
} finally {
mNsdManager.stopServiceDiscovery(listener);
}
assertThrows(TimeoutException.class, () -> discoverService(MESHCOP_SERVICE_TYPE));
tearDownTestNetwork(testNetwork);
}
private static void dropAllPermissions() {
......@@ -1163,17 +1163,14 @@ public class ThreadNetworkControllerTest {
}
}
private void setUpTestNetwork() {
assertThat(mTestNetworkTracker).isNull();
mTestNetworkTracker = new TapTestNetworkTracker(mContext, mHandlerThread.getLooper());
TestNetworkTracker setUpTestNetwork() {
return runAsShell(
MANAGE_TEST_NETWORKS,
() -> initTestNetwork(mContext, new LinkAddress("2001:db8:123::/64"), 10_000));
}
private void tearDownTestNetwork() throws InterruptedException {
if (mTestNetworkTracker != null) {
mTestNetworkTracker.tearDown();
}
mHandlerThread.quitSafely();
mHandlerThread.join();
void tearDownTestNetwork(TestNetworkTracker testNetwork) {
runAsShell(MANAGE_TEST_NETWORKS, () -> testNetwork.teardown());
}
private static class DefaultDiscoveryListener implements NsdManager.DiscoveryListener {
......
......@@ -16,6 +16,7 @@
package com.android.server.thread;
import static android.Manifest.permission.ACCESS_NETWORK_STATE;
import static android.net.thread.ActiveOperationalDataset.CHANNEL_PAGE_24_GHZ;
import static android.net.thread.ThreadNetworkController.STATE_DISABLED;
import static android.net.thread.ThreadNetworkController.STATE_ENABLED;
......
//
// Copyright (C) 2023 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 {
default_team: "trendy_team_fwk_thread_network",
default_applicable_licenses: ["Android-Apache-2.0"],
}
java_library {
name: "ThreadNetworkTestUtils",
min_sdk_version: "30",
static_libs: [
"compatibility-device-util-axt",
"net-tests-utils",
"net-utils-device-common",
"net-utils-device-common-bpf",
],
srcs: [
"src/**/*.java",
],
defaults: [
"framework-connectivity-test-defaults",
],
}
/*
* Copyright (C) 2024 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.thread.utils;
import static android.Manifest.permission.MANAGE_TEST_NETWORKS;
import static android.net.InetAddresses.parseNumericAddress;
import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
import static android.net.NetworkCapabilities.TRANSPORT_TEST;
import static android.system.OsConstants.AF_INET6;
import static android.system.OsConstants.IPPROTO_UDP;
import static android.system.OsConstants.SOCK_DGRAM;
import static com.android.testutils.RecorderCallback.CallbackEntry.LINK_PROPERTIES_CHANGED;
import static com.android.testutils.TestPermissionUtil.runAsShell;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.TestNetworkInterface;
import android.net.TestNetworkManager;
import android.net.TestNetworkSpecifier;
import android.os.Looper;
import android.system.ErrnoException;
import android.system.Os;
import com.android.compatibility.common.util.PollingCheck;
import com.android.testutils.TestableNetworkAgent;
import com.android.testutils.TestableNetworkCallback;
import java.io.FileDescriptor;
import java.io.IOException;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/** A class that can create/destroy a test network based on TAP interface. */
public final class TapTestNetworkTracker {
private static final Duration TIMEOUT = Duration.ofSeconds(2);
private final Context mContext;
private final Looper mLooper;
private TestNetworkInterface mInterface;
private TestableNetworkAgent mAgent;
private final TestableNetworkCallback mNetworkCallback;
private final ConnectivityManager mConnectivityManager;
/**
* Constructs a {@link TapTestNetworkTracker}.
*
* <p>It creates a TAP interface (e.g. testtap0) and registers a test network using that
* interface. It also requests the test network by {@link ConnectivityManager#requestNetwork} so
* the test network won't be automatically turned down by {@link
* com.android.server.ConnectivityService}.
*/
public TapTestNetworkTracker(Context context, Looper looper) {
mContext = context;
mLooper = looper;
mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
mNetworkCallback = new TestableNetworkCallback();
runAsShell(MANAGE_TEST_NETWORKS, this::setUpTestNetwork);
}
/** Tears down the test network. */
public void tearDown() {
runAsShell(MANAGE_TEST_NETWORKS, this::tearDownTestNetwork);
}
/** Returns the interface name of the test network. */
public String getInterfaceName() {
return mInterface.getInterfaceName();
}
private void setUpTestNetwork() throws Exception {
mInterface = mContext.getSystemService(TestNetworkManager.class).createTapInterface();
mConnectivityManager.requestNetwork(newNetworkRequest(), mNetworkCallback);
LinkProperties lp = new LinkProperties();
lp.setInterfaceName(getInterfaceName());
mAgent =
new TestableNetworkAgent(
mContext,
mLooper,
newNetworkCapabilities(),
lp,
new NetworkAgentConfig.Builder().build());
final Network network = mAgent.register();
mAgent.markConnected();
PollingCheck.check(
"No usable address on interface",
TIMEOUT.toMillis(),
() -> hasUsableAddress(network, getInterfaceName()));
lp.setLinkAddresses(makeLinkAddresses());
mAgent.sendLinkProperties(lp);
mNetworkCallback.eventuallyExpect(
LINK_PROPERTIES_CHANGED,
TIMEOUT.toMillis(),
l -> !l.getLp().getAddresses().isEmpty());
}
private void tearDownTestNetwork() throws IOException {
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
mAgent.unregister();
mInterface.getFileDescriptor().close();
mAgent.waitForIdle(TIMEOUT.toMillis());
}
private NetworkRequest newNetworkRequest() {
return new NetworkRequest.Builder()
.removeCapability(NET_CAPABILITY_TRUSTED)
.addTransportType(TRANSPORT_TEST)
.setNetworkSpecifier(new TestNetworkSpecifier(getInterfaceName()))
.build();
}
private NetworkCapabilities newNetworkCapabilities() {
return new NetworkCapabilities()
.removeCapability(NET_CAPABILITY_TRUSTED)
.addTransportType(TRANSPORT_TEST)
.setNetworkSpecifier(new TestNetworkSpecifier(getInterfaceName()));
}
private List<LinkAddress> makeLinkAddresses() {
List<LinkAddress> linkAddresses = new ArrayList<>();
List<InterfaceAddress> interfaceAddresses = Collections.emptyList();
try {
interfaceAddresses =
NetworkInterface.getByName(getInterfaceName()).getInterfaceAddresses();
} catch (SocketException ignored) {
// Ignore failures when getting the addresses.
}
for (InterfaceAddress address : interfaceAddresses) {
linkAddresses.add(
new LinkAddress(address.getAddress(), address.getNetworkPrefixLength()));
}
return linkAddresses;
}
private static boolean hasUsableAddress(Network network, String interfaceName) {
try {
if (NetworkInterface.getByName(interfaceName).getInterfaceAddresses().isEmpty()) {
return false;
}
} catch (SocketException e) {
return false;
}
// Check if the link-local address can be used. Address flags are not available without
// elevated permissions, so check that bindSocket works.
try {
FileDescriptor sock = Os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
network.bindSocket(sock);
Os.connect(sock, parseNumericAddress("ff02::fb%" + interfaceName), 12345);
Os.close(sock);
} catch (ErrnoException | IOException e) {
return false;
}
return true;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment