Update NsdManagerTest for newer backend usage
The new backend requires LinkProperties that reflect the actual
addresses on the interface. Make sure the test sets the addresses on the
test NetworkAgents that are used.
Also the new backend properly differentiates between boolean attributes
that have no value, and attributes with an empty value. As the new
backend is currently being enabled on U+, verify the new behavior in
that case.
Bug: 272197605
Test: atest NsdManagerTest
Change-Id: I8540af27bdd84aff84df9faba7327a8e9af802ef
diff --git a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
index de5e46f..a0b754b 100644
--- a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
+++ b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
@@ -19,6 +19,8 @@
import android.app.compat.CompatChanges
import android.net.ConnectivityManager
import android.net.ConnectivityManager.NetworkCallback
+import android.net.InetAddresses.parseNumericAddress
+import android.net.LinkAddress
import android.net.LinkProperties
import android.net.LocalSocket
import android.net.LocalSocketAddress
@@ -27,6 +29,7 @@
import android.net.NetworkCapabilities
import android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED
import android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED
+import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
import android.net.NetworkCapabilities.TRANSPORT_TEST
import android.net.NetworkRequest
import android.net.TestNetworkInterface
@@ -62,18 +65,28 @@
import android.os.HandlerThread
import android.os.Process.myTid
import android.platform.test.annotations.AppModeFull
+import android.system.ErrnoException
+import android.system.Os
+import android.system.OsConstants.AF_INET6
+import android.system.OsConstants.ENETUNREACH
+import android.system.OsConstants.IPPROTO_UDP
+import android.system.OsConstants.SOCK_DGRAM
import android.util.Log
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.runner.AndroidJUnit4
import com.android.compatibility.common.util.PollingCheck
import com.android.compatibility.common.util.PropertyUtil
+import com.android.modules.utils.build.SdkLevel.isAtLeastU
import com.android.net.module.util.ArrayTrackRecord
import com.android.net.module.util.TrackRecord
import com.android.networkstack.apishim.NsdShimImpl
import com.android.networkstack.apishim.common.NsdShim
import com.android.testutils.ConnectivityModuleTest
import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.RecorderCallback.CallbackEntry.CapabilitiesChanged
+import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChanged
import com.android.testutils.TestableNetworkAgent
+import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnNetworkCreated
import com.android.testutils.TestableNetworkCallback
import com.android.testutils.filters.CtsNetTestCasesMaxTargetSdk30
import com.android.testutils.filters.CtsNetTestCasesMaxTargetSdk33
@@ -82,6 +95,7 @@
import com.android.testutils.waitForIdle
import java.io.File
import java.io.IOException
+import java.net.NetworkInterface
import java.net.ServerSocket
import java.nio.charset.StandardCharsets
import java.util.Random
@@ -353,24 +367,56 @@
.build(), cb)
val agent = registerTestNetworkAgent(iface.interfaceName)
val network = agent.network ?: fail("Registered agent should have a network")
+
+ cb.eventuallyExpect<LinkPropertiesChanged>(TIMEOUT_MS) {
+ it.lp.linkAddresses.isNotEmpty()
+ }
+
// The network has no INTERNET capability, so will be marked validated immediately
- cb.expectAvailableThenValidatedCallbacks(network, TIMEOUT_MS)
+ // It does not matter if validated capabilities come before/after the link addresses change
+ cb.eventuallyExpect<CapabilitiesChanged>(TIMEOUT_MS, from = 0) {
+ it.caps.hasCapability(NET_CAPABILITY_VALIDATED)
+ }
return TestTapNetwork(iface, cb, agent, network)
}
private fun registerTestNetworkAgent(ifaceName: String): TestableNetworkAgent {
+ val lp = LinkProperties().apply {
+ interfaceName = ifaceName
+ }
+
val agent = TestableNetworkAgent(context, handlerThread.looper,
NetworkCapabilities().apply {
removeCapability(NET_CAPABILITY_TRUSTED)
addTransportType(TRANSPORT_TEST)
setNetworkSpecifier(TestNetworkSpecifier(ifaceName))
- },
- LinkProperties().apply {
- interfaceName = ifaceName
- },
- NetworkAgentConfig.Builder().build())
- agent.register()
+ }, lp, NetworkAgentConfig.Builder().build())
+ val network = agent.register()
agent.markConnected()
+ agent.expectCallback<OnNetworkCreated>()
+
+ // Wait until the link-local address can be used. Address flags are not available without
+ // elevated permissions, so check that bindSocket works.
+ PollingCheck.check("No usable v6 address on interface after $TIMEOUT_MS ms", TIMEOUT_MS) {
+ val sock = Os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)
+ tryTest {
+ network.bindSocket(sock)
+ Os.connect(sock, parseNumericAddress("ff02::fb%$ifaceName"), 12345)
+ true
+ }.catch<ErrnoException> {
+ if (it.errno != ENETUNREACH) {
+ throw it
+ }
+ false
+ } cleanup {
+ Os.close(sock)
+ }
+ }
+
+ lp.setLinkAddresses(NetworkInterface.getByName(ifaceName).interfaceAddresses.map {
+ LinkAddress(it.address, it.networkPrefixLength.toInt())
+ })
+ agent.sendLinkProperties(lp)
return agent
}
@@ -378,8 +424,9 @@
fun tearDown() {
if (TestUtils.shouldTestTApis()) {
runAsShell(MANAGE_TEST_NETWORKS) {
- testNetwork1.close(cm)
- testNetwork2.close(cm)
+ // Avoid throwing here if initializing failed in setUp
+ if (this::testNetwork1.isInitialized) testNetwork1.close(cm)
+ if (this::testNetwork2.isInitialized) testNetwork2.close(cm)
}
}
handlerThread.waitForIdle(TIMEOUT_MS)
@@ -465,7 +512,12 @@
assertTrue(resolvedService.attributes.containsKey("nullBinaryDataAttr"))
assertNull(resolvedService.attributes["nullBinaryDataAttr"])
assertTrue(resolvedService.attributes.containsKey("emptyBinaryDataAttr"))
- assertNull(resolvedService.attributes["emptyBinaryDataAttr"])
+ // TODO: change the check to target SDK U when this is what the code implements
+ if (isAtLeastU()) {
+ assertArrayEquals(byteArrayOf(), resolvedService.attributes["emptyBinaryDataAttr"])
+ } else {
+ assertNull(resolvedService.attributes["emptyBinaryDataAttr"])
+ }
assertEquals(localPort, resolvedService.port)
// Unregister the service