Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 60175d2d authored by Xiao Ma's avatar Xiao Ma
Browse files

Add basic IpReachabilityMonitor integration test.

    - verify the specific number of unicast NS for probe.
    - verify the notifyLost() callback will be triggered if probe
      failed.
    - verify the notifyLost() callback won't be triggered if
      probe succeed(i.e. receive solicited NA as reply).

Bug: 162944199
Test: atest NetworkStackIntegrationTest NetworkStackTests
Change-Id: I6ea04a624b0f0485625a3ec46d7a5544f9d2713b
parent 66d8399c
Loading
Loading
Loading
Loading
+25 −1
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ import android.net.util.NetworkStackUtils;
import android.net.util.SharedLog;
import android.os.Build;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
@@ -596,10 +597,32 @@ public class IpClient extends StateMachine {
            return new IpConnectivityLog();
        }

        /**
         * Get a NetworkQuirkMetrics instance.
         */
        public NetworkQuirkMetrics getNetworkQuirkMetrics() {
            return new NetworkQuirkMetrics();
        }

        /**
         * Get a IpReachabilityMonitor instance.
         */
        public IpReachabilityMonitor getIpReachabilityMonitor(Context context,
                InterfaceParams ifParams, Handler h, SharedLog log,
                IpReachabilityMonitor.Callback callback, boolean usingMultinetworkPolicyTracker,
                IpReachabilityMonitor.Dependencies deps, final INetd netd) {
            return new IpReachabilityMonitor(context, ifParams, h, log, callback,
                    usingMultinetworkPolicyTracker, deps, netd);
        }

        /**
         * Get a IpReachabilityMonitor dependencies instance.
         */
        public IpReachabilityMonitor.Dependencies getIpReachabilityMonitorDeps(Context context,
                String name) {
            return IpReachabilityMonitor.Dependencies.makeDefault(context, name);
        }

        /**
         * Return whether a feature guarded by a feature flag is enabled.
         * @see NetworkStackUtils#isFeatureEnabled(Context, String, String)
@@ -1776,7 +1799,7 @@ public class IpClient extends StateMachine {

    private boolean startIpReachabilityMonitor() {
        try {
            mIpReachabilityMonitor = new IpReachabilityMonitor(
            mIpReachabilityMonitor = mDependencies.getIpReachabilityMonitor(
                    mContext,
                    mInterfaceParams,
                    getHandler(),
@@ -1788,6 +1811,7 @@ public class IpClient extends StateMachine {
                        }
                    },
                    mConfiguration.mUsingMultinetworkPolicyTracker,
                    mDependencies.getIpReachabilityMonitorDeps(mContext, mInterfaceParams.name),
                    mNetd);
        } catch (IllegalArgumentException iae) {
            // Failed to start IpReachabilityMonitor. Log it and call
+3 −3
Original line number Diff line number Diff line
@@ -199,9 +199,9 @@ public class IpReachabilityMonitor {

    public IpReachabilityMonitor(
            Context context, InterfaceParams ifParams, Handler h, SharedLog log, Callback callback,
            boolean usingMultinetworkPolicyTracker, final INetd netd) {
        this(context, ifParams, h, log, callback, usingMultinetworkPolicyTracker,
                Dependencies.makeDefault(context, ifParams.name), new IpConnectivityLog(), netd);
            boolean usingMultinetworkPolicyTracker, Dependencies dependencies, final INetd netd) {
        this(context, ifParams, h, log, callback, usingMultinetworkPolicyTracker, dependencies,
                new IpConnectivityLog(), netd);
    }

    @VisibleForTesting
+13 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package android.net.ip

import android.net.ipmemorystore.NetworkAttributes
import android.util.ArrayMap
import java.net.Inet6Address
import kotlin.test.assertEquals
import org.mockito.Mockito.any
import org.mockito.ArgumentCaptor
import org.mockito.Mockito.eq
@@ -56,4 +58,15 @@ class IpClientIntegrationTest : IpClientIntegrationTestCommon() {
    override fun assertIpMemoryNeverStoreNetworkAttributes(l2Key: String, timeout: Long) {
        verify(mIpMemoryStore, never()).storeNetworkAttributes(eq(l2Key), any(), any())
    }

    override fun assertNotifyNeighborLost(targetIp: Inet6Address) {
        val target = ArgumentCaptor.forClass(Inet6Address::class.java)

        verify(mCallback, timeout(TEST_TIMEOUT_MS)).notifyLost(target.capture(), any())
        assertEquals(targetIp, target.getValue())
    }

    override fun assertNeverNotifyNeighborLost() {
        verify(mCallback, never()).notifyLost(any(), any())
    }
}
+170 −24
Original line number Diff line number Diff line
@@ -40,13 +40,17 @@ import static com.android.net.module.util.NetworkStackConstants.ETHER_ADDR_LEN;
import static com.android.net.module.util.NetworkStackConstants.ETHER_BROADCAST;
import static com.android.net.module.util.NetworkStackConstants.ETHER_HEADER_LEN;
import static com.android.net.module.util.NetworkStackConstants.ETHER_TYPE_OFFSET;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_SLLA;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_NEIGHBOR_ADVERTISEMENT;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_NEIGHBOR_SOLICITATION;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ROUTER_SOLICITATION;
import static com.android.net.module.util.NetworkStackConstants.IPV4_ADDR_ANY;
import static com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_ALL_NODES_MULTICAST;
import static com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_ALL_ROUTERS_MULTICAST;
import static com.android.net.module.util.NetworkStackConstants.IPV6_HEADER_LEN;
import static com.android.net.module.util.NetworkStackConstants.IPV6_PROTOCOL_OFFSET;
import static com.android.net.module.util.NetworkStackConstants.NEIGHBOR_ADVERTISEMENT_FLAG_ROUTER;
import static com.android.net.module.util.NetworkStackConstants.NEIGHBOR_ADVERTISEMENT_FLAG_SOLICITED;
import static com.android.net.module.util.NetworkStackConstants.PIO_FLAG_AUTONOMOUS;
import static com.android.net.module.util.NetworkStackConstants.PIO_FLAG_ON_LINK;

@@ -108,6 +112,7 @@ import android.net.dhcp.DhcpDiscoverPacket;
import android.net.dhcp.DhcpPacket;
import android.net.dhcp.DhcpPacket.ParseException;
import android.net.dhcp.DhcpRequestPacket;
import android.net.ip.IpNeighborMonitor.NeighborEventConsumer;
import android.net.ipmemorystore.NetworkAttributes;
import android.net.ipmemorystore.OnNetworkAttributesRetrievedListener;
import android.net.ipmemorystore.Status;
@@ -119,6 +124,7 @@ import android.net.shared.ProvisioningConfiguration;
import android.net.shared.ProvisioningConfiguration.ScanResultInfo;
import android.net.util.InterfaceParams;
import android.net.util.NetworkStackUtils;
import android.net.util.SharedLog;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
@@ -141,6 +147,7 @@ import com.android.internal.util.HexDump;
import com.android.internal.util.StateMachine;
import com.android.net.module.util.ArrayTrackRecord;
import com.android.net.module.util.Ipv6Utils;
import com.android.net.module.util.structs.LlaOption;
import com.android.net.module.util.structs.PrefixInformationOption;
import com.android.net.module.util.structs.RdnssOption;
import com.android.networkstack.apishim.CaptivePortalDataShimImpl;
@@ -150,6 +157,7 @@ import com.android.networkstack.arp.ArpPacket;
import com.android.networkstack.metrics.IpProvisioningMetrics;
import com.android.networkstack.metrics.NetworkQuirkMetrics;
import com.android.networkstack.packets.NeighborAdvertisement;
import com.android.networkstack.packets.NeighborSolicitation;
import com.android.server.NetworkObserver;
import com.android.server.NetworkObserverRegistry;
import com.android.server.NetworkStackService.NetworkStackServiceManager;
@@ -263,6 +271,7 @@ public abstract class IpClientIntegrationTestCommon {
    @Mock private PowerManager.WakeLock mTimeoutWakeLock;
    @Mock protected NetworkStackIpMemoryStore mIpMemoryStore;
    @Mock private NetworkQuirkMetrics.Dependencies mNetworkQuirkMetricsDeps;
    @Mock protected IpReachabilityMonitor.Callback mCallback;

    @Spy private INetd mNetd;
    private NetworkObserverRegistry mNetworkObserverRegistry;
@@ -272,7 +281,7 @@ public abstract class IpClientIntegrationTestCommon {

    /***** END signature required test members *****/

    private IIpClientCallbacks mCb;
    protected IIpClientCallbacks mCb;
    private IIpClient mIIpClient;
    private String mIfaceName;
    private HandlerThread mPacketReaderThread;
