/*
 * Copyright (C) 2012 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;

import static android.net.NetworkScoreManager.CACHE_FILTER_NONE;

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

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyListOf;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;

import android.Manifest.permission;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.INetworkRecommendationProvider;
import android.net.INetworkScoreCache;
import android.net.NetworkKey;
import android.net.NetworkScoreManager;
import android.net.NetworkScorerAppData;
import android.net.ScoredNetwork;
import android.net.Uri;
import android.net.WifiKey;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiSsid;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.UserHandle;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;

import com.android.server.devicepolicy.MockUtils;

import com.google.android.collect.Lists;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.UnaryOperator;

/**
 * Tests for {@link NetworkScoreService}.
 */
@RunWith(AndroidJUnit4.class)
@MediumTest
public class NetworkScoreServiceTest {
    private static final String SSID = "ssid";
    private static final String SSID_2 = "ssid_2";
    private static final String SSID_3 = "ssid_3";
    private static final String INVALID_BSSID = "invalid_bssid";
    private static final ComponentName RECOMMENDATION_SERVICE_COMP =
            new ComponentName("newPackageName", "newScoringServiceClass");
    private static final String RECOMMENDATION_SERVICE_LABEL = "Test Recommendation Service";
    private static final ComponentName USE_WIFI_ENABLE_ACTIVITY_COMP =
            new ComponentName("useWifiPackageName", "enableUseWifiActivityClass");
    private static final ScoredNetwork SCORED_NETWORK =
            new ScoredNetwork(new NetworkKey(new WifiKey(quote(SSID), "00:00:00:00:00:00")),
                    null /* rssiCurve*/);
    private static final ScoredNetwork SCORED_NETWORK_2 =
            new ScoredNetwork(new NetworkKey(new WifiKey(quote(SSID_2), "00:00:00:00:00:00")),
                    null /* rssiCurve*/);
    private static final String NETWORK_AVAILABLE_NOTIFICATION_CHANNEL_ID =
            "networkAvailableNotificationChannelId";
    private static final NetworkScorerAppData NEW_SCORER = new NetworkScorerAppData(
            1, RECOMMENDATION_SERVICE_COMP, RECOMMENDATION_SERVICE_LABEL,
            USE_WIFI_ENABLE_ACTIVITY_COMP, NETWORK_AVAILABLE_NOTIFICATION_CHANNEL_ID);

    @Mock private NetworkScorerAppManager mNetworkScorerAppManager;
    @Mock private Context mContext;
    @Mock private Resources mResources;
    @Mock private INetworkScoreCache.Stub mNetworkScoreCache, mNetworkScoreCache2;
    @Mock private IBinder mScoreCacheIBinder, mScoreCacheIBinder2;
    @Mock private IBinder mServiceConnectionIBinder;
    @Mock private INetworkRecommendationProvider mRecommendationProvider;
    @Mock private UnaryOperator<List<ScoredNetwork>> mCurrentNetworkFilter;
    @Mock private UnaryOperator<List<ScoredNetwork>> mScanResultsFilter;
    @Mock private WifiInfo mWifiInfo;
    @Mock private NetworkScoreService.ScoringServiceConnection mServiceConnection;
    @Captor private ArgumentCaptor<List<ScoredNetwork>> mScoredNetworkCaptor;

    private ContentResolver mContentResolver;
    private NetworkScoreService mNetworkScoreService;
    private HandlerThread mHandlerThread;
    private List<ScanResult> mScanResults;

    private static String quote(String str) {
        return String.format("\"%s\"", str);
    }

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        when(mNetworkScoreCache.asBinder()).thenReturn(mScoreCacheIBinder);
        when(mNetworkScoreCache2.asBinder()).thenReturn(mScoreCacheIBinder2);
        when(mServiceConnectionIBinder.queryLocalInterface(anyString()))
                .thenReturn(mRecommendationProvider);
        mContentResolver = InstrumentationRegistry.getContext().getContentResolver();
        when(mContext.getContentResolver()).thenReturn(mContentResolver);
        when(mContext.getResources()).thenReturn(mResources);
        when(mWifiInfo.getSSID()).thenReturn(SCORED_NETWORK.networkKey.wifiKey.ssid);
        when(mWifiInfo.getBSSID()).thenReturn(SCORED_NETWORK.networkKey.wifiKey.bssid);
        when(mServiceConnection.getAppData()).thenReturn(NEW_SCORER);
        when(mServiceConnection.getRecommendationProvider()).thenReturn(mRecommendationProvider);
        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
        mHandlerThread = new HandlerThread("NetworkScoreServiceTest");
        mHandlerThread.start();
        mNetworkScoreService = new NetworkScoreService(mContext, mNetworkScorerAppManager,
                networkScorerAppData -> mServiceConnection, mHandlerThread.getLooper());
        WifiConfiguration configuration = new WifiConfiguration();
        configuration.SSID = "NetworkScoreServiceTest_SSID";
        configuration.BSSID = "NetworkScoreServiceTest_BSSID";
        populateScanResults();
    }

    private void populateScanResults() {
        mScanResults = new ArrayList<>();
        mScanResults.add(createScanResult(SSID, SCORED_NETWORK.networkKey.wifiKey.bssid));
        mScanResults.add(createScanResult(SSID_2, SCORED_NETWORK_2.networkKey.wifiKey.bssid));
        mScanResults.add(createScanResult(SSID_3, "10:10:00:00:10:10"));
    }

    private ScanResult createScanResult(String ssid, String bssid) {
        ScanResult result = new ScanResult();
        result.wifiSsid = WifiSsid.createFromAsciiEncoded(ssid);
        result.BSSID = bssid;
        return result;
    }

    @After
    public void tearDown() throws Exception {
        mHandlerThread.quitSafely();
    }

    @Test
    public void testOnUserUnlocked() {
        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);

        mNetworkScoreService.onUserUnlocked(0);

        verify(mNetworkScorerAppManager).updateState();
        verify(mNetworkScorerAppManager).migrateNetworkScorerAppSettingIfNeeded();
        verify(mServiceConnection).bind(mContext);
    }

    @Test
    public void testRequestScores_noPermission() throws Exception {
        doThrow(new SecurityException()).when(mContext)
            .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES),
                anyString());
        try {
            mNetworkScoreService.requestScores(null);
            fail("REQUEST_NETWORK_SCORES not enforced.");
        } catch (SecurityException e) {
            // expected
        }
    }

    @Test
    public void testRequestScores_providerNotConnected() throws Exception {
        assertFalse(mNetworkScoreService.requestScores(new NetworkKey[0]));
        verifyZeroInteractions(mRecommendationProvider);
    }

    @Test
    public void testRequestScores_providerThrowsRemoteException() throws Exception {
        doThrow(new RemoteException()).when(mRecommendationProvider)
            .requestScores(any(NetworkKey[].class));
        mNetworkScoreService.onUserUnlocked(0);

        assertFalse(mNetworkScoreService.requestScores(new NetworkKey[0]));
    }

    @Test
    public void testRequestScores_providerAvailable() throws Exception {
        mNetworkScoreService.onUserUnlocked(0);

        final NetworkKey[] networks = new NetworkKey[0];
        assertTrue(mNetworkScoreService.requestScores(networks));
        verify(mRecommendationProvider).requestScores(networks);
    }

    @Test
    public void dispatchingContentObserver_nullUri() throws Exception {
        NetworkScoreService.DispatchingContentObserver observer =
                new NetworkScoreService.DispatchingContentObserver(mContext, null /*handler*/);

        observer.onChange(false, null);
        // nothing to assert or verify but since we passed in a null handler we'd see a NPE
        // if it were interacted with.
    }

    @Test
    public void dispatchingContentObserver_dispatchUri() throws Exception {
        final CountDownHandler handler = new CountDownHandler(mHandlerThread.getLooper());
        NetworkScoreService.DispatchingContentObserver observer =
                new NetworkScoreService.DispatchingContentObserver(mContext, handler);
        Uri uri = Uri.parse("content://settings/global/network_score_service_test");
        int expectedWhat = 24;
        observer.observe(uri, expectedWhat);

        observer.onChange(false, uri);
        final boolean msgHandled = handler.latch.await(3, TimeUnit.SECONDS);
        assertTrue(msgHandled);
        assertEquals(expectedWhat, handler.receivedWhat);
    }

    @Test
    public void testUpdateScores_notActiveScorer() {
        bindToScorer(false /*callerIsScorer*/);

        try {
            mNetworkScoreService.updateScores(new ScoredNetwork[0]);
            fail("SecurityException expected");
        } catch (SecurityException e) {
            // expected
        }
    }

    @Test
    public void testUpdateScores_oneRegisteredCache() throws RemoteException {
        bindToScorer(true /*callerIsScorer*/);

        mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
                mNetworkScoreCache, CACHE_FILTER_NONE);

        mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});

        verify(mNetworkScoreCache).updateScores(mScoredNetworkCaptor.capture());

        assertEquals(1, mScoredNetworkCaptor.getValue().size());
        assertEquals(SCORED_NETWORK, mScoredNetworkCaptor.getValue().get(0));
    }

    @Test
    public void testUpdateScores_twoRegisteredCaches() throws RemoteException {
        bindToScorer(true /*callerIsScorer*/);

        mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
                mNetworkScoreCache, CACHE_FILTER_NONE);
        mNetworkScoreService.registerNetworkScoreCache(
                NetworkKey.TYPE_WIFI, mNetworkScoreCache2, CACHE_FILTER_NONE);

        // updateScores should update both caches
        mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});

        verify(mNetworkScoreCache).updateScores(anyListOf(ScoredNetwork.class));
        verify(mNetworkScoreCache2).updateScores(anyListOf(ScoredNetwork.class));

        mNetworkScoreService.unregisterNetworkScoreCache(
                NetworkKey.TYPE_WIFI, mNetworkScoreCache2);

        // updateScores should only update the first cache since the 2nd has been unregistered
        mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});

        verify(mNetworkScoreCache, times(2)).updateScores(anyListOf(ScoredNetwork.class));

        mNetworkScoreService.unregisterNetworkScoreCache(
                NetworkKey.TYPE_WIFI, mNetworkScoreCache);

        // updateScores should not update any caches since they are both unregistered
        mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});

        // The register and unregister calls grab the binder from the score cache.
        verify(mNetworkScoreCache, atLeastOnce()).asBinder();
        verify(mNetworkScoreCache2, atLeastOnce()).asBinder();
        verifyNoMoreInteractions(mNetworkScoreCache, mNetworkScoreCache2);
    }

    @Test
    public void testClearScores_notActiveScorer_noRequestNetworkScoresPermission() {
        bindToScorer(false /*callerIsScorer*/);
        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
            .thenReturn(PackageManager.PERMISSION_DENIED);
        try {
            mNetworkScoreService.clearScores();
            fail("SecurityException expected");
        } catch (SecurityException e) {
            // expected
        }
    }

    @Test
    public void testClearScores_activeScorer_noRequestNetworkScoresPermission() {
        bindToScorer(true /*callerIsScorer*/);
        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
            .thenReturn(PackageManager.PERMISSION_DENIED);

        mNetworkScoreService.clearScores();
    }

    @Test
    public void testClearScores_activeScorer() throws RemoteException {
        bindToScorer(true /*callerIsScorer*/);

        mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
                CACHE_FILTER_NONE);
        mNetworkScoreService.clearScores();

        verify(mNetworkScoreCache).clearScores();
    }

    @Test
    public void testClearScores_notActiveScorer_hasRequestNetworkScoresPermission()
            throws RemoteException {
        bindToScorer(false /*callerIsScorer*/);
        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
                .thenReturn(PackageManager.PERMISSION_GRANTED);

        mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
                CACHE_FILTER_NONE);
        mNetworkScoreService.clearScores();

        verify(mNetworkScoreCache).clearScores();
    }

    @Test
    public void testSetActiveScorer_noScoreNetworksPermission() {
        when(mContext.checkCallingOrSelfPermission(permission.SCORE_NETWORKS))
                .thenReturn(PackageManager.PERMISSION_DENIED);

        try {
            mNetworkScoreService.setActiveScorer(null);
            fail("SecurityException expected");
        } catch (SecurityException e) {
            // expected
        }
    }

    @Test
    public void testSetActiveScorer_requestNetworkScoresPermission() {
        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
                .thenReturn(PackageManager.PERMISSION_GRANTED);

        mNetworkScoreService.setActiveScorer(null);
    }

    @Test
    public void testDisableScoring_notActiveScorer_noRequestNetworkScoresPermission() {
        bindToScorer(false /*callerIsScorer*/);
        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
                .thenReturn(PackageManager.PERMISSION_DENIED);

        try {
            mNetworkScoreService.disableScoring();
            fail("SecurityException expected");
        } catch (SecurityException e) {
            // expected
        }
    }

    @Test
    public void testDisableScoring_activeScorer_noRequestNetworkScoresPermission() {
        bindToScorer(true /*callerIsScorer*/);
        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
                .thenReturn(PackageManager.PERMISSION_DENIED);

        mNetworkScoreService.disableScoring();
    }

    @Test
    public void testGetAllValidScorer_noRequestNetworkScoresPermission() {
        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
                .thenReturn(PackageManager.PERMISSION_DENIED);

        try {
            mNetworkScoreService.getAllValidScorers();
            fail("SecurityException expected");
        } catch (SecurityException e) {
            // expected
        }
    }

    @Test
    public void testGetAllValidScorer_requestNetworkScoresPermission() {
        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
                .thenReturn(PackageManager.PERMISSION_GRANTED);

        mNetworkScoreService.getAllValidScorers();
    }

    @Test
    public void testRegisterNetworkScoreCache_noRequestNetworkScoresPermission() {
        doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
                eq(permission.REQUEST_NETWORK_SCORES), anyString());

        try {
            mNetworkScoreService.registerNetworkScoreCache(
                NetworkKey.TYPE_WIFI, mNetworkScoreCache, CACHE_FILTER_NONE);
            fail("SecurityException expected");
        } catch (SecurityException e) {
            // expected
        }
    }

    @Test
    public void testUnregisterNetworkScoreCache_noRequestNetworkScoresPermission() {
        doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
                eq(permission.REQUEST_NETWORK_SCORES), anyString());

        try {
            mNetworkScoreService.unregisterNetworkScoreCache(
                    NetworkKey.TYPE_WIFI, mNetworkScoreCache);
            fail("SecurityException expected");
        } catch (SecurityException e) {
            // expected
        }
    }

    @Test
    public void testDump_doesNotCrash() {
        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
        StringWriter stringWriter = new StringWriter();

        mNetworkScoreService.dump(
                new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);

        assertFalse(stringWriter.toString().isEmpty());
    }

    @Test
    public void testIsCallerActiveScorer_noBoundService() throws Exception {
        // No active scorer.
        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(null);
        mNetworkScoreService.onUserUnlocked(0);

        mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid());

        verify(mServiceConnection, never()).getAppData();
    }

    @Test
    public void testIsCallerActiveScorer_boundServiceIsNotCaller() throws Exception {
        bindToScorer(false /*callerIsScorer*/);

        assertFalse(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
    }

    @Test
    public void testIsCallerActiveScorer_boundServiceIsCaller() throws Exception {
        bindToScorer(true /*callerIsScorer*/);

        assertTrue(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
    }

    @Test
    public void testGetActiveScorerPackage_notActive() throws Exception {
        // No active scorer.
        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(null);
        mNetworkScoreService.onUserUnlocked(0);

        mNetworkScoreService.getActiveScorerPackage();

        verify(mServiceConnection, never()).getPackageName();
    }

    @Test
    public void testGetActiveScorerPackage_active() throws Exception {
        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
        mNetworkScoreService.onUserUnlocked(0);

        mNetworkScoreService.getActiveScorerPackage();

        verify(mServiceConnection).getPackageName();
    }

    @Test
    public void testGetActiveScorerPackage_missingRequiredPermissions() throws Exception {
        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
                .thenReturn(PackageManager.PERMISSION_DENIED);
        when(mContext.checkCallingOrSelfPermission(permission.SCORE_NETWORKS))
                .thenReturn(PackageManager.PERMISSION_DENIED);

        try {
            mNetworkScoreService.getActiveScorerPackage();
            fail("SecurityException expected");
        } catch (SecurityException e) {
            // expected
        }
    }

    @Test
    public void testGetActiveScorerPackage_noRequestScoresPermission() throws Exception {
        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
                .thenReturn(PackageManager.PERMISSION_DENIED);
        when(mContext.checkCallingOrSelfPermission(permission.SCORE_NETWORKS))
                .thenReturn(PackageManager.PERMISSION_GRANTED);

        try {
            mNetworkScoreService.getActiveScorerPackage();
        } catch (SecurityException e) {
            fail("Unexpected SecurityException");
        }
    }

    @Test
    public void testGetActiveScorerPackage_noScoreNetworksPermission() throws Exception {
        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
                .thenReturn(PackageManager.PERMISSION_GRANTED);
        when(mContext.checkCallingOrSelfPermission(permission.SCORE_NETWORKS))
                .thenReturn(PackageManager.PERMISSION_DENIED);

        try {
            mNetworkScoreService.getActiveScorerPackage();
        } catch (SecurityException e) {
            fail("Unexpected SecurityException");
        }
    }

    @Test
    public void testCacheUpdatingConsumer_nullFilter() throws Exception {
        List<ScoredNetwork> scoredNetworkList = Lists.newArrayList(SCORED_NETWORK);
        NetworkScoreService.FilteringCacheUpdatingConsumer consumer =
                new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
                        new ArrayList<>(scoredNetworkList), NetworkKey.TYPE_WIFI,
                        mCurrentNetworkFilter, mScanResultsFilter);

        consumer.accept(mNetworkScoreCache, null /*cookie*/);

        verify(mNetworkScoreCache).updateScores(scoredNetworkList);
        verifyZeroInteractions(mCurrentNetworkFilter, mScanResultsFilter);
    }

    @Test
    public void testCacheUpdatingConsumer_noneFilter() throws Exception {
        List<ScoredNetwork> scoredNetworkList = Lists.newArrayList(SCORED_NETWORK);
        NetworkScoreService.FilteringCacheUpdatingConsumer
                consumer = new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
                new ArrayList<>(scoredNetworkList),
                NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);

        consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_NONE);

        verify(mNetworkScoreCache).updateScores(scoredNetworkList);
        verifyZeroInteractions(mCurrentNetworkFilter, mScanResultsFilter);
    }

    @Test
    public void testCacheUpdatingConsumer_unknownFilter() throws Exception {
        List<ScoredNetwork> scoredNetworkList = Lists.newArrayList(SCORED_NETWORK);
        NetworkScoreService.FilteringCacheUpdatingConsumer
                consumer = new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
                new ArrayList<>(scoredNetworkList),
                NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);

        consumer.accept(mNetworkScoreCache, -1 /*cookie*/);

        verify(mNetworkScoreCache).updateScores(scoredNetworkList);
        verifyZeroInteractions(mCurrentNetworkFilter, mScanResultsFilter);
    }

    @Test
    public void testCacheUpdatingConsumer_nonIntFilter() throws Exception {
        List<ScoredNetwork> scoredNetworkList = Lists.newArrayList(SCORED_NETWORK);
        NetworkScoreService.FilteringCacheUpdatingConsumer
                consumer = new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
                new ArrayList<>(scoredNetworkList),
                NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);

        consumer.accept(mNetworkScoreCache, "not an int" /*cookie*/);

        verify(mNetworkScoreCache).updateScores(scoredNetworkList);
        verifyZeroInteractions(mCurrentNetworkFilter, mScanResultsFilter);
    }

    @Test
    public void testCacheUpdatingConsumer_emptyScoreList() throws Exception {
        NetworkScoreService.FilteringCacheUpdatingConsumer
                consumer = new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
                Collections.emptyList(),
                NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);

        consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_NONE);

        verifyZeroInteractions(mNetworkScoreCache, mCurrentNetworkFilter, mScanResultsFilter);
    }

    @Test
    public void testCacheUpdatingConsumer_currentNetworkFilter() throws Exception {
        List<ScoredNetwork> scoredNetworkList =
                Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2);
        NetworkScoreService.FilteringCacheUpdatingConsumer
                consumer = new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
                new ArrayList<>(scoredNetworkList),
                NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);

        List<ScoredNetwork> filteredList = new ArrayList<>(scoredNetworkList);
        filteredList.remove(SCORED_NETWORK);
        when(mCurrentNetworkFilter.apply(scoredNetworkList)).thenReturn(filteredList);
        consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_CURRENT_NETWORK);

        verify(mNetworkScoreCache).updateScores(filteredList);
        verifyZeroInteractions(mScanResultsFilter);
    }

    @Test
    public void testCacheUpdatingConsumer_scanResultsFilter() throws Exception {
        List<ScoredNetwork> scoredNetworkList =
                Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2);
        NetworkScoreService.FilteringCacheUpdatingConsumer
                consumer = new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
                new ArrayList<>(scoredNetworkList),
                NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);

        List<ScoredNetwork> filteredList = new ArrayList<>(scoredNetworkList);
        filteredList.remove(SCORED_NETWORK);
        when(mScanResultsFilter.apply(scoredNetworkList)).thenReturn(filteredList);
        consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_SCAN_RESULTS);

        verify(mNetworkScoreCache).updateScores(filteredList);
        verifyZeroInteractions(mCurrentNetworkFilter);
    }

    @Test
    public void testCurrentNetworkScoreCacheFilter_nullWifiInfo() throws Exception {
        NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
                new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> null /*WifiInfo*/);

        List<ScoredNetwork> actualList =
                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));

        assertTrue(actualList.isEmpty());
    }

    @Test
    public void testCurrentNetworkScoreCacheFilter_invalidWifiInfo_nullSsid() throws Exception {
        when(mWifiInfo.getSSID()).thenReturn(null);
        NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
                new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo);

        List<ScoredNetwork> actualList =
                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));

        assertTrue(actualList.isEmpty());
    }

    @Test
    public void testCurrentNetworkScoreCacheFilter_invalidWifiInfo_noneSsid() throws Exception {
        when(mWifiInfo.getSSID()).thenReturn(WifiSsid.NONE);
        NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
                new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo);

        List<ScoredNetwork> actualList =
                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));

        assertTrue(actualList.isEmpty());
    }

    @Test
    public void testCurrentNetworkScoreCacheFilter_invalidWifiInfo_emptySsid() throws Exception {
        when(mWifiInfo.getSSID()).thenReturn("");
        NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
                new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo);

        List<ScoredNetwork> actualList =
                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));

        assertTrue(actualList.isEmpty());
    }

    @Test
    public void testCurrentNetworkScoreCacheFilter_invalidWifiInfo_invalidBssid() throws Exception {
        when(mWifiInfo.getBSSID()).thenReturn(INVALID_BSSID);
        NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
                new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo);

        List<ScoredNetwork> actualList =
                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));

        assertTrue(actualList.isEmpty());
    }

    @Test
    public void testCurrentNetworkScoreCacheFilter_scoreFiltered() throws Exception {
        NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
                new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo);

        List<ScoredNetwork> actualList =
                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));

        List<ScoredNetwork> expectedList = Collections.singletonList(SCORED_NETWORK);
        assertEquals(expectedList, actualList);
    }

    @Test
    public void testCurrentNetworkScoreCacheFilter_currentNetworkNotInList() throws Exception {
        when(mWifiInfo.getSSID()).thenReturn("\"notInList\"");
        NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
                new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo);

        List<ScoredNetwork> actualList =
                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));

        assertTrue(actualList.isEmpty());
    }

    @Test
    public void testScanResultsScoreCacheFilter_emptyScanResults() throws Exception {
        NetworkScoreService.ScanResultsScoreCacheFilter cacheFilter =
                new NetworkScoreService.ScanResultsScoreCacheFilter(Collections::emptyList);

        List<ScoredNetwork> actualList =
                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));

        assertTrue(actualList.isEmpty());
    }

    @Test
    public void testScanResultsScoreCacheFilter_invalidScanResults() throws Exception {
        List<ScanResult> invalidScanResults = Lists.newArrayList(
                new ScanResult(),
                createScanResult("", SCORED_NETWORK.networkKey.wifiKey.bssid),
                createScanResult(WifiSsid.NONE, SCORED_NETWORK.networkKey.wifiKey.bssid),
                createScanResult(SSID, null),
                createScanResult(SSID, INVALID_BSSID)
        );
        NetworkScoreService.ScanResultsScoreCacheFilter cacheFilter =
                new NetworkScoreService.ScanResultsScoreCacheFilter(() -> invalidScanResults);

        List<ScoredNetwork> actualList =
                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));

        assertTrue(actualList.isEmpty());
    }

    @Test
    public void testScanResultsScoreCacheFilter_scoresFiltered() throws Exception {
        NetworkScoreService.ScanResultsScoreCacheFilter cacheFilter =
                new NetworkScoreService.ScanResultsScoreCacheFilter(() -> mScanResults);

        ScoredNetwork unmatchedScore =
                new ScoredNetwork(new NetworkKey(new WifiKey(quote("newSsid"),
                        "00:00:00:00:00:00")), null /* rssiCurve*/);

        List<ScoredNetwork> actualList =
                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2,
                        unmatchedScore));

        List<ScoredNetwork> expectedList = Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2);
        assertEquals(expectedList, actualList);
    }

    @Test
    public void testGetActiveScorer_notConnected_canRequestScores() throws Exception {
        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
                .thenReturn(PackageManager.PERMISSION_GRANTED);
        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(null);
        mNetworkScoreService.onUserUnlocked(0);

        mNetworkScoreService.getActiveScorer();

        verify(mServiceConnection, never()).getAppData();
    }

    @Test
    public void testGetActiveScorer_notConnected_canNotRequestScores() throws Exception {
        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
                .thenReturn(PackageManager.PERMISSION_DENIED);
        try {
            mNetworkScoreService.getActiveScorer();
            fail("SecurityException expected.");
        } catch (SecurityException e) {
            // expected
        }
    }

    @Test
    public void testGetActiveScorer_connected_canRequestScores()
            throws Exception {
        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
                .thenReturn(PackageManager.PERMISSION_GRANTED);
        mNetworkScoreService.onUserUnlocked(0);

        mNetworkScoreService.getActiveScorer();

        verify(mServiceConnection).getAppData();
    }

    @Test
    public void testGetActiveScorer_connected_canNotRequestScores()
            throws Exception {
        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
                .thenReturn(PackageManager.PERMISSION_DENIED);
        bindToScorer(false);
        try {
            mNetworkScoreService.getActiveScorer();
            fail("SecurityException expected.");
        } catch (SecurityException e) {
            // expected
        }
    }

    @Test
    public void testServiceConnection_bind_notBound() throws Exception {
        NetworkScoreService.ScoringServiceConnection connection = new NetworkScoreService
                .ScoringServiceConnection(NEW_SCORER);
        connection.bind(mContext);

        verify(mContext).bindServiceAsUser(MockUtils.checkIntent(
                new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
                        .setComponent(RECOMMENDATION_SERVICE_COMP)),
                eq(connection),
                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
                eq(UserHandle.SYSTEM));
    }

    @Test
    public void testServiceConnection_bind_alreadyBound() throws Exception {
        NetworkScoreService.ScoringServiceConnection connection = new NetworkScoreService
                .ScoringServiceConnection(NEW_SCORER);

        when(mContext.bindServiceAsUser(MockUtils.checkIntent(
                new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
                        .setComponent(RECOMMENDATION_SERVICE_COMP)),
                eq(connection),
                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
                eq(UserHandle.SYSTEM))).thenReturn(true /*bound*/);

        // Calling bind more than once should only result in 1 bindService call.
        connection.bind(mContext);
        connection.bind(mContext);

        verify(mContext, times(1)).bindServiceAsUser(MockUtils.checkIntent(
                new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
                        .setComponent(RECOMMENDATION_SERVICE_COMP)),
                eq(connection),
                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
                eq(UserHandle.SYSTEM));
    }

    @Test
    public void testServiceConnection_bindFails() throws Exception {
        NetworkScoreService.ScoringServiceConnection connection = new NetworkScoreService
                .ScoringServiceConnection(NEW_SCORER);

        when(mContext.bindServiceAsUser(MockUtils.checkIntent(
                new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
                        .setComponent(RECOMMENDATION_SERVICE_COMP)),
                eq(connection),
                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
                eq(UserHandle.SYSTEM))).thenReturn(false /*bound*/);

        connection.bind(mContext);

        verify(mContext).unbindService(connection);
    }

    @Test
    public void testServiceConnection_unbind_notBound() throws Exception {
        NetworkScoreService.ScoringServiceConnection connection = new NetworkScoreService
                .ScoringServiceConnection(NEW_SCORER);

        connection.unbind(mContext);

        verify(mContext, never()).unbindService(connection);
    }

    @Test
    public void testServiceConnection_unbind_alreadyBound() throws Exception {
        NetworkScoreService.ScoringServiceConnection connection = new NetworkScoreService
                .ScoringServiceConnection(NEW_SCORER);

        when(mContext.bindServiceAsUser(MockUtils.checkIntent(
                new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
                        .setComponent(RECOMMENDATION_SERVICE_COMP)),
                eq(connection),
                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
                eq(UserHandle.SYSTEM))).thenReturn(true /*bound*/);

        connection.bind(mContext);
        connection.unbind(mContext);

        verify(mContext).unbindService(connection);
    }

    @Test
    public void testServiceConnection_dump_doesNotCrash() throws Exception {
        NetworkScoreService.ScoringServiceConnection connection = new NetworkScoreService
                .ScoringServiceConnection(NEW_SCORER);
        final StringWriter stringWriter = new StringWriter();

        connection.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);

        assertFalse(stringWriter.toString().isEmpty());
    }

    private void bindToScorer(boolean callerIsScorer) {
        final int callingUid = callerIsScorer ? Binder.getCallingUid() : Binder.getCallingUid() + 1;
        NetworkScorerAppData appData = new NetworkScorerAppData(callingUid,
                RECOMMENDATION_SERVICE_COMP, RECOMMENDATION_SERVICE_LABEL,
                USE_WIFI_ENABLE_ACTIVITY_COMP, NETWORK_AVAILABLE_NOTIFICATION_CHANNEL_ID);
        when(mServiceConnection.getAppData()).thenReturn(appData);
        mNetworkScoreService.onUserUnlocked(0);
    }

    private static class CountDownHandler extends Handler {
        CountDownLatch latch = new CountDownLatch(1);
        int receivedWhat;

        CountDownHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            latch.countDown();
            receivedWhat = msg.what;
        }
    }
}
