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

Commit 2b7c71e2 authored by Maciej Żenczykowski's avatar Maciej Żenczykowski Committed by Gerrit Code Review
Browse files

Merge "Deflake and fix testIpClientClearingIpAddressState."

parents 4e86daf4 58da4e39
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