@@ -327,7 +336,10 @@ public abstract class IpClientIntegrationTestCommon {
    private static final String HOSTNAME = "testhostname";
    private static final int TEST_DEFAULT_MTU = 1500;
    private static final int TEST_MIN_MTU = 1280;
    private static final byte[] SERVER_MAC = new byte[] { 0x00, 0x1A, 0x11, 0x22, 0x33, 0x44 };
    private static final MacAddress ROUTER_MAC = MacAddress.fromString("00:1A:11:22:33:44");
    private static final byte[] ROUTER_MAC_BYTES = ROUTER_MAC.toByteArray();
    private static final Inet6Address ROUTER_LINK_LOCAL =
                (Inet6Address) InetAddresses.parseNumericAddress("fe80::1");
    private static final String TEST_HOST_NAME = "AOSP on Crosshatch";
    private static final String TEST_HOST_NAME_TRANSLITERATION = "AOSP-on-Crosshatch";
    private static final String TEST_CAPTIVE_PORTAL_URL = "https://example.com/capportapi";
@@ -400,6 +412,15 @@ public abstract class IpClientIntegrationTestCommon {
            return mDhcpClient;
        }

        @Override
        public IpReachabilityMonitor getIpReachabilityMonitor(Context context,
                InterfaceParams ifParams, Handler h, SharedLog log,
                IpReachabilityMonitor.Callback callback, boolean usingMultinetworkPolicyTracker,
                IpReachabilityMonitor.Dependencies deps, final INetd netd) {
            return new IpReachabilityMonitor(context, ifParams, h, log, mCallback,
                    usingMultinetworkPolicyTracker, deps, netd);
        }

        @Override
        public boolean isFeatureEnabled(final Context context, final String name,
                final boolean defaultEnabled) {
@@ -439,6 +460,23 @@ public abstract class IpClientIntegrationTestCommon {
            };
        }

        @Override
        public IpReachabilityMonitor.Dependencies getIpReachabilityMonitorDeps(Context context,
                String name) {
            return new IpReachabilityMonitor.Dependencies() {
                public void acquireWakeLock(long durationMs) {
                    // It doesn't matter for the integration test app on whether the wake lock
                    // is acquired or not.
                    return;
                }

                public IpNeighborMonitor makeIpNeighborMonitor(Handler h, SharedLog log,
                        NeighborEventConsumer cb) {
                    return new IpNeighborMonitor(h, log, cb);
                }
            };
        }

        @Override
        public int getDeviceConfigPropertyInt(String name, int defaultValue) {
            Integer value = mIntConfigProperties.get(name);
@@ -472,6 +510,10 @@ public abstract class IpClientIntegrationTestCommon {

    protected abstract void assertIpMemoryNeverStoreNetworkAttributes(String l2Key, long timeout);

    protected abstract void assertNotifyNeighborLost(Inet6Address targetIp);

    protected abstract void assertNeverNotifyNeighborLost();

    protected final boolean testSkipped() {
        // TODO: split out a test suite for root tests, and fail hard instead of skipping the test
        // if it is run on devices where TestNetworkStackServiceClient is not supported
@@ -712,6 +754,14 @@ public abstract class IpClientIntegrationTestCommon {
        }
    }

    private NeighborSolicitation parseNeighborSolicitationOrNull(final byte[] packet) {
        try {
            return NeighborSolicitation.parse(packet, packet.length);
        } catch (NeighborSolicitation.ParseException e) {
            return null;
        }
    }

    private static ByteBuffer buildDhcpOfferPacket(final DhcpPacket packet,
            final Inet4Address clientAddress, final Integer leaseTimeSec, final short mtu,
            final String captivePortalUrl, final Integer ipv6OnlyWaitTime) {
@@ -761,7 +811,7 @@ public abstract class IpClientIntegrationTestCommon {

    private void sendArpReply(final byte[] clientMac) throws IOException {
        final ByteBuffer packet = ArpPacket.buildArpPacket(clientMac /* dst */,
                SERVER_MAC /* src */, INADDR_ANY.getAddress() /* target IP */,
                ROUTER_MAC_BYTES /* srcMac */, INADDR_ANY.getAddress() /* target IP */,
                clientMac /* target HW address */, CLIENT_ADDR.getAddress() /* sender IP */,
                (short) ARP_REPLY);
        mPacketReader.sendResponse(packet);
@@ -769,7 +819,7 @@ public abstract class IpClientIntegrationTestCommon {

    private void sendArpProbe() throws IOException {
        final ByteBuffer packet = ArpPacket.buildArpPacket(DhcpPacket.ETHER_BROADCAST /* dst */,
                SERVER_MAC /* src */, CLIENT_ADDR.getAddress() /* target IP */,
                ROUTER_MAC_BYTES /* srcMac */, CLIENT_ADDR.getAddress() /* target IP */,
                new byte[ETHER_ADDR_LEN] /* target HW address */,
                INADDR_ANY.getAddress() /* sender IP */, (short) ARP_REQUEST);
        mPacketReader.sendResponse(packet);
@@ -1458,20 +1508,23 @@ public abstract class IpClientIntegrationTestCommon {
        HandlerUtils.waitForIdle(mIpc.getHandler(), TEST_TIMEOUT_MS);
    }

    private boolean isRouterSolicitation(final byte[] packetBytes) {
    private boolean isIcmpv6PacketOfType(final byte[] packetBytes, int type) {
        ByteBuffer packet = ByteBuffer.wrap(packetBytes);
        return packet.getShort(ETHER_TYPE_OFFSET) == (short) ETH_P_IPV6
                && packet.get(ETHER_HEADER_LEN + IPV6_PROTOCOL_OFFSET) == (byte) IPPROTO_ICMPV6
                && packet.get(ETHER_HEADER_LEN + IPV6_HEADER_LEN)
                        == (byte) ICMPV6_ROUTER_SOLICITATION;
                && packet.get(ETHER_HEADER_LEN + IPV6_HEADER_LEN) == (byte) type;
    }

    private boolean isRouterSolicitation(final byte[] packetBytes) {
        return isIcmpv6PacketOfType(packetBytes, ICMPV6_ROUTER_SOLICITATION);
    }

    private boolean isNeighborAdvertisement(final byte[] packetBytes) {
        ByteBuffer packet = ByteBuffer.wrap(packetBytes);
        return packet.getShort(ETHER_TYPE_OFFSET) == (short) ETH_P_IPV6
                && packet.get(ETHER_HEADER_LEN + IPV6_PROTOCOL_OFFSET) == (byte) IPPROTO_ICMPV6
                && packet.get(ETHER_HEADER_LEN + IPV6_HEADER_LEN)
                        == (byte) ICMPV6_NEIGHBOR_ADVERTISEMENT;
        return isIcmpv6PacketOfType(packetBytes, ICMPV6_NEIGHBOR_ADVERTISEMENT);
    }

    private boolean isNeighborSolicitation(final byte[] packetBytes) {
        return isIcmpv6PacketOfType(packetBytes, ICMPV6_NEIGHBOR_SOLICITATION);
    }

    private NeighborAdvertisement getNextNeighborAdvertisement() throws ParseException {
@@ -1484,6 +1537,16 @@ public abstract class IpClientIntegrationTestCommon {
        return na;
    }

    private NeighborSolicitation getNextNeighborSolicitation() throws ParseException {
        final byte[] packet = mPacketReader.popPacket(PACKET_TIMEOUT_MS,
                this::isNeighborSolicitation);
        if (packet == null) return null;

        final NeighborSolicitation ns = parseNeighborSolicitationOrNull(packet);
        assertNotNull("Invalid neighbour solicitation received", ns);
        return ns;
    }

    private void waitForRouterSolicitation() throws ParseException {
        assertNotNull("No router solicitation received on interface within timeout",
                mPacketReader.popPacket(PACKET_TIMEOUT_MS, this::isRouterSolicitation));
@@ -1521,17 +1584,18 @@ public abstract class IpClientIntegrationTestCommon {
        return RdnssOption.build(lifetime, servers);
    }

    private static ByteBuffer buildSllaOption() throws Exception {
        return LlaOption.build((byte) ICMPV6_ND_OPTION_SLLA, ROUTER_MAC);
    }

    private static ByteBuffer buildRaPacket(short lifetime, ByteBuffer... options)
            throws Exception {
        final MacAddress dstMac = MacAddress.fromString("33:33:00:00:00:01");
        final MacAddress srcMac = MacAddress.fromString("01:02:03:04:05:06");
        final Inet6Address routerLinkLocal =
                (Inet6Address) InetAddresses.parseNumericAddress("fe80::1");

        return Ipv6Utils.buildRaPacket(srcMac, dstMac, routerLinkLocal,
                IPV6_ADDR_ALL_NODES_MULTICAST, (byte) 0 /* M=0, O=0 */, lifetime,
                0 /* Reachable time, unspecified */, 100 /* Retrans time 100ms */,
                options);
        final MacAddress dstMac =
                NetworkStackUtils.ipv6MulticastToEthernetMulticast(IPV6_ADDR_ALL_ROUTERS_MULTICAST);
        return Ipv6Utils.buildRaPacket(ROUTER_MAC /* srcMac */, dstMac,
                ROUTER_LINK_LOCAL /* srcIp */, IPV6_ADDR_ALL_NODES_MULTICAST /* dstIp */,
                (byte) 0 /* M=0, O=0 */, lifetime, 0 /* Reachable time, unspecified */,
                100 /* Retrans time 100ms */, options);
    }

    private static ByteBuffer buildRaPacket(ByteBuffer... options) throws Exception {
@@ -1575,7 +1639,8 @@ public abstract class IpClientIntegrationTestCommon {
        final String dnsServer = "2001:4860:4860::64";
        final ByteBuffer pio = buildPioOption(3600, 1800, "2001:db8:1::/64");
        final ByteBuffer rdnss = buildRdnssOption(3600, dnsServer);
        final ByteBuffer ra = buildRaPacket(pio, rdnss);
        final ByteBuffer slla = buildSllaOption();
        final ByteBuffer ra = buildRaPacket(pio, rdnss, slla);

        return doIpv6OnlyProvisioning(inOrder, ra);
    }
@@ -2383,7 +2448,8 @@ public abstract class IpClientIntegrationTestCommon {
        final String dnsServer = "2001:4860:4860::64";
        final ByteBuffer pio = buildPioOption(3600, 1800, "2001:db8:1::/64");
        final ByteBuffer rdnss = buildRdnssOption(3600, dnsServer);
        final ByteBuffer ra = buildRaPacket(pio, rdnss);
        final ByteBuffer slla = buildSllaOption();
        final ByteBuffer ra = buildRaPacket(pio, rdnss, slla);

        doIpv6OnlyProvisioning(inOrder, ra);

@@ -2965,7 +3031,7 @@ public abstract class IpClientIntegrationTestCommon {
    @Test
    public void testGratuitousArpAndNaAfterRoaming_disableExpFlag() throws Exception {
        startGratuitousArpAndNaAfterRoamingTest(false /* isGratuitousArpNaRoamingEnabled */,
                true /* hasIpv6 */, true /* hasIpv6 */);
                true /* hasIpv4 */, true /* hasIpv6 */);
        performDualStackProvisioning();
        forceLayer2Roaming();

@@ -3007,4 +3073,84 @@ public abstract class IpClientIntegrationTestCommon {
        assertEquals(0, naList.size());
        assertEquals(1, arpList.size());
    }

    private void assertNeighborSolicitation(final NeighborSolicitation ns,
            final Inet6Address target) {
        assertEquals(ETH_P_IPV6, ns.ethHdr.etherType);
        assertEquals(IPPROTO_ICMPV6, ns.ipv6Hdr.nextHeader);
        assertEquals(0xff, ns.ipv6Hdr.hopLimit);
        assertTrue(ns.ipv6Hdr.srcIp.isLinkLocalAddress());
        assertEquals(ICMPV6_NEIGHBOR_SOLICITATION, ns.icmpv6Hdr.type);
        assertEquals(0, ns.icmpv6Hdr.code);
        assertEquals(0, ns.nsHdr.reserved);
        assertEquals(target, ns.nsHdr.target);
        assertEquals(ns.slla.linkLayerAddress, ns.ethHdr.srcMac);
    }

    private void assertUnicastNeighborSolicitation(final NeighborSolicitation ns,
            final MacAddress dstMac, final Inet6Address dstIp, final Inet6Address target) {
        assertEquals(dstMac, ns.ethHdr.dstMac);
        assertEquals(dstIp, ns.ipv6Hdr.dstIp);
        assertNeighborSolicitation(ns, target);
    }

    private void prepareIpReachabilityMonitorTest() throws Exception {
        final ScanResultInfo info = makeScanResultInfo(TEST_DEFAULT_SSID, TEST_DEFAULT_BSSID);
        ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
                .withLayer2Information(new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
                       MacAddress.fromString(TEST_DEFAULT_BSSID)))
                .withScanResultInfo(info)
                .withDisplayName(TEST_DEFAULT_SSID)
                .withoutIPv4()
                .build();
        startIpClientProvisioning(config);
        verify(mCb, timeout(TEST_TIMEOUT_MS)).setFallbackMulticastFilter(false);
        doIpv6OnlyProvisioning();

        // Simulate the roaming.
        forceLayer2Roaming();
    }

    @Test
    public void testIpReachabilityMonitor_probeFailed() throws Exception {
        prepareIpReachabilityMonitorTest();

        NeighborSolicitation packet;
        final List<NeighborSolicitation> nsList = new ArrayList<NeighborSolicitation>();
        while ((packet = getNextNeighborSolicitation()) != null) {
            // Filter out the NSes used for duplicate address detetction, the target address
            // is the global IPv6 address inside these NSes.
            if (packet.nsHdr.target.isLinkLocalAddress()) {
                nsList.add(packet);
            }
        }
        assertEquals(IpReachabilityMonitor.MIN_NUD_SOLICIT_NUM, nsList.size());
        for (NeighborSolicitation ns : nsList) {
            assertUnicastNeighborSolicitation(ns, ROUTER_MAC /* dstMac */,
                    ROUTER_LINK_LOCAL /* dstIp */, ROUTER_LINK_LOCAL /* targetIp */);
        }
        assertNotifyNeighborLost(ROUTER_LINK_LOCAL /* targetIp */);
    }

    @Test
    public void testIpReachabilityMonitor_probeReachable() throws Exception {
        prepareIpReachabilityMonitorTest();

        NeighborSolicitation ns;
        while ((ns = getNextNeighborSolicitation()) != null) {
            // Filter out the NSes used for duplicate address detetction, the target address
            // is the global IPv6 address inside these NSes.
            if (ns.nsHdr.target.isLinkLocalAddress()) break;
        }
        assertUnicastNeighborSolicitation(ns, ROUTER_MAC /* dstMac */,
                ROUTER_LINK_LOCAL /* dstIp */, ROUTER_LINK_LOCAL /* targetIp */);

        // Reply Neighbor Advertisement and check notifyLost callback won't be triggered.
        int flag = NEIGHBOR_ADVERTISEMENT_FLAG_ROUTER | NEIGHBOR_ADVERTISEMENT_FLAG_SOLICITED;
        final ByteBuffer na = NeighborAdvertisement.build(ROUTER_MAC /* srcMac */,
                ns.ethHdr.srcMac /* dstMac */, ROUTER_LINK_LOCAL /* srcIp */,
                ns.ipv6Hdr.srcIp /* dstIp */, flag, ROUTER_LINK_LOCAL /* target */);
        mPacketReader.sendResponse(na);
        assertNeverNotifyNeighborLost();
    }
}
+11 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.util.Log
import androidx.test.platform.app.InstrumentationRegistry
import com.android.net.module.util.DeviceConfigUtils
import java.lang.System.currentTimeMillis
import java.net.Inet6Address
import java.util.concurrent.CompletableFuture
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
@@ -45,6 +46,8 @@ import org.junit.After
import org.junit.AfterClass
import org.junit.BeforeClass
import org.mockito.ArgumentCaptor
import org.mockito.Mockito.anyString
import org.mockito.Mockito.never
import org.mockito.Mockito.timeout
import org.mockito.Mockito.verify

@@ -260,4 +263,12 @@ class IpClientRootTest : IpClientIntegrationTestCommon() {
        mStore.retrieveNetworkAttributes(l2Key, listener)
        assertNull(listener.getBlockingNetworkAttributes(timeout))
    }

    override fun assertNotifyNeighborLost(targetIp: Inet6Address) {
        verify(mCb, timeout(TEST_TIMEOUT_MS)).onReachabilityLost(anyString())
    }

    override fun assertNeverNotifyNeighborLost() {
        verify(mCb, never()).onReachabilityLost(anyString())
    }
}
Loading