/*
 * Copyright (C) 2018 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.wifi;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.Context;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.net.wifi.WifiInfo;
import android.os.Handler;
import android.provider.Settings;
import android.support.test.filters.SmallTest;

import com.android.internal.R;

import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;

/**
 * Unit tests for {@link com.android.server.wifi.ScoringParams}.
 */
@SmallTest
public class ScoringParamsTest {

    private static final String EXPECTED_DEFAULTS =
            "rssi2=-83:-80:-73:-60,rssi5=-80:-77:-70:-57,pps=0:1:100,horizon=15,nud=8,expid=0";

    private ScoringParams mScoringParams;

    /**
     * Sets up for unit test
     */
    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        setUpResources(mResources);
        when(mContext.getResources()).thenReturn(mResources);
        mScoringParams = new ScoringParams();
    }

    /**
     * Check that thresholds are properly ordered, and in range.
     */
    private void checkThresholds(int frequency) {
        assertTrue(-127 < mScoringParams.getExitRssi(frequency));
        assertTrue(mScoringParams.getExitRssi(frequency)
                <= mScoringParams.getEntryRssi(frequency));
        assertTrue(mScoringParams.getEntryRssi(frequency)
                <= mScoringParams.getSufficientRssi(frequency));
        assertTrue(mScoringParams.getSufficientRssi(frequency)
                <= mScoringParams.getGoodRssi(frequency));
        assertTrue(mScoringParams.getGoodRssi(frequency) < 0);
    }

    /**
     * Test basic constructor
     */
    @Test
    public void testBasicConstructor() throws Exception {
        mScoringParams = new ScoringParams();
        checkThresholds(2412);
        checkThresholds(5020);
        assertEquals(15, mScoringParams.getHorizonSeconds());
    }

    /**
     * Test toString
     */
    @Test
    public void testToString() throws Exception {
        mScoringParams = new ScoringParams();
        String expect = EXPECTED_DEFAULTS;
        String actual = mScoringParams.toString();
        assertEquals(expect, actual);
    }

    /**
     * Test complete update
     */
    @Test
    public void testUpdateEverything() throws Exception {
        mScoringParams = new ScoringParams();
        String params = EXPECTED_DEFAULTS.replaceAll("8", "9");
        assertTrue(mScoringParams.update(params));
        assertEquals(params, mScoringParams.toString());
    }

    /**
     * Test partial update
     */
    @Test
    public void testPartialUpdate() throws Exception {
        mScoringParams = new ScoringParams();
        String before = mScoringParams.toString();
        String partial = "rssi5=-88:-77:-66:-55";
        assertFalse(before.contains(partial));
        assertTrue(mScoringParams.update(partial));
        String after = mScoringParams.toString();
        assertTrue(after + " should contain " + partial, after.contains(partial));
        assertEquals(before.replaceAll("rssi5=[^,]*,", partial + ","), after);
    }

    /**
     * Test some failed updates
     */
    @Test
    public void testUpdateFail() throws Exception {
        mScoringParams = new ScoringParams();
        String before = mScoringParams.toString();
        assertFalse(mScoringParams.update("word"));
        assertFalse(mScoringParams.update("42"));
        assertFalse(mScoringParams.update(" "));
        assertFalse(mScoringParams.update("horizon=flat"));
        assertFalse(mScoringParams.update("horizon=+"));
        assertFalse(mScoringParams.update(",,,,,,,,,,,,,,,,,,"));
        assertFalse(mScoringParams.update("rssi2=-86"));
        assertFalse(mScoringParams.update("rssi2=-99:-88:-77:-66:-55"));
        assertFalse(mScoringParams.update("rssi5=one:two:three:four"));
        assertFalse(mScoringParams.update("nud=-1"));
        assertFalse(mScoringParams.update("nud=11"));
        assertFalse(mScoringParams.update("pps=1:2:3:4"));
        assertFalse(mScoringParams.update("pps=1:0:9"));
        assertFalse(mScoringParams.update("pps=packets-per-second"));
        assertEquals(before, mScoringParams.toString());
    }

    /**
     * Duplicate keys not allowed
     */
    @Test
    public void testDuplicateKeysNotAllowed() throws Exception {
        mScoringParams = new ScoringParams();
        String before = mScoringParams.toString();
        String partial = "rssi5=-88:-77:-66:-55";
        assertFalse(mScoringParams.update(partial + "," + partial));
        assertEquals(before, mScoringParams.toString());
    }

    /**
     * Range and ordering checks for rssi values should work
     */
    @Test
    public void testRssiRangeChecks() throws Exception {
        mScoringParams = new ScoringParams();
        String before = mScoringParams.toString();
        assertFalse("Must be negative", mScoringParams.update("rssi2=0:1:2:3"));
        assertFalse("Must be ordered", mScoringParams.update("rssi5=-88:-89:-66:-55"));
        assertFalse("Must be not too negative", mScoringParams.update("rssi5=-128:-77:-66:-55"));
        String what = "rssi5=" + WifiInfo.INVALID_RSSI + ":-77:-66:-55";
        assertFalse(what, mScoringParams.update(what));
        assertEquals(before, mScoringParams.toString());
    }

    /**
     * Range checks should catch wild values
     */
    @Test
    public void testScalarRangeChecks() throws Exception {
        mScoringParams = new ScoringParams();
        assertTrue(mScoringParams.update("horizon=60"));
        assertFalse(mScoringParams.update("horizon=61"));
        assertTrue(mScoringParams.update("horizon=-9")); // Not recommended, but shouldn't break
        assertFalse(mScoringParams.update("horizon=-10"));
    }

    /**
     * Test that nud is hooked up
     */
    @Test
    public void testNudKnob() throws Exception {
        mScoringParams = new ScoringParams();
        assertTrue(mScoringParams.update("nud=6"));
        assertEquals(6, mScoringParams.getNudKnob());
    }

    /**
     * Test that expid is hooked up
     */
    @Test
    public void testExperimentIdentifier() throws Exception {
        mScoringParams = new ScoringParams();
        assertEquals(0, mScoringParams.getExperimentIdentifier());
        assertTrue(mScoringParams.update("expid=99"));
        assertEquals(99, mScoringParams.getExperimentIdentifier());
    }

    /**
     * Check character set
     */
    @Test
    public void testBadCharacterChecks() throws Exception {
        mScoringParams = new ScoringParams();
        String before = mScoringParams.toString();
        assertFalse(mScoringParams.update("\007ding\007=7"));
        assertTrue(mScoringParams.update("unknown_key=14,ThatThing=987654321"));
        assertEquals(before, mScoringParams.toString());
    }

    /**
     * Sanitize should hide garbage characters and truncate length
     */
    @Test
    public void testSanitize() throws Exception {
        mScoringParams = new ScoringParams();
        String longKey = "A123456789_123456789_123456789_123456789_123456789";
        String longVal = "9.99999999999999999999999999999999999999999999999";
        String param100 = longKey + "=" + longVal;
        assertEquals(param100, mScoringParams.sanitize(param100));
        assertEquals(101, mScoringParams.sanitize(param100 + "00000000000").length());
        assertEquals(param100.substring(0, 90),
                mScoringParams.sanitize(param100 + "00000000000").substring(0, 90));
        assertEquals("q?=???", mScoringParams.sanitize("q\b= ~["));
        assertEquals("", mScoringParams.sanitize(null));
    }

    /**
     * Test that empty updates are OK
     */
    @Test
    public void testEmptyUpdate() throws Exception {
        mScoringParams = new ScoringParams();
        String before = mScoringParams.toString();
        assertTrue(mScoringParams.update(""));
        assertTrue(mScoringParams.update(null));
        assertEquals(before, mScoringParams.toString());
    }

    /**
     * Tests for obtaining values from device configuration (config.xml)
     */
    int mBad2GHz, mEntry2GHz, mSufficient2GHz, mGood2GHz;
    int mBad5GHz, mEntry5GHz, mSufficient5GHz, mGood5GHz;

    @Mock Context mContext;
    @Spy private MockResources mResources = new MockResources();

    private int setupIntegerResource(int resourceName, int value) {
        doReturn(value).when(mResources).getInteger(resourceName);
        return value;
    }

    /**
     * Sets up resource values for testing
     *
     * See frameworks/base/core/res/res/values/config.xml
     */
    private void setUpResources(Resources resources) {
        mBad2GHz = setupIntegerResource(
                R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz, -88);
        mEntry2GHz = setupIntegerResource(
                R.integer.config_wifi_framework_wifi_score_entry_rssi_threshold_24GHz, -77);
        mSufficient2GHz = setupIntegerResource(
                R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz, -66);
        mGood2GHz = setupIntegerResource(
                R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_24GHz, -55);
        mBad5GHz = setupIntegerResource(
                R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz, -80);
        mEntry5GHz = setupIntegerResource(
                R.integer.config_wifi_framework_wifi_score_entry_rssi_threshold_5GHz, -70);
        mSufficient5GHz = setupIntegerResource(
                R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz, -60);
        mGood5GHz = setupIntegerResource(
                R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_5GHz, -50);
    }

    /**
     * Check that we get the config.xml values, if that's what we want
     */
    @Test
    public void testContextConstructor() throws Exception {
        mScoringParams = new ScoringParams(mContext);

        assertEquals(mBad2GHz, mScoringParams.getExitRssi(2412));
        assertEquals(mEntry2GHz, mScoringParams.getEntryRssi(2480));
        assertEquals(mSufficient2GHz, mScoringParams.getSufficientRssi(2400));
        assertEquals(mGood2GHz, mScoringParams.getGoodRssi(2499));
        assertEquals(mGood2GHz, mScoringParams.getGoodRssi(ScoringParams.BAND2));

        assertEquals(mBad5GHz, mScoringParams.getExitRssi(5000));
        assertEquals(mEntry5GHz, mScoringParams.getEntryRssi(5010));
        assertEquals(mSufficient5GHz, mScoringParams.getSufficientRssi(5100));
        assertEquals(mGood5GHz, mScoringParams.getGoodRssi(5678));
        assertEquals(mGood5GHz, mScoringParams.getGoodRssi(ScoringParams.BAND5));
    }

    /**
     * Additional mocks for handling Settings
     */
    @Mock FrameworkFacade mFrameworkFacade;
    @Mock Handler mHandler;

    /**
     * Test getting updates from Settings
     *
     * Exercises the ContentObserver notification path
     */
    @Test
    public void testFullConstructorWithUpdatesFromSettings() throws Exception {
        ArgumentCaptor<ContentObserver> captor = ArgumentCaptor.forClass(ContentObserver.class);
        when(mFrameworkFacade.getStringSetting(mContext, Settings.Global.WIFI_SCORE_PARAMS))
                .thenReturn(null);
        mScoringParams = new ScoringParams(mContext, mFrameworkFacade, mHandler);
        verify(mFrameworkFacade)
                .registerContentObserver(eq(mContext), any(), anyBoolean(), captor.capture());

        String before = mScoringParams.toString();
        String changed = before.replace('8', '9');
        assertFalse(changed.equals(before));

        when(mFrameworkFacade.getStringSetting(mContext, Settings.Global.WIFI_SCORE_PARAMS))
                .thenReturn(changed);
        captor.getValue().onChange(/*selfChange*/ false);
        assertEquals(changed, mScoringParams.toString());

        when(mFrameworkFacade.getStringSetting(mContext, Settings.Global.WIFI_SCORE_PARAMS))
                .thenReturn("");
        captor.getValue().onChange(/*selfChange*/ false);
        assertEquals(before, mScoringParams.toString());
    }

    @Test
    public void testBadSettings() throws Exception {
        ArgumentCaptor<ContentObserver> captor = ArgumentCaptor.forClass(ContentObserver.class);
        when(mFrameworkFacade.getStringSetting(mContext, Settings.Global.WIFI_SCORE_PARAMS))
                .thenReturn(null);
        mScoringParams = new ScoringParams(mContext, mFrameworkFacade, mHandler);
        verify(mFrameworkFacade)
                .registerContentObserver(eq(mContext), any(), anyBoolean(), captor.capture());

        String before = mScoringParams.toString();
        String garbage = "what??";

        when(mFrameworkFacade.getStringSetting(mContext, Settings.Global.WIFI_SCORE_PARAMS))
                .thenReturn(garbage);
        captor.getValue().onChange(/*selfChange*/ false);
        assertEquals(before, mScoringParams.toString());
    }
}
