Merge "Update NSD tests without AsyncChannel" am: 469d941752

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/1823893

Change-Id: I897bdce6cdaf4ea390d8ce6be03b87bacd6da82e
This commit is contained in:
Remi NGUYEN VAN
2021-11-22 06:19:18 +00:00
committed by Automerger Merge Worker
2 changed files with 162 additions and 177 deletions

View File

@@ -20,6 +20,7 @@ import static libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChange
import static libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -33,14 +34,19 @@ import static org.mockito.Mockito.when;
import android.compat.testing.PlatformCompatChangeRule;
import android.content.ContentResolver;
import android.content.Context;
import android.net.nsd.INsdManagerCallback;
import android.net.nsd.INsdServiceConnector;
import android.net.nsd.NsdManager;
import android.net.nsd.NsdServiceInfo;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import androidx.annotation.NonNull;
import androidx.test.filters.SmallTest;
import com.android.server.NsdService.DaemonConnection;
@@ -56,11 +62,15 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import org.mockito.AdditionalAnswers;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import java.util.LinkedList;
import java.util.Queue;
// TODOs:
// - test client can send requests and receive replies
// - test NSD_ON ENABLE/DISABLED listening
@@ -73,6 +83,11 @@ public class NsdServiceTest {
private static final long CLEANUP_DELAY_MS = 500;
private static final long TIMEOUT_MS = 500;
// Records INsdManagerCallback created when NsdService#connect is called.
// Only accessed on the test thread, since NsdService#connect is called by the NsdManager
// constructor called on the test thread.
private final Queue<INsdManagerCallback> mCreatedCallbacks = new LinkedList<>();
@Rule
public TestRule compatChangeRule = new PlatformCompatChangeRule();
@Mock Context mContext;
@@ -83,6 +98,16 @@ public class NsdServiceTest {
HandlerThread mThread;
TestHandler mHandler;
private static class LinkToDeathRecorder extends Binder {
IBinder.DeathRecipient mDr;
@Override
public void linkToDeath(@NonNull DeathRecipient recipient, int flags) {
super.linkToDeath(recipient, flags);
mDr = recipient;
}
}
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -103,26 +128,30 @@ public class NsdServiceTest {
@Test
@DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
public void testPreSClients() {
public void testPreSClients() throws Exception {
when(mSettings.isEnabled()).thenReturn(true);
NsdService service = makeService();
// Pre S client connected, the daemon should be started.
NsdManager client1 = connectClient(service);
connectClient(service);
waitForIdle();
final INsdManagerCallback cb1 = getCallback();
final IBinder.DeathRecipient deathRecipient1 = verifyLinkToDeath(cb1);
verify(mDaemon, times(1)).maybeStart();
verifyDaemonCommands("start-service");
NsdManager client2 = connectClient(service);
connectClient(service);
waitForIdle();
final INsdManagerCallback cb2 = getCallback();
final IBinder.DeathRecipient deathRecipient2 = verifyLinkToDeath(cb2);
verify(mDaemon, times(1)).maybeStart();
client1.disconnect();
deathRecipient1.binderDied();
// Still 1 client remains, daemon shouldn't be stopped.
waitForIdle();
verify(mDaemon, never()).maybeStop();
client2.disconnect();
deathRecipient2.binderDied();
// All clients are disconnected, the daemon should be stopped.
verifyDelayMaybeStopDaemon(CLEANUP_DELAY_MS);
verifyDaemonCommands("stop-service");
@@ -130,43 +159,51 @@ public class NsdServiceTest {
@Test
@EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
public void testNoDaemonStartedWhenClientsConnect() {
public void testNoDaemonStartedWhenClientsConnect() throws Exception {
when(mSettings.isEnabled()).thenReturn(true);
NsdService service = makeService();
final NsdService service = makeService();
// Creating an NsdManager will not cause any cmds executed, which means
// no daemon is started.
NsdManager client1 = connectClient(service);
connectClient(service);
waitForIdle();
verify(mDaemon, never()).execute(any());
final INsdManagerCallback cb1 = getCallback();
final IBinder.DeathRecipient deathRecipient1 = verifyLinkToDeath(cb1);
// Creating another NsdManager will not cause any cmds executed.
NsdManager client2 = connectClient(service);
connectClient(service);
waitForIdle();
verify(mDaemon, never()).execute(any());
final INsdManagerCallback cb2 = getCallback();
final IBinder.DeathRecipient deathRecipient2 = verifyLinkToDeath(cb2);
// If there is no active request, try to clean up the daemon
// every time the client disconnects.
client1.disconnect();
deathRecipient1.binderDied();
verifyDelayMaybeStopDaemon(CLEANUP_DELAY_MS);
reset(mDaemon);
client2.disconnect();
deathRecipient2.binderDied();
verifyDelayMaybeStopDaemon(CLEANUP_DELAY_MS);
}
client1.disconnect();
client2.disconnect();
private IBinder.DeathRecipient verifyLinkToDeath(INsdManagerCallback cb)
throws Exception {
final IBinder.DeathRecipient dr = ((LinkToDeathRecorder) cb.asBinder()).mDr;
assertNotNull(dr);
return dr;
}
@Test
@EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
public void testClientRequestsAreGCedAtDisconnection() {
public void testClientRequestsAreGCedAtDisconnection() throws Exception {
when(mSettings.isEnabled()).thenReturn(true);
NsdService service = makeService();
NsdManager client = connectClient(service);
NsdManager client = connectClient(service);
waitForIdle();
final INsdManagerCallback cb1 = getCallback();
final IBinder.DeathRecipient deathRecipient = verifyLinkToDeath(cb1);
verify(mDaemon, never()).maybeStart();
verify(mDaemon, never()).execute(any());
@@ -195,18 +232,16 @@ public class NsdServiceTest {
verifyDaemonCommand("resolve 4 a_name a_type local.");
// Client disconnects, stop the daemon after CLEANUP_DELAY_MS.
client.disconnect();
deathRecipient.binderDied();
verifyDelayMaybeStopDaemon(CLEANUP_DELAY_MS);
// checks that request are cleaned
verifyDaemonCommands("stop-register 2", "stop-discover 3",
"stop-resolve 4", "stop-service");
client.disconnect();
}
@Test
@EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
public void testCleanupDelayNoRequestActive() {
public void testCleanupDelayNoRequestActive() throws Exception {
when(mSettings.isEnabled()).thenReturn(true);
NsdService service = makeService();
@@ -218,6 +253,8 @@ public class NsdServiceTest {
client.registerService(request, PROTOCOL, listener1);
waitForIdle();
verify(mDaemon, times(1)).maybeStart();
final INsdManagerCallback cb1 = getCallback();
final IBinder.DeathRecipient deathRecipient = verifyLinkToDeath(cb1);
verifyDaemonCommands("start-service", "register 2 a_name a_type 2201");
client.unregisterService(listener1);
@@ -226,7 +263,7 @@ public class NsdServiceTest {
verifyDelayMaybeStopDaemon(CLEANUP_DELAY_MS);
verifyDaemonCommand("stop-service");
reset(mDaemon);
client.disconnect();
deathRecipient.binderDied();
// Client disconnects, after CLEANUP_DELAY_MS, maybeStop the daemon.
verifyDelayMaybeStopDaemon(CLEANUP_DELAY_MS);
}
@@ -240,12 +277,29 @@ public class NsdServiceTest {
mDaemonCallback = callback;
return mDaemon;
};
NsdService service = new NsdService(mContext, mSettings,
mHandler, supplier, CLEANUP_DELAY_MS);
final NsdService service = new NsdService(mContext, mSettings,
mHandler, supplier, CLEANUP_DELAY_MS) {
@Override
public INsdServiceConnector connect(INsdManagerCallback baseCb) {
// Wrap the callback in a transparent mock, to mock asBinder returning a
// LinkToDeathRecorder. This will allow recording the binder death recipient
// registered on the callback. Use a transparent mock and not a spy as the actual
// implementation class is not public and cannot be spied on by Mockito.
final INsdManagerCallback cb = mock(INsdManagerCallback.class,
AdditionalAnswers.delegatesTo(baseCb));
doReturn(new LinkToDeathRecorder()).when(cb).asBinder();
mCreatedCallbacks.add(cb);
return super.connect(cb);
}
};
verify(mDaemon, never()).execute(any(String.class));
return service;
}
private INsdManagerCallback getCallback() {
return mCreatedCallbacks.remove();
}
NsdManager connectClient(NsdService service) {
return new NsdManager(mContext, service);
}