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

Commit 23dbe7f7 authored by Maciej Żenczykowski's avatar Maciej Żenczykowski Committed by Automerger Merge Worker
Browse files

Merge "Deflake and fix testIpClientClearingIpAddressState." am: 2b7c71e2

Change-Id: I1242434ee3f70aa353478b76ac723be64775cf8b
parents 443e4365 2b7c71e2
Loading
Loading
Loading
Loading
+80 −11
Original line number Diff line number Diff line
@@ -130,6 +130,7 @@ import com.android.networkstack.apishim.CaptivePortalDataShimImpl;
import com.android.networkstack.apishim.ConstantsShim;
import com.android.networkstack.apishim.ShimUtils;
import com.android.networkstack.arp.ArpPacket;
import com.android.server.NetworkObserver;
import com.android.server.NetworkObserverRegistry;
import com.android.server.NetworkStackService.NetworkStackServiceManager;
import com.android.server.connectivity.ipmemorystore.IpMemoryStoreService;
@@ -164,6 +165,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * Tests for IpClient.
@@ -195,6 +198,7 @@ public class IpClientIntegrationTest {
    @Spy private INetd mNetd;

    private String mIfaceName;
    private NetworkObserverRegistry mNetworkObserverRegistry;
    private HandlerThread mPacketReaderThread;
    private Handler mHandler;
    private TapPacketReader mPacketReader;
@@ -437,10 +441,10 @@ public class IpClientIntegrationTest {
        when(mContext.getSystemService(eq(Context.NETD_SERVICE))).thenReturn(netdIBinder);
        assertNotNull(mNetd);

        final NetworkObserverRegistry reg = new NetworkObserverRegistry();
        reg.register(mNetd);
        mIpc = new IpClient(mContext, mIfaceName, mCb, reg, mNetworkStackServiceManager,
                mDependencies);
        mNetworkObserverRegistry = new NetworkObserverRegistry();
        mNetworkObserverRegistry.register(mNetd);
        mIpc = new IpClient(mContext, mIfaceName, mCb, mNetworkObserverRegistry,
                mNetworkStackServiceManager, mDependencies);
    }

    private boolean packetContainsExpectedField(final byte[] packet, final int offset,
@@ -1176,6 +1180,19 @@ public class IpClientIntegrationTest {
        fail("No router solicitation received on interface within timeout");
    }

    private void sendBasicRouterAdvertisement(boolean waitForRs) throws Exception {
        final String dnsServer = "2001:4860:4860::64";
        final ByteBuffer pio = buildPioOption(3600, 1800, "2001:db8:1::/64");
        ByteBuffer rdnss = buildRdnssOption(3600, dnsServer);
        ByteBuffer ra = buildRaPacket(pio, rdnss);

        if (waitForRs) {
            waitForRouterSolicitation();
        }

        mPacketReader.sendResponse(ra);
    }

    // TODO: move this and the following method to a common location and use them in ApfTest.
    private static ByteBuffer buildPioOption(int valid, int preferred, String prefixString)
            throws Exception {
@@ -1428,6 +1445,41 @@ public class IpClientIntegrationTest {
        expectNat64PrefixUpdate(inOrder, otherPrefix);
    }

    private void addIpAddressAndWaitForIt(final String iface) throws Exception {
        final CountDownLatch latch = new CountDownLatch(1);

        final String addr1 = "192.0.2.99";
        final String addr2 = "192.0.2.3";
        final int prefixLength = 26;

        // Add two IPv4 addresses to the specified interface, and proceed when the NetworkObserver
        // has seen the second one. This ensures that every other NetworkObserver registered with
        // mNetworkObserverRegistry - in particular, IpClient's - has seen the addition of the first
        // address.
        final LinkAddress trigger = new LinkAddress(addr2 + "/" + prefixLength);
        NetworkObserver observer = new NetworkObserver() {
            @Override
            public void onInterfaceAddressUpdated(LinkAddress address, String ifName) {
                if (ifName.equals(iface) && address.isSameAddressAs(trigger)) {
                    latch.countDown();
                }
            }
        };

        mNetworkObserverRegistry.registerObserverForNonblockingCallback(observer);
        try {
            mNetd.interfaceAddAddress(iface, addr1, prefixLength);
            mNetd.interfaceAddAddress(iface, addr2, prefixLength);
            assertTrue("Trigger IP address " + addr2 + " not seen after " + TEST_TIMEOUT_MS + "ms",
                    latch.await(TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS));
        } finally {
            mNetworkObserverRegistry.unregisterObserver(observer);
        }

        // Wait for IpClient to process the addition of the address.
        HandlerUtilsKt.waitForIdle(mIpc.getHandler(), TEST_TIMEOUT_MS);
    }

    @Test
    public void testIpClientClearingIpAddressState() throws Exception {
        final long currentTime = System.currentTimeMillis();
@@ -1446,14 +1498,31 @@ public class IpClientIntegrationTest {

        // Pretend that something else (e.g., Tethering) used the interface and left an IP address
        // configured on it. When IpClient starts, it must clear this address before proceeding.
        // TODO: test IPv6 instead, since the DHCP client will remove this address by replacing it
        // with the new address.
        mNetd.interfaceAddAddress(mIfaceName, "192.0.2.99", 26);
        // The address must be noticed before startProvisioning is called, or IpClient will
        // immediately declare provisioning success due to the presence of an IPv4 address.
        // The address must be IPv4 because IpClient clears IPv6 addresses on startup.
        //
        // TODO: once IpClient gets IP addresses directly from netlink instead of from netd, it
        // may be sufficient to call waitForIdle to see if IpClient has seen the address.
        addIpAddressAndWaitForIt(mIfaceName);

        // start IpClient again and should enter Clearing State and wait for the message from kernel
        performDhcpHandshake(true /* isSuccessLease */, TEST_LEASE_DURATION_S,
                true /* isDhcpLeaseCacheEnabled */, false /* shouldReplyRapidCommitAck */,
                TEST_DEFAULT_MTU, false /* isDhcpIpConflictDetectEnabled */);
        disableRouterSolicitationDelay();

        ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
                .withoutIpReachabilityMonitor()
                .build();
        mIpc.startProvisioning(config);

        sendBasicRouterAdvertisement(true /*waitForRs*/);

        // Check that the IPv4 addresses configured earlier are not in LinkProperties...
        ArgumentCaptor<LinkProperties> captor = ArgumentCaptor.forClass(LinkProperties.class);
        verify(mCb, timeout(TEST_TIMEOUT_MS)).onProvisioningSuccess(captor.capture());
        assertFalse(captor.getValue().hasIpv4Address());

        // ... or configured on the interface.
        InterfaceConfigurationParcel cfg = mNetd.interfaceGetCfg(mIfaceName);
        assertEquals("0.0.0.0", cfg.ipv4Addr);
    }

    @Test