Merge "[Thread] use TestRule to filter Thread tests" into main am: f8ffba4c04
Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/2996876 Change-Id: I12335903cb53a8d4e1fa5d4a8273646814537501 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
commit
51d9b9f241
8 changed files with 255 additions and 130 deletions
|
|
@ -74,42 +74,61 @@ import java.util.Arrays;
|
|||
public final class ActiveOperationalDataset implements Parcelable {
|
||||
/** The maximum length of the Active Operational Dataset TLV array in bytes. */
|
||||
public static final int LENGTH_MAX_DATASET_TLVS = 254;
|
||||
|
||||
/** The length of Extended PAN ID in bytes. */
|
||||
public static final int LENGTH_EXTENDED_PAN_ID = 8;
|
||||
|
||||
/** The minimum length of Network Name as UTF-8 bytes. */
|
||||
public static final int LENGTH_MIN_NETWORK_NAME_BYTES = 1;
|
||||
|
||||
/** The maximum length of Network Name as UTF-8 bytes. */
|
||||
public static final int LENGTH_MAX_NETWORK_NAME_BYTES = 16;
|
||||
|
||||
/** The length of Network Key in bytes. */
|
||||
public static final int LENGTH_NETWORK_KEY = 16;
|
||||
|
||||
/** The length of Mesh-Local Prefix in bits. */
|
||||
public static final int LENGTH_MESH_LOCAL_PREFIX_BITS = 64;
|
||||
|
||||
/** The length of PSKc in bytes. */
|
||||
public static final int LENGTH_PSKC = 16;
|
||||
|
||||
/** The 2.4 GHz channel page. */
|
||||
public static final int CHANNEL_PAGE_24_GHZ = 0;
|
||||
|
||||
/** The minimum 2.4GHz channel. */
|
||||
public static final int CHANNEL_MIN_24_GHZ = 11;
|
||||
|
||||
/** The maximum 2.4GHz channel. */
|
||||
public static final int CHANNEL_MAX_24_GHZ = 26;
|
||||
|
||||
/** @hide */
|
||||
@VisibleForTesting public static final int TYPE_CHANNEL = 0;
|
||||
|
||||
/** @hide */
|
||||
@VisibleForTesting public static final int TYPE_PAN_ID = 1;
|
||||
|
||||
/** @hide */
|
||||
@VisibleForTesting public static final int TYPE_EXTENDED_PAN_ID = 2;
|
||||
|
||||
/** @hide */
|
||||
@VisibleForTesting public static final int TYPE_NETWORK_NAME = 3;
|
||||
|
||||
/** @hide */
|
||||
@VisibleForTesting public static final int TYPE_PSKC = 4;
|
||||
|
||||
/** @hide */
|
||||
@VisibleForTesting public static final int TYPE_NETWORK_KEY = 5;
|
||||
|
||||
/** @hide */
|
||||
@VisibleForTesting public static final int TYPE_MESH_LOCAL_PREFIX = 7;
|
||||
|
||||
/** @hide */
|
||||
@VisibleForTesting public static final int TYPE_SECURITY_POLICY = 12;
|
||||
|
||||
/** @hide */
|
||||
@VisibleForTesting public static final int TYPE_ACTIVE_TIMESTAMP = 14;
|
||||
|
||||
/** @hide */
|
||||
@VisibleForTesting public static final int TYPE_CHANNEL_MASK = 53;
|
||||
|
||||
|
|
@ -975,8 +994,10 @@ public final class ActiveOperationalDataset implements Parcelable {
|
|||
public static final class SecurityPolicy {
|
||||
/** The default Rotation Time in hours. */
|
||||
public static final int DEFAULT_ROTATION_TIME_HOURS = 672;
|
||||
|
||||
/** The minimum length of Security Policy flags in bytes. */
|
||||
public static final int LENGTH_MIN_SECURITY_POLICY_FLAGS = 1;
|
||||
|
||||
/** The length of Rotation Time TLV value in bytes. */
|
||||
private static final int LENGTH_SECURITY_POLICY_ROTATION_TIME = 2;
|
||||
|
||||
|
|
|
|||
|
|
@ -46,10 +46,13 @@ import java.io.InputStream;
|
|||
*/
|
||||
public class ThreadPersistentSettings {
|
||||
private static final String TAG = "ThreadPersistentSettings";
|
||||
|
||||
/** File name used for storing settings. */
|
||||
private static final String FILE_NAME = "ThreadPersistentSettings.xml";
|
||||
|
||||
/** Current config store data version. This will be incremented for any additions. */
|
||||
private static final int CURRENT_SETTINGS_STORE_DATA_VERSION = 1;
|
||||
|
||||
/**
|
||||
* Stores the version of the data. This can be used to handle migration of data if some
|
||||
* non-backward compatible change introduced.
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
|
|||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.junit.Assume.assumeNotNull;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
|
||||
|
|
@ -60,7 +59,8 @@ 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.net.thread.utils.ThreadFeatureCheckerRule;
|
||||
import android.net.thread.utils.ThreadFeatureCheckerRule.RequiresThreadFeature;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.OutcomeReceiver;
|
||||
|
||||
|
|
@ -69,16 +69,12 @@ import androidx.test.core.app.ApplicationProvider;
|
|||
import androidx.test.filters.LargeTest;
|
||||
|
||||
import com.android.net.module.util.ArrayTrackRecord;
|
||||
import com.android.testutils.DevSdkIgnoreRule;
|
||||
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
|
||||
import com.android.testutils.DevSdkIgnoreRunner;
|
||||
import com.android.testutils.FunctionalUtils.ThrowingRunnable;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
|
|
@ -99,8 +95,7 @@ import java.util.function.Predicate;
|
|||
|
||||
/** CTS tests for {@link ThreadNetworkController}. */
|
||||
@LargeTest
|
||||
@RunWith(DevSdkIgnoreRunner.class)
|
||||
@IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) // Thread is available on only U+
|
||||
@RequiresThreadFeature
|
||||
public class ThreadNetworkControllerTest {
|
||||
private static final int JOIN_TIMEOUT_MILLIS = 30 * 1000;
|
||||
private static final int LEAVE_TIMEOUT_MILLIS = 2_000;
|
||||
|
|
@ -114,7 +109,7 @@ public class ThreadNetworkControllerTest {
|
|||
private static final String THREAD_NETWORK_PRIVILEGED =
|
||||
"android.permission.THREAD_NETWORK_PRIVILEGED";
|
||||
|
||||
@Rule public DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
|
||||
@Rule public final ThreadFeatureCheckerRule mThreadRule = new ThreadFeatureCheckerRule();
|
||||
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private ExecutorService mExecutor;
|
||||
|
|
@ -127,14 +122,10 @@ public class ThreadNetworkControllerTest {
|
|||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
ThreadNetworkManager manager = mContext.getSystemService(ThreadNetworkManager.class);
|
||||
if (manager != null) {
|
||||
mController = manager.getAllThreadNetworkControllers().get(0);
|
||||
}
|
||||
|
||||
// TODO: we will also need it in tearDown(), it's better to have a Rule to skip
|
||||
// tests if a feature is not available.
|
||||
assumeNotNull(mController);
|
||||
mController =
|
||||
mContext.getSystemService(ThreadNetworkManager.class)
|
||||
.getAllThreadNetworkControllers()
|
||||
.get(0);
|
||||
|
||||
mGrantedPermissions = new HashSet<String>();
|
||||
mExecutor = Executors.newSingleThreadExecutor();
|
||||
|
|
@ -147,9 +138,6 @@ public class ThreadNetworkControllerTest {
|
|||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (mController == null) {
|
||||
return;
|
||||
}
|
||||
dropAllPermissions();
|
||||
leaveAndWait(mController);
|
||||
tearDownTestNetwork();
|
||||
|
|
|
|||
|
|
@ -24,8 +24,6 @@ import static android.net.thread.utils.IntegrationTestUtils.RESTART_JOIN_TIMEOUT
|
|||
import static android.net.thread.utils.IntegrationTestUtils.isExpectedIcmpv6Packet;
|
||||
import static android.net.thread.utils.IntegrationTestUtils.isFromIpv6Source;
|
||||
import static android.net.thread.utils.IntegrationTestUtils.isInMulticastGroup;
|
||||
import static android.net.thread.utils.IntegrationTestUtils.isMulticastRoutingSupported;
|
||||
import static android.net.thread.utils.IntegrationTestUtils.isSimulatedThreadRadioSupported;
|
||||
import static android.net.thread.utils.IntegrationTestUtils.isToIpv6Destination;
|
||||
import static android.net.thread.utils.IntegrationTestUtils.newPacketReader;
|
||||
import static android.net.thread.utils.IntegrationTestUtils.pollForPacket;
|
||||
|
|
@ -44,8 +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.Assume.assumeNotNull;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
|
||||
|
|
@ -56,6 +52,10 @@ import android.net.MacAddress;
|
|||
import android.net.thread.utils.FullThreadDevice;
|
||||
import android.net.thread.utils.InfraNetworkDevice;
|
||||
import android.net.thread.utils.OtDaemonController;
|
||||
import android.net.thread.utils.ThreadFeatureCheckerRule;
|
||||
import android.net.thread.utils.ThreadFeatureCheckerRule.RequiresIpv6MulticastRouting;
|
||||
import android.net.thread.utils.ThreadFeatureCheckerRule.RequiresSimulationThreadDevice;
|
||||
import android.net.thread.utils.ThreadFeatureCheckerRule.RequiresThreadFeature;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
|
||||
|
|
@ -68,6 +68,7 @@ import com.android.testutils.TestNetworkTracker;
|
|||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
|
|
@ -82,19 +83,11 @@ import java.util.function.Predicate;
|
|||
|
||||
/** Integration test cases for Thread Border Routing feature. */
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@RequiresThreadFeature
|
||||
@RequiresSimulationThreadDevice
|
||||
@LargeTest
|
||||
public class BorderRoutingTest {
|
||||
private static final String TAG = BorderRoutingTest.class.getSimpleName();
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private ThreadNetworkController mController;
|
||||
private OtDaemonController mOtCtl;
|
||||
private HandlerThread mHandlerThread;
|
||||
private Handler mHandler;
|
||||
private TestNetworkTracker mInfraNetworkTracker;
|
||||
private List<FullThreadDevice> mFtds;
|
||||
private TapPacketReader mInfraNetworkReader;
|
||||
private InfraNetworkDevice mInfraDevice;
|
||||
|
||||
private static final int NUM_FTD = 2;
|
||||
private static final Inet6Address GROUP_ADDR_SCOPE_5 =
|
||||
(Inet6Address) InetAddresses.parseNumericAddress("ff05::1234");
|
||||
|
|
@ -114,17 +107,25 @@ public class BorderRoutingTest {
|
|||
private static final ActiveOperationalDataset DEFAULT_DATASET =
|
||||
ActiveOperationalDataset.fromThreadTlvs(DEFAULT_DATASET_TLVS);
|
||||
|
||||
@Rule public final ThreadFeatureCheckerRule mThreadRule = new ThreadFeatureCheckerRule();
|
||||
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private ThreadNetworkController mController;
|
||||
private OtDaemonController mOtCtl;
|
||||
private HandlerThread mHandlerThread;
|
||||
private Handler mHandler;
|
||||
private TestNetworkTracker mInfraNetworkTracker;
|
||||
private List<FullThreadDevice> mFtds;
|
||||
private TapPacketReader mInfraNetworkReader;
|
||||
private InfraNetworkDevice mInfraDevice;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
assumeTrue(isSimulatedThreadRadioSupported());
|
||||
final ThreadNetworkManager manager = mContext.getSystemService(ThreadNetworkManager.class);
|
||||
if (manager != null) {
|
||||
mController = manager.getAllThreadNetworkControllers().get(0);
|
||||
}
|
||||
|
||||
// Run the tests on only devices where the Thread feature is available
|
||||
assumeNotNull(mController);
|
||||
|
||||
// TODO: b/323301831 - This is a workaround to avoid unnecessary delay to re-form a network
|
||||
mOtCtl = new OtDaemonController();
|
||||
mOtCtl.factoryReset();
|
||||
|
|
@ -151,10 +152,6 @@ public class BorderRoutingTest {
|
|||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (mController == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
runAsShell(
|
||||
PERMISSION_THREAD_NETWORK_PRIVILEGED,
|
||||
NETWORK_SETTINGS,
|
||||
|
|
@ -225,8 +222,6 @@ public class BorderRoutingTest {
|
|||
@Test
|
||||
public void unicastRouting_borderRouterSendsUdpToThreadDevice_datagramReceived()
|
||||
throws Exception {
|
||||
assumeTrue(isSimulatedThreadRadioSupported());
|
||||
|
||||
/*
|
||||
* <pre>
|
||||
* Topology:
|
||||
|
|
@ -260,9 +255,9 @@ public class BorderRoutingTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@RequiresIpv6MulticastRouting
|
||||
public void multicastRouting_ftdSubscribedMulticastAddress_infraLinkJoinsMulticastGroup()
|
||||
throws Exception {
|
||||
assumeTrue(isMulticastRoutingSupported());
|
||||
/*
|
||||
* <pre>
|
||||
* Topology:
|
||||
|
|
@ -281,10 +276,10 @@ public class BorderRoutingTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@RequiresIpv6MulticastRouting
|
||||
public void
|
||||
multicastRouting_ftdSubscribedScope3MulticastAddress_infraLinkNotJoinMulticastGroup()
|
||||
throws Exception {
|
||||
assumeTrue(isMulticastRoutingSupported());
|
||||
/*
|
||||
* <pre>
|
||||
* Topology:
|
||||
|
|
@ -303,9 +298,9 @@ public class BorderRoutingTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@RequiresIpv6MulticastRouting
|
||||
public void multicastRouting_ftdSubscribedMulticastAddress_canPingfromInfraLink()
|
||||
throws Exception {
|
||||
assumeTrue(isMulticastRoutingSupported());
|
||||
/*
|
||||
* <pre>
|
||||
* Topology:
|
||||
|
|
@ -325,9 +320,9 @@ public class BorderRoutingTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@RequiresIpv6MulticastRouting
|
||||
public void multicastRouting_inboundForwarding_afterBrRejoinFtdRepliesSubscribedAddress()
|
||||
throws Exception {
|
||||
assumeTrue(isMulticastRoutingSupported());
|
||||
|
||||
// TODO (b/327311034): Testing bbr state switch from primary mode to secondary mode and back
|
||||
// to primary mode requires an additional BR in the Thread network. This is not currently
|
||||
|
|
@ -335,9 +330,9 @@ public class BorderRoutingTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@RequiresIpv6MulticastRouting
|
||||
public void multicastRouting_ftdSubscribedScope3MulticastAddress_cannotPingfromInfraLink()
|
||||
throws Exception {
|
||||
assumeTrue(isMulticastRoutingSupported());
|
||||
/*
|
||||
* <pre>
|
||||
* Topology:
|
||||
|
|
@ -357,9 +352,9 @@ public class BorderRoutingTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@RequiresIpv6MulticastRouting
|
||||
public void multicastRouting_ftdNotSubscribedMulticastAddress_cannotPingFromInfraDevice()
|
||||
throws Exception {
|
||||
assumeTrue(isMulticastRoutingSupported());
|
||||
/*
|
||||
* <pre>
|
||||
* Topology:
|
||||
|
|
@ -378,9 +373,9 @@ public class BorderRoutingTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@RequiresIpv6MulticastRouting
|
||||
public void multicastRouting_multipleFtdsSubscribedDifferentAddresses_canPingFromInfraDevice()
|
||||
throws Exception {
|
||||
assumeTrue(isMulticastRoutingSupported());
|
||||
/*
|
||||
* <pre>
|
||||
* Topology:
|
||||
|
|
@ -414,9 +409,9 @@ public class BorderRoutingTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@RequiresIpv6MulticastRouting
|
||||
public void multicastRouting_multipleFtdsSubscribedSameAddress_canPingFromInfraDevice()
|
||||
throws Exception {
|
||||
assumeTrue(isMulticastRoutingSupported());
|
||||
/*
|
||||
* <pre>
|
||||
* Topology:
|
||||
|
|
@ -449,8 +444,8 @@ public class BorderRoutingTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@RequiresIpv6MulticastRouting
|
||||
public void multicastRouting_outboundForwarding_scopeLargerThan3IsForwarded() throws Exception {
|
||||
assumeTrue(isMulticastRoutingSupported());
|
||||
/*
|
||||
* <pre>
|
||||
* Topology:
|
||||
|
|
@ -474,9 +469,9 @@ public class BorderRoutingTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@RequiresIpv6MulticastRouting
|
||||
public void multicastRouting_outboundForwarding_scopeSmallerThan4IsNotForwarded()
|
||||
throws Exception {
|
||||
assumeTrue(isMulticastRoutingSupported());
|
||||
/*
|
||||
* <pre>
|
||||
* Topology:
|
||||
|
|
@ -497,8 +492,8 @@ public class BorderRoutingTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@RequiresIpv6MulticastRouting
|
||||
public void multicastRouting_outboundForwarding_llaToScope4IsNotForwarded() throws Exception {
|
||||
assumeTrue(isMulticastRoutingSupported());
|
||||
/*
|
||||
* <pre>
|
||||
* Topology:
|
||||
|
|
@ -520,8 +515,8 @@ public class BorderRoutingTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@RequiresIpv6MulticastRouting
|
||||
public void multicastRouting_outboundForwarding_mlaToScope4IsNotForwarded() throws Exception {
|
||||
assumeTrue(isMulticastRoutingSupported());
|
||||
/*
|
||||
* <pre>
|
||||
* Topology:
|
||||
|
|
@ -546,9 +541,9 @@ public class BorderRoutingTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@RequiresIpv6MulticastRouting
|
||||
public void multicastRouting_infraNetworkSwitch_ftdRepliesToSubscribedAddress()
|
||||
throws Exception {
|
||||
assumeTrue(isMulticastRoutingSupported());
|
||||
/*
|
||||
* <pre>
|
||||
* Topology:
|
||||
|
|
@ -575,8 +570,8 @@ public class BorderRoutingTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@RequiresIpv6MulticastRouting
|
||||
public void multicastRouting_infraNetworkSwitch_outboundPacketIsForwarded() throws Exception {
|
||||
assumeTrue(isMulticastRoutingSupported());
|
||||
/*
|
||||
* <pre>
|
||||
* Topology:
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ import static android.net.thread.utils.IntegrationTestUtils.RESTART_JOIN_TIMEOUT
|
|||
import static android.net.thread.utils.IntegrationTestUtils.SERVICE_DISCOVERY_TIMEOUT;
|
||||
import static android.net.thread.utils.IntegrationTestUtils.discoverForServiceLost;
|
||||
import static android.net.thread.utils.IntegrationTestUtils.discoverService;
|
||||
import static android.net.thread.utils.IntegrationTestUtils.isSimulatedThreadRadioSupported;
|
||||
import static android.net.thread.utils.IntegrationTestUtils.resolveService;
|
||||
import static android.net.thread.utils.IntegrationTestUtils.resolveServiceUntil;
|
||||
import static android.net.thread.utils.IntegrationTestUtils.waitFor;
|
||||
|
|
@ -36,8 +35,6 @@ import static com.google.common.truth.Truth.assertThat;
|
|||
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
|
||||
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assume.assumeNotNull;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
|
@ -47,6 +44,9 @@ import android.net.nsd.NsdManager;
|
|||
import android.net.nsd.NsdServiceInfo;
|
||||
import android.net.thread.utils.FullThreadDevice;
|
||||
import android.net.thread.utils.TapTestNetworkTracker;
|
||||
import android.net.thread.utils.ThreadFeatureCheckerRule;
|
||||
import android.net.thread.utils.ThreadFeatureCheckerRule.RequiresSimulationThreadDevice;
|
||||
import android.net.thread.utils.ThreadFeatureCheckerRule.RequiresThreadFeature;
|
||||
import android.os.HandlerThread;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
|
@ -58,6 +58,7 @@ import com.google.common.truth.Correspondence;
|
|||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
|
|
@ -73,18 +74,13 @@ import java.util.concurrent.TimeoutException;
|
|||
|
||||
/** Integration test cases for Service Discovery feature. */
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@RequiresThreadFeature
|
||||
@RequiresSimulationThreadDevice
|
||||
@LargeTest
|
||||
@Ignore("TODO: b/328527773 - enable the test when it's stable")
|
||||
public class ServiceDiscoveryTest {
|
||||
private static final String TAG = ServiceDiscoveryTest.class.getSimpleName();
|
||||
private static final int NUM_FTD = 3;
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
|
||||
private HandlerThread mHandlerThread;
|
||||
private ThreadNetworkController mController;
|
||||
private NsdManager mNsdManager;
|
||||
private TapTestNetworkTracker mTestNetworkTracker;
|
||||
private List<FullThreadDevice> mFtds;
|
||||
|
||||
// A valid Thread Active Operational Dataset generated from OpenThread CLI "dataset init new".
|
||||
private static final byte[] DEFAULT_DATASET_TLVS =
|
||||
|
|
@ -100,6 +96,16 @@ public class ServiceDiscoveryTest {
|
|||
private static final Correspondence<byte[], byte[]> BYTE_ARRAY_EQUALITY =
|
||||
Correspondence.from(Arrays::equals, "is equivalent to");
|
||||
|
||||
@Rule public final ThreadFeatureCheckerRule mThreadRule = new ThreadFeatureCheckerRule();
|
||||
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
|
||||
private HandlerThread mHandlerThread;
|
||||
private ThreadNetworkController mController;
|
||||
private NsdManager mNsdManager;
|
||||
private TapTestNetworkTracker mTestNetworkTracker;
|
||||
private List<FullThreadDevice> mFtds;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
final ThreadNetworkManager manager = mContext.getSystemService(ThreadNetworkManager.class);
|
||||
|
|
@ -107,12 +113,6 @@ public class ServiceDiscoveryTest {
|
|||
mController = manager.getAllThreadNetworkControllers().get(0);
|
||||
}
|
||||
|
||||
// Run the tests on only devices where the Thread feature is available.
|
||||
assumeNotNull(mController);
|
||||
|
||||
// Run the tests only when the device uses simulated Thread radio.
|
||||
assumeTrue(isSimulatedThreadRadioSupported());
|
||||
|
||||
// BR forms a network.
|
||||
CompletableFuture<Void> joinFuture = new CompletableFuture<>();
|
||||
runAsShell(
|
||||
|
|
@ -150,12 +150,6 @@ public class ServiceDiscoveryTest {
|
|||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (mController == null) {
|
||||
return;
|
||||
}
|
||||
if (!isSimulatedThreadRadioSupported()) {
|
||||
return;
|
||||
}
|
||||
for (FullThreadDevice ftd : mFtds) {
|
||||
// Clear registered SRP hosts and services
|
||||
if (ftd.isSrpHostRegistered()) {
|
||||
|
|
|
|||
|
|
@ -33,14 +33,14 @@ import static com.google.common.io.BaseEncoding.base16;
|
|||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
|
||||
|
||||
import static org.junit.Assume.assumeNotNull;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.net.thread.ThreadNetworkController.StateCallback;
|
||||
import android.net.thread.utils.OtDaemonController;
|
||||
import android.net.thread.utils.ThreadFeatureCheckerRule;
|
||||
import android.net.thread.utils.ThreadFeatureCheckerRule.RequiresThreadFeature;
|
||||
import android.os.SystemClock;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
|
@ -49,6 +49,7 @@ import androidx.test.runner.AndroidJUnit4;
|
|||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
|
|
@ -58,12 +59,9 @@ import java.util.concurrent.CompletableFuture;
|
|||
|
||||
/** Tests for E2E Android Thread integration with ot-daemon, ConnectivityService, etc.. */
|
||||
@LargeTest
|
||||
@RequiresThreadFeature
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ThreadIntegrationTest {
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private ThreadNetworkController mController;
|
||||
private OtDaemonController mOtCtl;
|
||||
|
||||
// A valid Thread Active Operational Dataset generated from OpenThread CLI "dataset init new".
|
||||
private static final byte[] DEFAULT_DATASET_TLVS =
|
||||
base16().decode(
|
||||
|
|
@ -75,16 +73,18 @@ public class ThreadIntegrationTest {
|
|||
private static final ActiveOperationalDataset DEFAULT_DATASET =
|
||||
ActiveOperationalDataset.fromThreadTlvs(DEFAULT_DATASET_TLVS);
|
||||
|
||||
@Rule public final ThreadFeatureCheckerRule mThreadRule = new ThreadFeatureCheckerRule();
|
||||
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private ThreadNetworkController mController;
|
||||
private OtDaemonController mOtCtl;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
final ThreadNetworkManager manager = mContext.getSystemService(ThreadNetworkManager.class);
|
||||
if (manager != null) {
|
||||
mController = manager.getAllThreadNetworkControllers().get(0);
|
||||
}
|
||||
|
||||
// Run the tests on only devices where the Thread feature is available
|
||||
assumeNotNull(mController);
|
||||
|
||||
mController =
|
||||
mContext.getSystemService(ThreadNetworkManager.class)
|
||||
.getAllThreadNetworkControllers()
|
||||
.get(0);
|
||||
mOtCtl = new OtDaemonController();
|
||||
leaveAndWait(mController);
|
||||
|
||||
|
|
@ -94,10 +94,6 @@ public class ThreadIntegrationTest {
|
|||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (mController == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
setTestUpStreamNetworkAndWait(mController, null);
|
||||
leaveAndWait(mController);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import static android.system.OsConstants.IPPROTO_ICMPV6;
|
|||
import static com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow;
|
||||
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_PIO;
|
||||
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT;
|
||||
import static com.android.testutils.DeviceInfoUtils.isKernelVersionAtLeast;
|
||||
|
||||
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
|
||||
|
||||
|
|
@ -32,8 +31,6 @@ import android.net.nsd.NsdServiceInfo;
|
|||
import android.net.thread.ThreadNetworkController;
|
||||
import android.os.Handler;
|
||||
import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.VintfRuntimeInfo;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
|
|
@ -65,8 +62,6 @@ import java.util.concurrent.TimeUnit;
|
|||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** Static utility methods relating to Thread integration tests. */
|
||||
public final class IntegrationTestUtils {
|
||||
|
|
@ -79,35 +74,8 @@ public final class IntegrationTestUtils {
|
|||
public static final Duration CALLBACK_TIMEOUT = Duration.ofSeconds(1);
|
||||
public static final Duration SERVICE_DISCOVERY_TIMEOUT = Duration.ofSeconds(20);
|
||||
|
||||
private static final String KERNEL_VERSION_MULTICAST_ROUTING_SUPPORTED = "5.15.0";
|
||||
private static final int KERNEL_ANDROID_VERSION_MULTICAST_ROUTING_SUPPORTED = 14;
|
||||
|
||||
private IntegrationTestUtils() {}
|
||||
|
||||
/** Returns whether the device supports simulated Thread radio. */
|
||||
public static boolean isSimulatedThreadRadioSupported() {
|
||||
// The integration test uses SIMULATION Thread radio so that it only supports CuttleFish.
|
||||
return SystemProperties.get("ro.product.model").startsWith("Cuttlefish");
|
||||
}
|
||||
|
||||
public static boolean isMulticastRoutingSupported() {
|
||||
return isKernelVersionAtLeast(KERNEL_VERSION_MULTICAST_ROUTING_SUPPORTED)
|
||||
&& isKernelAndroidVersionAtLeast(
|
||||
KERNEL_ANDROID_VERSION_MULTICAST_ROUTING_SUPPORTED);
|
||||
}
|
||||
|
||||
private static boolean isKernelAndroidVersionAtLeast(int n) {
|
||||
final String osRelease = VintfRuntimeInfo.getOsRelease();
|
||||
final Pattern pattern = Pattern.compile("android(\\d+)");
|
||||
Matcher matcher = pattern.matcher(osRelease);
|
||||
|
||||
if (matcher.find()) {
|
||||
int version = Integer.parseInt(matcher.group(1));
|
||||
return (version >= n);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for the given {@link Supplier} to be true until given timeout.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* 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 com.android.testutils.DeviceInfoUtils.isKernelVersionAtLeast;
|
||||
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.thread.ThreadNetworkManager;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.VintfRuntimeInfo;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runners.model.Statement;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A rule used to skip Thread tests when the device doesn't support a specific feature indicated by
|
||||
* {@code ThreadFeatureCheckerRule.Requires*}.
|
||||
*/
|
||||
public final class ThreadFeatureCheckerRule implements TestRule {
|
||||
private static final String KERNEL_VERSION_MULTICAST_ROUTING_SUPPORTED = "5.15.0";
|
||||
private static final int KERNEL_ANDROID_VERSION_MULTICAST_ROUTING_SUPPORTED = 14;
|
||||
|
||||
/**
|
||||
* Annotates a test class or method requires the Thread feature to run.
|
||||
*
|
||||
* <p>In Absence of the Thread feature, the test class or method will be ignored.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
public @interface RequiresThreadFeature {}
|
||||
|
||||
/**
|
||||
* Annotates a test class or method requires the kernel IPv6 multicast routing feature to run.
|
||||
*
|
||||
* <p>In Absence of the multicast routing feature, the test class or method will be ignored.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
public @interface RequiresIpv6MulticastRouting {}
|
||||
|
||||
/**
|
||||
* Annotates a test class or method requires the simulation Thread device (i.e. ot-cli-ftd) to
|
||||
* run.
|
||||
*
|
||||
* <p>In Absence of the simulation device, the test class or method will be ignored.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
public @interface RequiresSimulationThreadDevice {}
|
||||
|
||||
@Override
|
||||
public Statement apply(final Statement base, Description description) {
|
||||
return new Statement() {
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
if (hasAnnotation(RequiresThreadFeature.class, description)) {
|
||||
assumeTrue(
|
||||
"Skipping test because the Thread feature is unavailable",
|
||||
hasThreadFeature());
|
||||
}
|
||||
|
||||
if (hasAnnotation(RequiresIpv6MulticastRouting.class, description)) {
|
||||
assumeTrue(
|
||||
"Skipping test because kernel IPv6 multicast routing is unavailable",
|
||||
hasIpv6MulticastRouting());
|
||||
}
|
||||
|
||||
if (hasAnnotation(RequiresSimulationThreadDevice.class, description)) {
|
||||
assumeTrue(
|
||||
"Skipping test because simulation Thread device is unavailable",
|
||||
hasSimulationThreadDevice());
|
||||
}
|
||||
|
||||
base.evaluate();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/** Returns {@code true} if a test method or the test class is annotated with annotation. */
|
||||
private <T extends Annotation> boolean hasAnnotation(
|
||||
Class<T> annotationClass, Description description) {
|
||||
// Method annotation
|
||||
boolean hasAnnotation = description.getAnnotation(annotationClass) != null;
|
||||
|
||||
// Class annotation
|
||||
Class<?> clazz = description.getTestClass();
|
||||
while (!hasAnnotation && clazz != Object.class) {
|
||||
hasAnnotation |= clazz.getAnnotation(annotationClass) != null;
|
||||
clazz = clazz.getSuperclass();
|
||||
}
|
||||
|
||||
return hasAnnotation;
|
||||
}
|
||||
|
||||
/** Returns {@code true} if this device has the Thread feature supported. */
|
||||
private static boolean hasThreadFeature() {
|
||||
final Context context = ApplicationProvider.getApplicationContext();
|
||||
return context.getSystemService(ThreadNetworkManager.class) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this device has the kernel IPv6 multicast routing feature enabled.
|
||||
*/
|
||||
private static boolean hasIpv6MulticastRouting() {
|
||||
// The kernel IPv6 multicast routing (i.e. IPV6_MROUTE) is enabled on kernel version
|
||||
// android14-5.15.0 and later
|
||||
return isKernelVersionAtLeast(KERNEL_VERSION_MULTICAST_ROUTING_SUPPORTED)
|
||||
&& isKernelAndroidVersionAtLeast(
|
||||
KERNEL_ANDROID_VERSION_MULTICAST_ROUTING_SUPPORTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the android version in the kernel version of this device is equal to
|
||||
* or larger than the given {@code minVersion}.
|
||||
*/
|
||||
private static boolean isKernelAndroidVersionAtLeast(int minVersion) {
|
||||
final String osRelease = VintfRuntimeInfo.getOsRelease();
|
||||
final Pattern pattern = Pattern.compile("android(\\d+)");
|
||||
Matcher matcher = pattern.matcher(osRelease);
|
||||
|
||||
if (matcher.find()) {
|
||||
int version = Integer.parseInt(matcher.group(1));
|
||||
return (version >= minVersion);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Returns {@code true} if the simulation Thread device is supported. */
|
||||
private static boolean hasSimulationThreadDevice() {
|
||||
// Simulation radio is supported on only Cuttlefish
|
||||
return SystemProperties.get("ro.product.model").startsWith("Cuttlefish");
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue