/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.connectivity;

import static android.net.CaptivePortal.APP_RETURN_DISMISSED;
import static android.net.DnsResolver.TYPE_A;
import static android.net.DnsResolver.TYPE_AAAA;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_SKIPPED;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.metrics.ValidationProbeEvent.PROBE_HTTP;
import static android.net.util.DataStallUtils.CONFIG_DATA_STALL_CONSECUTIVE_DNS_TIMEOUT_THRESHOLD;
import static android.net.util.DataStallUtils.CONFIG_DATA_STALL_EVALUATION_TYPE;
import static android.net.util.DataStallUtils.CONFIG_DATA_STALL_MIN_EVALUATE_INTERVAL;
import static android.net.util.DataStallUtils.CONFIG_DATA_STALL_TCP_POLLING_INTERVAL;
import static android.net.util.DataStallUtils.CONFIG_DATA_STALL_VALID_DNS_TIME_THRESHOLD;
import static android.net.util.DataStallUtils.DATA_STALL_EVALUATION_TYPE_DNS;
import static android.net.util.DataStallUtils.DATA_STALL_EVALUATION_TYPE_TCP;
import static android.net.util.DataStallUtils.DEFAULT_DATA_STALL_EVALUATION_TYPES;
import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS;
import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_OTHER_FALLBACK_URLS;
import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_USE_HTTPS;
import static android.net.util.NetworkStackUtils.DEFAULT_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT;
import static android.net.util.NetworkStackUtils.DISMISS_PORTAL_IN_VALIDATED_NETWORK;
import static android.net.util.NetworkStackUtils.DNS_PROBE_PRIVATE_IP_NO_INTERNET_VERSION;
import static android.net.util.NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTPS_URL;
import static android.net.util.NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTP_URL;
import static android.net.util.NetworkStackUtils.TEST_URL_EXPIRATION_TIME;
import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;

import static com.android.networkstack.util.DnsUtils.PRIVATE_DNS_PROBE_HOST_SUFFIX;
import static com.android.server.connectivity.NetworkMonitor.INITIAL_REEVALUATE_DELAY_MS;
import static com.android.server.connectivity.NetworkMonitor.extractCharset;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.after;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.atMost;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import static java.lang.System.currentTimeMillis;
import static java.util.Collections.singletonList;
import static java.util.stream.Collectors.toList;

import android.annotation.NonNull;
import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.net.CaptivePortalData;
import android.net.ConnectivityManager;
import android.net.DataStallReportParcelable;
import android.net.DnsResolver;
import android.net.INetd;
import android.net.INetworkMonitorCallbacks;
import android.net.InetAddresses;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkTestResultParcelable;
import android.net.Uri;
import android.net.captiveportal.CaptivePortalProbeResult;
import android.net.metrics.IpConnectivityLog;
import android.net.shared.PrivateDnsConfig;
import android.net.util.SharedLog;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.provider.Settings;
import android.telephony.CellIdentityGsm;
import android.telephony.CellIdentityLte;
import android.telephony.CellInfo;
import android.telephony.CellInfoGsm;
import android.telephony.CellInfoLte;
import android.telephony.CellSignalStrength;
import android.telephony.TelephonyManager;
import android.util.ArrayMap;

import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import com.android.networkstack.NetworkStackNotifier;
import com.android.networkstack.R;
import com.android.networkstack.apishim.CaptivePortalDataShimImpl;
import com.android.networkstack.apishim.ConstantsShim;
import com.android.networkstack.apishim.NetworkInformationShimImpl;
import com.android.networkstack.apishim.common.CaptivePortalDataShim;
import com.android.networkstack.apishim.common.NetworkInformationShim;
import com.android.networkstack.apishim.common.ShimUtils;
import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
import com.android.networkstack.metrics.DataStallDetectionStats;
import com.android.networkstack.metrics.DataStallStatsUtils;
import com.android.networkstack.netlink.TcpSocketTracker;
import com.android.server.NetworkStackService.NetworkStackServiceManager;
import com.android.server.connectivity.nano.CellularData;
import com.android.server.connectivity.nano.DnsEvent;
import com.android.server.connectivity.nano.WifiData;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import com.android.testutils.HandlerUtils;

import com.google.protobuf.nano.MessageNano;

import junit.framework.AssertionFailedError;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.net.HttpURLConnection;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLHandshakeException;

@RunWith(AndroidJUnit4.class)
@SmallTest
@SuppressLint("NewApi")  // Uses hidden APIs, which the linter would identify as missing APIs.
public class NetworkMonitorTest {
    private static final String LOCATION_HEADER = "location";
    private static final String CONTENT_TYPE_HEADER = "Content-Type";

    @Rule
    public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();

    private @Mock Context mContext;
    private @Mock Configuration mConfiguration;
    private @Mock Resources mResources;
    private @Mock IpConnectivityLog mLogger;
    private @Mock SharedLog mValidationLogger;
    private @Mock DnsResolver mDnsResolver;
    private @Mock ConnectivityManager mCm;
    private @Mock TelephonyManager mTelephony;
    private @Mock WifiManager mWifi;
    private @Mock NetworkStackServiceManager mServiceManager;
    private @Mock NetworkStackNotifier mNotifier;
    private @Mock HttpURLConnection mHttpConnection;
    private @Mock HttpURLConnection mOtherHttpConnection1;
    private @Mock HttpURLConnection mOtherHttpConnection2;
    private @Mock HttpURLConnection mHttpsConnection;
    private @Mock HttpURLConnection mOtherHttpsConnection1;
    private @Mock HttpURLConnection mOtherHttpsConnection2;
    private @Mock HttpURLConnection mFallbackConnection;
    private @Mock HttpURLConnection mOtherFallbackConnection;
    private @Mock HttpURLConnection mTestOverriddenUrlConnection;
    private @Mock HttpURLConnection mCapportApiConnection;
    private @Mock HttpURLConnection mSpeedTestConnection;
    private @Mock Random mRandom;
    private @Mock NetworkMonitor.Dependencies mDependencies;
    // Mockito can't create a mock of INetworkMonitorCallbacks on Q because it can't find
    // CaptivePortalData on notifyCaptivePortalDataChanged. Use a spy on a mock IBinder instead.
    private INetworkMonitorCallbacks mCallbacks = spy(
            INetworkMonitorCallbacks.Stub.asInterface(mock(IBinder.class)));
    private @Spy Network mCleartextDnsNetwork = new Network(TEST_NETID);
    private @Mock Network mNetwork;
    private @Mock DataStallStatsUtils mDataStallStatsUtils;
    private @Mock TcpSocketTracker.Dependencies mTstDependencies;
    private @Mock INetd mNetd;
    private @Mock TcpSocketTracker mTst;
    private HashSet<WrappedNetworkMonitor> mCreatedNetworkMonitors;
    private HashSet<BroadcastReceiver> mRegisteredReceivers;
    private @Mock Context mMccContext;
    private @Mock Resources mMccResource;
    private @Mock WifiInfo mWifiInfo;

    private static final int TEST_NETID = 4242;
    private static final String TEST_HTTP_URL = "http://www.google.com/gen_204";
    private static final String TEST_HTTP_OTHER_URL1 = "http://other1.google.com/gen_204";
    private static final String TEST_HTTP_OTHER_URL2 = "http://other2.google.com/gen_204";
    private static final String TEST_HTTPS_URL = "https://www.google.com/gen_204";
    private static final String TEST_HTTPS_OTHER_URL1 = "https://other1.google.com/gen_204";
    private static final String TEST_HTTPS_OTHER_URL2 = "https://other2.google.com/gen_204";
    private static final String TEST_FALLBACK_URL = "http://fallback.google.com/gen_204";
    private static final String TEST_OTHER_FALLBACK_URL = "http://otherfallback.google.com/gen_204";
    private static final String TEST_INVALID_OVERRIDE_URL = "https://override.example.com/test";
    private static final String TEST_OVERRIDE_URL = "http://localhost:12345/test";
    private static final String TEST_CAPPORT_API_URL = "https://capport.example.com/api";
    private static final String TEST_LOGIN_URL = "https://testportal.example.com/login";
    private static final String TEST_VENUE_INFO_URL = "https://venue.example.com/info";
    private static final String TEST_SPEED_TEST_URL = "https://speedtest.example.com";
    private static final String TEST_RELATIVE_URL = "/test/relative/gen_204";
    private static final String TEST_MCCMNC = "123456";
    private static final String TEST_FRIENDLY_NAME = "Friendly Name";
    private static final String[] TEST_HTTP_URLS = {TEST_HTTP_OTHER_URL1, TEST_HTTP_OTHER_URL2};
    private static final String[] TEST_HTTPS_URLS = {TEST_HTTPS_OTHER_URL1, TEST_HTTPS_OTHER_URL2};
    private static final int TEST_TCP_FAIL_RATE = 99;
    private static final int TEST_TCP_PACKET_COUNT = 50;
    private static final long TEST_ELAPSED_TIME_MS = 123456789L;
    private static final int TEST_SIGNAL_STRENGTH = -100;
    private static final int VALIDATION_RESULT_INVALID = 0;
    private static final int VALIDATION_RESULT_PORTAL = 0;
    private static final String TEST_REDIRECT_URL = "android.com";
    private static final int PROBES_PRIVDNS_VALID = NETWORK_VALIDATION_PROBE_DNS
            | NETWORK_VALIDATION_PROBE_HTTPS | NETWORK_VALIDATION_PROBE_PRIVDNS;

    private static final int RETURN_CODE_DNS_SUCCESS = 0;
    private static final int RETURN_CODE_DNS_TIMEOUT = 255;
    private static final int DEFAULT_DNS_TIMEOUT_THRESHOLD = 5;

    private static final int HANDLER_TIMEOUT_MS = 1000;
    private static final int TEST_MIN_STALL_EVALUATE_INTERVAL_MS = 500;
    private static final int STALL_EXPECTED_LAST_PROBE_TIME_MS =
            TEST_MIN_STALL_EVALUATE_INTERVAL_MS + HANDLER_TIMEOUT_MS;
    private static final LinkProperties TEST_LINK_PROPERTIES = new LinkProperties();

    // Cannot have a static member for the LinkProperties with captive portal API information, as
    // the initializer would crash on Q (the members in LinkProperties were introduced in R).
    private static LinkProperties makeCapportLPs() {
        final LinkProperties lp = new LinkProperties(TEST_LINK_PROPERTIES);
        lp.setCaptivePortalApiUrl(Uri.parse(TEST_CAPPORT_API_URL));
        return lp;
    }

    private static final NetworkCapabilities CELL_METERED_CAPABILITIES = new NetworkCapabilities()
            .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
            .addCapability(NET_CAPABILITY_INTERNET);

