Add onServiceNameDiscovered/onServiceNameRemoved
Add onServiceNameDiscovered method which is used to listen the discovery callbacks. It would be called once the service is found even the response is incomplete. This is different from onServiceFound which needs to receive a complete response. onServiceNameRemoved is used for service removal if received response is incomplete. Bug: 254166302 Test: atest FramworksNetTests Change-Id: I03313b045d74bb65f7fe6ac93673f02ce3b2c664
This commit is contained in:
@@ -18,6 +18,7 @@ package com.android.server.connectivity.mdns;
|
||||
|
||||
import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
@@ -26,16 +27,18 @@ import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.net.InetAddresses;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.server.connectivity.mdns.MdnsServiceInfo.TextEntry;
|
||||
@@ -49,6 +52,7 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
@@ -72,7 +76,7 @@ import java.util.concurrent.TimeUnit;
|
||||
@RunWith(DevSdkIgnoreRunner.class)
|
||||
@DevSdkIgnoreRule.IgnoreUpTo(SC_V2)
|
||||
public class MdnsServiceTypeClientTests {
|
||||
|
||||
private static final int INTERFACE_INDEX = 999;
|
||||
private static final String SERVICE_TYPE = "_googlecast._tcp.local";
|
||||
private static final String[] SERVICE_TYPE_LABELS = TextUtils.split(SERVICE_TYPE, "\\.");
|
||||
|
||||
@@ -379,15 +383,41 @@ public class MdnsServiceTypeClientTests {
|
||||
assertNull(currentThreadExecutor.getAndClearLastScheduledRunnable());
|
||||
}
|
||||
|
||||
private static void verifyServiceInfo(MdnsServiceInfo serviceInfo, String serviceName,
|
||||
String[] serviceType, String ipv4Address, String ipv6Address, int port,
|
||||
List<String> subTypes, Map<String, String> attributes, int interfaceIndex) {
|
||||
assertEquals(serviceName, serviceInfo.getServiceInstanceName());
|
||||
assertArrayEquals(serviceType, serviceInfo.getServiceType());
|
||||
assertEquals(ipv4Address, serviceInfo.getIpv4Address());
|
||||
assertEquals(ipv6Address, serviceInfo.getIpv6Address());
|
||||
assertEquals(port, serviceInfo.getPort());
|
||||
assertEquals(subTypes, serviceInfo.getSubtypes());
|
||||
for (String key : attributes.keySet()) {
|
||||
assertEquals(attributes.get(key), serviceInfo.getAttributeByKey(key));
|
||||
}
|
||||
assertEquals(interfaceIndex, serviceInfo.getInterfaceIndex());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void processResponse_incompleteResponse() {
|
||||
client.startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions());
|
||||
|
||||
MdnsResponse response = mock(MdnsResponse.class);
|
||||
when(response.getServiceInstanceName()).thenReturn("service-instance-1");
|
||||
doReturn(INTERFACE_INDEX).when(response).getInterfaceIndex();
|
||||
when(response.isComplete()).thenReturn(false);
|
||||
|
||||
client.processResponse(response);
|
||||
verify(mockListenerOne).onServiceNameDiscovered(serviceInfoCaptor.capture());
|
||||
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(0),
|
||||
"service-instance-1",
|
||||
SERVICE_TYPE_LABELS,
|
||||
null /* ipv4Address */,
|
||||
null /* ipv6Address */,
|
||||
0 /* port */,
|
||||
List.of() /* subTypes */,
|
||||
Collections.singletonMap("key", null) /* attributes */,
|
||||
INTERFACE_INDEX);
|
||||
|
||||
verify(mockListenerOne, never()).onServiceFound(any(MdnsServiceInfo.class));
|
||||
verify(mockListenerOne, never()).onServiceUpdated(any(MdnsServiceInfo.class));
|
||||
@@ -404,7 +434,7 @@ public class MdnsServiceTypeClientTests {
|
||||
"service-instance-1",
|
||||
ipV4Address,
|
||||
5353,
|
||||
Collections.singletonList("ABCDE"),
|
||||
/* subtype= */ "ABCDE",
|
||||
Collections.emptyMap(),
|
||||
/* interfaceIndex= */ 20);
|
||||
client.processResponse(initialResponse);
|
||||
@@ -415,14 +445,26 @@ public class MdnsServiceTypeClientTests {
|
||||
"service-instance-1",
|
||||
ipV4Address,
|
||||
5354,
|
||||
Collections.singletonList("ABCDE"),
|
||||
/* subtype= */ "ABCDE",
|
||||
Collections.singletonMap("key", "value"),
|
||||
/* interfaceIndex= */ 20);
|
||||
client.processResponse(secondResponse);
|
||||
|
||||
// Verify onServiceNameDiscovered was called once for the initial response.
|
||||
verify(mockListenerOne).onServiceNameDiscovered(serviceInfoCaptor.capture());
|
||||
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(0),
|
||||
"service-instance-1",
|
||||
SERVICE_TYPE_LABELS,
|
||||
ipV4Address /* ipv4Address */,
|
||||
null /* ipv6Address */,
|
||||
5353 /* port */,
|
||||
Collections.singletonList("ABCDE") /* subTypes */,
|
||||
Collections.singletonMap("key", null) /* attributes */,
|
||||
20 /* interfaceIndex */);
|
||||
|
||||
// Verify onServiceFound was called once for the initial response.
|
||||
verify(mockListenerOne).onServiceFound(serviceInfoCaptor.capture());
|
||||
MdnsServiceInfo initialServiceInfo = serviceInfoCaptor.getAllValues().get(0);
|
||||
MdnsServiceInfo initialServiceInfo = serviceInfoCaptor.getAllValues().get(1);
|
||||
assertEquals(initialServiceInfo.getServiceInstanceName(), "service-instance-1");
|
||||
assertEquals(initialServiceInfo.getIpv4Address(), ipV4Address);
|
||||
assertEquals(initialServiceInfo.getPort(), 5353);
|
||||
@@ -432,7 +474,7 @@ public class MdnsServiceTypeClientTests {
|
||||
|
||||
// Verify onServiceUpdated was called once for the second response.
|
||||
verify(mockListenerOne).onServiceUpdated(serviceInfoCaptor.capture());
|
||||
MdnsServiceInfo updatedServiceInfo = serviceInfoCaptor.getAllValues().get(1);
|
||||
MdnsServiceInfo updatedServiceInfo = serviceInfoCaptor.getAllValues().get(2);
|
||||
assertEquals(updatedServiceInfo.getServiceInstanceName(), "service-instance-1");
|
||||
assertEquals(updatedServiceInfo.getIpv4Address(), ipV4Address);
|
||||
assertEquals(updatedServiceInfo.getPort(), 5354);
|
||||
@@ -453,7 +495,7 @@ public class MdnsServiceTypeClientTests {
|
||||
"service-instance-1",
|
||||
ipV6Address,
|
||||
5353,
|
||||
Collections.singletonList("ABCDE"),
|
||||
/* subtype= */ "ABCDE",
|
||||
Collections.emptyMap(),
|
||||
/* interfaceIndex= */ 20);
|
||||
client.processResponse(initialResponse);
|
||||
@@ -464,7 +506,7 @@ public class MdnsServiceTypeClientTests {
|
||||
"service-instance-1",
|
||||
ipV6Address,
|
||||
5354,
|
||||
Collections.singletonList("ABCDE"),
|
||||
/* subtype= */ "ABCDE",
|
||||
Collections.singletonMap("key", "value"),
|
||||
/* interfaceIndex= */ 20);
|
||||
client.processResponse(secondResponse);
|
||||
@@ -472,9 +514,21 @@ public class MdnsServiceTypeClientTests {
|
||||
System.out.println("secondResponses ip"
|
||||
+ secondResponse.getInet6AddressRecord().getInet6Address().getHostAddress());
|
||||
|
||||
// Verify onServiceNameDiscovered was called once for the initial response.
|
||||
verify(mockListenerOne).onServiceNameDiscovered(serviceInfoCaptor.capture());
|
||||
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(0),
|
||||
"service-instance-1",
|
||||
SERVICE_TYPE_LABELS,
|
||||
null /* ipv4Address */,
|
||||
ipV6Address /* ipv6Address */,
|
||||
5353 /* port */,
|
||||
Collections.singletonList("ABCDE") /* subTypes */,
|
||||
Collections.singletonMap("key", null) /* attributes */,
|
||||
20 /* interfaceIndex */);
|
||||
|
||||
// Verify onServiceFound was called once for the initial response.
|
||||
verify(mockListenerOne).onServiceFound(serviceInfoCaptor.capture());
|
||||
MdnsServiceInfo initialServiceInfo = serviceInfoCaptor.getAllValues().get(0);
|
||||
MdnsServiceInfo initialServiceInfo = serviceInfoCaptor.getAllValues().get(1);
|
||||
assertEquals(initialServiceInfo.getServiceInstanceName(), "service-instance-1");
|
||||
assertEquals(initialServiceInfo.getIpv6Address(), ipV6Address);
|
||||
assertEquals(initialServiceInfo.getPort(), 5353);
|
||||
@@ -484,7 +538,7 @@ public class MdnsServiceTypeClientTests {
|
||||
|
||||
// Verify onServiceUpdated was called once for the second response.
|
||||
verify(mockListenerOne).onServiceUpdated(serviceInfoCaptor.capture());
|
||||
MdnsServiceInfo updatedServiceInfo = serviceInfoCaptor.getAllValues().get(1);
|
||||
MdnsServiceInfo updatedServiceInfo = serviceInfoCaptor.getAllValues().get(2);
|
||||
assertEquals(updatedServiceInfo.getServiceInstanceName(), "service-instance-1");
|
||||
assertEquals(updatedServiceInfo.getIpv6Address(), ipV6Address);
|
||||
assertEquals(updatedServiceInfo.getPort(), 5354);
|
||||
@@ -494,6 +548,23 @@ public class MdnsServiceTypeClientTests {
|
||||
assertEquals(updatedServiceInfo.getInterfaceIndex(), 20);
|
||||
}
|
||||
|
||||
private void verifyServiceRemovedNoCallback(MdnsServiceBrowserListener listener) {
|
||||
verify(listener, never()).onServiceRemoved(any());
|
||||
verify(listener, never()).onServiceNameRemoved(any());
|
||||
}
|
||||
|
||||
private void verifyServiceRemovedCallback(MdnsServiceBrowserListener listener,
|
||||
String serviceName, String[] serviceType, int interfaceIndex) {
|
||||
verify(listener).onServiceRemoved(argThat(
|
||||
info -> serviceName.equals(info.getServiceInstanceName())
|
||||
&& Arrays.equals(serviceType, info.getServiceType())
|
||||
&& info.getInterfaceIndex() == interfaceIndex));
|
||||
verify(listener).onServiceNameRemoved(argThat(
|
||||
info -> serviceName.equals(info.getServiceInstanceName())
|
||||
&& Arrays.equals(serviceType, info.getServiceType())
|
||||
&& info.getInterfaceIndex() == interfaceIndex));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void processResponse_goodBye() throws Exception {
|
||||
client.startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions());
|
||||
@@ -501,37 +572,32 @@ public class MdnsServiceTypeClientTests {
|
||||
|
||||
final String serviceName = "service-instance-1";
|
||||
final String ipV6Address = "2000:3333::da6c:63ff:fe7c:7483";
|
||||
final int interfaceIndex = 999;
|
||||
// Process the initial response.
|
||||
final MdnsResponse initialResponse =
|
||||
createResponse(
|
||||
serviceName,
|
||||
ipV6Address,
|
||||
5353 /* port */,
|
||||
Collections.singletonList("ABCDE"),
|
||||
/* subtype= */ "ABCDE",
|
||||
Collections.emptyMap(),
|
||||
interfaceIndex);
|
||||
INTERFACE_INDEX);
|
||||
client.processResponse(initialResponse);
|
||||
MdnsResponse response = mock(MdnsResponse.class);
|
||||
doReturn("goodbye-service").when(response).getServiceInstanceName();
|
||||
doReturn(interfaceIndex).when(response).getInterfaceIndex();
|
||||
doReturn(INTERFACE_INDEX).when(response).getInterfaceIndex();
|
||||
doReturn(true).when(response).isGoodbye();
|
||||
client.processResponse(response);
|
||||
// Verify onServiceRemoved won't be called if the service is not existed.
|
||||
verify(mockListenerOne, never()).onServiceRemoved(any());
|
||||
verify(mockListenerTwo, never()).onServiceRemoved(any());
|
||||
// Verify removed callback won't be called if the service is not existed.
|
||||
verifyServiceRemovedNoCallback(mockListenerOne);
|
||||
verifyServiceRemovedNoCallback(mockListenerTwo);
|
||||
|
||||
// Verify onServiceRemoved would be called.
|
||||
// Verify removed callback would be called.
|
||||
doReturn(serviceName).when(response).getServiceInstanceName();
|
||||
client.processResponse(response);
|
||||
verify(mockListenerOne).onServiceRemoved(argThat(
|
||||
info -> serviceName.equals(info.getServiceInstanceName())
|
||||
&& Arrays.equals(SERVICE_TYPE_LABELS, info.getServiceType())
|
||||
&& info.getInterfaceIndex() == interfaceIndex));
|
||||
verify(mockListenerTwo).onServiceRemoved(argThat(
|
||||
info -> serviceName.equals(info.getServiceInstanceName())
|
||||
&& Arrays.equals(SERVICE_TYPE_LABELS, info.getServiceType())
|
||||
&& info.getInterfaceIndex() == interfaceIndex));
|
||||
verifyServiceRemovedCallback(
|
||||
mockListenerOne, serviceName, SERVICE_TYPE_LABELS, INTERFACE_INDEX);
|
||||
verifyServiceRemovedCallback(
|
||||
mockListenerTwo, serviceName, SERVICE_TYPE_LABELS, INTERFACE_INDEX);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -542,15 +608,28 @@ public class MdnsServiceTypeClientTests {
|
||||
"service-instance-1",
|
||||
"192.168.1.1",
|
||||
5353,
|
||||
Collections.singletonList("ABCDE"),
|
||||
Collections.emptyMap());
|
||||
/* subtype= */ "ABCDE",
|
||||
Collections.emptyMap(),
|
||||
INTERFACE_INDEX);
|
||||
client.processResponse(initialResponse);
|
||||
|
||||
client.startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions());
|
||||
|
||||
// Verify onServiceNameDiscovered was called once for the existing response.
|
||||
verify(mockListenerOne).onServiceNameDiscovered(serviceInfoCaptor.capture());
|
||||
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(0),
|
||||
"service-instance-1",
|
||||
SERVICE_TYPE_LABELS,
|
||||
"192.168.1.1" /* ipv4Address */,
|
||||
null /* ipv6Address */,
|
||||
5353 /* port */,
|
||||
Collections.singletonList("ABCDE") /* subTypes */,
|
||||
Collections.singletonMap("key", null) /* attributes */,
|
||||
INTERFACE_INDEX);
|
||||
|
||||
// Verify onServiceFound was called once for the existing response.
|
||||
verify(mockListenerOne).onServiceFound(serviceInfoCaptor.capture());
|
||||
MdnsServiceInfo existingServiceInfo = serviceInfoCaptor.getAllValues().get(0);
|
||||
MdnsServiceInfo existingServiceInfo = serviceInfoCaptor.getAllValues().get(1);
|
||||
assertEquals(existingServiceInfo.getServiceInstanceName(), "service-instance-1");
|
||||
assertEquals(existingServiceInfo.getIpv4Address(), "192.168.1.1");
|
||||
assertEquals(existingServiceInfo.getPort(), 5353);
|
||||
@@ -567,6 +646,7 @@ public class MdnsServiceTypeClientTests {
|
||||
|
||||
// Verify onServiceFound was not called on the newly registered listener after the existing
|
||||
// response is gone.
|
||||
verify(mockListenerTwo, never()).onServiceNameDiscovered(any(MdnsServiceInfo.class));
|
||||
verify(mockListenerTwo, never()).onServiceFound(any(MdnsServiceInfo.class));
|
||||
}
|
||||
|
||||
@@ -580,9 +660,9 @@ public class MdnsServiceTypeClientTests {
|
||||
|
||||
// Process the initial response.
|
||||
MdnsResponse initialResponse =
|
||||
createResponse(
|
||||
createMockResponse(
|
||||
serviceInstanceName, "192.168.1.1", 5353, List.of("ABCDE"),
|
||||
Map.of());
|
||||
Map.of(), INTERFACE_INDEX);
|
||||
client.processResponse(initialResponse);
|
||||
|
||||
// Clear the scheduled runnable.
|
||||
@@ -592,8 +672,8 @@ public class MdnsServiceTypeClientTests {
|
||||
when(initialResponse.getServiceRecord().getRemainingTTL(anyLong())).thenReturn((long) 0);
|
||||
firstMdnsTask.run();
|
||||
|
||||
// Verify onServiceRemoved was not called.
|
||||
verify(mockListenerOne, never()).onServiceRemoved(any());
|
||||
// Verify removed callback was not called.
|
||||
verifyServiceRemovedNoCallback(mockListenerOne);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -614,9 +694,9 @@ public class MdnsServiceTypeClientTests {
|
||||
|
||||
// Process the initial response.
|
||||
MdnsResponse initialResponse =
|
||||
createResponse(
|
||||
createMockResponse(
|
||||
serviceInstanceName, "192.168.1.1", 5353, List.of("ABCDE"),
|
||||
Map.of(), 999 /* interfaceIndex */);
|
||||
Map.of(), INTERFACE_INDEX);
|
||||
client.processResponse(initialResponse);
|
||||
|
||||
// Clear the scheduled runnable.
|
||||
@@ -626,18 +706,16 @@ public class MdnsServiceTypeClientTests {
|
||||
when(initialResponse.getServiceRecord().getRemainingTTL(anyLong())).thenReturn((long) 1000);
|
||||
firstMdnsTask.run();
|
||||
|
||||
// Verify onServiceRemoved was not called.
|
||||
verify(mockListenerOne, never()).onServiceRemoved(any());
|
||||
// Verify removed callback was not called.
|
||||
verifyServiceRemovedNoCallback(mockListenerOne);
|
||||
|
||||
// Simulate the case where the response is after TTL.
|
||||
when(initialResponse.getServiceRecord().getRemainingTTL(anyLong())).thenReturn((long) 0);
|
||||
firstMdnsTask.run();
|
||||
|
||||
// Verify onServiceRemoved was called.
|
||||
verify(mockListenerOne, times(1)).onServiceRemoved(argThat(
|
||||
info -> serviceInstanceName.equals(info.getServiceInstanceName())
|
||||
&& Arrays.equals(SERVICE_TYPE_LABELS, info.getServiceType())
|
||||
&& info.getInterfaceIndex() == 999));
|
||||
// Verify removed callback was called.
|
||||
verifyServiceRemovedCallback(
|
||||
mockListenerOne, serviceInstanceName, SERVICE_TYPE_LABELS, INTERFACE_INDEX);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -656,9 +734,9 @@ public class MdnsServiceTypeClientTests {
|
||||
|
||||
// Process the initial response.
|
||||
MdnsResponse initialResponse =
|
||||
createResponse(
|
||||
createMockResponse(
|
||||
serviceInstanceName, "192.168.1.1", 5353, List.of("ABCDE"),
|
||||
Map.of());
|
||||
Map.of(), INTERFACE_INDEX);
|
||||
client.processResponse(initialResponse);
|
||||
|
||||
// Clear the scheduled runnable.
|
||||
@@ -668,8 +746,8 @@ public class MdnsServiceTypeClientTests {
|
||||
when(initialResponse.getServiceRecord().getRemainingTTL(anyLong())).thenReturn((long) 0);
|
||||
firstMdnsTask.run();
|
||||
|
||||
// Verify onServiceRemoved was not called.
|
||||
verify(mockListenerOne, never()).onServiceRemoved(any());
|
||||
// Verify removed callback was not called.
|
||||
verifyServiceRemovedNoCallback(mockListenerOne);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -690,9 +768,9 @@ public class MdnsServiceTypeClientTests {
|
||||
|
||||
// Process the initial response.
|
||||
MdnsResponse initialResponse =
|
||||
createResponse(
|
||||
createMockResponse(
|
||||
serviceInstanceName, "192.168.1.1", 5353, List.of("ABCDE"),
|
||||
Map.of(), 999 /* interfaceIndex */);
|
||||
Map.of(), INTERFACE_INDEX);
|
||||
client.processResponse(initialResponse);
|
||||
|
||||
// Clear the scheduled runnable.
|
||||
@@ -702,11 +780,117 @@ public class MdnsServiceTypeClientTests {
|
||||
when(initialResponse.getServiceRecord().getRemainingTTL(anyLong())).thenReturn((long) 0);
|
||||
firstMdnsTask.run();
|
||||
|
||||
// Verify onServiceRemoved was called.
|
||||
verify(mockListenerOne, times(1)).onServiceRemoved(argThat(
|
||||
info -> serviceInstanceName.equals(info.getServiceInstanceName())
|
||||
&& Arrays.equals(SERVICE_TYPE_LABELS, info.getServiceType())
|
||||
&& info.getInterfaceIndex() == 999));
|
||||
// Verify removed callback was called.
|
||||
verifyServiceRemovedCallback(
|
||||
mockListenerOne, serviceInstanceName, SERVICE_TYPE_LABELS, INTERFACE_INDEX);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessResponse_InOrder() throws Exception {
|
||||
final String serviceName = "service-instance";
|
||||
final String ipV4Address = "192.0.2.0";
|
||||
final String ipV6Address = "2001:db8::";
|
||||
client.startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions());
|
||||
InOrder inOrder = inOrder(mockListenerOne);
|
||||
|
||||
// Process the initial response which is incomplete.
|
||||
final MdnsResponse initialResponse =
|
||||
createResponse(
|
||||
serviceName,
|
||||
null,
|
||||
5353,
|
||||
"ABCDE" /* subtype */,
|
||||
Collections.emptyMap(),
|
||||
INTERFACE_INDEX);
|
||||
client.processResponse(initialResponse);
|
||||
|
||||
// Process a second response which has ip address to make response become complete.
|
||||
final MdnsResponse secondResponse =
|
||||
createResponse(
|
||||
serviceName,
|
||||
ipV4Address,
|
||||
5353,
|
||||
"ABCDE" /* subtype */,
|
||||
Collections.emptyMap(),
|
||||
INTERFACE_INDEX);
|
||||
client.processResponse(secondResponse);
|
||||
|
||||
// Process a third response with a different ip address, port and updated text attributes.
|
||||
final MdnsResponse thirdResponse =
|
||||
createResponse(
|
||||
serviceName,
|
||||
ipV6Address,
|
||||
5354,
|
||||
"ABCDE" /* subtype */,
|
||||
Collections.singletonMap("key", "value"),
|
||||
INTERFACE_INDEX);
|
||||
client.processResponse(thirdResponse);
|
||||
|
||||
// Process the last response which is goodbye message.
|
||||
final MdnsResponse lastResponse = mock(MdnsResponse.class);
|
||||
doReturn(serviceName).when(lastResponse).getServiceInstanceName();
|
||||
doReturn(true).when(lastResponse).isGoodbye();
|
||||
client.processResponse(lastResponse);
|
||||
|
||||
// Verify onServiceNameDiscovered was first called for the initial response.
|
||||
inOrder.verify(mockListenerOne).onServiceNameDiscovered(serviceInfoCaptor.capture());
|
||||
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(0),
|
||||
serviceName,
|
||||
SERVICE_TYPE_LABELS,
|
||||
null /* ipv4Address */,
|
||||
null /* ipv6Address */,
|
||||
5353 /* port */,
|
||||
Collections.singletonList("ABCDE") /* subTypes */,
|
||||
Collections.singletonMap("key", null) /* attributes */,
|
||||
INTERFACE_INDEX);
|
||||
|
||||
// Verify onServiceFound was second called for the second response.
|
||||
inOrder.verify(mockListenerOne).onServiceFound(serviceInfoCaptor.capture());
|
||||
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(1),
|
||||
serviceName,
|
||||
SERVICE_TYPE_LABELS,
|
||||
ipV4Address /* ipv4Address */,
|
||||
null /* ipv6Address */,
|
||||
5353 /* port */,
|
||||
Collections.singletonList("ABCDE") /* subTypes */,
|
||||
Collections.singletonMap("key", null) /* attributes */,
|
||||
INTERFACE_INDEX);
|
||||
|
||||
// Verify onServiceUpdated was third called for the third response.
|
||||
inOrder.verify(mockListenerOne).onServiceUpdated(serviceInfoCaptor.capture());
|
||||
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(2),
|
||||
serviceName,
|
||||
SERVICE_TYPE_LABELS,
|
||||
ipV4Address /* ipv4Address */,
|
||||
ipV6Address /* ipv6Address */,
|
||||
5354 /* port */,
|
||||
Collections.singletonList("ABCDE") /* subTypes */,
|
||||
Collections.singletonMap("key", "value") /* attributes */,
|
||||
INTERFACE_INDEX);
|
||||
|
||||
// Verify onServiceRemoved was called for the last response.
|
||||
inOrder.verify(mockListenerOne).onServiceRemoved(serviceInfoCaptor.capture());
|
||||
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(3),
|
||||
serviceName,
|
||||
SERVICE_TYPE_LABELS,
|
||||
ipV4Address /* ipv4Address */,
|
||||
ipV6Address /* ipv6Address */,
|
||||
5354 /* port */,
|
||||
Collections.singletonList("ABCDE") /* subTypes */,
|
||||
Collections.singletonMap("key", "value") /* attributes */,
|
||||
INTERFACE_INDEX);
|
||||
|
||||
// Verify onServiceNameRemoved was called for the last response.
|
||||
inOrder.verify(mockListenerOne).onServiceNameRemoved(serviceInfoCaptor.capture());
|
||||
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(4),
|
||||
serviceName,
|
||||
SERVICE_TYPE_LABELS,
|
||||
ipV4Address /* ipv4Address */,
|
||||
ipV6Address /* ipv6Address */,
|
||||
5354 /* port */,
|
||||
Collections.singletonList("ABCDE") /* subTypes */,
|
||||
Collections.singletonMap("key", "value") /* attributes */,
|
||||
INTERFACE_INDEX);
|
||||
}
|
||||
|
||||
// verifies that the right query was enqueued with the right delay, and send query by executing
|
||||
@@ -771,19 +955,8 @@ public class MdnsServiceTypeClientTests {
|
||||
}
|
||||
}
|
||||
|
||||
private MdnsResponse createResponse(
|
||||
@NonNull String serviceInstanceName,
|
||||
@NonNull String host,
|
||||
int port,
|
||||
@NonNull List<String> subtypes,
|
||||
@NonNull Map<String, String> textAttributes)
|
||||
throws Exception {
|
||||
return createResponse(serviceInstanceName, host, port, subtypes, textAttributes,
|
||||
/* interfaceIndex= */ -1);
|
||||
}
|
||||
|
||||
// Creates a complete mDNS response.
|
||||
private MdnsResponse createResponse(
|
||||
// Creates a mock mDNS response.
|
||||
private MdnsResponse createMockResponse(
|
||||
@NonNull String serviceInstanceName,
|
||||
@NonNull String host,
|
||||
int port,
|
||||
@@ -830,4 +1003,73 @@ public class MdnsServiceTypeClientTests {
|
||||
doReturn(new ArrayList<>(subtypes)).when(response).getSubtypes();
|
||||
return response;
|
||||
}
|
||||
|
||||
// Creates a mDNS response.
|
||||
private MdnsResponse createResponse(
|
||||
@NonNull String serviceInstanceName,
|
||||
@Nullable String host,
|
||||
int port,
|
||||
@NonNull String subtype,
|
||||
@NonNull Map<String, String> textAttributes,
|
||||
int interfaceIndex)
|
||||
throws Exception {
|
||||
MdnsResponse response = new MdnsResponse(0);
|
||||
response.setInterfaceIndex(interfaceIndex);
|
||||
|
||||
// Set PTR record
|
||||
final MdnsPointerRecord pointerRecord = new MdnsPointerRecord(
|
||||
new String[]{subtype, MdnsConstants.SUBTYPE_LABEL, "test"} /* name */,
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
120000L /* ttlMillis */,
|
||||
new String[]{serviceInstanceName});
|
||||
response.addPointerRecord(pointerRecord);
|
||||
|
||||
// Set SRV record.
|
||||
final MdnsServiceRecord serviceRecord = new MdnsServiceRecord(
|
||||
new String[] {"service"} /* name */,
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
120000L /* ttlMillis */,
|
||||
0 /* servicePriority */,
|
||||
0 /* serviceWeight */,
|
||||
port,
|
||||
new String[]{"hostname"});
|
||||
response.setServiceRecord(serviceRecord);
|
||||
|
||||
// Set A/AAAA record.
|
||||
if (host != null) {
|
||||
if (InetAddresses.parseNumericAddress(host) instanceof Inet6Address) {
|
||||
final MdnsInetAddressRecord inetAddressRecord = new MdnsInetAddressRecord(
|
||||
new String[] {"address"} /* name */,
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
120000L /* ttlMillis */,
|
||||
Inet6Address.getByName(host));
|
||||
response.setInet6AddressRecord(inetAddressRecord);
|
||||
} else {
|
||||
final MdnsInetAddressRecord inetAddressRecord = new MdnsInetAddressRecord(
|
||||
new String[] {"address"} /* name */,
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
120000L /* ttlMillis */,
|
||||
Inet4Address.getByName(host));
|
||||
response.setInet4AddressRecord(inetAddressRecord);
|
||||
}
|
||||
}
|
||||
|
||||
// Set TXT record.
|
||||
final List<TextEntry> textEntries = new ArrayList<>();
|
||||
for (Map.Entry<String, String> kv : textAttributes.entrySet()) {
|
||||
textEntries.add(new TextEntry(kv.getKey(), kv.getValue().getBytes(UTF_8)));
|
||||
}
|
||||
final MdnsTextRecord textRecord = new MdnsTextRecord(
|
||||
new String[] {"text"} /* name */,
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
120000L /* ttlMillis */,
|
||||
textEntries);
|
||||
response.setTextRecord(textRecord);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user