Merge "Use case-insensitive matching in discovery/advertising"
This commit is contained in:
@@ -51,6 +51,7 @@ private const val SERVICE_ID_1 = 1
|
||||
private const val SERVICE_ID_2 = 2
|
||||
private const val LONG_SERVICE_ID_1 = 3
|
||||
private const val LONG_SERVICE_ID_2 = 4
|
||||
private const val CASE_INSENSITIVE_TEST_SERVICE_ID = 5
|
||||
private const val TIMEOUT_MS = 10_000L
|
||||
private val TEST_ADDR = parseNumericAddress("2001:db8::123")
|
||||
private val TEST_LINKADDR = LinkAddress(TEST_ADDR, 64 /* prefixLength */)
|
||||
@@ -78,6 +79,13 @@ private val ALL_NETWORKS_SERVICE = NsdServiceInfo("TestServiceName", "_advertise
|
||||
network = null
|
||||
}
|
||||
|
||||
private val ALL_NETWORKS_SERVICE_2 =
|
||||
NsdServiceInfo("TESTSERVICENAME", "_ADVERTISERTEST._tcp").apply {
|
||||
port = 12345
|
||||
hostAddresses = listOf(TEST_ADDR)
|
||||
network = null
|
||||
}
|
||||
|
||||
private val LONG_ALL_NETWORKS_SERVICE =
|
||||
NsdServiceInfo("a".repeat(48) + "TestServiceName", "_longadvertisertest._tcp").apply {
|
||||
port = 12345
|
||||
@@ -228,6 +236,9 @@ class MdnsAdvertiserTest {
|
||||
postSync { advertiser.addService(LONG_SERVICE_ID_2, LONG_ALL_NETWORKS_SERVICE,
|
||||
null /* subtype */) }
|
||||
|
||||
postSync { advertiser.addService(CASE_INSENSITIVE_TEST_SERVICE_ID, ALL_NETWORKS_SERVICE_2,
|
||||
null /* subtype */) }
|
||||
|
||||
// Callbacks for matching network and all networks both get the socket
|
||||
postSync {
|
||||
oneNetSocketCb.onSocketCreated(TEST_NETWORK_1, mockSocket1, listOf(TEST_LINKADDR))
|
||||
@@ -249,6 +260,14 @@ class MdnsAdvertiserTest {
|
||||
network = LONG_ALL_NETWORKS_SERVICE.network
|
||||
}
|
||||
|
||||
val expectedCaseInsensitiveRenamed = NsdServiceInfo(
|
||||
"${ALL_NETWORKS_SERVICE_2.serviceName} (3)", ALL_NETWORKS_SERVICE_2.serviceType
|
||||
).apply {
|
||||
port = ALL_NETWORKS_SERVICE_2.port
|
||||
hostAddresses = ALL_NETWORKS_SERVICE_2.hostAddresses
|
||||
network = ALL_NETWORKS_SERVICE_2.network
|
||||
}
|
||||
|
||||
val intAdvCbCaptor = ArgumentCaptor.forClass(MdnsInterfaceAdvertiser.Callback::class.java)
|
||||
verify(mockDeps).makeAdvertiser(eq(mockSocket1), eq(listOf(TEST_LINKADDR)),
|
||||
eq(thread.looper), any(), intAdvCbCaptor.capture(), eq(TEST_HOSTNAME), any()
|
||||
@@ -261,6 +280,8 @@ class MdnsAdvertiserTest {
|
||||
argThat { it.matches(LONG_SERVICE_1) }, eq(null))
|
||||
verify(mockInterfaceAdvertiser1).addService(eq(LONG_SERVICE_ID_2),
|
||||
argThat { it.matches(expectedLongRenamed) }, eq(null))
|
||||
verify(mockInterfaceAdvertiser1).addService(eq(CASE_INSENSITIVE_TEST_SERVICE_ID),
|
||||
argThat { it.matches(expectedCaseInsensitiveRenamed) }, eq(null))
|
||||
|
||||
doReturn(false).`when`(mockInterfaceAdvertiser1).isProbing(SERVICE_ID_1)
|
||||
postSync { intAdvCbCaptor.value.onRegisterServiceSucceeded(
|
||||
|
||||
@@ -31,7 +31,7 @@ class MdnsPacketWriterTest {
|
||||
@Test
|
||||
fun testNameCompression() {
|
||||
val writer = MdnsPacketWriter(ByteArray(1000))
|
||||
writer.writeLabels(arrayOf("my", "first", "name"))
|
||||
writer.writeLabels(arrayOf("my", "FIRST", "name"))
|
||||
writer.writeLabels(arrayOf("my", "second", "name"))
|
||||
writer.writeLabels(arrayOf("other", "first", "name"))
|
||||
writer.writeLabels(arrayOf("my", "second", "name"))
|
||||
@@ -41,7 +41,7 @@ class MdnsPacketWriterTest {
|
||||
InetSocketAddress(InetAddresses.parseNumericAddress("2001:db8::123"), 123))
|
||||
|
||||
// Each label takes length + 1. So "first.name" offset = 3, "name" offset = 9
|
||||
val expected = "my".label() + "first".label() + "name".label() + 0x00.toByte() +
|
||||
val expected = "my".label() + "FIRST".label() + "name".label() + 0x00.toByte() +
|
||||
// "my.second.name" offset = 15
|
||||
"my".label() + "second".label() + byteArrayOf(0xC0.toByte(), 9) +
|
||||
"other".label() + byteArrayOf(0xC0.toByte(), 3) +
|
||||
|
||||
@@ -48,6 +48,7 @@ private const val SHORT_TIMEOUT_MS = 200L
|
||||
|
||||
private val TEST_SERVICE_NAME_1 = arrayOf("testservice", "_nmt", "_tcp", "local")
|
||||
private val TEST_SERVICE_NAME_2 = arrayOf("testservice2", "_nmt", "_tcp", "local")
|
||||
private val TEST_SERVICE_NAME_3 = arrayOf("Testservice", "_nmt", "_tcp", "local")
|
||||
|
||||
@RunWith(DevSdkIgnoreRunner::class)
|
||||
@IgnoreUpTo(Build.VERSION_CODES.S_V2)
|
||||
@@ -128,6 +129,15 @@ class MdnsProberTest {
|
||||
assertProbesSent(probeInfo, expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCreateProberCaseInsensitive() {
|
||||
val probeInfo = TestProbeInfo(
|
||||
listOf(makeServiceRecord(TEST_SERVICE_NAME_1, 37890),
|
||||
makeServiceRecord(TEST_SERVICE_NAME_2, 37890),
|
||||
makeServiceRecord(TEST_SERVICE_NAME_3, 37890)))
|
||||
assertEquals(2, probeInfo.getPacket(0).questions.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testProbeMultipleRecords() {
|
||||
val replySender = MdnsReplySender("testiface", thread.looper, socket, buffer)
|
||||
|
||||
@@ -43,6 +43,7 @@ import org.junit.runner.RunWith
|
||||
|
||||
private const val TEST_SERVICE_ID_1 = 42
|
||||
private const val TEST_SERVICE_ID_2 = 43
|
||||
private const val TEST_SERVICE_ID_3 = 44
|
||||
private const val TEST_PORT = 12345
|
||||
private const val TEST_SUBTYPE = "_subtype"
|
||||
private val TEST_HOSTNAME = arrayOf("Android_000102030405060708090A0B0C0D0E0F", "local")
|
||||
@@ -63,6 +64,12 @@ private val TEST_SERVICE_2 = NsdServiceInfo().apply {
|
||||
port = TEST_PORT
|
||||
}
|
||||
|
||||
private val TEST_SERVICE_3 = NsdServiceInfo().apply {
|
||||
serviceType = "_TESTSERVICE._tcp"
|
||||
serviceName = "MyTESTSERVICE"
|
||||
port = TEST_PORT
|
||||
}
|
||||
|
||||
@RunWith(DevSdkIgnoreRunner::class)
|
||||
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
|
||||
class MdnsRecordRepositoryTest {
|
||||
@@ -124,6 +131,9 @@ class MdnsRecordRepositoryTest {
|
||||
assertFailsWith(NameConflictException::class) {
|
||||
repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_1, null /* subtype */)
|
||||
}
|
||||
assertFailsWith(NameConflictException::class) {
|
||||
repository.addService(TEST_SERVICE_ID_3, TEST_SERVICE_3, null /* subtype */)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -364,6 +374,27 @@ class MdnsRecordRepositoryTest {
|
||||
assertContentEquals(expectedV4, getReverseDnsAddress(parseNumericAddress("192.0.2.123")))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetReplyCaseInsensitive() {
|
||||
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME)
|
||||
repository.initWithService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
|
||||
val questionsCaseInSensitive =
|
||||
listOf(MdnsPointerRecord(arrayOf("_TESTSERVICE", "_TCP", "local"),
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
// TTL and data is empty for a question
|
||||
0L /* ttlMillis */,
|
||||
null /* pointer */))
|
||||
val queryCaseInsensitive = MdnsPacket(0 /* flags */, questionsCaseInSensitive,
|
||||
listOf() /* answers */, listOf() /* authorityRecords */,
|
||||
listOf() /* additionalRecords */)
|
||||
val src = InetSocketAddress(parseNumericAddress("192.0.2.123"), 5353)
|
||||
val replyCaseInsensitive = repository.getReply(queryCaseInsensitive, src)
|
||||
assertNotNull(replyCaseInsensitive)
|
||||
assertEquals(1, replyCaseInsensitive.answers.size)
|
||||
assertEquals(7, replyCaseInsensitive.additionalAnswers.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetReply() {
|
||||
doGetReplyTest(subtype = null)
|
||||
@@ -489,6 +520,34 @@ class MdnsRecordRepositoryTest {
|
||||
repository.getConflictingServices(packet))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetConflictingServicesCaseInsensitive() {
|
||||
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME)
|
||||
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1, null /* subtype */)
|
||||
repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_2, null /* subtype */)
|
||||
|
||||
val packet = MdnsPacket(
|
||||
0 /* flags */,
|
||||
emptyList() /* questions */,
|
||||
listOf(
|
||||
MdnsServiceRecord(
|
||||
arrayOf("MYTESTSERVICE", "_TESTSERVICE", "_tcp", "local"),
|
||||
0L /* receiptTimeMillis */, true /* cacheFlush */, 0L /* ttlMillis */,
|
||||
0 /* servicePriority */, 0 /* serviceWeight */,
|
||||
TEST_SERVICE_1.port + 1,
|
||||
TEST_HOSTNAME),
|
||||
MdnsTextRecord(
|
||||
arrayOf("MYOTHERTESTSERVICE", "_TESTSERVICE", "_tcp", "local"),
|
||||
0L /* receiptTimeMillis */, true /* cacheFlush */, 0L /* ttlMillis */,
|
||||
listOf(TextEntry.fromString("somedifferent=entry"))),
|
||||
) /* answers */,
|
||||
emptyList() /* authorityRecords */,
|
||||
emptyList() /* additionalRecords */)
|
||||
|
||||
assertEquals(setOf(TEST_SERVICE_ID_1, TEST_SERVICE_ID_2),
|
||||
repository.getConflictingServices(packet))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetConflictingServices_IdenticalService() {
|
||||
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME)
|
||||
@@ -505,7 +564,7 @@ class MdnsRecordRepositoryTest {
|
||||
0L /* receiptTimeMillis */, true /* cacheFlush */,
|
||||
otherTtlMillis, 0 /* servicePriority */, 0 /* serviceWeight */,
|
||||
TEST_SERVICE_1.port,
|
||||
TEST_HOSTNAME),
|
||||
arrayOf("ANDROID_000102030405060708090A0B0C0D0E0F", "local")),
|
||||
MdnsTextRecord(
|
||||
arrayOf("MyOtherTestService", "_testservice", "_tcp", "local"),
|
||||
0L /* receiptTimeMillis */, true /* cacheFlush */,
|
||||
@@ -517,6 +576,35 @@ class MdnsRecordRepositoryTest {
|
||||
// Above records are identical to the actual registrations: no conflict
|
||||
assertEquals(emptySet(), repository.getConflictingServices(packet))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetConflictingServicesCaseInsensitive_IdenticalService() {
|
||||
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME)
|
||||
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1, null /* subtype */)
|
||||
repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_2, null /* subtype */)
|
||||
|
||||
val otherTtlMillis = 1234L
|
||||
val packet = MdnsPacket(
|
||||
0 /* flags */,
|
||||
emptyList() /* questions */,
|
||||
listOf(
|
||||
MdnsServiceRecord(
|
||||
arrayOf("MYTESTSERVICE", "_TESTSERVICE", "_tcp", "local"),
|
||||
0L /* receiptTimeMillis */, true /* cacheFlush */,
|
||||
otherTtlMillis, 0 /* servicePriority */, 0 /* serviceWeight */,
|
||||
TEST_SERVICE_1.port,
|
||||
TEST_HOSTNAME),
|
||||
MdnsTextRecord(
|
||||
arrayOf("MyOtherTestService", "_TESTSERVICE", "_tcp", "local"),
|
||||
0L /* receiptTimeMillis */, true /* cacheFlush */,
|
||||
otherTtlMillis, emptyList()),
|
||||
) /* answers */,
|
||||
emptyList() /* authorityRecords */,
|
||||
emptyList() /* additionalRecords */)
|
||||
|
||||
// Above records are identical to the actual registrations: no conflict
|
||||
assertEquals(emptySet(), repository.getConflictingServices(packet))
|
||||
}
|
||||
}
|
||||
|
||||
private fun MdnsRecordRepository.initWithService(
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* 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 com.android.server.connectivity.mdns
|
||||
|
||||
import android.os.Build
|
||||
import com.android.testutils.DevSdkIgnoreRule
|
||||
import com.android.testutils.DevSdkIgnoreRunner
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(DevSdkIgnoreRunner::class)
|
||||
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
|
||||
class MdnsRecordTest {
|
||||
|
||||
@Test
|
||||
fun testPointerRecordHasSubType() {
|
||||
val ptrRecord1 = MdnsPointerRecord(
|
||||
arrayOf("_testtype", "_sub", "_tcp", "local"),
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
4500000 /* ttlMillis */,
|
||||
arrayOf("testservice", "_testtype", "_tcp", "local")
|
||||
)
|
||||
val ptrRecord2 = MdnsPointerRecord(
|
||||
arrayOf("_testtype", "_SUB", "_tcp", "local"),
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
4500000 /* ttlMillis */,
|
||||
arrayOf("testservice", "_testtype", "_tcp", "local")
|
||||
)
|
||||
assertTrue(ptrRecord1.hasSubtype())
|
||||
assertTrue(ptrRecord2.hasSubtype())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testEqualsCaseInsensitive() {
|
||||
val ptrRecord1 = MdnsPointerRecord(
|
||||
arrayOf("_testtype", "_tcp", "local"),
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
4500000 /* ttlMillis */,
|
||||
arrayOf("testservice", "_testtype", "_tcp", "local")
|
||||
)
|
||||
val ptrRecord2 = MdnsPointerRecord(
|
||||
arrayOf("_testType", "_tcp", "local"),
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
4500000 /* ttlMillis */,
|
||||
arrayOf("testsErvice", "_testtype", "_Tcp", "local")
|
||||
)
|
||||
assertEquals(ptrRecord1, ptrRecord2)
|
||||
assertEquals(ptrRecord1.hashCode(), ptrRecord2.hashCode())
|
||||
|
||||
val srvRecord1 = MdnsServiceRecord(
|
||||
arrayOf("testservice", "_testtype", "_tcp", "local"),
|
||||
123 /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
2000 /* ttlMillis */,
|
||||
0 /* servicePriority */,
|
||||
0 /* serviceWeight */,
|
||||
80 /* port */,
|
||||
arrayOf("hostname")
|
||||
)
|
||||
val srvRecord2 = MdnsServiceRecord(
|
||||
arrayOf("Testservice", "_testtype", "_tcp", "local"),
|
||||
123 /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
2000 /* ttlMillis */,
|
||||
0 /* servicePriority */,
|
||||
0 /* serviceWeight */,
|
||||
80 /* port */,
|
||||
arrayOf("Hostname")
|
||||
)
|
||||
assertEquals(srvRecord1, srvRecord2)
|
||||
assertEquals(srvRecord1.hashCode(), srvRecord2.hashCode())
|
||||
|
||||
val nsecRecord1 = MdnsNsecRecord(
|
||||
arrayOf("hostname"),
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
2000L, /* ttlMillis */
|
||||
arrayOf("hostname"),
|
||||
intArrayOf(1, 2, 3) /* types */
|
||||
)
|
||||
val nsecRecord2 = MdnsNsecRecord(
|
||||
arrayOf("HOSTNAME"),
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
2000L, /* ttlMillis */
|
||||
arrayOf("HOSTNAME"),
|
||||
intArrayOf(1, 2, 3) /* types */
|
||||
)
|
||||
assertEquals(nsecRecord1, nsecRecord2)
|
||||
assertEquals(nsecRecord1.hashCode(), nsecRecord2.hashCode())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testLabelsAreSuffix() {
|
||||
val labels1 = arrayOf("a", "b", "c")
|
||||
val labels2 = arrayOf("B", "C")
|
||||
val labels3 = arrayOf("b", "c")
|
||||
val labels4 = arrayOf("b", "d")
|
||||
assertTrue(MdnsRecord.labelsAreSuffix(labels2, labels1))
|
||||
assertTrue(MdnsRecord.labelsAreSuffix(labels3, labels1))
|
||||
assertFalse(MdnsRecord.labelsAreSuffix(labels4, labels1))
|
||||
}
|
||||
}
|
||||
@@ -269,14 +269,9 @@ public class MdnsResponseDecoderTests {
|
||||
assertEquals("st=0", textStrings.get(6));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecodeIPv6AnswerPacket() throws IOException {
|
||||
MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, CAST_SERVICE_TYPE);
|
||||
assertNotNull(data6);
|
||||
|
||||
responses = decode(decoder, data6);
|
||||
assertEquals(1, responses.size());
|
||||
MdnsResponse response = responses.valueAt(0);
|
||||
private void verifyResponse(ArraySet<MdnsResponse> responseArraySet) {
|
||||
assertEquals(1, responseArraySet.size());
|
||||
MdnsResponse response = responseArraySet.valueAt(0);
|
||||
assertTrue(response.isComplete());
|
||||
|
||||
MdnsInetAddressRecord inet6AddressRecord = response.getInet6AddressRecord();
|
||||
@@ -289,6 +284,22 @@ public class MdnsResponseDecoderTests {
|
||||
assertEquals(inet6Addr.getHostAddress(), "2000:3333::da6c:63ff:fe7c:7483");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecodeIPv6AnswerPacket() throws IOException {
|
||||
MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, CAST_SERVICE_TYPE);
|
||||
assertNotNull(data6);
|
||||
verifyResponse(decode(decoder, data6));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecodeCaseInsensitiveMatch() throws IOException {
|
||||
final String[] castServiceTypeUpperCase =
|
||||
new String[] {"_GOOGLECAST", "_TCP", "LOCAL"};
|
||||
MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, castServiceTypeUpperCase);
|
||||
assertNotNull(data6);
|
||||
verifyResponse(decode(decoder, data6));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsComplete() {
|
||||
MdnsResponse response = new MdnsResponse(responses.valueAt(0));
|
||||
|
||||
@@ -228,6 +228,12 @@ public class MdnsResponseTests {
|
||||
final MdnsResponse response = makeCompleteResponse(TEST_TTL_MS);
|
||||
|
||||
assertFalse(response.addPointerRecord(response.getPointerRecords().get(0)));
|
||||
final String[] serviceName = new String[] { "MYSERVICE", "_TYPE", "_tcp", "local" };
|
||||
final String[] serviceType = new String[] { "_TYPE", "_tcp", "local" };
|
||||
MdnsPointerRecord pointerRecordCaseInsensitive =
|
||||
new MdnsPointerRecord(serviceType, 0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */, TEST_TTL_MS, serviceName);
|
||||
assertFalse(response.addPointerRecord(pointerRecordCaseInsensitive));
|
||||
assertFalse(response.addInet6AddressRecord(response.getInet6AddressRecord()));
|
||||
assertFalse(response.addInet4AddressRecord(response.getInet4AddressRecord()));
|
||||
assertFalse(response.setServiceRecord(response.getServiceRecord()));
|
||||
@@ -270,4 +276,30 @@ public class MdnsResponseTests {
|
||||
// All records were replaced, not added
|
||||
assertEquals(ttlZeroResponse.getRecords().size(), response.getRecords().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dropUnmatchedAddressRecords_caseInsensitive() {
|
||||
|
||||
final String[] hostname = new String[] { "MyHostname" };
|
||||
final String[] upperCaseHostName = new String[] { "MYHOSTNAME" };
|
||||
final String[] serviceName = new String[] { "MyService", "_type", "_tcp", "local" };
|
||||
final String[] serviceType = new String[] { "_type", "_tcp", "local" };
|
||||
final MdnsResponse response = new MdnsResponse(/* now= */ 0, serviceName, INTERFACE_INDEX,
|
||||
mNetwork);
|
||||
response.addPointerRecord(new MdnsPointerRecord(serviceType, 0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */, TEST_TTL_MS, serviceName));
|
||||
response.setServiceRecord(new MdnsServiceRecord(serviceName, 0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */, TEST_TTL_MS, 0 /* servicePriority */,
|
||||
0 /* serviceWeight */, 0 /* servicePort */, hostname));
|
||||
response.setTextRecord(new MdnsTextRecord(serviceName, 0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */, TEST_TTL_MS, emptyList() /* entries */));
|
||||
response.addInet4AddressRecord(new MdnsInetAddressRecord(
|
||||
upperCaseHostName , 0L /* receiptTimeMillis */, true /* cacheFlush */,
|
||||
TEST_TTL_MS, parseNumericAddress("192.0.2.123")));
|
||||
response.addInet6AddressRecord(new MdnsInetAddressRecord(
|
||||
upperCaseHostName, 0L /* receiptTimeMillis */, true /* cacheFlush */,
|
||||
TEST_TTL_MS, parseNumericAddress("2001:db8::123")));
|
||||
|
||||
assertFalse(response.dropUnmatchedAddressRecords());
|
||||
}
|
||||
}
|
||||
@@ -1036,10 +1036,11 @@ public class MdnsServiceTypeClientTests {
|
||||
final String otherInstance = "instance2";
|
||||
final String ipV4Address = "192.0.2.0";
|
||||
final String ipV6Address = "2001:db8::";
|
||||
final String capitalizedRequestInstance = "Instance1";
|
||||
|
||||
final MdnsSearchOptions resolveOptions = MdnsSearchOptions.newBuilder()
|
||||
// Use different case in the options
|
||||
.setResolveInstanceName("Instance1").build();
|
||||
.setResolveInstanceName(capitalizedRequestInstance).build();
|
||||
|
||||
client.startSendAndReceive(mockListenerOne, resolveOptions);
|
||||
client.startSendAndReceive(mockListenerTwo, MdnsSearchOptions.getDefaultOptions());
|
||||
@@ -1067,8 +1068,9 @@ public class MdnsServiceTypeClientTests {
|
||||
Collections.emptyMap(), 0L /* ttl */), INTERFACE_INDEX, mockNetwork);
|
||||
|
||||
// mockListenerOne gets notified for the requested instance
|
||||
verify(mockListenerOne).onServiceNameDiscovered(matchServiceName(requestedInstance));
|
||||
verify(mockListenerOne).onServiceFound(matchServiceName(requestedInstance));
|
||||
verify(mockListenerOne).onServiceNameDiscovered(
|
||||
matchServiceName(capitalizedRequestInstance));
|
||||
verify(mockListenerOne).onServiceFound(matchServiceName(capitalizedRequestInstance));
|
||||
|
||||
// ...but does not get any callback for the other instance
|
||||
verify(mockListenerOne, never()).onServiceFound(matchServiceName(otherInstance));
|
||||
@@ -1079,8 +1081,9 @@ public class MdnsServiceTypeClientTests {
|
||||
// mockListenerTwo gets notified for both though
|
||||
final InOrder inOrder = inOrder(mockListenerTwo);
|
||||
inOrder.verify(mockListenerTwo).onServiceNameDiscovered(
|
||||
matchServiceName(requestedInstance));
|
||||
inOrder.verify(mockListenerTwo).onServiceFound(matchServiceName(requestedInstance));
|
||||
matchServiceName(capitalizedRequestInstance));
|
||||
inOrder.verify(mockListenerTwo).onServiceFound(
|
||||
matchServiceName(capitalizedRequestInstance));
|
||||
|
||||
inOrder.verify(mockListenerTwo).onServiceNameDiscovered(matchServiceName(otherInstance));
|
||||
inOrder.verify(mockListenerTwo).onServiceFound(matchServiceName(otherInstance));
|
||||
@@ -1179,8 +1182,7 @@ public class MdnsServiceTypeClientTests {
|
||||
final String ipV4Address = "192.0.2.0";
|
||||
|
||||
final MdnsSearchOptions resolveOptions = MdnsSearchOptions.newBuilder()
|
||||
// Use different case in the options
|
||||
.setResolveInstanceName("Instance1").build();
|
||||
.setResolveInstanceName("instance1").build();
|
||||
|
||||
client.startSendAndReceive(mockListenerOne, resolveOptions);
|
||||
// Ensure the first task is executed so it schedules a future task
|
||||
|
||||
@@ -17,11 +17,14 @@
|
||||
package com.android.server.connectivity.mdns.util
|
||||
|
||||
import android.os.Build
|
||||
import com.android.server.connectivity.mdns.util.MdnsUtils.equalsDnsLabelIgnoreDnsCase
|
||||
import com.android.server.connectivity.mdns.util.MdnsUtils.equalsIgnoreDnsCase
|
||||
import com.android.server.connectivity.mdns.util.MdnsUtils.toDnsLabelsLowerCase
|
||||
import com.android.server.connectivity.mdns.util.MdnsUtils.toDnsLowerCase
|
||||
import com.android.server.connectivity.mdns.util.MdnsUtils.truncateServiceName
|
||||
import com.android.testutils.DevSdkIgnoreRule
|
||||
import com.android.testutils.DevSdkIgnoreRunner
|
||||
import org.junit.Assert.assertArrayEquals
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
@@ -49,6 +52,12 @@ class MdnsUtilsTest {
|
||||
"\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f<"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testToDnsLabelsLowerCase() {
|
||||
assertArrayEquals(arrayOf("test", "tÉst", "ţést"),
|
||||
toDnsLabelsLowerCase(arrayOf("TeSt", "TÉST", "ţést")))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testEqualsIgnoreDnsCase() {
|
||||
assertTrue(equalsIgnoreDnsCase("TEST", "Test"))
|
||||
@@ -72,4 +81,25 @@ class MdnsUtilsTest {
|
||||
assertEquals(truncateServiceName("测试abcde", 7), "测试a")
|
||||
assertEquals(truncateServiceName("测试abcde", 100), "测试abcde")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testEqualsLabelIgnoreDnsCase() {
|
||||
assertTrue(equalsDnsLabelIgnoreDnsCase(arrayOf("TEST", "Test"), arrayOf("test", "test")))
|
||||
assertFalse(equalsDnsLabelIgnoreDnsCase(arrayOf("TEST", "Test"), arrayOf("test")))
|
||||
assertFalse(equalsDnsLabelIgnoreDnsCase(arrayOf("Test"), arrayOf("test", "test")))
|
||||
assertFalse(equalsDnsLabelIgnoreDnsCase(arrayOf("TEST", "Test"), arrayOf("test", "tést")))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testTypeEqualsOrIsSubtype() {
|
||||
assertTrue(MdnsUtils.typeEqualsOrIsSubtype(arrayOf("_type", "_tcp", "local"),
|
||||
arrayOf("_type", "_TCP", "local")))
|
||||
assertTrue(MdnsUtils.typeEqualsOrIsSubtype(arrayOf("_type", "_tcp", "local"),
|
||||
arrayOf("a", "_SUB", "_type", "_TCP", "local")))
|
||||
assertFalse(MdnsUtils.typeEqualsOrIsSubtype(arrayOf("_sub", "_type", "_tcp", "local"),
|
||||
arrayOf("_type", "_TCP", "local")))
|
||||
assertFalse(MdnsUtils.typeEqualsOrIsSubtype(
|
||||
arrayOf("a", "_other", "_type", "_tcp", "local"),
|
||||
arrayOf("a", "_SUB", "_type", "_TCP", "local")))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user