    private static final NetworkCapabilities CELL_NOT_METERED_CAPABILITIES =
            new NetworkCapabilities()
                .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
                .addCapability(NET_CAPABILITY_INTERNET)
                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);

    private static final NetworkCapabilities WIFI_NOT_METERED_CAPABILITIES =
            new NetworkCapabilities()
                .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                .addCapability(NET_CAPABILITY_INTERNET)
                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);

    private static final NetworkCapabilities CELL_NO_INTERNET_CAPABILITIES =
            new NetworkCapabilities().addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);

    private static final NetworkCapabilities WIFI_OEM_PAID_CAPABILITIES =
            new NetworkCapabilities()
                .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                .addCapability(NET_CAPABILITY_INTERNET)
                .addCapability(NET_CAPABILITY_NOT_METERED)
                .addCapability(NET_CAPABILITY_OEM_PAID)
                .removeCapability(NET_CAPABILITY_NOT_RESTRICTED);

    /**
     * Fakes DNS responses.
     *
     * Allows test methods to configure the IP addresses that will be resolved by
     * Network#getAllByName and by DnsResolver#query.
     */
    class FakeDns {
        /** Data class to record the Dns entry. */
        class DnsEntry {
            final String mHostname;
            final int mType;
            final List<InetAddress> mAddresses;
            DnsEntry(String host, int type, List<InetAddress> addr) {
                mHostname = host;
                mType = type;
                mAddresses = addr;
            }
            // Full match or partial match that target host contains the entry hostname to support
            // random private dns probe hostname.
            private boolean matches(String hostname, int type) {
                return hostname.endsWith(mHostname) && type == mType;
            }
        }
        private final ArrayList<DnsEntry> mAnswers = new ArrayList<DnsEntry>();
        private boolean mNonBypassPrivateDnsWorking = true;

        /** Whether DNS queries on mNonBypassPrivateDnsWorking should succeed. */
        private void setNonBypassPrivateDnsWorking(boolean working) {
            mNonBypassPrivateDnsWorking = working;
        }

        /** Clears all DNS entries. */
        private synchronized void clearAll() {
            mAnswers.clear();
        }

        /** Returns the answer for a given name and type on the given mock network. */
        private synchronized List<InetAddress> getAnswer(Object mock, String hostname, int type) {
            if (mock == mNetwork && !mNonBypassPrivateDnsWorking) {
                return null;
            }

            return mAnswers.stream().filter(e -> e.matches(hostname, type))
                    .map(answer -> answer.mAddresses).findFirst().orElse(null);
        }

        /** Sets the answer for a given name and type. */
        private synchronized void setAnswer(String hostname, String[] answer, int type)
                throws UnknownHostException {
            DnsEntry record = new DnsEntry(hostname, type, generateAnswer(answer));
            // Remove the existing one.
            mAnswers.removeIf(entry -> entry.matches(hostname, type));
            // Add or replace a new record.
            mAnswers.add(record);
        }

        private List<InetAddress> generateAnswer(String[] answer) {
            if (answer == null) return new ArrayList<>();
            return Arrays.stream(answer).map(addr -> InetAddress.parseNumericAddress(addr))
                    .collect(toList());
        }

        /** Simulates a getAllByName call for the specified name on the specified mock network. */
        private InetAddress[] getAllByName(Object mock, String hostname)
                throws UnknownHostException {
            List<InetAddress> answer = queryAllTypes(mock, hostname);
            if (answer == null || answer.size() == 0) {
                throw new UnknownHostException(hostname);
            }
            return answer.toArray(new InetAddress[0]);
        }

        // Regardless of the type, depends on what the responses contained in the network.
        private List<InetAddress> queryAllTypes(Object mock, String hostname) {
            List<InetAddress> answer = new ArrayList<>();
            addAllIfNotNull(answer, getAnswer(mock, hostname, TYPE_A));
            addAllIfNotNull(answer, getAnswer(mock, hostname, TYPE_AAAA));
            return answer;
        }

        private void addAllIfNotNull(List<InetAddress> list, List<InetAddress> c) {
            if (c != null) {
                list.addAll(c);
            }
        }

        /** Starts mocking DNS queries. */
        private void startMocking() throws UnknownHostException {
            // Queries on mNetwork using getAllByName.
            doAnswer(invocation -> {
                return getAllByName(invocation.getMock(), invocation.getArgument(0));
            }).when(mNetwork).getAllByName(any());

            // Queries on mCleartextDnsNetwork using DnsResolver#query.
            doAnswer(invocation -> {
                return mockQuery(invocation, 1 /* posHostname */, 3 /* posExecutor */,
                        5 /* posCallback */, -1 /* posType */);
            }).when(mDnsResolver).query(any(), any(), anyInt(), any(), any(), any());

            // Queries on mCleartextDnsNetwork using DnsResolver#query with QueryType.
            doAnswer(invocation -> {
                return mockQuery(invocation, 1 /* posHostname */, 4 /* posExecutor */,
                        6 /* posCallback */, 2 /* posType */);
            }).when(mDnsResolver).query(any(), any(), anyInt(), anyInt(), any(), any(), any());
        }

        // Mocking queries on DnsResolver#query.
        private Answer mockQuery(InvocationOnMock invocation, int posHostname, int posExecutor,
                int posCallback, int posType) {
            String hostname = (String) invocation.getArgument(posHostname);
            Executor executor = (Executor) invocation.getArgument(posExecutor);
            DnsResolver.Callback<List<InetAddress>> callback = invocation.getArgument(posCallback);
            List<InetAddress> answer;

            answer = posType != -1
                    ? getAnswer(invocation.getMock(), hostname, invocation.getArgument(posType)) :
                    queryAllTypes(invocation.getMock(), hostname);

            if (answer != null && answer.size() > 0) {
                new Handler(Looper.getMainLooper()).post(() -> {
                    executor.execute(() -> callback.onAnswer(answer, 0));
                });
            }
            // If no answers, do nothing. sendDnsProbeWithTimeout will time out and throw UHE.
            return null;
        }
    }

    private FakeDns mFakeDns;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        when(mDependencies.getPrivateDnsBypassNetwork(any())).thenReturn(mCleartextDnsNetwork);
        when(mDependencies.getDnsResolver()).thenReturn(mDnsResolver);
        when(mDependencies.getRandom()).thenReturn(mRandom);
        when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_MODE), anyInt()))
                .thenReturn(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
        when(mDependencies.getDeviceConfigPropertyInt(any(), eq(CAPTIVE_PORTAL_USE_HTTPS),
                anyInt())).thenReturn(1);
        when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_HTTP_URL), any()))
                .thenReturn(TEST_HTTP_URL);
        when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_HTTPS_URL), any()))
                .thenReturn(TEST_HTTPS_URL);

        doReturn(mCleartextDnsNetwork).when(mNetwork).getPrivateDnsBypassingCopy();

        when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(mCm);
        when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephony);
        when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifi);
        when(mContext.getResources()).thenReturn(mResources);

        when(mServiceManager.getNotifier()).thenReturn(mNotifier);

        when(mTelephony.getDataNetworkType()).thenReturn(TelephonyManager.NETWORK_TYPE_LTE);
        when(mTelephony.getNetworkOperator()).thenReturn(TEST_MCCMNC);
        when(mTelephony.getSimOperator()).thenReturn(TEST_MCCMNC);

        when(mResources.getString(anyInt())).thenReturn("");
        when(mResources.getStringArray(anyInt())).thenReturn(new String[0]);
        doReturn(mConfiguration).when(mResources).getConfiguration();
        when(mMccContext.getResources()).thenReturn(mMccResource);

        setFallbackUrl(TEST_FALLBACK_URL);
        setOtherFallbackUrls(TEST_OTHER_FALLBACK_URL);
        setFallbackSpecs(null); // Test with no fallback spec by default
        when(mRandom.nextInt()).thenReturn(0);

        when(mTstDependencies.getNetd()).thenReturn(mNetd);
        // DNS probe timeout should not be defined more than half of HANDLER_TIMEOUT_MS. Otherwise,
        // it will fail the test because of timeout expired for querying AAAA and A sequentially.
        when(mResources.getInteger(eq(R.integer.config_captive_portal_dns_probe_timeout)))
                .thenReturn(200);

        doAnswer((invocation) -> {
            URL url = invocation.getArgument(0);
            switch(url.toString()) {
                case TEST_HTTP_URL:
                    return mHttpConnection;
                case TEST_HTTP_OTHER_URL1:
                    return mOtherHttpConnection1;
                case TEST_HTTP_OTHER_URL2:
                    return mOtherHttpConnection2;
                case TEST_HTTPS_URL:
                    return mHttpsConnection;
                case TEST_HTTPS_OTHER_URL1:
                    return mOtherHttpsConnection1;
                case TEST_HTTPS_OTHER_URL2:
                    return mOtherHttpsConnection2;
                case TEST_FALLBACK_URL:
                    return mFallbackConnection;
                case TEST_OTHER_FALLBACK_URL:
                    return mOtherFallbackConnection;
                case TEST_OVERRIDE_URL:
                case TEST_INVALID_OVERRIDE_URL:
                    return mTestOverriddenUrlConnection;
                case TEST_CAPPORT_API_URL:
                    return mCapportApiConnection;
                case TEST_SPEED_TEST_URL:
                    return mSpeedTestConnection;
                default:
                    fail("URL not mocked: " + url.toString());
                    return null;
            }
        }).when(mCleartextDnsNetwork).openConnection(any());
        when(mHttpConnection.getRequestProperties()).thenReturn(new ArrayMap<>());
        when(mHttpsConnection.getRequestProperties()).thenReturn(new ArrayMap<>());

        mFakeDns = new FakeDns();
        mFakeDns.startMocking();
        // Set private dns suffix answer. sendPrivateDnsProbe() in NetworkMonitor send probe with
        // one time hostname. The hostname will be [random generated UUID] + HOST_SUFFIX differently
        // each time. That means the host answer cannot be pre-set into the answer list. Thus, set
        // the host suffix and use partial match in FakeDns to match the target host and reply the
        // intended answer.
        mFakeDns.setAnswer(PRIVATE_DNS_PROBE_HOST_SUFFIX, new String[]{"192.0.2.2"}, TYPE_A);
        mFakeDns.setAnswer(PRIVATE_DNS_PROBE_HOST_SUFFIX, new String[]{"2001:db8::1"}, TYPE_AAAA);

        when(mContext.registerReceiver(any(BroadcastReceiver.class), any())).then((invocation) -> {
            mRegisteredReceivers.add(invocation.getArgument(0));
            return new Intent();
        });

        doAnswer((invocation) -> {
            mRegisteredReceivers.remove(invocation.getArgument(0));
            return null;
        }).when(mContext).unregisterReceiver(any());

        resetCallbacks();

        setMinDataStallEvaluateInterval(TEST_MIN_STALL_EVALUATE_INTERVAL_MS);
        setDataStallEvaluationType(DATA_STALL_EVALUATION_TYPE_DNS);
        setValidDataStallDnsTimeThreshold(500);
        setConsecutiveDnsTimeoutThreshold(5);
        mCreatedNetworkMonitors = new HashSet<>();
        mRegisteredReceivers = new HashSet<>();
        setDismissPortalInValidatedNetwork(false);
    }

    @After
    public void tearDown() {
        mFakeDns.clearAll();
        // Make a local copy of mCreatedNetworkMonitors because during the iteration below,
        // WrappedNetworkMonitor#onQuitting will delete elements from it on the handler threads.
        WrappedNetworkMonitor[] networkMonitors = mCreatedNetworkMonitors.toArray(
                new WrappedNetworkMonitor[0]);
        for (WrappedNetworkMonitor nm : networkMonitors) {
            nm.notifyNetworkDisconnected();
            nm.awaitQuit();
        }
        assertEquals("NetworkMonitor still running after disconnect",
                0, mCreatedNetworkMonitors.size());
        assertEquals("BroadcastReceiver still registered after disconnect",
                0, mRegisteredReceivers.size());
    }

    private void resetCallbacks() {
        resetCallbacks(6);
    }

    private void resetCallbacks(int interfaceVersion) {
        reset(mCallbacks);
        try {
            doReturn(interfaceVersion).when(mCallbacks).getInterfaceVersion();
        } catch (RemoteException e) {
            // Can't happen as mCallbacks is a mock
            fail("Error mocking getInterfaceVersion" + e);
        }
    }

    private TcpSocketTracker getTcpSocketTrackerOrNull(NetworkMonitor.Dependencies dp) {
        return ((dp.getDeviceConfigPropertyInt(
                NAMESPACE_CONNECTIVITY,
                CONFIG_DATA_STALL_EVALUATION_TYPE,
                DEFAULT_DATA_STALL_EVALUATION_TYPES)
                & DATA_STALL_EVALUATION_TYPE_TCP) != 0) ? mTst : null;
    }

    private class WrappedNetworkMonitor extends NetworkMonitor {
        private long mProbeTime = 0;
        private final ConditionVariable mQuitCv = new ConditionVariable(false);

        WrappedNetworkMonitor() {
            super(mContext, mCallbacks, mNetwork, mLogger, mValidationLogger, mServiceManager,
                    mDependencies, getTcpSocketTrackerOrNull(mDependencies));
        }

        @Override
        protected long getLastProbeTime() {
            return mProbeTime;
        }

        protected void setLastProbeTime(long time) {
            mProbeTime = time;
        }

        @Override
        protected void addDnsEvents(@NonNull final DataStallDetectionStats.Builder stats) {
            if ((getDataStallEvaluationType() & DATA_STALL_EVALUATION_TYPE_DNS) != 0) {
                generateTimeoutDnsEvent(stats, DEFAULT_DNS_TIMEOUT_THRESHOLD);
            }
        }

        @Override
        protected void onQuitting() {
            assertTrue(mCreatedNetworkMonitors.remove(this));
            mQuitCv.open();
        }

        protected void awaitQuit() {
            assertTrue("NetworkMonitor did not quit after " + HANDLER_TIMEOUT_MS + "ms",
                    mQuitCv.block(HANDLER_TIMEOUT_MS));
        }

        protected Context getContext() {
            return mContext;
        }
    }

    private WrappedNetworkMonitor makeMonitor(NetworkCapabilities nc) {
        final WrappedNetworkMonitor nm = new WrappedNetworkMonitor();
        nm.start();
        setNetworkCapabilities(nm, nc);
        HandlerUtils.waitForIdle(nm.getHandler(), HANDLER_TIMEOUT_MS);
        mCreatedNetworkMonitors.add(nm);
        when(mTstDependencies.isTcpInfoParsingSupported()).thenReturn(false);

        return nm;
    }

    private WrappedNetworkMonitor makeCellMeteredNetworkMonitor() {
        final WrappedNetworkMonitor nm = makeMonitor(CELL_METERED_CAPABILITIES);
        return nm;
    }

    private WrappedNetworkMonitor makeCellNotMeteredNetworkMonitor() {
        final WrappedNetworkMonitor nm = makeMonitor(CELL_NOT_METERED_CAPABILITIES);
        return nm;
    }

    private WrappedNetworkMonitor makeWifiNotMeteredNetworkMonitor() {
        final WrappedNetworkMonitor nm = makeMonitor(WIFI_NOT_METERED_CAPABILITIES);
        return nm;
    }

    private void setNetworkCapabilities(NetworkMonitor nm, NetworkCapabilities nc) {
        nm.notifyNetworkCapabilitiesChanged(nc);
        HandlerUtils.waitForIdle(nm.getHandler(), HANDLER_TIMEOUT_MS);
    }

    @Test
    public void testOnlyWifiTransport() {
        final WrappedNetworkMonitor wnm = makeMonitor(CELL_METERED_CAPABILITIES);
        assertFalse(wnm.onlyWifiTransport());
        final NetworkCapabilities nc = new NetworkCapabilities()
                .addTransportType(TRANSPORT_WIFI)
                .addTransportType(TRANSPORT_VPN);
        setNetworkCapabilities(wnm, nc);
        assertFalse(wnm.onlyWifiTransport());
        nc.removeTransportType(TRANSPORT_VPN);
        setNetworkCapabilities(wnm, nc);
        assertTrue(wnm.onlyWifiTransport());
    }

    @Test
    public void testNeedEvaluatingBandwidth() throws Exception {
        // Make metered network first, the transport type is TRANSPORT_CELLULAR. That means the
        // test cannot pass the condition check in needEvaluatingBandwidth().
        final WrappedNetworkMonitor wnm1 = makeCellMeteredNetworkMonitor();
        // Don't set the config_evaluating_bandwidth_url to make
        // the condition check fail in needEvaluatingBandwidth().
        assertFalse(wnm1.needEvaluatingBandwidth());
        // Make the NetworkCapabilities to have the TRANSPORT_WIFI but it still cannot meet the
        // condition check.
        final NetworkCapabilities nc = new NetworkCapabilities()
                .addTransportType(TRANSPORT_WIFI);
        setNetworkCapabilities(wnm1, nc);
        assertFalse(wnm1.needEvaluatingBandwidth());
        // Make the network to be non-metered wifi but it still cannot meet the condition check
        // since the config_evaluating_bandwidth_url is not set.
        nc.addCapability(NET_CAPABILITY_NOT_METERED);
        setNetworkCapabilities(wnm1, nc);
        assertFalse(wnm1.needEvaluatingBandwidth());
        // All configurations are set correctly.
        doReturn(TEST_SPEED_TEST_URL).when(mResources).getString(
                R.string.config_evaluating_bandwidth_url);
        final WrappedNetworkMonitor wnm2 = makeCellMeteredNetworkMonitor();
        setNetworkCapabilities(wnm2, nc);
        assertTrue(wnm2.needEvaluatingBandwidth());
        // Set mIsBandwidthCheckPassedOrIgnored to true and expect needEvaluatingBandwidth() will
        // return false.
        wnm2.mIsBandwidthCheckPassedOrIgnored = true;
        assertFalse(wnm2.needEvaluatingBandwidth());
        // Reset mIsBandwidthCheckPassedOrIgnored back to false.
        wnm2.mIsBandwidthCheckPassedOrIgnored = false;
        // Shouldn't evaluate network bandwidth on the metered wifi.
        nc.removeCapability(NET_CAPABILITY_NOT_METERED);
        setNetworkCapabilities(wnm2, nc);
        assertFalse(wnm2.needEvaluatingBandwidth());
        // Shouldn't evaluate network bandwidth on the unmetered cellular.
        nc.addCapability(NET_CAPABILITY_NOT_METERED);
        nc.removeTransportType(TRANSPORT_WIFI);
        nc.addTransportType(TRANSPORT_CELLULAR);
        assertFalse(wnm2.needEvaluatingBandwidth());
    }

    @Test
    public void testEvaluatingBandwidthState_meteredNetwork() throws Exception {
        setStatus(mHttpsConnection, 204);
        setStatus(mHttpConnection, 204);
        final NetworkCapabilities meteredCap = new NetworkCapabilities()
                .addTransportType(TRANSPORT_WIFI)
                .addCapability(NET_CAPABILITY_INTERNET);
        doReturn(TEST_SPEED_TEST_URL).when(mResources).getString(
                R.string.config_evaluating_bandwidth_url);
        final NetworkMonitor nm = runNetworkTest(TEST_LINK_PROPERTIES, meteredCap,
                NETWORK_VALIDATION_RESULT_VALID, NETWORK_VALIDATION_PROBE_DNS
                | NETWORK_VALIDATION_PROBE_HTTPS, null /* redirectUrl */);
        // Evaluating bandwidth process won't be executed when the network is metered wifi.
        // Check that the connection hasn't been opened and the state should transition to validated
        // state directly.
        verify(mCleartextDnsNetwork, never()).openConnection(new URL(TEST_SPEED_TEST_URL));
        assertEquals(NETWORK_VALIDATION_RESULT_VALID,
                nm.getEvaluationState().getEvaluationResult());
    }

    @Test
    public void testEvaluatingBandwidthState_nonMeteredNetworkWithWrongConfig() throws Exception {
        setStatus(mHttpsConnection, 204);
        setStatus(mHttpConnection, 204);
        final NetworkCapabilities nonMeteredCap = new NetworkCapabilities()
                .addTransportType(TRANSPORT_WIFI)
                .addCapability(NET_CAPABILITY_INTERNET)
                .addCapability(NET_CAPABILITY_NOT_METERED);
        doReturn("").when(mResources).getString(R.string.config_evaluating_bandwidth_url);
        final NetworkMonitor nm = runNetworkTest(TEST_LINK_PROPERTIES, nonMeteredCap,
                NETWORK_VALIDATION_RESULT_VALID, NETWORK_VALIDATION_PROBE_DNS
                | NETWORK_VALIDATION_PROBE_HTTPS, null /* redirectUrl */);
        // Non-metered network with wrong configuration(the config_evaluating_bandwidth_url is
        // empty). Check that the connection hasn't been opened and the state should transition to
        // validated state directly.
        verify(mCleartextDnsNetwork, never()).openConnection(new URL(TEST_SPEED_TEST_URL));
        assertEquals(NETWORK_VALIDATION_RESULT_VALID,
                nm.getEvaluationState().getEvaluationResult());
    }

    @Test
    public void testMatchesHttpContent() throws Exception {
        final WrappedNetworkMonitor wnm = makeCellNotMeteredNetworkMonitor();
        doReturn("[\\s\\S]*line2[\\s\\S]*").when(mResources).getString(
                R.string.config_network_validation_failed_content_regexp);
        assertTrue(wnm.matchesHttpContent("This is line1\nThis is line2\nThis is line3",
                R.string.config_network_validation_failed_content_regexp));
        assertFalse(wnm.matchesHttpContent("hello",
                R.string.config_network_validation_failed_content_regexp));
        // Set an invalid regex and expect to get the false even though the regex is the same as the
        // content.
        doReturn("[").when(mResources).getString(
                R.string.config_network_validation_failed_content_regexp);
        assertFalse(wnm.matchesHttpContent("[",
                R.string.config_network_validation_failed_content_regexp));
    }

    @Test
    public void testMatchesHttpContentLength() throws Exception {
        final WrappedNetworkMonitor wnm = makeCellNotMeteredNetworkMonitor();
        // Set the range of content length.
        doReturn(100).when(mResources).getInteger(R.integer.config_min_matches_http_content_length);
        doReturn(1000).when(mResources).getInteger(
                R.integer.config_max_matches_http_content_length);
        assertFalse(wnm.matchesHttpContentLength(100));
        assertFalse(wnm.matchesHttpContentLength(1000));
        assertTrue(wnm.matchesHttpContentLength(500));

        // Test the invalid value.
        assertFalse(wnm.matchesHttpContentLength(-1));
        assertFalse(wnm.matchesHttpContentLength(0));
        assertFalse(wnm.matchesHttpContentLength(Integer.MAX_VALUE + 1L));

        // Set the wrong value for min and max config to make sure the function is working even
        // though the config is wrong.
        doReturn(1000).when(mResources).getInteger(
                R.integer.config_min_matches_http_content_length);
        doReturn(100).when(mResources).getInteger(
                R.integer.config_max_matches_http_content_length);
        assertFalse(wnm.matchesHttpContentLength(100));
        assertFalse(wnm.matchesHttpContentLength(1000));
        assertFalse(wnm.matchesHttpContentLength(500));
    }

    @Test
    public void testGetResStringConfig() throws Exception {
        final WrappedNetworkMonitor wnm = makeCellNotMeteredNetworkMonitor();
        // Set the config and expect to get the customized value.
        final String regExp = ".*HTTP.*200.*not a captive portal.*";
        doReturn(regExp).when(mResources).getString(
                R.string.config_network_validation_failed_content_regexp);
        assertEquals(regExp, wnm.getResStringConfig(mContext,
                R.string.config_network_validation_failed_content_regexp, null));
        doThrow(new Resources.NotFoundException()).when(mResources).getString(eq(
                R.string.config_network_validation_failed_content_regexp));
        // If the config is not found, then expect to get the default value - null.
        assertNull(wnm.getResStringConfig(mContext,
                R.string.config_network_validation_failed_content_regexp, null));
    }

    @Test
    public void testGetResIntConfig() throws Exception {
        final WrappedNetworkMonitor wnm = makeCellNotMeteredNetworkMonitor();
        // Set the config and expect to get the customized value.
        doReturn(100).when(mResources).getInteger(R.integer.config_min_matches_http_content_length);
        doReturn(1000).when(mResources).getInteger(
                R.integer.config_max_matches_http_content_length);
        assertEquals(100, wnm.getResIntConfig(mContext,
                R.integer.config_min_matches_http_content_length, Integer.MAX_VALUE));
        assertEquals(1000, wnm.getResIntConfig(mContext,
                R.integer.config_max_matches_http_content_length, 0));
        doThrow(new Resources.NotFoundException())
                .when(mResources).getInteger(
                        eq(R.integer.config_min_matches_http_content_length));
        doThrow(new Resources.NotFoundException())
                .when(mResources).getInteger(eq(R.integer.config_max_matches_http_content_length));
        // If the config is not found, then expect to get the default value.
        assertEquals(Integer.MAX_VALUE, wnm.getResIntConfig(mContext,
                R.integer.config_min_matches_http_content_length, Integer.MAX_VALUE));
        assertEquals(0, wnm.getResIntConfig(mContext,
                R.integer.config_max_matches_http_content_length, 0));
    }

    @Test
    public void testGetHttpProbeUrl() {
        final WrappedNetworkMonitor wnm = makeCellNotMeteredNetworkMonitor();
        // If config_captive_portal_http_url is set and the global setting is set, the config is
        // used.
        doReturn(TEST_HTTP_URL).when(mResources).getString(R.string.config_captive_portal_http_url);
        doReturn(TEST_HTTP_OTHER_URL2).when(mResources).getString(
                R.string.default_captive_portal_http_url);
        when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_HTTP_URL), any()))
                .thenReturn(TEST_HTTP_OTHER_URL1);
        assertEquals(TEST_HTTP_URL, wnm.getCaptivePortalServerHttpUrl());
        // If config_captive_portal_http_url is unset and the global setting is set, the global
        // setting is used.
        doReturn(null).when(mResources).getString(R.string.config_captive_portal_http_url);
        assertEquals(TEST_HTTP_OTHER_URL1, wnm.getCaptivePortalServerHttpUrl());
        // If both config_captive_portal_http_url and global setting are unset,
        // default_captive_portal_http_url is used.
        when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_HTTP_URL), any()))
                .thenReturn(null);
        assertEquals(TEST_HTTP_OTHER_URL2, wnm.getCaptivePortalServerHttpUrl());
    }

    @Test
    public void testGetLocationMcc() throws Exception {
        final WrappedNetworkMonitor wnm = makeCellNotMeteredNetworkMonitor();
        doReturn(PackageManager.PERMISSION_DENIED).when(mContext).checkPermission(
                eq(android.Manifest.permission.ACCESS_FINE_LOCATION),  anyInt(), anyInt());
        assertNull(wnm.getLocationMcc());
        doReturn(PackageManager.PERMISSION_GRANTED).when(mContext).checkPermission(
                eq(android.Manifest.permission.ACCESS_FINE_LOCATION),  anyInt(), anyInt());
        doReturn(new ContextWrapper(mContext)).when(mContext).createConfigurationContext(any());
        doReturn(null).when(mTelephony).getAllCellInfo();
        assertNull(wnm.getLocationMcc());
        // Prepare CellInfo and check if the vote mechanism is working or not.
        final List<CellInfo> cellList = new ArrayList<CellInfo>();
        doReturn(cellList).when(mTelephony).getAllCellInfo();
        assertNull(wnm.getLocationMcc());
        cellList.add(makeTestCellInfoGsm("460"));
        cellList.add(makeTestCellInfoGsm("460"));
        cellList.add(makeTestCellInfoLte("466"));
        // The count of 460 is 2 and the count of 466 is 1, so the getLocationMcc() should return
        // 460.
        assertEquals("460", wnm.getLocationMcc());
        // getCustomizedContextOrDefault() shouldn't return mContext when using neighbor mcc
        // is enabled and the sim is not ready.
        doReturn(true).when(mResources).getBoolean(R.bool.config_no_sim_card_uses_neighbor_mcc);
        doReturn(TelephonyManager.SIM_STATE_ABSENT).when(mTelephony).getSimState();
        assertEquals(460,
                wnm.getCustomizedContextOrDefault().getResources().getConfiguration().mcc);
        doReturn(false).when(mResources).getBoolean(R.bool.config_no_sim_card_uses_neighbor_mcc);
        assertEquals(wnm.getContext(), wnm.getCustomizedContextOrDefault());
    }

    @Test
    public void testGetMccMncOverrideInfo() {
        final WrappedNetworkMonitor wnm = makeCellNotMeteredNetworkMonitor();
        doReturn(new ContextWrapper(mContext)).when(mContext).createConfigurationContext(any());
        // 1839 is VZW's carrier id.
        doReturn(1839).when(mTelephony).getSimCarrierId();
        assertNull(wnm.getMccMncOverrideInfo());
        // 1854 is CTC's carrier id.
        doReturn(1854).when(mTelephony).getSimCarrierId();
        assertNotNull(wnm.getMccMncOverrideInfo());
        // Check if the mcc & mnc has changed as expected.
        assertEquals(460,
                wnm.getCustomizedContextOrDefault().getResources().getConfiguration().mcc);
        assertEquals(03,
                wnm.getCustomizedContextOrDefault().getResources().getConfiguration().mnc);
        // Every mcc and mnc should be set in sCarrierIdToMccMnc.
        // Check if there is any unset value in mcc or mnc.
        for (int i = 0; i < wnm.sCarrierIdToMccMnc.size(); i++) {
            assertNotEquals(-1, wnm.sCarrierIdToMccMnc.valueAt(i).mcc);
            assertNotEquals(-1, wnm.sCarrierIdToMccMnc.valueAt(i).mnc);
        }
    }

    private CellInfoGsm makeTestCellInfoGsm(String mcc) throws Exception {
        final CellInfoGsm info = new CellInfoGsm();
        final CellIdentityGsm ci = makeCellIdentityGsm(0, 0, 0, 0, mcc, "01", "", "");
        info.setCellIdentity(ci);
        return info;
    }

    private CellInfoLte makeTestCellInfoLte(String mcc) throws Exception {
        final CellInfoLte info = new CellInfoLte();
        final CellIdentityLte ci = makeCellIdentityLte(0, 0, 0, 0, 0, mcc, "01", "", "");
        info.setCellIdentity(ci);
        return info;
    }

    private void setupNoSimCardNeighborMcc() throws Exception {
        // Enable using neighbor resource by camping mcc feature.
        doReturn(true).when(mResources).getBoolean(R.bool.config_no_sim_card_uses_neighbor_mcc);
        final List<CellInfo> cellList = new ArrayList<CellInfo>();
        final int testMcc = 460;
        cellList.add(makeTestCellInfoGsm(Integer.toString(testMcc)));
        doReturn(cellList).when(mTelephony).getAllCellInfo();
        final Configuration config = mResources.getConfiguration();
        config.mcc = testMcc;
        doReturn(mMccContext).when(mContext).createConfigurationContext(eq(config));
    }

    @Test
    public void testMakeFallbackUrls() throws Exception {
        final WrappedNetworkMonitor wnm = makeCellNotMeteredNetworkMonitor();
        // Value exist in setting provider.
        URL[] urls = wnm.makeCaptivePortalFallbackUrls();
        assertEquals(urls[0].toString(), TEST_FALLBACK_URL);

        // Clear setting provider value. Verify it to get configuration from resource instead.
        setFallbackUrl(null);
        // Verify that getting resource with exception.
        when(mResources.getStringArray(R.array.config_captive_portal_fallback_urls))
                .thenThrow(Resources.NotFoundException.class);
        urls = wnm.makeCaptivePortalFallbackUrls();
        assertEquals(urls.length, 0);

        // Verify resource return 2 different URLs.
        doReturn(new String[] {"http://testUrl1.com", "http://testUrl2.com"}).when(mResources)
                .getStringArray(R.array.config_captive_portal_fallback_urls);
        urls = wnm.makeCaptivePortalFallbackUrls();
        assertEquals(urls.length, 2);
        assertEquals("http://testUrl1.com", urls[0].toString());
        assertEquals("http://testUrl2.com", urls[1].toString());

        // Even though the using neighbor resource by camping mcc feature is enabled, the
        // customized context has been assigned and won't change. So calling
        // makeCaptivePortalFallbackUrls() still gets the original value.
        setupNoSimCardNeighborMcc();
        doReturn(new String[] {"http://testUrl3.com"}).when(mMccResource)
                .getStringArray(R.array.config_captive_portal_fallback_urls);
        urls = wnm.makeCaptivePortalFallbackUrls();
        assertEquals(urls.length, 2);
        assertEquals("http://testUrl1.com", urls[0].toString());
        assertEquals("http://testUrl2.com", urls[1].toString());
    }

    @Test
    public void testMakeFallbackUrlsWithCustomizedContext() throws Exception {
        // Value is expected to be replaced by location resource.
        setupNoSimCardNeighborMcc();
        doReturn(new String[] {"http://testUrl.com"}).when(mMccResource)
                .getStringArray(R.array.config_captive_portal_fallback_urls);
        final WrappedNetworkMonitor wnm = makeCellNotMeteredNetworkMonitor();
        final URL[] urls = wnm.makeCaptivePortalFallbackUrls();
        assertEquals(urls.length, 1);
        assertEquals("http://testUrl.com", urls[0].toString());
    }

    private static CellIdentityGsm makeCellIdentityGsm(int lac, int cid, int arfcn, int bsic,
            String mccStr, String mncStr, String alphal, String alphas)
            throws ReflectiveOperationException {
        if (ShimUtils.isAtLeastR()) {
            return new CellIdentityGsm(lac, cid, arfcn, bsic, mccStr, mncStr, alphal, alphas,
                    Collections.emptyList() /* additionalPlmns */);
        } else {
            // API <= Q does not have the additionalPlmns parameter
            final Constructor<CellIdentityGsm> constructor = CellIdentityGsm.class.getConstructor(
                    int.class, int.class, int.class, int.class, String.class, String.class,
                    String.class, String.class);
            return constructor.newInstance(lac, cid, arfcn, bsic, mccStr, mncStr, alphal, alphas);
        }
    }

    private static CellIdentityLte makeCellIdentityLte(int ci, int pci, int tac, int earfcn,
            int bandwidth, String mccStr, String mncStr, String alphal, String alphas)
            throws ReflectiveOperationException {
        if (ShimUtils.isAtLeastR()) {
            return new CellIdentityLte(ci, pci, tac, earfcn, new int[] {} /* bands */,
                    bandwidth, mccStr, mncStr, alphal, alphas,
                    Collections.emptyList() /* additionalPlmns */, null /* csgInfo */);
        } else {
            // API <= Q does not have the additionalPlmns and csgInfo parameters
            final Constructor<CellIdentityLte> constructor = CellIdentityLte.class.getConstructor(
                    int.class, int.class, int.class, int.class, int.class, String.class,
                    String.class, String.class, String.class);
            return constructor.newInstance(ci, pci, tac, earfcn, bandwidth, mccStr, mncStr, alphal,
                    alphas);
        }
    }

    @Test
    public void testGetIntSetting() throws Exception {
        WrappedNetworkMonitor wnm = makeCellNotMeteredNetworkMonitor();

        // No config resource, no device config. Expect to get default resource.
        doThrow(new Resources.NotFoundException())
                .when(mResources).getInteger(eq(R.integer.config_captive_portal_dns_probe_timeout));
        doAnswer(invocation -> {
            int defaultValue = invocation.getArgument(2);
            return defaultValue;
        }).when(mDependencies).getDeviceConfigPropertyInt(any(),
                eq(NetworkMonitor.CONFIG_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT),
                anyInt());
        assertEquals(DEFAULT_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT, wnm.getIntSetting(mContext,
                R.integer.config_captive_portal_dns_probe_timeout,
                NetworkMonitor.CONFIG_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT,
                DEFAULT_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT));

        // Set device config. Expect to get device config.
        when(mDependencies.getDeviceConfigPropertyInt(any(),
                eq(NetworkMonitor.CONFIG_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT), anyInt()))
                        .thenReturn(1234);
        assertEquals(1234, wnm.getIntSetting(mContext,
                R.integer.config_captive_portal_dns_probe_timeout,
                NetworkMonitor.CONFIG_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT,
                DEFAULT_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT));

        // Set config resource. Expect to get config resource.
        when(mResources.getInteger(eq(R.integer.config_captive_portal_dns_probe_timeout)))
                .thenReturn(5678);
        assertEquals(5678, wnm.getIntSetting(mContext,
                R.integer.config_captive_portal_dns_probe_timeout,
                NetworkMonitor.CONFIG_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT,
                DEFAULT_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT));
    }

    @Test
    public void testIsCaptivePortal_HttpProbeIsPortal() throws Exception {
        setSslException(mHttpsConnection);
        setPortal302(mHttpConnection);
        runPortalNetworkTest();
    }

    @Test
    public void testIsCaptivePortal_Http200EmptyResponse() throws Exception {
        setSslException(mHttpsConnection);
        setStatus(mHttpConnection, 200);
        // Invalid if there is no content (can't login to an empty page)
        runNetworkTest(VALIDATION_RESULT_INVALID, 0 /* probesSucceeded */, null);
        verify(mCallbacks, never()).showProvisioningNotification(any(), any());
    }

    private void doCaptivePortal200ResponseTest(String expectedRedirectUrl) throws Exception {
        setSslException(mHttpsConnection);
        setStatus(mHttpConnection, 200);
        doReturn(100L).when(mHttpConnection).getContentLengthLong();
        // Redirect URL was null before S
        runNetworkTest(VALIDATION_RESULT_PORTAL, 0 /* probesSucceeded */, expectedRedirectUrl);
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS)).showProvisioningNotification(any(), any());
    }

    @Test @IgnoreAfter(Build.VERSION_CODES.R)
    public void testIsCaptivePortal_HttpProbeIs200Portal_R() throws Exception {
        doCaptivePortal200ResponseTest(null);
    }

    @Test @IgnoreUpTo(Build.VERSION_CODES.R)
    public void testIsCaptivePortal_HttpProbeIs200Portal() throws Exception {
        doCaptivePortal200ResponseTest(TEST_HTTP_URL);
    }

    private void setupPrivateIpResponse(String privateAddr) throws Exception {
        setSslException(mHttpsConnection);
        setPortal302(mHttpConnection);
        final String httpHost = new URL(TEST_HTTP_URL).getHost();
        mFakeDns.setAnswer(httpHost, new String[] { "2001:db8::123" }, TYPE_AAAA);
        final InetAddress parsedPrivateAddr = InetAddresses.parseNumericAddress(privateAddr);
        mFakeDns.setAnswer(httpHost, new String[] { privateAddr },
                (parsedPrivateAddr instanceof Inet6Address) ? TYPE_AAAA : TYPE_A);
    }

    @Test
    public void testIsCaptivePortal_PrivateIpNotPortal_Enabled_IPv4() throws Exception {
        when(mDependencies.isFeatureEnabled(any(), eq(DNS_PROBE_PRIVATE_IP_NO_INTERNET_VERSION)))
                .thenReturn(true);
        setupPrivateIpResponse("192.168.1.1");
        runFailedNetworkTest();
    }

    @Test
    public void testIsCaptivePortal_PrivateIpNotPortal_Enabled_IPv6() throws Exception {
        when(mDependencies.isFeatureEnabled(any(), eq(DNS_PROBE_PRIVATE_IP_NO_INTERNET_VERSION)))
                .thenReturn(true);
        setupPrivateIpResponse("fec0:1234::1");
        runFailedNetworkTest();
    }

    @Test
    public void testIsCaptivePortal_PrivateIpNotPortal_Disabled() throws Exception {
        setupPrivateIpResponse("192.168.1.1");
        runPortalNetworkTest();
    }

    @Test
    public void testIsCaptivePortal_HttpsProbeIsNotPortal() throws Exception {
        setStatus(mHttpsConnection, 204);
        setStatus(mHttpConnection, 500);

        runValidatedNetworkTest();
    }

    @Test
    public void testIsCaptivePortal_FallbackProbeIsPortal() throws Exception {
        setSslException(mHttpsConnection);
        setStatus(mHttpConnection, 500);
        setPortal302(mFallbackConnection);
        runPortalNetworkTest();
    }

    @Test
    public void testIsCaptivePortal_HttpSucceedFallbackProbeIsPortal() throws Exception {
        setSslException(mHttpsConnection);
        setStatus(mHttpConnection, 204);
        setPortal302(mFallbackConnection);
        runPortalNetworkTest();
    }

    @Test
    public void testIsCaptivePortal_FallbackProbeIsNotPortal() throws Exception {
        setSslException(mHttpsConnection);
        setStatus(mHttpConnection, 500);
        setStatus(mFallbackConnection, 500);

        // Fallback probe did not see portal, HTTPS failed -> inconclusive
        runFailedNetworkTest();
    }

    @Test
    public void testIsCaptivePortal_OtherFallbackProbeIsPortal() throws Exception {
        // Set all fallback probes but one to invalid URLs to verify they are being skipped
        setFallbackUrl(TEST_FALLBACK_URL);
        setOtherFallbackUrls(TEST_FALLBACK_URL + "," + TEST_OTHER_FALLBACK_URL);

        setSslException(mHttpsConnection);
        setStatus(mHttpConnection, 500);
        setStatus(mFallbackConnection, 500);
        setPortal302(mOtherFallbackConnection);

        // TEST_OTHER_FALLBACK_URL is third
        when(mRandom.nextInt()).thenReturn(2);

        // First check always uses the first fallback URL: inconclusive
        final NetworkMonitor monitor = runFailedNetworkTest();
        verify(mFallbackConnection, times(1)).getResponseCode();
        verify(mOtherFallbackConnection, never()).getResponseCode();

        // Second check should be triggered automatically after the reevaluate delay, and uses the
        // URL chosen by mRandom
        // Ensure that the reevaluate delay is not changed to a large value, otherwise this test
        // would block for too long and a different test strategy should be used.
        assertTrue(INITIAL_REEVALUATE_DELAY_MS < 2000);
        verify(mOtherFallbackConnection, timeout(INITIAL_REEVALUATE_DELAY_MS + HANDLER_TIMEOUT_MS))
                .getResponseCode();
        verifyNetworkTested(VALIDATION_RESULT_PORTAL, 0 /* probesSucceeded */, TEST_LOGIN_URL);
    }

    @Test
    public void testIsCaptivePortal_AllProbesFailed() throws Exception {
        setSslException(mHttpsConnection);
        setStatus(mHttpConnection, 500);
        setStatus(mFallbackConnection, 404);

        runFailedNetworkTest();
        verify(mFallbackConnection, times(1)).getResponseCode();
        verify(mOtherFallbackConnection, never()).getResponseCode();
    }

    @Test
    public void testIsCaptivePortal_InvalidUrlSkipped() throws Exception {
        setFallbackUrl("invalid");
        setOtherFallbackUrls("otherinvalid," + TEST_OTHER_FALLBACK_URL + ",yetanotherinvalid");

        setSslException(mHttpsConnection);
        setStatus(mHttpConnection, 500);
        setPortal302(mOtherFallbackConnection);
        runPortalNetworkTest();
        verify(mOtherFallbackConnection, times(1)).getResponseCode();
        verify(mFallbackConnection, never()).getResponseCode();
    }

    @Test
    public void testIsCaptivePortal_CapportApiIsPortalWithNullPortalUrl() throws Exception {
        assumeTrue(CaptivePortalDataShimImpl.isSupported());
        setSslException(mHttpsConnection);
        final long bytesRemaining = 10_000L;
        final long secondsRemaining = 500L;
        // Set content without partal url.
        setApiContent(mCapportApiConnection, "{'captive': true,"
                + "'venue-info-url': '" + TEST_VENUE_INFO_URL + "',"
                + "'bytes-remaining': " + bytesRemaining + ","
                + "'seconds-remaining': " + secondsRemaining + "}");
        setPortal302(mHttpConnection);

        runNetworkTest(makeCapportLPs(), CELL_METERED_CAPABILITIES, VALIDATION_RESULT_PORTAL,
                0 /* probesSucceeded*/, TEST_LOGIN_URL);

        verify(mCapportApiConnection).getResponseCode();

        verify(mHttpConnection, times(1)).getResponseCode();
        verify(mCallbacks, never()).notifyCaptivePortalDataChanged(any());
    }

    @Test
    public void testIsCaptivePortal_CapportApiIsPortalWithValidPortalUrl() throws Exception {
        assumeTrue(CaptivePortalDataShimImpl.isSupported());
        setSslException(mHttpsConnection);
        final long bytesRemaining = 10_000L;
        final long secondsRemaining = 500L;

        setApiContent(mCapportApiConnection, "{'captive': true,"
                + "'user-portal-url': '" + TEST_LOGIN_URL + "',"
                + "'venue-info-url': '" + TEST_VENUE_INFO_URL + "',"
                + "'bytes-remaining': " + bytesRemaining + ","
                + "'seconds-remaining': " + secondsRemaining + "}");

        runNetworkTest(makeCapportLPs(), CELL_METERED_CAPABILITIES, VALIDATION_RESULT_PORTAL,
                0 /* probesSucceeded*/, TEST_LOGIN_URL);

        verify(mHttpConnection, never()).getResponseCode();
        verify(mCapportApiConnection).getResponseCode();

        final ArgumentCaptor<CaptivePortalData> capportDataCaptor =
                ArgumentCaptor.forClass(CaptivePortalData.class);
        verify(mCallbacks).notifyCaptivePortalDataChanged(capportDataCaptor.capture());
        final CaptivePortalData p = capportDataCaptor.getValue();
        assertTrue(p.isCaptive());
        assertEquals(Uri.parse(TEST_LOGIN_URL), p.getUserPortalUrl());
        assertEquals(Uri.parse(TEST_VENUE_INFO_URL), p.getVenueInfoUrl());
        assertEquals(bytesRemaining, p.getByteLimit());
        final long expectedExpiry = currentTimeMillis() + secondsRemaining * 1000;
        // Actual expiry will be slightly lower as some time as passed
        assertTrue(p.getExpiryTimeMillis() <= expectedExpiry);
        assertTrue(p.getExpiryTimeMillis() > expectedExpiry - 30_000);
    }

    @Test
    public void testIsCaptivePortal_CapportApiRevalidation() throws Exception {
        assumeTrue(CaptivePortalDataShimImpl.isSupported());
        setValidProbes();
        final NetworkMonitor nm = runValidatedNetworkTest();

        setApiContent(mCapportApiConnection, "{'captive': true, "
                + "'user-portal-url': '" + TEST_LOGIN_URL + "'}");
        nm.notifyLinkPropertiesChanged(makeCapportLPs());

        verifyNetworkTested(VALIDATION_RESULT_PORTAL, 0 /* probesSucceeded */,
                TEST_LOGIN_URL);
        final ArgumentCaptor<CaptivePortalData> capportCaptor = ArgumentCaptor.forClass(
                CaptivePortalData.class);
        verify(mCallbacks).notifyCaptivePortalDataChanged(capportCaptor.capture());
        assertEquals(Uri.parse(TEST_LOGIN_URL), capportCaptor.getValue().getUserPortalUrl());

        // HTTP probe was sent on first validation but not re-sent when there was a portal URL.
        verify(mHttpConnection, times(1)).getResponseCode();
        verify(mCapportApiConnection, times(1)).getResponseCode();
    }

    @Test
    public void testIsCaptivePortal_NoRevalidationBeforeNetworkConnected() throws Exception {
        assumeTrue(CaptivePortalDataShimImpl.isSupported());

        final NetworkMonitor nm = makeCellMeteredNetworkMonitor();

        final LinkProperties lp = makeCapportLPs();

        // LinkProperties changed, but NM should not revalidate before notifyNetworkConnected
        nm.notifyLinkPropertiesChanged(lp);
        verify(mHttpConnection, after(100).never()).getResponseCode();
        verify(mHttpsConnection, never()).getResponseCode();
        verify(mCapportApiConnection, never()).getResponseCode();

        setValidProbes();
        setApiContent(mCapportApiConnection, "{'captive': true, "
                + "'user-portal-url': '" + TEST_LOGIN_URL + "'}");

        // After notifyNetworkConnected, validation uses the capport API contents
        nm.notifyNetworkConnected(lp, CELL_METERED_CAPABILITIES);
        verifyNetworkTested(VALIDATION_RESULT_PORTAL, 0 /* probesSucceeded */, TEST_LOGIN_URL);

        verify(mHttpConnection, never()).getResponseCode();
        verify(mCapportApiConnection).getResponseCode();
    }

    @Test
    public void testIsCaptivePortal_CapportApiNotPortalNotValidated() throws Exception {
        assumeTrue(CaptivePortalDataShimImpl.isSupported());
        setSslException(mHttpsConnection);
        setStatus(mHttpConnection, 500);
        setApiContent(mCapportApiConnection, "{'captive': false,"
                + "'venue-info-url': '" + TEST_VENUE_INFO_URL + "'}");
        runNetworkTest(makeCapportLPs(), CELL_METERED_CAPABILITIES, VALIDATION_RESULT_INVALID,
                0 /* probesSucceeded */, null /* redirectUrl */);

        final ArgumentCaptor<CaptivePortalData> capportCaptor = ArgumentCaptor.forClass(
                CaptivePortalData.class);
        verify(mCallbacks).notifyCaptivePortalDataChanged(capportCaptor.capture());
        assertEquals(Uri.parse(TEST_VENUE_INFO_URL), capportCaptor.getValue().getVenueInfoUrl());
    }

    @Test
    public void testIsCaptivePortal_CapportApiNotPortalPartial() throws Exception {
        assumeTrue(CaptivePortalDataShimImpl.isSupported());
        setSslException(mHttpsConnection);
        setStatus(mHttpConnection, 204);
        setApiContent(mCapportApiConnection, "{'captive': false,"
                + "'venue-info-url': '" + TEST_VENUE_INFO_URL + "'}");
        runNetworkTest(makeCapportLPs(), CELL_METERED_CAPABILITIES,
                NETWORK_VALIDATION_RESULT_PARTIAL,
                NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP,
                null /* redirectUrl */);

        final ArgumentCaptor<CaptivePortalData> capportCaptor = ArgumentCaptor.forClass(
                CaptivePortalData.class);
        verify(mCallbacks).notifyCaptivePortalDataChanged(capportCaptor.capture());
        assertEquals(Uri.parse(TEST_VENUE_INFO_URL), capportCaptor.getValue().getVenueInfoUrl());
    }

    @Test
    public void testIsCaptivePortal_CapportApiNotPortalValidated() throws Exception {
        assumeTrue(CaptivePortalDataShimImpl.isSupported());
        setStatus(mHttpsConnection, 204);
        setStatus(mHttpConnection, 204);
        setApiContent(mCapportApiConnection, "{'captive': false,"
                + "'venue-info-url': '" + TEST_VENUE_INFO_URL + "'}");
        runNetworkTest(makeCapportLPs(), CELL_METERED_CAPABILITIES,
                NETWORK_VALIDATION_RESULT_VALID,
                NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP
                        | NETWORK_VALIDATION_PROBE_HTTPS,
                null /* redirectUrl */);

        final ArgumentCaptor<CaptivePortalData> capportCaptor = ArgumentCaptor.forClass(
                CaptivePortalData.class);
        verify(mCallbacks).notifyCaptivePortalDataChanged(capportCaptor.capture());
        assertEquals(Uri.parse(TEST_VENUE_INFO_URL), capportCaptor.getValue().getVenueInfoUrl());
    }

    @Test
    public void testIsCaptivePortal_CapportApiInvalidContent() throws Exception {
        assumeTrue(CaptivePortalDataShimImpl.isSupported());
        setSslException(mHttpsConnection);
        setPortal302(mHttpConnection);
        setApiContent(mCapportApiConnection, "{SomeInvalidText");
        runNetworkTest(makeCapportLPs(), CELL_METERED_CAPABILITIES,
                VALIDATION_RESULT_PORTAL, 0 /* probesSucceeded */,
                TEST_LOGIN_URL);

        verify(mCallbacks, never()).notifyCaptivePortalDataChanged(any());
        verify(mHttpConnection).getResponseCode();
    }

    private void runCapportApiInvalidUrlTest(String url) throws Exception {
        assumeTrue(CaptivePortalDataShimImpl.isSupported());
        setSslException(mHttpsConnection);
        setPortal302(mHttpConnection);
        final LinkProperties lp = new LinkProperties(TEST_LINK_PROPERTIES);
        lp.setCaptivePortalApiUrl(Uri.parse(url));
        runNetworkTest(makeCapportLPs(), CELL_METERED_CAPABILITIES,
                VALIDATION_RESULT_PORTAL, 0 /* probesSucceeded */,
                TEST_LOGIN_URL);

        verify(mCallbacks, never()).notifyCaptivePortalDataChanged(any());
        verify(mCapportApiConnection, never()).getInputStream();
        verify(mHttpConnection).getResponseCode();
    }

    @Test
    public void testIsCaptivePortal_HttpIsInvalidCapportApiScheme() throws Exception {
        runCapportApiInvalidUrlTest("http://capport.example.com");
    }

    @Test
    public void testIsCaptivePortal_FileIsInvalidCapportApiScheme() throws Exception {
        runCapportApiInvalidUrlTest("file://localhost/myfile");
    }

    @Test
    public void testIsCaptivePortal_InvalidUrlFormat() throws Exception {
        runCapportApiInvalidUrlTest("ThisIsNotAValidUrl");
    }

    @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
    public void testIsCaptivePortal_CapportApiNotSupported() throws Exception {
        // Test that on a R+ device, if NetworkStack was compiled without CaptivePortalData support
        // (built against Q), NetworkMonitor behaves as expected.
        assumeFalse(CaptivePortalDataShimImpl.isSupported());
        setSslException(mHttpsConnection);
        setPortal302(mHttpConnection);
        setApiContent(mCapportApiConnection, "{'captive': false,"
                + "'venue-info-url': '" + TEST_VENUE_INFO_URL + "'}");
        runNetworkTest(makeCapportLPs(), CELL_METERED_CAPABILITIES, VALIDATION_RESULT_PORTAL,
                0 /* probesSucceeded */,
                TEST_LOGIN_URL);

        verify(mCallbacks, never()).notifyCaptivePortalDataChanged(any());
        verify(mHttpConnection).getResponseCode();
    }

    @Test
    public void testIsCaptivePortal_HttpsProbeMatchesFailRegex() throws Exception {
        setStatus(mHttpsConnection, 200);
        setStatus(mHttpConnection, 500);
        final String content = "test";
        doReturn(new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)))
                .when(mHttpsConnection).getInputStream();
        doReturn(Long.valueOf(content.length())).when(mHttpsConnection).getContentLengthLong();
        doReturn(1).when(mResources).getInteger(R.integer.config_min_matches_http_content_length);
        doReturn(10).when(mResources).getInteger(
                R.integer.config_max_matches_http_content_length);
        doReturn("te.t").when(mResources).getString(
                R.string.config_network_validation_failed_content_regexp);
        runFailedNetworkTest();
    }

    @Test
    public void testIsCaptivePortal_HttpProbeMatchesSuccessRegex() throws Exception {
        setStatus(mHttpsConnection, 500);
        setStatus(mHttpConnection, 200);
        final String content = "test";
        doReturn(new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)))
                .when(mHttpConnection).getInputStream();
        doReturn(Long.valueOf(content.length())).when(mHttpConnection).getContentLengthLong();
        doReturn(1).when(mResources).getInteger(R.integer.config_min_matches_http_content_length);
        doReturn(10).when(mResources).getInteger(
                R.integer.config_max_matches_http_content_length);
        doReturn("te.t").when(mResources).getString(
                R.string.config_network_validation_success_content_regexp);
        runPartialConnectivityNetworkTest(
                NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP);
    }

    private void setupFallbackSpec() throws IOException {
        setFallbackSpecs("http://example.com@@/@@204@@/@@"
                + "@@,@@"
                + TEST_OTHER_FALLBACK_URL + "@@/@@30[12]@@/@@https://(www\\.)?google.com/?.*");

        setSslException(mHttpsConnection);
        setStatus(mHttpConnection, 500);

        // Use the 2nd fallback spec
        when(mRandom.nextInt()).thenReturn(1);
    }

    @Test
    public void testIsCaptivePortal_FallbackSpecIsFail() throws Exception {
        setupFallbackSpec();
        set302(mOtherFallbackConnection, "https://www.google.com/test?q=3");

        runNetworkTest(VALIDATION_RESULT_INVALID,
                NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_FALLBACK,
                null /* redirectUrl */);
        verify(mOtherFallbackConnection, times(1)).getResponseCode();
        verify(mFallbackConnection, never()).getResponseCode();
    }

    @Test
    public void testIsCaptivePortal_FallbackSpecIsPortal() throws Exception {
        setupFallbackSpec();
        setPortal302(mOtherFallbackConnection);
        runPortalNetworkTest();
    }

    @Test
    public void testIsCaptivePortal_IgnorePortals() throws Exception {
        setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE);
        setSslException(mHttpsConnection);
        setPortal302(mHttpConnection);

        runNoValidationNetworkTest();
    }

    @Test
    public void testIsCaptivePortal_OverriddenHttpsUrlValid() throws Exception {
        setDeviceConfig(TEST_URL_EXPIRATION_TIME,
                String.valueOf(currentTimeMillis() + TimeUnit.MINUTES.toMillis(9)));
        setDeviceConfig(TEST_CAPTIVE_PORTAL_HTTPS_URL, TEST_OVERRIDE_URL);
        setStatus(mTestOverriddenUrlConnection, 204);
        setStatus(mHttpConnection, 204);

        runValidatedNetworkTest();
        verify(mHttpsConnection, never()).getResponseCode();
        verify(mTestOverriddenUrlConnection).getResponseCode();
    }

    @Test
    public void testIsCaptivePortal_OverriddenHttpUrlPortal() throws Exception {
        setDeviceConfig(TEST_URL_EXPIRATION_TIME,
                String.valueOf(currentTimeMillis() + TimeUnit.MINUTES.toMillis(9)));
        setDeviceConfig(TEST_CAPTIVE_PORTAL_HTTP_URL, TEST_OVERRIDE_URL);
        setStatus(mHttpsConnection, 500);
        setPortal302(mTestOverriddenUrlConnection);

        runPortalNetworkTest();
        verify(mHttpConnection, never()).getResponseCode();
        verify(mTestOverriddenUrlConnection).getResponseCode();
    }

    @Test
    public void testIsCaptivePortal_InvalidHttpOverrideUrl() throws Exception {
        setDeviceConfig(TEST_URL_EXPIRATION_TIME,
                String.valueOf(currentTimeMillis() + TimeUnit.MINUTES.toMillis(9)));
        setDeviceConfig(TEST_CAPTIVE_PORTAL_HTTP_URL, TEST_INVALID_OVERRIDE_URL);
        setStatus(mHttpsConnection, 500);
        setPortal302(mHttpConnection);

        runPortalNetworkTest();
        verify(mTestOverriddenUrlConnection, never()).getResponseCode();
        verify(mHttpConnection).getResponseCode();
    }

    @Test
    public void testIsCaptivePortal_InvalidHttpsOverrideUrl() throws Exception {
        setDeviceConfig(TEST_URL_EXPIRATION_TIME,
                String.valueOf(currentTimeMillis() + TimeUnit.MINUTES.toMillis(9)));
        setDeviceConfig(TEST_CAPTIVE_PORTAL_HTTPS_URL, TEST_INVALID_OVERRIDE_URL);
        setStatus(mHttpsConnection, 204);
        setStatus(mHttpConnection, 204);

        runValidatedNetworkTest();
        verify(mTestOverriddenUrlConnection, never()).getResponseCode();
        verify(mHttpsConnection).getResponseCode();
    }

    @Test
    public void testIsCaptivePortal_ExpiredHttpsOverrideUrl() throws Exception {
        setDeviceConfig(TEST_URL_EXPIRATION_TIME,
                String.valueOf(currentTimeMillis() - TimeUnit.MINUTES.toMillis(1)));
        setDeviceConfig(TEST_CAPTIVE_PORTAL_HTTPS_URL, TEST_OVERRIDE_URL);
        setStatus(mHttpsConnection, 204);
        setStatus(mHttpConnection, 204);

        runValidatedNetworkTest();
        verify(mTestOverriddenUrlConnection, never()).getResponseCode();
        verify(mHttpsConnection).getResponseCode();
    }

    @Test
    public void testIsCaptivePortal_TestHttpUrlExpirationTooLarge() throws Exception {
        setDeviceConfig(TEST_URL_EXPIRATION_TIME,
                String.valueOf(currentTimeMillis() + TimeUnit.MINUTES.toMillis(20)));
        setDeviceConfig(TEST_CAPTIVE_PORTAL_HTTP_URL, TEST_OVERRIDE_URL);
        setStatus(mHttpsConnection, 500);
        setPortal302(mHttpConnection);

        runPortalNetworkTest();
        verify(mTestOverriddenUrlConnection, never()).getResponseCode();
        verify(mHttpConnection).getResponseCode();
    }

    @Test
    public void testIsCaptivePortal_TestUrlsWithUrlOverlays() throws Exception {
        setupResourceForMultipleProbes();
        doReturn(TEST_HTTPS_URL).when(mResources)
                .getString(R.string.config_captive_portal_https_url);
        doReturn(TEST_HTTP_URL).when(mResources)
                .getString(R.string.config_captive_portal_http_url);

        setDeviceConfig(TEST_URL_EXPIRATION_TIME,
                String.valueOf(currentTimeMillis() + TimeUnit.MINUTES.toMillis(9)));
        setDeviceConfig(TEST_CAPTIVE_PORTAL_HTTPS_URL, TEST_OVERRIDE_URL);
        setDeviceConfig(TEST_CAPTIVE_PORTAL_HTTP_URL, TEST_OVERRIDE_URL);
        setStatus(mTestOverriddenUrlConnection, 204);

        runValidatedNetworkTest();
        verify(mHttpsConnection, never()).getResponseCode();
        verify(mHttpConnection, never()).getResponseCode();
        verify(mOtherHttpsConnection1, never()).getResponseCode();
        verify(mOtherHttpsConnection2, never()).getResponseCode();
        verify(mOtherHttpConnection1, never()).getResponseCode();
        verify(mOtherHttpConnection2, never()).getResponseCode();

        // Used for both HTTP and HTTPS: can be called once (if HTTPS validates first) or twice
        verify(mTestOverriddenUrlConnection, atLeastOnce()).getResponseCode();
    }

    @Test
    public void testIsDataStall_EvaluationDisabled() {
        setDataStallEvaluationType(0);
        WrappedNetworkMonitor wrappedMonitor = makeCellMeteredNetworkMonitor();
        wrappedMonitor.setLastProbeTime(SystemClock.elapsedRealtime() - 100);
        assertFalse(wrappedMonitor.isDataStall());
    }

    @Test
    public void testIsDataStall_EvaluationDnsOnNotMeteredNetwork() throws Exception {
        WrappedNetworkMonitor wrappedMonitor = makeCellNotMeteredNetworkMonitor();
        wrappedMonitor.setLastProbeTime(SystemClock.elapsedRealtime() - 100);
        makeDnsTimeoutEvent(wrappedMonitor, DEFAULT_DNS_TIMEOUT_THRESHOLD);
        assertTrue(wrappedMonitor.isDataStall());
        verify(mCallbacks).notifyDataStallSuspected(
                matchDnsDataStallParcelable(DEFAULT_DNS_TIMEOUT_THRESHOLD));
    }

    @Test
    public void testIsDataStall_EvaluationDnsOnMeteredNetwork() throws Exception {
        WrappedNetworkMonitor wrappedMonitor = makeCellMeteredNetworkMonitor();
        wrappedMonitor.setLastProbeTime(SystemClock.elapsedRealtime() - 100);
        assertFalse(wrappedMonitor.isDataStall());

        wrappedMonitor.setLastProbeTime(
                SystemClock.elapsedRealtime() - STALL_EXPECTED_LAST_PROBE_TIME_MS);
        makeDnsTimeoutEvent(wrappedMonitor, DEFAULT_DNS_TIMEOUT_THRESHOLD);
        assertTrue(wrappedMonitor.isDataStall());
        verify(mCallbacks).notifyDataStallSuspected(
                matchDnsDataStallParcelable(DEFAULT_DNS_TIMEOUT_THRESHOLD));
    }

    @Test
    public void testIsDataStall_EvaluationDnsWithDnsTimeoutCount() throws Exception {
        WrappedNetworkMonitor wrappedMonitor = makeCellMeteredNetworkMonitor();
        wrappedMonitor.setLastProbeTime(
                SystemClock.elapsedRealtime() - STALL_EXPECTED_LAST_PROBE_TIME_MS);
        makeDnsTimeoutEvent(wrappedMonitor, 3);
        assertFalse(wrappedMonitor.isDataStall());
        // Reset consecutive timeout counts.
        makeDnsSuccessEvent(wrappedMonitor, 1);
        makeDnsTimeoutEvent(wrappedMonitor, 2);
        assertFalse(wrappedMonitor.isDataStall());

        makeDnsTimeoutEvent(wrappedMonitor, 3);
        assertTrue(wrappedMonitor.isDataStall());

        // The expected timeout count is the previous 2 DNS timeouts + the most recent 3 timeouts
        verify(mCallbacks).notifyDataStallSuspected(
                matchDnsDataStallParcelable(5 /* timeoutCount */));

        // Set the value to larger than the default dns log size.
        setConsecutiveDnsTimeoutThreshold(51);
        wrappedMonitor = makeCellMeteredNetworkMonitor();
        wrappedMonitor.setLastProbeTime(
                SystemClock.elapsedRealtime() - STALL_EXPECTED_LAST_PROBE_TIME_MS);
        makeDnsTimeoutEvent(wrappedMonitor, 50);
        assertFalse(wrappedMonitor.isDataStall());

        makeDnsTimeoutEvent(wrappedMonitor, 1);
        assertTrue(wrappedMonitor.isDataStall());

        // The expected timeout count is the previous 50 DNS timeouts + the most recent timeout
        verify(mCallbacks).notifyDataStallSuspected(
                matchDnsDataStallParcelable(51 /* timeoutCount */));
    }

    @Test
    public void testIsDataStall_SkipEvaluateOnValidationNotRequiredNetwork() {
        // Make DNS and TCP stall condition satisfied.
        setDataStallEvaluationType(DATA_STALL_EVALUATION_TYPE_DNS | DATA_STALL_EVALUATION_TYPE_TCP);
        when(mTstDependencies.isTcpInfoParsingSupported()).thenReturn(true);
        when(mTst.getLatestReceivedCount()).thenReturn(0);
        when(mTst.isDataStallSuspected()).thenReturn(true);
        final WrappedNetworkMonitor nm = makeMonitor(CELL_NO_INTERNET_CAPABILITIES);
        nm.setLastProbeTime(SystemClock.elapsedRealtime() - 1000);
        makeDnsTimeoutEvent(nm, DEFAULT_DNS_TIMEOUT_THRESHOLD);
        assertFalse(nm.isDataStall());
    }

    @Test
    public void testIsDataStall_EvaluationDnsWithDnsTimeThreshold() throws Exception {
        // Test dns events happened in valid dns time threshold.
        WrappedNetworkMonitor wrappedMonitor = makeCellMeteredNetworkMonitor();
        wrappedMonitor.setLastProbeTime(SystemClock.elapsedRealtime() - 100);
        makeDnsTimeoutEvent(wrappedMonitor, DEFAULT_DNS_TIMEOUT_THRESHOLD);
        assertFalse(wrappedMonitor.isDataStall());
        wrappedMonitor.setLastProbeTime(
                SystemClock.elapsedRealtime() - STALL_EXPECTED_LAST_PROBE_TIME_MS);
        assertTrue(wrappedMonitor.isDataStall());
        verify(mCallbacks).notifyDataStallSuspected(
                matchDnsDataStallParcelable(DEFAULT_DNS_TIMEOUT_THRESHOLD));

        // Test dns events happened before valid dns time threshold.
        setValidDataStallDnsTimeThreshold(0);
        wrappedMonitor = makeCellMeteredNetworkMonitor();
        wrappedMonitor.setLastProbeTime(SystemClock.elapsedRealtime() - 100);
        makeDnsTimeoutEvent(wrappedMonitor, DEFAULT_DNS_TIMEOUT_THRESHOLD);
        assertFalse(wrappedMonitor.isDataStall());
        wrappedMonitor.setLastProbeTime(
                SystemClock.elapsedRealtime() - STALL_EXPECTED_LAST_PROBE_TIME_MS);
        assertFalse(wrappedMonitor.isDataStall());
    }

    @Test
    public void testIsDataStall_EvaluationTcp() throws Exception {
        // Evaluate TCP only. Expect ignoring DNS signal.
        setDataStallEvaluationType(DATA_STALL_EVALUATION_TYPE_TCP);
        WrappedNetworkMonitor wrappedMonitor = makeMonitor(CELL_METERED_CAPABILITIES);
        assertFalse(wrappedMonitor.isDataStall());
        // Packet received.
        when(mTstDependencies.isTcpInfoParsingSupported()).thenReturn(true);
        when(mTst.getLatestReceivedCount()).thenReturn(5);
        // Trigger a tcp event immediately.
        setTcpPollingInterval(0);
        wrappedMonitor.sendTcpPollingEvent();
        HandlerUtils.waitForIdle(wrappedMonitor.getHandler(), HANDLER_TIMEOUT_MS);
        assertFalse(wrappedMonitor.isDataStall());

        when(mTst.getLatestReceivedCount()).thenReturn(0);
        when(mTst.isDataStallSuspected()).thenReturn(true);
        // Trigger a tcp event immediately.
        setTcpPollingInterval(0);
        wrappedMonitor.sendTcpPollingEvent();
        HandlerUtils.waitForIdle(wrappedMonitor.getHandler(), HANDLER_TIMEOUT_MS);
        assertTrue(wrappedMonitor.isDataStall());
        verify(mCallbacks).notifyDataStallSuspected(matchTcpDataStallParcelable());
    }

    @Test
    public void testIsDataStall_EvaluationDnsAndTcp() throws Exception {
        setDataStallEvaluationType(DATA_STALL_EVALUATION_TYPE_DNS | DATA_STALL_EVALUATION_TYPE_TCP);
        setupTcpDataStall();
        final WrappedNetworkMonitor nm = makeMonitor(CELL_METERED_CAPABILITIES);
        nm.setLastProbeTime(SystemClock.elapsedRealtime() - STALL_EXPECTED_LAST_PROBE_TIME_MS);
        makeDnsTimeoutEvent(nm, DEFAULT_DNS_TIMEOUT_THRESHOLD);
        assertTrue(nm.isDataStall());
        verify(mCallbacks).notifyDataStallSuspected(
                matchDnsAndTcpDataStallParcelable(DEFAULT_DNS_TIMEOUT_THRESHOLD));

        when(mTst.getLatestReceivedCount()).thenReturn(5);
        // Trigger a tcp event immediately.
        setTcpPollingInterval(0);
        nm.sendTcpPollingEvent();
        HandlerUtils.waitForIdle(nm.getHandler(), HANDLER_TIMEOUT_MS);
        assertFalse(nm.isDataStall());
    }

    @Test
    public void testIsDataStall_DisableTcp() {
        // Disable tcp detection with only DNS detect. keep the tcp signal but set to no DNS signal.
        setDataStallEvaluationType(DATA_STALL_EVALUATION_TYPE_DNS);
        WrappedNetworkMonitor wrappedMonitor = makeMonitor(CELL_METERED_CAPABILITIES);
        makeDnsSuccessEvent(wrappedMonitor, 1);
        wrappedMonitor.sendTcpPollingEvent();
        HandlerUtils.waitForIdle(wrappedMonitor.getHandler(), HANDLER_TIMEOUT_MS);
        assertFalse(wrappedMonitor.isDataStall());
        verify(mTst, never()).isDataStallSuspected();
        verify(mTst, never()).pollSocketsInfo();
    }

    @Test
    public void testBrokenNetworkNotValidated() throws Exception {
        setSslException(mHttpsConnection);
        setStatus(mHttpConnection, 500);
        setStatus(mFallbackConnection, 404);

        runFailedNetworkTest();
    }

    private void doValidationSkippedTest(NetworkCapabilities nc) throws Exception {
        // For S+, the RESULT_SKIPPED bit will be included on networks that both do not require
        // validation and for which validation is not performed.
        final int validationResult = ShimUtils.isAtLeastS()
                ? NETWORK_VALIDATION_RESULT_VALID | NETWORK_VALIDATION_RESULT_SKIPPED
                : NETWORK_VALIDATION_RESULT_VALID;
        runNetworkTest(TEST_LINK_PROPERTIES, nc, validationResult,
                0 /* probesSucceeded */, null /* redirectUrl */);
        verify(mCleartextDnsNetwork, never()).openConnection(any());
    }

    @Test
    public void testNoInternetCapabilityValidated() throws Exception {
        doValidationSkippedTest(CELL_NO_INTERNET_CAPABILITIES);
    }

    @Test
    public void testNoTrustedCapabilityValidated() throws Exception {
        // Cannot use the NetworkCapabilities builder on Q
        final NetworkCapabilities nc = new NetworkCapabilities()
                .addCapability(NET_CAPABILITY_INTERNET)
                .removeCapability(NET_CAPABILITY_TRUSTED)
                .addTransportType(TRANSPORT_CELLULAR);
        if (ShimUtils.isAtLeastS()) {
            nc.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
        }
        doValidationSkippedTest(nc);
    }

    @Test
    public void testRestrictedCapabilityValidated() throws Exception {
        // Cannot use the NetworkCapabilities builder on Q
        final NetworkCapabilities nc = new NetworkCapabilities()
                .addCapability(NET_CAPABILITY_INTERNET)
                .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
                .addTransportType(TRANSPORT_CELLULAR);
        if (ShimUtils.isAtLeastS()) {
            nc.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
        }
        doValidationSkippedTest(nc);
    }

    private NetworkCapabilities getVcnUnderlyingCarrierWifiCaps() {
        // Must be called from within the test because NOT_VCN_MANAGED is an invalid capability
        // value up to Android R. Thus, this must be guarded by an SDK check in tests that use this.
        return new NetworkCapabilities.Builder()
                .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
                .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
                .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
                .addCapability(NET_CAPABILITY_INTERNET)
                .build();
    }

    @Test
    public void testVcnUnderlyingNetwork() throws Exception {
        assumeTrue(ShimUtils.isAtLeastS());
        setStatus(mHttpsConnection, 204);
        setStatus(mHttpConnection, 204);

        final NetworkMonitor nm = runNetworkTest(
                TEST_LINK_PROPERTIES, getVcnUnderlyingCarrierWifiCaps(),
                NETWORK_VALIDATION_RESULT_VALID,
                NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS,
                null /* redirectUrl */);
        assertEquals(NETWORK_VALIDATION_RESULT_VALID,
                nm.getEvaluationState().getEvaluationResult());
    }

    @Test
    public void testVcnUnderlyingNetworkBadNetwork() throws Exception {
        assumeTrue(ShimUtils.isAtLeastS());
        setSslException(mHttpsConnection);
        setStatus(mHttpConnection, 500);
        setStatus(mFallbackConnection, 404);

        final NetworkMonitor nm = runNetworkTest(
                TEST_LINK_PROPERTIES, getVcnUnderlyingCarrierWifiCaps(),
                VALIDATION_RESULT_INVALID, 0 /* probesSucceeded */, null /* redirectUrl */);
        assertEquals(VALIDATION_RESULT_INVALID,
                nm.getEvaluationState().getEvaluationResult());
    }

    @Test
    public void testLaunchCaptivePortalApp() throws Exception {
        setSslException(mHttpsConnection);
        setPortal302(mHttpConnection);
        when(mHttpConnection.getHeaderField(eq("location"))).thenReturn(TEST_LOGIN_URL);
        final NetworkMonitor nm = makeMonitor(CELL_METERED_CAPABILITIES);
        notifyNetworkConnected(nm, CELL_METERED_CAPABILITIES);

        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
                .showProvisioningNotification(any(), any());

        assertEquals(1, mRegisteredReceivers.size());

        // Check that startCaptivePortalApp sends the expected intent.
        nm.launchCaptivePortalApp();

        final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
        final ArgumentCaptor<Network> networkCaptor = ArgumentCaptor.forClass(Network.class);
        verify(mCm, timeout(HANDLER_TIMEOUT_MS).times(1))
                .startCaptivePortalApp(networkCaptor.capture(), bundleCaptor.capture());
        verify(mNotifier).notifyCaptivePortalValidationPending(networkCaptor.getValue());
        final Bundle bundle = bundleCaptor.getValue();
        final Network bundleNetwork = bundle.getParcelable(ConnectivityManager.EXTRA_NETWORK);
        assertEquals(TEST_NETID, bundleNetwork.netId);
        // network is passed both in bundle and as parameter, as the bundle is opaque to the
        // framework and only intended for the captive portal app, but the framework needs
        // the network to identify the right NetworkMonitor.
        assertEquals(TEST_NETID, networkCaptor.getValue().netId);
        // Portal URL should be detection URL.
        final String redirectUrl = bundle.getString(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL);
        assertEquals(TEST_HTTP_URL, redirectUrl);

        // Have the app report that the captive portal is dismissed, and check that we revalidate.
        setStatus(mHttpsConnection, 204);
        setStatus(mHttpConnection, 204);

        resetCallbacks();
        nm.notifyCaptivePortalAppFinished(APP_RETURN_DISMISSED);
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).atLeastOnce())
                .notifyNetworkTestedWithExtras(matchNetworkTestResultParcelable(
                        NETWORK_VALIDATION_RESULT_VALID,
                        NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP));
        assertEquals(0, mRegisteredReceivers.size());
    }

    @Test
    public void testPrivateDnsSuccess() throws Exception {
        setStatus(mHttpsConnection, 204);
        setStatus(mHttpConnection, 204);

        // Verify dns query only get v6 address.
        mFakeDns.setAnswer("dns6.google", new String[]{"2001:db8::53"}, TYPE_AAAA);
        WrappedNetworkMonitor wnm = makeCellNotMeteredNetworkMonitor();
        wnm.notifyPrivateDnsSettingsChanged(new PrivateDnsConfig("dns6.google",
                new InetAddress[0]));
        notifyNetworkConnected(wnm, CELL_NOT_METERED_CAPABILITIES);
        verifyNetworkTested(NETWORK_VALIDATION_RESULT_VALID, PROBES_PRIVDNS_VALID);
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)).notifyProbeStatusChanged(
                eq(PROBES_PRIVDNS_VALID), eq(PROBES_PRIVDNS_VALID));

        // Verify dns query only get v4 address.
        resetCallbacks();
        mFakeDns.setAnswer("dns4.google", new String[]{"192.0.2.1"}, TYPE_A);
        wnm.notifyPrivateDnsSettingsChanged(new PrivateDnsConfig("dns4.google",
                new InetAddress[0]));
        verifyNetworkTested(NETWORK_VALIDATION_RESULT_VALID, PROBES_PRIVDNS_VALID);
        // NetworkMonitor will check if the probes has changed or not, if the probes has not
        // changed, the callback won't be fired.
        verify(mCallbacks, never()).notifyProbeStatusChanged(
                eq(PROBES_PRIVDNS_VALID), eq(PROBES_PRIVDNS_VALID));

        // Verify dns query get both v4 and v6 address.
        resetCallbacks();
        mFakeDns.setAnswer("dns.google", new String[]{"2001:db8::54"}, TYPE_AAAA);
        mFakeDns.setAnswer("dns.google", new String[]{"192.0.2.3"}, TYPE_A);
        wnm.notifyPrivateDnsSettingsChanged(new PrivateDnsConfig("dns.google", new InetAddress[0]));
        verifyNetworkTested(NETWORK_VALIDATION_RESULT_VALID, PROBES_PRIVDNS_VALID);
        verify(mCallbacks, never()).notifyProbeStatusChanged(
                eq(PROBES_PRIVDNS_VALID), eq(PROBES_PRIVDNS_VALID));
    }

    @Test
    public void testProbeStatusChanged() throws Exception {
        // Set no record in FakeDns and expect validation to fail.
        setStatus(mHttpsConnection, 204);
        setStatus(mHttpConnection, 204);

        WrappedNetworkMonitor wnm = makeCellNotMeteredNetworkMonitor();
        wnm.notifyPrivateDnsSettingsChanged(new PrivateDnsConfig("dns.google", new InetAddress[0]));
        wnm.notifyNetworkConnected(TEST_LINK_PROPERTIES, CELL_NOT_METERED_CAPABILITIES);
        verifyNetworkTested(VALIDATION_RESULT_INVALID,
                NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS);
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS)).notifyProbeStatusChanged(
                eq(PROBES_PRIVDNS_VALID), eq(NETWORK_VALIDATION_PROBE_DNS
                | NETWORK_VALIDATION_PROBE_HTTPS));
        // Fix DNS and retry, expect validation to succeed.
        resetCallbacks();
        mFakeDns.setAnswer("dns.google", new String[]{"2001:db8::1"}, TYPE_AAAA);

        wnm.forceReevaluation(Process.myUid());
        // ProbeCompleted should be reset to 0
        HandlerUtils.waitForIdle(wnm.getHandler(), HANDLER_TIMEOUT_MS);
        assertEquals(wnm.getEvaluationState().getProbeCompletedResult(), 0);
        verifyNetworkTested(NETWORK_VALIDATION_RESULT_VALID, PROBES_PRIVDNS_VALID);
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS)).notifyProbeStatusChanged(
                eq(PROBES_PRIVDNS_VALID), eq(PROBES_PRIVDNS_VALID));
    }

    @Test
    public void testPrivateDnsResolutionRetryUpdate() throws Exception {
        // Set no record in FakeDns and expect validation to fail.
        setStatus(mHttpsConnection, 204);
        setStatus(mHttpConnection, 204);

        WrappedNetworkMonitor wnm = makeCellNotMeteredNetworkMonitor();
        wnm.notifyPrivateDnsSettingsChanged(new PrivateDnsConfig("dns.google", new InetAddress[0]));
        wnm.notifyNetworkConnected(TEST_LINK_PROPERTIES, CELL_NOT_METERED_CAPABILITIES);
        verifyNetworkTested(VALIDATION_RESULT_INVALID,
                NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS);
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)).notifyProbeStatusChanged(
                eq(PROBES_PRIVDNS_VALID), eq(NETWORK_VALIDATION_PROBE_DNS
                | NETWORK_VALIDATION_PROBE_HTTPS));

        // Fix DNS and retry, expect validation to succeed.
        resetCallbacks();
        mFakeDns.setAnswer("dns.google", new String[]{"2001:db8::1"}, TYPE_AAAA);

        wnm.forceReevaluation(Process.myUid());
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).atLeastOnce())
                .notifyNetworkTestedWithExtras(matchNetworkTestResultParcelable(
                        NETWORK_VALIDATION_RESULT_VALID, PROBES_PRIVDNS_VALID));
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)).notifyProbeStatusChanged(
                eq(PROBES_PRIVDNS_VALID), eq(PROBES_PRIVDNS_VALID));

        // Change configuration to an invalid DNS name, expect validation to fail.
        resetCallbacks();
        mFakeDns.setAnswer("dns.bad", new String[0], TYPE_A);
        mFakeDns.setAnswer("dns.bad", new String[0], TYPE_AAAA);
        wnm.notifyPrivateDnsSettingsChanged(new PrivateDnsConfig("dns.bad", new InetAddress[0]));
        // Strict mode hostname resolve fail. Expect only notification for evaluation fail. No probe
        // notification.
        verifyNetworkTested(VALIDATION_RESULT_INVALID,
                NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS);
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)).notifyProbeStatusChanged(
                eq(PROBES_PRIVDNS_VALID), eq(NETWORK_VALIDATION_PROBE_DNS
                | NETWORK_VALIDATION_PROBE_HTTPS));

        // Change configuration back to working again, but make private DNS not work.
        // Expect validation to fail.
        resetCallbacks();
        mFakeDns.setNonBypassPrivateDnsWorking(false);
        wnm.notifyPrivateDnsSettingsChanged(new PrivateDnsConfig("dns.google",
                new InetAddress[0]));
        verifyNetworkTested(VALIDATION_RESULT_INVALID,
                NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS);
        // NetworkMonitor will check if the probes has changed or not, if the probes has not
        // changed, the callback won't be fired.
        verify(mCallbacks, never()).notifyProbeStatusChanged(
                eq(PROBES_PRIVDNS_VALID), eq(NETWORK_VALIDATION_PROBE_DNS
                | NETWORK_VALIDATION_PROBE_HTTPS));

        // Make private DNS work again. Expect validation to succeed.
        resetCallbacks();
        mFakeDns.setNonBypassPrivateDnsWorking(true);
        wnm.forceReevaluation(Process.myUid());
        verifyNetworkTested(NETWORK_VALIDATION_RESULT_VALID, PROBES_PRIVDNS_VALID);
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)).notifyProbeStatusChanged(
                eq(PROBES_PRIVDNS_VALID), eq(PROBES_PRIVDNS_VALID));
    }

    @Test
    public void testDataStall_StallDnsSuspectedAndSendMetricsOnCell() throws Exception {
        testDataStall_StallDnsSuspectedAndSendMetrics(NetworkCapabilities.TRANSPORT_CELLULAR,
                CELL_METERED_CAPABILITIES);
    }

    @Test
    public void testDataStall_StallDnsSuspectedAndSendMetricsOnWifi() throws Exception {
        testDataStall_StallDnsSuspectedAndSendMetrics(NetworkCapabilities.TRANSPORT_WIFI,
                WIFI_NOT_METERED_CAPABILITIES);
    }

    private void testDataStall_StallDnsSuspectedAndSendMetrics(int transport,
            NetworkCapabilities nc) throws Exception {
        // NM suspects data stall from DNS signal and sends data stall metrics.
        final WrappedNetworkMonitor nm = prepareNetworkMonitorForVerifyDataStall(nc);
        makeDnsTimeoutEvent(nm, 5);
        // Trigger a dns signal to start evaluate data stall and upload metrics.
        nm.notifyDnsResponse(RETURN_CODE_DNS_TIMEOUT);
        // Verify data sent as expected.
        verifySendDataStallDetectionStats(nm, DATA_STALL_EVALUATION_TYPE_DNS, transport);
    }

    @Test
    public void testDataStall_NoStallSuspectedAndSendMetrics() throws Exception {
        final WrappedNetworkMonitor nm = prepareNetworkMonitorForVerifyDataStall(
                CELL_METERED_CAPABILITIES);
        // Setup no data stall dns signal.
        makeDnsTimeoutEvent(nm, 3);
        assertFalse(nm.isDataStall());
        // Trigger a dns signal to start evaluate data stall.
        nm.notifyDnsResponse(RETURN_CODE_DNS_SUCCESS);
        verify(mDependencies, never()).writeDataStallDetectionStats(any(), any());
    }

    @Test
    public void testDataStall_StallTcpSuspectedAndSendMetricsOnCell() throws Exception {
        testDataStall_StallTcpSuspectedAndSendMetrics(CELL_METERED_CAPABILITIES);
    }

    @Test
    public void testDataStall_StallTcpSuspectedAndSendMetricsOnWifi() throws Exception {
        testDataStall_StallTcpSuspectedAndSendMetrics(WIFI_NOT_METERED_CAPABILITIES);
    }

    private void testDataStall_StallTcpSuspectedAndSendMetrics(NetworkCapabilities nc)
            throws Exception {
        assumeTrue(ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q));
        setupTcpDataStall();
        setTcpPollingInterval(0);
        // NM suspects data stall from TCP signal and sends data stall metrics.
        setDataStallEvaluationType(DATA_STALL_EVALUATION_TYPE_TCP);
        final WrappedNetworkMonitor nm = prepareNetworkMonitorForVerifyDataStall(nc);
        // Trigger a tcp event immediately.
        nm.sendTcpPollingEvent();
        // Allow only one transport type in the context of this test for simplification.
        final int[] transports = nc.getTransportTypes();
        assertEquals(1, transports.length);
        verifySendDataStallDetectionStats(nm, DATA_STALL_EVALUATION_TYPE_TCP, transports[0]);
    }

    private WrappedNetworkMonitor prepareNetworkMonitorForVerifyDataStall(NetworkCapabilities nc)
            throws Exception {
        // Connect a VALID network to simulate the data stall detection because data stall
        // evaluation will only start from validated state.
        setStatus(mHttpsConnection, 204);
        final WrappedNetworkMonitor nm;
        // Allow only one transport type in the context of this test for simplification.
        if (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
            nm = makeCellMeteredNetworkMonitor();
        } else if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
            nm = makeWifiNotMeteredNetworkMonitor();
            setupTestWifiInfo();
        } else {
            nm = null;
            fail("Undefined transport type");
        }
        nm.notifyNetworkConnected(TEST_LINK_PROPERTIES, nc);
        verifyNetworkTested(NETWORK_VALIDATION_RESULT_VALID,
                NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS);
        nm.setLastProbeTime(SystemClock.elapsedRealtime() - STALL_EXPECTED_LAST_PROBE_TIME_MS);
        return nm;
    }

    private void setupTcpDataStall() {
        when(mTstDependencies.isTcpInfoParsingSupported()).thenReturn(true);
        when(mTst.getLatestReceivedCount()).thenReturn(0);
        when(mTst.getLatestPacketFailPercentage()).thenReturn(TEST_TCP_FAIL_RATE);
        when(mTst.getSentSinceLastRecv()).thenReturn(TEST_TCP_PACKET_COUNT);
        when(mTst.isDataStallSuspected()).thenReturn(true);
        when(mTst.pollSocketsInfo()).thenReturn(true);
    }

    private void verifySendDataStallDetectionStats(WrappedNetworkMonitor nm, int evalType,
            int transport) {
        // Verify data sent as expectated.
        final ArgumentCaptor<CaptivePortalProbeResult> probeResultCaptor =
                ArgumentCaptor.forClass(CaptivePortalProbeResult.class);
        final ArgumentCaptor<DataStallDetectionStats> statsCaptor =
                ArgumentCaptor.forClass(DataStallDetectionStats.class);
        verify(mDependencies, timeout(HANDLER_TIMEOUT_MS).times(1))
                .writeDataStallDetectionStats(statsCaptor.capture(), probeResultCaptor.capture());
        // Ensure probe will not stop due to rate-limiting mechanism.
        nm.setLastProbeTime(SystemClock.elapsedRealtime() - STALL_EXPECTED_LAST_PROBE_TIME_MS);
        assertTrue(nm.isDataStall());
        assertTrue(probeResultCaptor.getValue().isSuccessful());
        verifyTestDataStallDetectionStats(evalType, transport, statsCaptor.getValue());
    }

    private void verifyTestDataStallDetectionStats(int evalType, int transport,
            DataStallDetectionStats stats) {
        assertEquals(transport, stats.mNetworkType);
        switch (transport) {
            case NetworkCapabilities.TRANSPORT_WIFI:
                assertArrayEquals(makeTestWifiDataNano(), stats.mWifiInfo);
                // Expedient way to check stats.mCellularInfo contains the neutral byte array that
                // is sent to represent a lack of data, as stats.mCellularInfo is not supposed to
                // contain null.
                assertArrayEquals(DataStallDetectionStats.emptyCellDataIfNull(null),
                        stats.mCellularInfo);
                break;
            case NetworkCapabilities.TRANSPORT_CELLULAR:
                // Expedient way to check stats.mWifiInfo contains the neutral byte array that is
                // sent to represent a lack of data, as stats.mWifiInfo is not supposed to contain
                // null.
                assertArrayEquals(DataStallDetectionStats.emptyWifiInfoIfNull(null),
                        stats.mWifiInfo);
                assertArrayEquals(makeTestCellDataNano(), stats.mCellularInfo);
                break;
            default:
                // Add other cases.
                fail("Unexpected transport type");
        }

        assertEquals(evalType, stats.mEvaluationType);
        if ((evalType & DATA_STALL_EVALUATION_TYPE_TCP) != 0) {
            assertEquals(TEST_TCP_FAIL_RATE, stats.mTcpFailRate);
            assertEquals(TEST_TCP_PACKET_COUNT, stats.mTcpSentSinceLastRecv);
        } else {
            assertEquals(DataStallDetectionStats.UNSPECIFIED_TCP_FAIL_RATE, stats.mTcpFailRate);
            assertEquals(DataStallDetectionStats.UNSPECIFIED_TCP_PACKETS_COUNT,
                    stats.mTcpSentSinceLastRecv);
        }

        if ((evalType & DATA_STALL_EVALUATION_TYPE_DNS) != 0) {
            assertArrayEquals(stats.mDns, makeTestDnsTimeoutNano(DEFAULT_DNS_TIMEOUT_THRESHOLD));
        } else {
            assertArrayEquals(stats.mDns, makeTestDnsTimeoutNano(0 /* times */));
        }
    }

    private DataStallDetectionStats makeTestDataStallDetectionStats(int evaluationType,
            int transportType) {
        final DataStallDetectionStats.Builder stats = new DataStallDetectionStats.Builder()
                .setEvaluationType(evaluationType)
                .setNetworkType(transportType);
        switch (transportType) {
            case NetworkCapabilities.TRANSPORT_CELLULAR:
                stats.setCellData(TelephonyManager.NETWORK_TYPE_LTE /* radioType */,
                        true /* roaming */,
                        TEST_MCCMNC /* networkMccmnc */,
                        TEST_MCCMNC /* simMccmnc */,
                        CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN /* signalStrength */);
                break;
            case NetworkCapabilities.TRANSPORT_WIFI:
                setupTestWifiInfo();
                stats.setWiFiData(mWifiInfo);
                break;
            default:
                break;
        }

        if ((evaluationType & DATA_STALL_EVALUATION_TYPE_TCP) != 0) {
            generateTestTcpStats(stats);
        }

        if ((evaluationType & DATA_STALL_EVALUATION_TYPE_DNS) != 0) {
            generateTimeoutDnsEvent(stats, DEFAULT_DNS_TIMEOUT_THRESHOLD);
        }

        return stats.build();
    }

    private byte[] makeTestDnsTimeoutNano(int timeoutCount) {
        // Make a expected nano dns message.
        final DnsEvent event = new DnsEvent();
        event.dnsReturnCode = new int[timeoutCount];
        event.dnsTime = new long[timeoutCount];
        Arrays.fill(event.dnsReturnCode, RETURN_CODE_DNS_TIMEOUT);
        Arrays.fill(event.dnsTime, TEST_ELAPSED_TIME_MS);
        return MessageNano.toByteArray(event);
    }

    private byte[] makeTestCellDataNano() {
        final CellularData data = new CellularData();
        data.ratType = DataStallEventProto.RADIO_TECHNOLOGY_LTE;
        data.networkMccmnc = TEST_MCCMNC;
        data.simMccmnc = TEST_MCCMNC;
        data.isRoaming = true;
        data.signalStrength = 0;
        return MessageNano.toByteArray(data);
    }

    private byte[] makeTestWifiDataNano() {
        final WifiData data = new WifiData();
        data.wifiBand = DataStallEventProto.AP_BAND_2GHZ;
        data.signalStrength = TEST_SIGNAL_STRENGTH;
        return MessageNano.toByteArray(data);
    }

    private void setupTestWifiInfo() {
        when(mWifi.getConnectionInfo()).thenReturn(mWifiInfo);
        when(mWifiInfo.getRssi()).thenReturn(TEST_SIGNAL_STRENGTH);
        // Set to 2.4G band. Map to DataStallEventProto.AP_BAND_2GHZ proto definition.
        when(mWifiInfo.getFrequency()).thenReturn(2450);
    }

    private void testDataStallMetricsWithCellular(int evalType) {
        testDataStallMetrics(evalType, NetworkCapabilities.TRANSPORT_CELLULAR);
    }

    private void testDataStallMetricsWithWiFi(int evalType) {
        testDataStallMetrics(evalType, NetworkCapabilities.TRANSPORT_WIFI);
    }

    private void testDataStallMetrics(int evalType, int transportType) {
        setDataStallEvaluationType(evalType);
        final NetworkCapabilities nc = new NetworkCapabilities()
                .addTransportType(transportType)
                .addCapability(NET_CAPABILITY_INTERNET);
        final WrappedNetworkMonitor wrappedMonitor = makeMonitor(nc);
        setupTestWifiInfo();
        final DataStallDetectionStats stats =
                makeTestDataStallDetectionStats(evalType, transportType);
        assertEquals(wrappedMonitor.buildDataStallDetectionStats(transportType, evalType), stats);

        if ((evalType & DATA_STALL_EVALUATION_TYPE_TCP) != 0) {
            verify(mTst, timeout(HANDLER_TIMEOUT_MS).atLeastOnce()).getLatestPacketFailPercentage();
        } else {
            verify(mTst, never()).getLatestPacketFailPercentage();
        }
    }

    @Test
    public void testCollectDataStallMetrics_DnsWithCellular() {
        testDataStallMetricsWithCellular(DATA_STALL_EVALUATION_TYPE_DNS);
    }

    @Test
    public void testCollectDataStallMetrics_DnsWithWiFi() {
        testDataStallMetricsWithWiFi(DATA_STALL_EVALUATION_TYPE_DNS);
    }

    @Test
    public void testCollectDataStallMetrics_TcpWithCellular() {
        assumeTrue(ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q));
        testDataStallMetricsWithCellular(DATA_STALL_EVALUATION_TYPE_TCP);
    }

    @Test
    public void testCollectDataStallMetrics_TcpWithWiFi() {
        assumeTrue(ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q));
        testDataStallMetricsWithWiFi(DATA_STALL_EVALUATION_TYPE_TCP);
    }

    @Test
    public void testCollectDataStallMetrics_TcpAndDnsWithWifi() {
        assumeTrue(ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q));
        testDataStallMetricsWithWiFi(
                DATA_STALL_EVALUATION_TYPE_TCP | DATA_STALL_EVALUATION_TYPE_DNS);
    }

    @Test
    public void testCollectDataStallMetrics_TcpAndDnsWithCellular() {
        assumeTrue(ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q));
        testDataStallMetricsWithCellular(
                DATA_STALL_EVALUATION_TYPE_TCP | DATA_STALL_EVALUATION_TYPE_DNS);
    }

    @Test
    public void testIgnoreHttpsProbe() throws Exception {
        setSslException(mHttpsConnection);
        setStatus(mHttpConnection, 204);
        // Expect to send HTTP, HTTPS, FALLBACK probe and evaluation result notifications to CS.
        final NetworkMonitor nm = runNetworkTest(NETWORK_VALIDATION_RESULT_PARTIAL,
                NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP,
                null /* redirectUrl */);

        resetCallbacks();
        nm.setAcceptPartialConnectivity();
        // Expect to update evaluation result notifications to CS.
        verifyNetworkTested(NETWORK_VALIDATION_RESULT_PARTIAL | NETWORK_VALIDATION_RESULT_VALID,
                NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP);
    }

    @Test
    public void testIsPartialConnectivity() throws Exception {
        setStatus(mHttpsConnection, 500);
        setStatus(mHttpConnection, 204);
        setStatus(mFallbackConnection, 500);
        runPartialConnectivityNetworkTest(
                NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP);
    }

    @Test
    public void testIsCaptivePortal_OnlyFallbackSucceed() throws Exception {
        setStatus(mHttpsConnection, 500);
        setStatus(mHttpConnection, 500);
        setStatus(mFallbackConnection, 204);
        runNetworkTest(VALIDATION_RESULT_INVALID,
                NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_FALLBACK,
                null /* redirectUrl */);
    }

    private void assertIpAddressArrayEquals(String[] expected, InetAddress[] actual) {
        String[] actualStrings = new String[actual.length];
        for (int i = 0; i < actual.length; i++) {
            actualStrings[i] = actual[i].getHostAddress();
        }
        assertArrayEquals("Array of IP addresses differs", expected, actualStrings);
    }

    @Test
    public void testSendDnsProbeWithTimeout() throws Exception {
        WrappedNetworkMonitor wnm = makeCellNotMeteredNetworkMonitor();
        final int shortTimeoutMs = 200;
        // v6 only.
        String[] expected = new String[]{"2001:db8::"};
        mFakeDns.setAnswer("www.google.com", expected, TYPE_AAAA);
        InetAddress[] actual = wnm.sendDnsProbeWithTimeout("www.google.com", shortTimeoutMs);
        assertIpAddressArrayEquals(expected, actual);
        // v4 only.
        expected = new String[]{"192.0.2.1"};
        mFakeDns.setAnswer("www.android.com", expected, TYPE_A);
        actual = wnm.sendDnsProbeWithTimeout("www.android.com", shortTimeoutMs);
        assertIpAddressArrayEquals(expected, actual);
        // Both v4 & v6.
        expected = new String[]{"192.0.2.1", "2001:db8::"};
        mFakeDns.setAnswer("www.googleapis.com", new String[]{"192.0.2.1"}, TYPE_A);
        mFakeDns.setAnswer("www.googleapis.com", new String[]{"2001:db8::"}, TYPE_AAAA);
        actual = wnm.sendDnsProbeWithTimeout("www.googleapis.com", shortTimeoutMs);
        assertIpAddressArrayEquals(expected, actual);
        // Clear DNS response.
        mFakeDns.setAnswer("www.android.com", new String[0], TYPE_A);
        try {
            actual = wnm.sendDnsProbeWithTimeout("www.android.com", shortTimeoutMs);
            fail("No DNS results, expected UnknownHostException");
        } catch (UnknownHostException e) {
        }

        mFakeDns.setAnswer("www.android.com", null, TYPE_A);
        mFakeDns.setAnswer("www.android.com", null, TYPE_AAAA);
        try {
            wnm.sendDnsProbeWithTimeout("www.android.com", shortTimeoutMs);
            fail("DNS query timed out, expected UnknownHostException");
        } catch (UnknownHostException e) {
        }
    }

    @Test
    public void testNotifyNetwork_WithforceReevaluation() throws Exception {
        setValidProbes();
        final NetworkMonitor nm = runValidatedNetworkTest();
        // Verify forceReevaluation will not reset the validation result but only probe result until
        // getting the validation result.
        resetCallbacks();
        setSslException(mHttpsConnection);
        setStatus(mHttpConnection, 500);
        setStatus(mFallbackConnection, 204);
        nm.forceReevaluation(Process.myUid());
        // Expect to send HTTP, HTTPs, FALLBACK and evaluation results.
        verifyNetworkTested(VALIDATION_RESULT_INVALID,
                NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_FALLBACK,
                null /* redirectUrl */);
        HandlerUtils.waitForIdle(nm.getHandler(), HANDLER_TIMEOUT_MS);
    }

    @Test
    public void testNotifyNetwork_NotifyNetworkTestedOldInterfaceVersion() throws Exception {
        // Use old interface version so notifyNetworkTested is used over
        // notifyNetworkTestedWithExtras
        resetCallbacks(4);

        // Trigger Network validation
        setStatus(mHttpsConnection, 204);
        setStatus(mHttpConnection, 204);
        final NetworkMonitor nm = makeMonitor(CELL_METERED_CAPABILITIES);
        nm.notifyNetworkConnected(TEST_LINK_PROPERTIES, CELL_METERED_CAPABILITIES);

        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS))
                .notifyNetworkTested(eq(NETWORK_VALIDATION_RESULT_VALID
                        | NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS),
                        eq(null) /* redirectUrl */);
    }

    @Test
    public void testDismissPortalInValidatedNetworkEnabledOsSupported() throws Exception {
        assumeTrue(ShimUtils.isAtLeastR());
        testDismissPortalInValidatedNetworkEnabled(TEST_LOGIN_URL, TEST_LOGIN_URL);
    }

    @Test
    public void testDismissPortalInValidatedNetworkEnabledOsSupported_NullLocationUrl()
            throws Exception {
        assumeTrue(ShimUtils.isAtLeastR());
        testDismissPortalInValidatedNetworkEnabled(TEST_HTTP_URL, null /* locationUrl */);
    }

    @Test
    public void testDismissPortalInValidatedNetworkEnabledOsSupported_InvalidLocationUrl()
            throws Exception {
        assumeTrue(ShimUtils.isAtLeastR());
        testDismissPortalInValidatedNetworkEnabled(TEST_HTTP_URL, TEST_RELATIVE_URL);
    }

    @Test
    public void testDismissPortalInValidatedNetworkEnabledOsNotSupported() throws Exception {
        assumeFalse(ShimUtils.isAtLeastR());
        testDismissPortalInValidatedNetworkEnabled(TEST_HTTP_URL, TEST_LOGIN_URL);
    }

    private void testDismissPortalInValidatedNetworkEnabled(String expectedUrl, String locationUrl)
            throws Exception {
        setDismissPortalInValidatedNetwork(true);
        setSslException(mHttpsConnection);
        setPortal302(mHttpConnection);
        when(mHttpConnection.getHeaderField(eq("location"))).thenReturn(locationUrl);
        final NetworkMonitor nm = makeMonitor(CELL_METERED_CAPABILITIES);
        notifyNetworkConnected(nm, CELL_METERED_CAPABILITIES);

        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
            .showProvisioningNotification(any(), any());

        assertEquals(1, mRegisteredReceivers.size());
        // Check that startCaptivePortalApp sends the expected intent.
        nm.launchCaptivePortalApp();

        final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
        final ArgumentCaptor<Network> networkCaptor = ArgumentCaptor.forClass(Network.class);
        verify(mCm, timeout(HANDLER_TIMEOUT_MS).times(1))
            .startCaptivePortalApp(networkCaptor.capture(), bundleCaptor.capture());
        verify(mNotifier).notifyCaptivePortalValidationPending(networkCaptor.getValue());
        final Bundle bundle = bundleCaptor.getValue();
        final Network bundleNetwork = bundle.getParcelable(ConnectivityManager.EXTRA_NETWORK);
        assertEquals(TEST_NETID, bundleNetwork.netId);
        // Network is passed both in bundle and as parameter, as the bundle is opaque to the
        // framework and only intended for the captive portal app, but the framework needs
        // the network to identify the right NetworkMonitor.
        assertEquals(TEST_NETID, networkCaptor.getValue().netId);
        // Portal URL should be redirect URL.
        final String redirectUrl = bundle.getString(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL);
        assertEquals(expectedUrl, redirectUrl);
    }

    @Test
    public void testEvaluationState_clearProbeResults() throws Exception {
        setValidProbes();
        final NetworkMonitor nm = runValidatedNetworkTest();
        nm.getEvaluationState().clearProbeResults();
        // Verify probe results are all reset and only evaluation result left.
        assertEquals(NETWORK_VALIDATION_RESULT_VALID,
                nm.getEvaluationState().getEvaluationResult());
        assertEquals(0, nm.getEvaluationState().getProbeResults());
    }

    @Test
    public void testEvaluationState_reportProbeResult() throws Exception {
        setValidProbes();
        final NetworkMonitor nm = runValidatedNetworkTest();

        resetCallbacks();

        nm.reportHttpProbeResult(NETWORK_VALIDATION_PROBE_HTTP,
                CaptivePortalProbeResult.success(1 << PROBE_HTTP));
        // Verify result should be appended and notifyNetworkTestedWithExtras callback is triggered
        // once.
        assertEquals(NETWORK_VALIDATION_RESULT_VALID,
                nm.getEvaluationState().getEvaluationResult());
        assertEquals(NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS
                | NETWORK_VALIDATION_PROBE_HTTP, nm.getEvaluationState().getProbeResults());

        nm.reportHttpProbeResult(NETWORK_VALIDATION_PROBE_HTTP,
                CaptivePortalProbeResult.failed(1 << PROBE_HTTP));
        // Verify DNS probe result should not be cleared.
        assertEquals(NETWORK_VALIDATION_PROBE_DNS,
                nm.getEvaluationState().getProbeResults() & NETWORK_VALIDATION_PROBE_DNS);
    }

    @Test
    public void testEvaluationState_reportEvaluationResult() throws Exception {
        setStatus(mHttpsConnection, 500);
        setStatus(mHttpConnection, 204);
        final NetworkMonitor nm = runNetworkTest(NETWORK_VALIDATION_RESULT_PARTIAL,
                NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP,
                null /* redirectUrl */);

        nm.getEvaluationState().reportEvaluationResult(NETWORK_VALIDATION_RESULT_VALID,
                null /* redirectUrl */);
        verifyNetworkTested(NETWORK_VALIDATION_RESULT_VALID,
                NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP);

        nm.getEvaluationState().reportEvaluationResult(
                NETWORK_VALIDATION_RESULT_VALID | NETWORK_VALIDATION_RESULT_PARTIAL,
                null /* redirectUrl */);
        verifyNetworkTested(
                NETWORK_VALIDATION_RESULT_VALID | NETWORK_VALIDATION_RESULT_PARTIAL,
                NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP);

        nm.getEvaluationState().reportEvaluationResult(VALIDATION_RESULT_INVALID,
                TEST_REDIRECT_URL);
        verifyNetworkTested(VALIDATION_RESULT_INVALID,
                NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP,
                TEST_REDIRECT_URL);
    }

    @Test
    public void testExtractCharset() {
        assertEquals(StandardCharsets.UTF_8, extractCharset(null));
        assertEquals(StandardCharsets.UTF_8, extractCharset("text/html;charset=utf-8"));
        assertEquals(StandardCharsets.UTF_8, extractCharset("text/html;charset=UtF-8"));
        assertEquals(StandardCharsets.UTF_8, extractCharset("text/html; Charset=\"utf-8\""));
        assertEquals(StandardCharsets.UTF_8, extractCharset("image/png"));
        assertEquals(StandardCharsets.UTF_8, extractCharset("Text/HTML;"));
        assertEquals(StandardCharsets.UTF_8, extractCharset("multipart/form-data; boundary=-aa*-"));
        assertEquals(StandardCharsets.UTF_8, extractCharset("text/plain;something=else"));
        assertEquals(StandardCharsets.UTF_8, extractCharset("text/plain;charset=ImNotACharset"));

        assertEquals(StandardCharsets.ISO_8859_1, extractCharset("text/plain; CharSeT=ISO-8859-1"));
        assertEquals(Charset.forName("Shift_JIS"), extractCharset("text/plain;charset=Shift_JIS"));
        assertEquals(Charset.forName("Windows-1251"), extractCharset(
                "text/plain;charset=Windows-1251 ; somethingelse"));
    }

    @Test
    public void testReadAsString() throws IOException {
        final String repeatedString = "1aテスト-?";
        // Infinite stream repeating characters
        class TestInputStream extends InputStream {
            private final byte[] mBytes = repeatedString.getBytes(StandardCharsets.UTF_8);
            private int mPosition = -1;

            @Override
            public int read() {
                mPosition = (mPosition + 1) % mBytes.length;
                return mBytes[mPosition];
            }
        }

        final String readString = NetworkMonitor.readAsString(new TestInputStream(),
                1500 /* maxLength */, StandardCharsets.UTF_8);

        assertEquals(1500, readString.length());
        for (int i = 0; i < readString.length(); i++) {
            assertEquals(repeatedString.charAt(i % repeatedString.length()), readString.charAt(i));
        }
    }

    @Test
    public void testReadAsString_StreamShorterThanLimit() throws Exception {
        final WrappedNetworkMonitor wnm = makeCellNotMeteredNetworkMonitor();
        final byte[] content = "The HTTP response code is 200 but it is not a captive portal."
                .getBytes(StandardCharsets.UTF_8);
        assertEquals(new String(content), wnm.readAsString(new ByteArrayInputStream(content),
                content.length, StandardCharsets.UTF_8));
        // Test the case that the stream ends earlier than the limit.
        assertEquals(new String(content), wnm.readAsString(new ByteArrayInputStream(content),
                content.length + 10, StandardCharsets.UTF_8));
    }

    @Test
    public void testMultipleProbesOnPortalNetwork() throws Exception {
        setupResourceForMultipleProbes();
        // One of the http probes is portal, then result is portal.
        setPortal302(mOtherHttpConnection1);
        runPortalNetworkTest();
        // Get conclusive result from one of the HTTP probe. Expect to create 2 HTTP and 2 HTTPS
        // probes as resource configuration, but the portal can be detected before other probes
        // start.
        verify(mCleartextDnsNetwork, atMost(4)).openConnection(any());
        verify(mCleartextDnsNetwork, atLeastOnce()).openConnection(any());
        verify(mOtherHttpConnection1).getResponseCode();
    }

    @Test
    public void testMultipleProbesOnValidNetwork() throws Exception {
        setupResourceForMultipleProbes();
        // One of the https probes succeeds, then it's validated.
        setStatus(mOtherHttpsConnection2, 204);
        runValidatedNetworkTest();
        // Get conclusive result from one of the HTTPS probe. Expect to create 2 HTTP and 2 HTTPS
        // probes as resource configuration, but the network may validate from the HTTPS probe
        // before other probes start.
        verify(mCleartextDnsNetwork, atMost(4)).openConnection(any());
        verify(mCleartextDnsNetwork, atLeastOnce()).openConnection(any());
        verify(mOtherHttpsConnection2).getResponseCode();
    }

    @Test
    public void testMultipleProbesOnInValidNetworkForPrioritizedResource() throws Exception {
        setupResourceForMultipleProbes();
        // The configuration resource is prioritized. Only use configurations from resource.(i.e
        // Only configuration for mOtherHttpsConnection2, mOtherHttpsConnection2,
        // mOtherHttpConnection2, mOtherHttpConnection2 will affect the result.)
        // Configure mHttpsConnection is no-op.
        setStatus(mHttpsConnection, 204);
        runFailedNetworkTest();
        // No conclusive result from both HTTP and HTTPS probes. Expect to create 2 HTTP and 2 HTTPS
        // probes as resource configuration. All probes are expected to have been run because this
        // network is set to never validate (no probe has a success or portal result), so NM tests
        // all probes to completion.
        verify(mCleartextDnsNetwork, times(4)).openConnection(any());
        verify(mHttpsConnection, never()).getResponseCode();
    }

    @Test
    public void testMultipleProbesOnInValidNetwork() throws Exception {
        setupResourceForMultipleProbes();
        runFailedNetworkTest();
        // No conclusive result from both HTTP and HTTPS probes. Expect to create 2 HTTP and 2 HTTPS
        // probes as resource configuration.
        verify(mCleartextDnsNetwork, times(4)).openConnection(any());
    }

    @Test
    public void testIsCaptivePortal_FromExternalSource() throws Exception {
        assumeTrue(CaptivePortalDataShimImpl.isSupported());
        assumeTrue(ShimUtils.isAtLeastS());
        when(mDependencies.isFeatureEnabled(any(), eq(NAMESPACE_CONNECTIVITY),
                eq(DISMISS_PORTAL_IN_VALIDATED_NETWORK), anyBoolean())).thenReturn(true);
        final NetworkMonitor monitor = makeMonitor(WIFI_NOT_METERED_CAPABILITIES);

        NetworkInformationShim networkShim = NetworkInformationShimImpl.newInstance();
        CaptivePortalDataShim captivePortalData = new CaptivePortalDataShimImpl(
                new CaptivePortalData.Builder().setCaptive(true).build());
        final LinkProperties linkProperties = new LinkProperties(TEST_LINK_PROPERTIES);
        networkShim.setCaptivePortalData(linkProperties, captivePortalData);
        CaptivePortalDataShim captivePortalDataShim =
                networkShim.getCaptivePortalData(linkProperties);

        try {
            // Set up T&C captive portal info from Passpoint
            captivePortalData = captivePortalDataShim.withPasspointInfo(TEST_FRIENDLY_NAME,
                    Uri.parse(TEST_VENUE_INFO_URL), Uri.parse(TEST_LOGIN_URL));
        } catch (UnsupportedApiLevelException e) {
            // Minimum API level for this test is 31
            return;
        }

        networkShim.setCaptivePortalData(linkProperties, captivePortalData);
        monitor.notifyLinkPropertiesChanged(linkProperties);
        final NetworkCapabilities networkCapabilities =
                new NetworkCapabilities(WIFI_NOT_METERED_CAPABILITIES);
        monitor.notifyNetworkConnected(linkProperties, networkCapabilities);
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
                .showProvisioningNotification(any(), any());
        assertEquals(1, mRegisteredReceivers.size());
        verifyNetworkTested(VALIDATION_RESULT_PORTAL, 0 /* probesSucceeded */, TEST_LOGIN_URL);

        // Force reevaluation and confirm that the network is still captive
        HandlerUtils.waitForIdle(monitor.getHandler(), HANDLER_TIMEOUT_MS);
        resetCallbacks();
        monitor.forceReevaluation(Process.myUid());
        assertEquals(monitor.getEvaluationState().getProbeCompletedResult(), 0);
        verifyNetworkTested(VALIDATION_RESULT_PORTAL, 0 /* probesSucceeded */, TEST_LOGIN_URL);

        // Check that startCaptivePortalApp sends the expected intent.
        monitor.launchCaptivePortalApp();

        verify(mCm, timeout(HANDLER_TIMEOUT_MS).times(1)).startCaptivePortalApp(
                argThat(network -> TEST_NETID == network.netId),
                argThat(bundle -> bundle.getString(
                        ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL).equals(TEST_LOGIN_URL)
                        && TEST_NETID == ((Network) bundle.getParcelable(
                        ConnectivityManager.EXTRA_NETWORK)).netId));
    }

    @Test
    public void testOemPaidNetworkValidated() throws Exception {
        setValidProbes();

        final NetworkMonitor nm = runNetworkTest(TEST_LINK_PROPERTIES,
                WIFI_OEM_PAID_CAPABILITIES,
                NETWORK_VALIDATION_RESULT_VALID,
                NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS,
                null /* redirectUrl */);
        assertEquals(NETWORK_VALIDATION_RESULT_VALID,
                nm.getEvaluationState().getEvaluationResult());
    }

    @Test
    public void testOemPaidNetwork_AllProbesFailed() throws Exception {
        setSslException(mHttpsConnection);
        setStatus(mHttpConnection, 500);
        setStatus(mFallbackConnection, 404);

        runNetworkTest(TEST_LINK_PROPERTIES,
                WIFI_OEM_PAID_CAPABILITIES,
                VALIDATION_RESULT_INVALID, 0 /* probesSucceeded */, null /* redirectUrl */);
    }

    @Test
    public void testOemPaidNetworkNoInternetCapabilityValidated() throws Exception {
        setSslException(mHttpsConnection);
        setStatus(mHttpConnection, 500);
        setStatus(mFallbackConnection, 404);

        final NetworkCapabilities networkCapabilities =
                new NetworkCapabilities(WIFI_OEM_PAID_CAPABILITIES);
        networkCapabilities.removeCapability(NET_CAPABILITY_INTERNET);

        final int validationResult = ShimUtils.isAtLeastS()
                ? NETWORK_VALIDATION_RESULT_VALID | NETWORK_VALIDATION_RESULT_SKIPPED
                : NETWORK_VALIDATION_RESULT_VALID;
        runNetworkTest(TEST_LINK_PROPERTIES, networkCapabilities,
                validationResult, 0 /* probesSucceeded */, null /* redirectUrl */);

        verify(mCleartextDnsNetwork, never()).openConnection(any());
        verify(mHttpsConnection, never()).getResponseCode();
        verify(mHttpConnection, never()).getResponseCode();
        verify(mFallbackConnection, never()).getResponseCode();
    }

    @Test
    public void testOemPaidNetwork_CaptivePortalNotLaunched() throws Exception {
        setSslException(mHttpsConnection);
        setStatus(mFallbackConnection, 404);
        setPortal302(mHttpConnection);

        runNetworkTest(TEST_LINK_PROPERTIES, WIFI_OEM_PAID_CAPABILITIES,
                VALIDATION_RESULT_PORTAL, 0 /* probesSucceeded */,
                TEST_LOGIN_URL);

        verify(mCallbacks, never()).showProvisioningNotification(any(), any());
    }

    private void setupResourceForMultipleProbes() {
        // Configure the resource to send multiple probe.
        when(mResources.getStringArray(R.array.config_captive_portal_https_urls))
                .thenReturn(TEST_HTTPS_URLS);
        when(mResources.getStringArray(R.array.config_captive_portal_http_urls))
                .thenReturn(TEST_HTTP_URLS);
    }

    private void makeDnsTimeoutEvent(WrappedNetworkMonitor wrappedMonitor, int count) {
        for (int i = 0; i < count; i++) {
            wrappedMonitor.getDnsStallDetector().accumulateConsecutiveDnsTimeoutCount(
                    RETURN_CODE_DNS_TIMEOUT);
        }
    }

    private void makeDnsSuccessEvent(WrappedNetworkMonitor wrappedMonitor, int count) {
        for (int i = 0; i < count; i++) {
            wrappedMonitor.getDnsStallDetector().accumulateConsecutiveDnsTimeoutCount(
                    RETURN_CODE_DNS_SUCCESS);
        }
    }

    private DataStallDetectionStats makeEmptyDataStallDetectionStats() {
        return new DataStallDetectionStats.Builder().build();
    }

    private void setDataStallEvaluationType(int type) {
        when(mDependencies.getDeviceConfigPropertyInt(any(),
            eq(CONFIG_DATA_STALL_EVALUATION_TYPE), anyInt())).thenReturn(type);
    }

    private void setMinDataStallEvaluateInterval(int time) {
        when(mDependencies.getDeviceConfigPropertyInt(any(),
            eq(CONFIG_DATA_STALL_MIN_EVALUATE_INTERVAL), anyInt())).thenReturn(time);
    }

    private void setValidDataStallDnsTimeThreshold(int time) {
        when(mDependencies.getDeviceConfigPropertyInt(any(),
            eq(CONFIG_DATA_STALL_VALID_DNS_TIME_THRESHOLD), anyInt())).thenReturn(time);
    }

    private void setConsecutiveDnsTimeoutThreshold(int num) {
        when(mDependencies.getDeviceConfigPropertyInt(any(),
            eq(CONFIG_DATA_STALL_CONSECUTIVE_DNS_TIMEOUT_THRESHOLD), anyInt())).thenReturn(num);
    }

    private void setTcpPollingInterval(int time) {
        doReturn(time).when(mDependencies).getDeviceConfigPropertyInt(any(),
                eq(CONFIG_DATA_STALL_TCP_POLLING_INTERVAL), anyInt());
    }

    private void setFallbackUrl(String url) {
        when(mDependencies.getSetting(any(),
                eq(Settings.Global.CAPTIVE_PORTAL_FALLBACK_URL), any())).thenReturn(url);
    }

    private void setOtherFallbackUrls(String urls) {
        when(mDependencies.getDeviceConfigProperty(any(),
                eq(CAPTIVE_PORTAL_OTHER_FALLBACK_URLS), any())).thenReturn(urls);
    }

    private void setFallbackSpecs(String specs) {
        when(mDependencies.getDeviceConfigProperty(any(),
                eq(CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS), any())).thenReturn(specs);
    }

    private void setCaptivePortalMode(int mode) {
        when(mDependencies.getSetting(any(),
                eq(Settings.Global.CAPTIVE_PORTAL_MODE), anyInt())).thenReturn(mode);
    }

    private void setDismissPortalInValidatedNetwork(boolean enabled) {
        when(mDependencies.isFeatureEnabled(any(), any(),
                eq(DISMISS_PORTAL_IN_VALIDATED_NETWORK), anyBoolean())).thenReturn(enabled);
    }

    private void setDeviceConfig(String key, String value) {
        doReturn(value).when(mDependencies).getDeviceConfigProperty(eq(NAMESPACE_CONNECTIVITY),
                eq(key), any() /* defaultValue */);
    }

    private NetworkMonitor runPortalNetworkTest() throws RemoteException {
        final NetworkMonitor nm = runNetworkTest(VALIDATION_RESULT_PORTAL,
                0 /* probesSucceeded */, TEST_LOGIN_URL);
        assertEquals(1, mRegisteredReceivers.size());
        return nm;
    }

    private NetworkMonitor runNoValidationNetworkTest() throws RemoteException {
        final NetworkMonitor nm = runNetworkTest(NETWORK_VALIDATION_RESULT_VALID,
                0 /* probesSucceeded */, null /* redirectUrl */);
        assertEquals(0, mRegisteredReceivers.size());
        return nm;
    }

    private NetworkMonitor runFailedNetworkTest() throws RemoteException {
        final NetworkMonitor nm = runNetworkTest(
                VALIDATION_RESULT_INVALID, 0 /* probesSucceeded */, null /* redirectUrl */);
        assertEquals(0, mRegisteredReceivers.size());
        return nm;
    }

    private NetworkMonitor runPartialConnectivityNetworkTest(int probesSucceeded)
            throws RemoteException {
        final NetworkMonitor nm = runNetworkTest(NETWORK_VALIDATION_RESULT_PARTIAL,
                probesSucceeded, null /* redirectUrl */);
        assertEquals(0, mRegisteredReceivers.size());
        return nm;
    }

    private NetworkMonitor runValidatedNetworkTest() throws RemoteException {
        // Expect to send HTTPS and evaluation results.
        return runNetworkTest(NETWORK_VALIDATION_RESULT_VALID,
                NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS,
                null /* redirectUrl */);
    }

    private NetworkMonitor runNetworkTest(int testResult, int probesSucceeded, String redirectUrl)
            throws RemoteException {
        return runNetworkTest(TEST_LINK_PROPERTIES, CELL_METERED_CAPABILITIES, testResult,
                probesSucceeded, redirectUrl);
    }

    private NetworkMonitor runNetworkTest(LinkProperties lp, NetworkCapabilities nc,
            int testResult, int probesSucceeded, String redirectUrl) throws RemoteException {
        final NetworkMonitor monitor = makeMonitor(nc);
        monitor.notifyNetworkConnected(lp, nc);
        verifyNetworkTested(testResult, probesSucceeded, redirectUrl);
        HandlerUtils.waitForIdle(monitor.getHandler(), HANDLER_TIMEOUT_MS);

        return monitor;
    }

    private void verifyNetworkTested(int testResult, int probesSucceeded) throws RemoteException {
        verifyNetworkTested(testResult, probesSucceeded, null /* redirectUrl */);
    }

    private void verifyNetworkTested(int testResult, int probesSucceeded, String redirectUrl)
            throws RemoteException {
        try {
            verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS)).notifyNetworkTestedWithExtras(
                    matchNetworkTestResultParcelable(testResult, probesSucceeded, redirectUrl));
        } catch (AssertionFailedError e) {
            // Capture the callbacks up to now to give a better error message
            final ArgumentCaptor<NetworkTestResultParcelable> captor =
                    ArgumentCaptor.forClass(NetworkTestResultParcelable.class);

            // Call verify() again to verify the same method call verified by the previous verify
            // call which failed, but this time use a captor to log the exact parcel sent by
            // NetworkMonitor.
            // This assertion will fail if notifyNetworkTested was not called at all.
            verify(mCallbacks).notifyNetworkTestedWithExtras(captor.capture());

            final NetworkTestResultParcelable lastResult = captor.getValue();
            fail(String.format("notifyNetworkTestedWithExtras was not called with the "
                    + "expected result within timeout. "
                    + "Expected result %d, probes succeeded %d, redirect URL %s, "
                    + "last result was (%d, %d, %s).",
                    testResult, probesSucceeded, redirectUrl,
                    lastResult.result, lastResult.probesSucceeded, lastResult.redirectUrl));
        }
    }

    private void notifyNetworkConnected(NetworkMonitor nm, NetworkCapabilities nc) {
        nm.notifyNetworkConnected(TEST_LINK_PROPERTIES, nc);
    }

    private void setSslException(HttpURLConnection connection) throws IOException {
        doThrow(new SSLHandshakeException("Invalid cert")).when(connection).getResponseCode();
    }

    private void setValidProbes() throws IOException {
        setStatus(mHttpsConnection, 204);
        setStatus(mHttpConnection, 204);
    }

    private void set302(HttpURLConnection connection, String location) throws IOException {
        setStatus(connection, 302);
        doReturn(location).when(connection).getHeaderField(LOCATION_HEADER);
    }

    private void setPortal302(HttpURLConnection connection) throws IOException {
        set302(connection, TEST_LOGIN_URL);
    }

    private void setApiContent(HttpURLConnection connection, String content) throws IOException {
        setStatus(connection, 200);
        final Map<String, List<String>> headerFields = new HashMap<>();
        headerFields.put(
                CONTENT_TYPE_HEADER, singletonList("application/captive+json;charset=UTF-8"));
        doReturn(headerFields).when(connection).getHeaderFields();
        doReturn(new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)))
                .when(connection).getInputStream();
    }

    private void setStatus(HttpURLConnection connection, int status) throws IOException {
        doReturn(status).when(connection).getResponseCode();
    }

    private void generateTimeoutDnsEvent(DataStallDetectionStats.Builder stats, int num) {
        for (int i = 0; i < num; i++) {
            stats.addDnsEvent(RETURN_CODE_DNS_TIMEOUT, TEST_ELAPSED_TIME_MS /* timeMs */);
        }
    }

    private void generateTestTcpStats(DataStallDetectionStats.Builder stats) {
        when(mTst.getLatestPacketFailPercentage()).thenReturn(TEST_TCP_FAIL_RATE);
        when(mTst.getSentSinceLastRecv()).thenReturn(TEST_TCP_PACKET_COUNT);
        stats.setTcpFailRate(TEST_TCP_FAIL_RATE).setTcpSentSinceLastRecv(TEST_TCP_PACKET_COUNT);
    }

    private NetworkTestResultParcelable matchNetworkTestResultParcelable(final int result,
            final int probesSucceeded) {
        return matchNetworkTestResultParcelable(result, probesSucceeded, null /* redirectUrl */);
    }

    private NetworkTestResultParcelable matchNetworkTestResultParcelable(final int result,
            final int probesSucceeded, String redirectUrl) {
        // TODO: also verify probesAttempted
        return argThat(p -> p.result == result && p.probesSucceeded == probesSucceeded
                && Objects.equals(p.redirectUrl, redirectUrl));
    }

    private DataStallReportParcelable matchDnsAndTcpDataStallParcelable(final int timeoutCount) {
        return argThat(p ->
                (p.detectionMethod & ConstantsShim.DETECTION_METHOD_DNS_EVENTS) != 0
                && (p.detectionMethod & ConstantsShim.DETECTION_METHOD_TCP_METRICS) != 0
                && p.dnsConsecutiveTimeouts == timeoutCount);
    }

    private DataStallReportParcelable matchDnsDataStallParcelable(final int timeoutCount) {
        return argThat(p -> (p.detectionMethod & ConstantsShim.DETECTION_METHOD_DNS_EVENTS) != 0
                && p.dnsConsecutiveTimeouts == timeoutCount);
    }

    private DataStallReportParcelable matchTcpDataStallParcelable() {
        return argThat(p -> (p.detectionMethod & ConstantsShim.DETECTION_METHOD_TCP_METRICS) != 0);
    }
}

