Merge "Use case-insensitive matching in discovery/advertising"

This commit is contained in:
Yuyang Huang
2023-05-16 07:56:21 +00:00
committed by Gerrit Code Review
21 changed files with 442 additions and 54 deletions

View File

@@ -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(

View File

@@ -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) +

View File

@@ -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)

View File

@@ -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(

View File

@@ -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))
}
}

View File

@@ -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));

View File

@@ -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());
}
}

View File

@@ -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

View File

@@ -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")))
}
}