1db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi/* 2db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi * Copyright (C) 2017 The Android Open Source Project 3db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi * 4db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi * Licensed under the Apache License, Version 2.0 (the "License"); 5db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi * you may not use this file except in compliance with the License. 6db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi * You may obtain a copy of the License at 7db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi * 8db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi * http://www.apache.org/licenses/LICENSE-2.0 9db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi * 10db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi * Unless required by applicable law or agreed to in writing, software 11db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi * distributed under the License is distributed on an "AS IS" BASIS, 12db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi * See the License for the specific language governing permissions and 14db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi * limitations under the License. 15db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi */ 16db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 17db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichipackage android.net.nsd; 18db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 19db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichiimport static org.junit.Assert.assertEquals; 20db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichiimport static org.junit.Assert.assertNotNull; 2152d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichiimport static org.junit.Assert.fail; 22db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichiimport static org.mockito.Mockito.any; 2393f45916845814e5a50c26f770e0473212517fe1Hugo Benichiimport static org.mockito.Mockito.mock; 2493f45916845814e5a50c26f770e0473212517fe1Hugo Benichiimport static org.mockito.Mockito.never; 25db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichiimport static org.mockito.Mockito.reset; 26db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichiimport static org.mockito.Mockito.spy; 27db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichiimport static org.mockito.Mockito.timeout; 28db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichiimport static org.mockito.Mockito.times; 2993f45916845814e5a50c26f770e0473212517fe1Hugo Benichiimport static org.mockito.Mockito.verify; 3093f45916845814e5a50c26f770e0473212517fe1Hugo Benichiimport static org.mockito.Mockito.when; 31db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 32db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichiimport android.os.HandlerThread; 33db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichiimport android.os.Handler; 34db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichiimport android.os.Looper; 35db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichiimport android.content.Context; 36db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichiimport android.support.test.filters.SmallTest; 37db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichiimport android.support.test.runner.AndroidJUnit4; 38db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichiimport android.os.Message; 39db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichiimport android.os.Messenger; 40db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichiimport com.android.internal.util.AsyncChannel; 41db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichiimport org.junit.Before; 42db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichiimport org.junit.Test; 43db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichiimport org.junit.runner.RunWith; 44db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichiimport org.mockito.Mock; 45db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichiimport org.mockito.MockitoAnnotations; 46db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 4752d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichiimport java.util.function.Consumer; 4852d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi 49db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi@RunWith(AndroidJUnit4.class) 50db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi@SmallTest 51db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichipublic class NsdManagerTest { 52db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 538c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi static final int PROTOCOL = NsdManager.PROTOCOL_DNS_SD; 548c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi 55db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi @Mock Context mContext; 56db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi @Mock INsdManager mService; 57db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi MockServiceHandler mServiceHandler; 58db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 59db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi long mTimeoutMs = 100; // non-final so that tests can adjust the value. 60db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 61db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi @Before 62db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi public void setUp() throws Exception { 63db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi MockitoAnnotations.initMocks(this); 64db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 65db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi mServiceHandler = spy(MockServiceHandler.create(mContext)); 66db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi when(mService.getMessenger()).thenReturn(new Messenger(mServiceHandler)); 67db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi } 68db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 69db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi @Test 70db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi public void testResolveService() { 71db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi NsdManager manager = makeManager(); 72db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 73db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi NsdServiceInfo request = new NsdServiceInfo("a_name", "a_type"); 74db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi NsdServiceInfo reply = new NsdServiceInfo("resolved_name", "resolved_type"); 75db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi NsdManager.ResolveListener listener = mock(NsdManager.ResolveListener.class); 76db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 77db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi manager.resolveService(request, listener); 78db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi int key1 = verifyRequest(NsdManager.RESOLVE_SERVICE); 79db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi int err = 33; 80db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi sendResponse(NsdManager.RESOLVE_SERVICE_FAILED, err, key1, null); 81db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi verify(listener, timeout(mTimeoutMs).times(1)).onResolveFailed(request, err); 82db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 83db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi manager.resolveService(request, listener); 84db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi int key2 = verifyRequest(NsdManager.RESOLVE_SERVICE); 85db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi sendResponse(NsdManager.RESOLVE_SERVICE_SUCCEEDED, 0, key2, reply); 86db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi verify(listener, timeout(mTimeoutMs).times(1)).onServiceResolved(reply); 87db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi } 88db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 89db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi @Test 90db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi public void testParallelResolveService() { 91db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi NsdManager manager = makeManager(); 92db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 93db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi NsdServiceInfo request = new NsdServiceInfo("a_name", "a_type"); 94db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi NsdServiceInfo reply = new NsdServiceInfo("resolved_name", "resolved_type"); 95db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 96db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi NsdManager.ResolveListener listener1 = mock(NsdManager.ResolveListener.class); 97db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi NsdManager.ResolveListener listener2 = mock(NsdManager.ResolveListener.class); 98db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 99db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi manager.resolveService(request, listener1); 100db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi int key1 = verifyRequest(NsdManager.RESOLVE_SERVICE); 101db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 102db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi manager.resolveService(request, listener2); 103db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi int key2 = verifyRequest(NsdManager.RESOLVE_SERVICE); 104db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 105db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi sendResponse(NsdManager.RESOLVE_SERVICE_SUCCEEDED, 0, key2, reply); 106db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi sendResponse(NsdManager.RESOLVE_SERVICE_SUCCEEDED, 0, key1, reply); 107db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 108db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi verify(listener1, timeout(mTimeoutMs).times(1)).onServiceResolved(reply); 109db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi verify(listener2, timeout(mTimeoutMs).times(1)).onServiceResolved(reply); 11052d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi } 11152d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi 11252d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi @Test 1138c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi public void testRegisterService() { 1148c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi NsdManager manager = makeManager(); 1158c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi 1168c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi NsdServiceInfo request1 = new NsdServiceInfo("a_name", "a_type"); 1178c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi NsdServiceInfo request2 = new NsdServiceInfo("another_name", "another_type"); 1188c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi request1.setPort(2201); 1198c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi request2.setPort(2202); 1208c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi NsdManager.RegistrationListener listener1 = mock(NsdManager.RegistrationListener.class); 1218c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi NsdManager.RegistrationListener listener2 = mock(NsdManager.RegistrationListener.class); 1228c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi 1238c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi // Register two services 1248c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi manager.registerService(request1, PROTOCOL, listener1); 1258c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi int key1 = verifyRequest(NsdManager.REGISTER_SERVICE); 1268c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi 1278c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi manager.registerService(request2, PROTOCOL, listener2); 1288c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi int key2 = verifyRequest(NsdManager.REGISTER_SERVICE); 1298c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi 1308c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi // First reques fails, second request succeeds 1318c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi sendResponse(NsdManager.REGISTER_SERVICE_SUCCEEDED, 0, key2, request2); 1328c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi verify(listener2, timeout(mTimeoutMs).times(1)).onServiceRegistered(request2); 1338c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi 1348c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi int err = 1; 1358c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi sendResponse(NsdManager.REGISTER_SERVICE_FAILED, err, key1, request1); 1368c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi verify(listener1, timeout(mTimeoutMs).times(1)).onRegistrationFailed(request1, err); 1378c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi 1388c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi // Client retries first request, it succeeds 1398c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi manager.registerService(request1, PROTOCOL, listener1); 1408c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi int key3 = verifyRequest(NsdManager.REGISTER_SERVICE); 1418c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi 1428c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi sendResponse(NsdManager.REGISTER_SERVICE_SUCCEEDED, 0, key3, request1); 1438c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi verify(listener1, timeout(mTimeoutMs).times(1)).onServiceRegistered(request1); 1448c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi 1458c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi // First request is unregistered, it succeeds 1468c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi manager.unregisterService(listener1); 1478c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi int key3again = verifyRequest(NsdManager.UNREGISTER_SERVICE); 1488c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi assertEquals(key3, key3again); 1498c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi 1508c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi sendResponse(NsdManager.UNREGISTER_SERVICE_SUCCEEDED, 0, key3again, null); 1518c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi verify(listener1, timeout(mTimeoutMs).times(1)).onServiceUnregistered(request1); 1528c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi 1538c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi // Second request is unregistered, it fails 1548c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi manager.unregisterService(listener2); 1558c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi int key2again = verifyRequest(NsdManager.UNREGISTER_SERVICE); 1568c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi assertEquals(key2, key2again); 1578c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi 1588c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi sendResponse(NsdManager.UNREGISTER_SERVICE_FAILED, err, key2again, null); 1598c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi verify(listener2, timeout(mTimeoutMs).times(1)).onUnregistrationFailed(request2, err); 1608c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi 1618c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi // TODO: do not unregister listener until service is unregistered 1628c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi // Client retries unregistration of second request, it succeeds 1638c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi //manager.unregisterService(listener2); 1648c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi //int key2yetAgain = verifyRequest(NsdManager.UNREGISTER_SERVICE); 1658c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi //assertEquals(key2, key2yetAgain); 1668c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi 1678c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi //sendResponse(NsdManager.UNREGISTER_SERVICE_SUCCEEDED, 0, key2yetAgain, null); 1688c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi //verify(listener2, timeout(mTimeoutMs).times(1)).onServiceUnregistered(request2); 1698c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi } 1708c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi 1718c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi @Test 17293f45916845814e5a50c26f770e0473212517fe1Hugo Benichi public void testDiscoverService() { 17393f45916845814e5a50c26f770e0473212517fe1Hugo Benichi NsdManager manager = makeManager(); 17493f45916845814e5a50c26f770e0473212517fe1Hugo Benichi 17593f45916845814e5a50c26f770e0473212517fe1Hugo Benichi NsdServiceInfo reply1 = new NsdServiceInfo("a_name", "a_type"); 17693f45916845814e5a50c26f770e0473212517fe1Hugo Benichi NsdServiceInfo reply2 = new NsdServiceInfo("another_name", "a_type"); 17793f45916845814e5a50c26f770e0473212517fe1Hugo Benichi NsdServiceInfo reply3 = new NsdServiceInfo("a_third_name", "a_type"); 17893f45916845814e5a50c26f770e0473212517fe1Hugo Benichi 17993f45916845814e5a50c26f770e0473212517fe1Hugo Benichi NsdManager.DiscoveryListener listener = mock(NsdManager.DiscoveryListener.class); 18093f45916845814e5a50c26f770e0473212517fe1Hugo Benichi 18193f45916845814e5a50c26f770e0473212517fe1Hugo Benichi // Client registers for discovery, request fails 18293f45916845814e5a50c26f770e0473212517fe1Hugo Benichi manager.discoverServices("a_type", PROTOCOL, listener); 18393f45916845814e5a50c26f770e0473212517fe1Hugo Benichi int key1 = verifyRequest(NsdManager.DISCOVER_SERVICES); 18493f45916845814e5a50c26f770e0473212517fe1Hugo Benichi 18593f45916845814e5a50c26f770e0473212517fe1Hugo Benichi int err = 1; 18693f45916845814e5a50c26f770e0473212517fe1Hugo Benichi sendResponse(NsdManager.DISCOVER_SERVICES_FAILED, err, key1, null); 18793f45916845814e5a50c26f770e0473212517fe1Hugo Benichi verify(listener, timeout(mTimeoutMs).times(1)).onStartDiscoveryFailed("a_type", err); 18893f45916845814e5a50c26f770e0473212517fe1Hugo Benichi 18993f45916845814e5a50c26f770e0473212517fe1Hugo Benichi // Client retries, request succeeds 19093f45916845814e5a50c26f770e0473212517fe1Hugo Benichi manager.discoverServices("a_type", PROTOCOL, listener); 19193f45916845814e5a50c26f770e0473212517fe1Hugo Benichi int key2 = verifyRequest(NsdManager.DISCOVER_SERVICES); 19293f45916845814e5a50c26f770e0473212517fe1Hugo Benichi 19393f45916845814e5a50c26f770e0473212517fe1Hugo Benichi sendResponse(NsdManager.DISCOVER_SERVICES_STARTED, 0, key2, reply1); 19493f45916845814e5a50c26f770e0473212517fe1Hugo Benichi verify(listener, timeout(mTimeoutMs).times(1)).onDiscoveryStarted("a_type"); 19593f45916845814e5a50c26f770e0473212517fe1Hugo Benichi 19693f45916845814e5a50c26f770e0473212517fe1Hugo Benichi 19793f45916845814e5a50c26f770e0473212517fe1Hugo Benichi // mdns notifies about services 19893f45916845814e5a50c26f770e0473212517fe1Hugo Benichi sendResponse(NsdManager.SERVICE_FOUND, 0, key2, reply1); 19993f45916845814e5a50c26f770e0473212517fe1Hugo Benichi verify(listener, timeout(mTimeoutMs).times(1)).onServiceFound(reply1); 20093f45916845814e5a50c26f770e0473212517fe1Hugo Benichi 20193f45916845814e5a50c26f770e0473212517fe1Hugo Benichi sendResponse(NsdManager.SERVICE_FOUND, 0, key2, reply2); 20293f45916845814e5a50c26f770e0473212517fe1Hugo Benichi verify(listener, timeout(mTimeoutMs).times(1)).onServiceFound(reply2); 20393f45916845814e5a50c26f770e0473212517fe1Hugo Benichi 20493f45916845814e5a50c26f770e0473212517fe1Hugo Benichi sendResponse(NsdManager.SERVICE_LOST, 0, key2, reply2); 20593f45916845814e5a50c26f770e0473212517fe1Hugo Benichi verify(listener, timeout(mTimeoutMs).times(1)).onServiceLost(reply2); 20693f45916845814e5a50c26f770e0473212517fe1Hugo Benichi 20793f45916845814e5a50c26f770e0473212517fe1Hugo Benichi 20893f45916845814e5a50c26f770e0473212517fe1Hugo Benichi // Client unregisters its listener 20993f45916845814e5a50c26f770e0473212517fe1Hugo Benichi manager.stopServiceDiscovery(listener); 21093f45916845814e5a50c26f770e0473212517fe1Hugo Benichi int key2again = verifyRequest(NsdManager.STOP_DISCOVERY); 21193f45916845814e5a50c26f770e0473212517fe1Hugo Benichi assertEquals(key2, key2again); 21293f45916845814e5a50c26f770e0473212517fe1Hugo Benichi 21393f45916845814e5a50c26f770e0473212517fe1Hugo Benichi // TODO: unregister listener immediately and stop notifying it about services 21493f45916845814e5a50c26f770e0473212517fe1Hugo Benichi // Notifications are still passed to the client's listener 21593f45916845814e5a50c26f770e0473212517fe1Hugo Benichi sendResponse(NsdManager.SERVICE_LOST, 0, key2, reply1); 21693f45916845814e5a50c26f770e0473212517fe1Hugo Benichi verify(listener, timeout(mTimeoutMs).times(1)).onServiceLost(reply1); 21793f45916845814e5a50c26f770e0473212517fe1Hugo Benichi 21893f45916845814e5a50c26f770e0473212517fe1Hugo Benichi // Client is notified of complete unregistration 21993f45916845814e5a50c26f770e0473212517fe1Hugo Benichi sendResponse(NsdManager.STOP_DISCOVERY_SUCCEEDED, 0, key2again, "a_type"); 22093f45916845814e5a50c26f770e0473212517fe1Hugo Benichi verify(listener, timeout(mTimeoutMs).times(1)).onDiscoveryStopped("a_type"); 22193f45916845814e5a50c26f770e0473212517fe1Hugo Benichi 22293f45916845814e5a50c26f770e0473212517fe1Hugo Benichi // Notifications are not passed to the client anymore 22393f45916845814e5a50c26f770e0473212517fe1Hugo Benichi sendResponse(NsdManager.SERVICE_FOUND, 0, key2, reply3); 22493f45916845814e5a50c26f770e0473212517fe1Hugo Benichi verify(listener, timeout(mTimeoutMs).times(0)).onServiceLost(reply3); 22593f45916845814e5a50c26f770e0473212517fe1Hugo Benichi 22693f45916845814e5a50c26f770e0473212517fe1Hugo Benichi 22793f45916845814e5a50c26f770e0473212517fe1Hugo Benichi // Client registers for service discovery 22893f45916845814e5a50c26f770e0473212517fe1Hugo Benichi reset(listener); 22993f45916845814e5a50c26f770e0473212517fe1Hugo Benichi manager.discoverServices("a_type", PROTOCOL, listener); 23093f45916845814e5a50c26f770e0473212517fe1Hugo Benichi int key3 = verifyRequest(NsdManager.DISCOVER_SERVICES); 23193f45916845814e5a50c26f770e0473212517fe1Hugo Benichi 23293f45916845814e5a50c26f770e0473212517fe1Hugo Benichi sendResponse(NsdManager.DISCOVER_SERVICES_STARTED, 0, key3, reply1); 23393f45916845814e5a50c26f770e0473212517fe1Hugo Benichi verify(listener, timeout(mTimeoutMs).times(1)).onDiscoveryStarted("a_type"); 23493f45916845814e5a50c26f770e0473212517fe1Hugo Benichi 23593f45916845814e5a50c26f770e0473212517fe1Hugo Benichi // Client unregisters immediately, it fails 23693f45916845814e5a50c26f770e0473212517fe1Hugo Benichi manager.stopServiceDiscovery(listener); 23793f45916845814e5a50c26f770e0473212517fe1Hugo Benichi int key3again = verifyRequest(NsdManager.STOP_DISCOVERY); 23893f45916845814e5a50c26f770e0473212517fe1Hugo Benichi assertEquals(key3, key3again); 23993f45916845814e5a50c26f770e0473212517fe1Hugo Benichi 24093f45916845814e5a50c26f770e0473212517fe1Hugo Benichi err = 2; 24193f45916845814e5a50c26f770e0473212517fe1Hugo Benichi sendResponse(NsdManager.STOP_DISCOVERY_FAILED, err, key3again, "a_type"); 24293f45916845814e5a50c26f770e0473212517fe1Hugo Benichi verify(listener, timeout(mTimeoutMs).times(1)).onStopDiscoveryFailed("a_type", err); 24393f45916845814e5a50c26f770e0473212517fe1Hugo Benichi 24493f45916845814e5a50c26f770e0473212517fe1Hugo Benichi // New notifications are not passed to the client anymore 24593f45916845814e5a50c26f770e0473212517fe1Hugo Benichi sendResponse(NsdManager.SERVICE_FOUND, 0, key3, reply1); 24693f45916845814e5a50c26f770e0473212517fe1Hugo Benichi verify(listener, timeout(mTimeoutMs).times(0)).onServiceFound(reply1); 24793f45916845814e5a50c26f770e0473212517fe1Hugo Benichi } 24893f45916845814e5a50c26f770e0473212517fe1Hugo Benichi 24993f45916845814e5a50c26f770e0473212517fe1Hugo Benichi @Test 25052d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi public void testInvalidCalls() { 25152d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi NsdManager manager = new NsdManager(mContext, mService); 25252d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi 25352d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi NsdManager.RegistrationListener listener1 = mock(NsdManager.RegistrationListener.class); 25452d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi NsdManager.DiscoveryListener listener2 = mock(NsdManager.DiscoveryListener.class); 25552d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi NsdManager.ResolveListener listener3 = mock(NsdManager.ResolveListener.class); 25652d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi 25752d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi NsdServiceInfo invalidService = new NsdServiceInfo(null, null); 25852d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi NsdServiceInfo validService = new NsdServiceInfo("a_name", "a_type"); 25952d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi validService.setPort(2222); 26052d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi 26152d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi // Service registration 26252d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi // - invalid arguments 26352d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi mustFail(() -> { manager.unregisterService(null); }); 26452d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi mustFail(() -> { manager.registerService(null, -1, null); }); 2658c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi mustFail(() -> { manager.registerService(null, PROTOCOL, listener1); }); 2668c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi mustFail(() -> { manager.registerService(invalidService, PROTOCOL, listener1); }); 26752d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi mustFail(() -> { manager.registerService(validService, -1, listener1); }); 2688c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi mustFail(() -> { manager.registerService(validService, PROTOCOL, null); }); 2698c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi manager.registerService(validService, PROTOCOL, listener1); 27052d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi // - listener already registered 2718c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi mustFail(() -> { manager.registerService(validService, PROTOCOL, listener1); }); 27252d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi manager.unregisterService(listener1); 27352d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi // TODO: make listener immediately reusable 27452d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi //mustFail(() -> { manager.unregisterService(listener1); }); 2758c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi //manager.registerService(validService, PROTOCOL, listener1); 27652d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi 27752d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi // Discover service 27852d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi // - invalid arguments 27952d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi mustFail(() -> { manager.stopServiceDiscovery(null); }); 28052d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi mustFail(() -> { manager.discoverServices(null, -1, null); }); 2818c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi mustFail(() -> { manager.discoverServices(null, PROTOCOL, listener2); }); 28252d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi mustFail(() -> { manager.discoverServices("a_service", -1, listener2); }); 2838c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi mustFail(() -> { manager.discoverServices("a_service", PROTOCOL, null); }); 2848c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi manager.discoverServices("a_service", PROTOCOL, listener2); 28552d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi // - listener already registered 2868c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi mustFail(() -> { manager.discoverServices("another_service", PROTOCOL, listener2); }); 28752d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi manager.stopServiceDiscovery(listener2); 28852d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi // TODO: make listener immediately reusable 28952d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi //mustFail(() -> { manager.stopServiceDiscovery(listener2); }); 2908c5eeb0afc5dad35ee8ce11b9e82f7219a1a609dHugo Benichi //manager.discoverServices("another_service", PROTOCOL, listener2); 29152d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi 29252d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi // Resolver service 29352d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi // - invalid arguments 29452d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi mustFail(() -> { manager.resolveService(null, null); }); 29552d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi mustFail(() -> { manager.resolveService(null, listener3); }); 29652d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi mustFail(() -> { manager.resolveService(invalidService, listener3); }); 29752d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi mustFail(() -> { manager.resolveService(validService, null); }); 29852d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi manager.resolveService(validService, listener3); 29952d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi // - listener already registered:w 30052d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi mustFail(() -> { manager.resolveService(validService, listener3); }); 30152d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi } 30252d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi 30352d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi public void mustFail(Runnable fn) { 30452d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi try { 30552d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi fn.run(); 30652d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi fail(); 30752d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi } catch (Exception expected) { 30852d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi } 30952d9e733aedf210b50f1df389cc23fbf28ab97feHugo Benichi } 310db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 311db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi NsdManager makeManager() { 312db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi NsdManager manager = new NsdManager(mContext, mService); 313db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi // Acknowledge first two messages connecting the AsyncChannel. 314db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi verify(mServiceHandler, timeout(mTimeoutMs).times(2)).handleMessage(any()); 315db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi reset(mServiceHandler); 316db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi assertNotNull(mServiceHandler.chan); 317db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi return manager; 318db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi } 319db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 320db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi int verifyRequest(int expectedMessageType) { 321db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi verify(mServiceHandler, timeout(mTimeoutMs)).handleMessage(any()); 322db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi reset(mServiceHandler); 323db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi Message received = mServiceHandler.lastMessage; 324db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi assertEquals(NsdManager.nameOf(expectedMessageType), NsdManager.nameOf(received.what)); 325db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi return received.arg2; 326db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi } 327db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 328db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi void sendResponse(int replyType, int arg, int key, Object obj) { 329db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi mServiceHandler.chan.sendMessage(replyType, arg, key, obj); 330db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi } 331db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 332db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi // Implements the server side of AsyncChannel connection protocol 333db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi public static class MockServiceHandler extends Handler { 334db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi public Context mContext; 335db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi public AsyncChannel chan; 33622143956cfc6d9f59b0aac0e7007a3088200adddHugo Benichi public volatile Message lastMessage; 337db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 338db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi MockServiceHandler(Looper looper, Context context) { 339db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi super(looper); 340db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi mContext = context; 341db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi } 342db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 343db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi @Override 344db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi public void handleMessage(Message msg) { 345db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi lastMessage = obtainMessage(); 346db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi lastMessage.copyFrom(msg); 347db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi if (msg.what == AsyncChannel.CMD_CHANNEL_FULL_CONNECTION) { 348db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi chan = new AsyncChannel(); 349db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi chan.connect(mContext, this, msg.replyTo); 350db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi chan.sendMessage(AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED); 351db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi } 352db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi } 353db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi 354db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi public static MockServiceHandler create(Context context) { 355db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi HandlerThread t = new HandlerThread("mock-service-handler"); 356db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi t.start(); 357db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi return new MockServiceHandler(t.getLooper(), context); 358db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi } 359db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi } 360db8adb798394af6381974444bfa0c47f4b30f0fbHugo Benichi} 361