/*
 * 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.wifi;

import static org.mockito.Mockito.*;
import static org.mockito.MockitoAnnotations.*;

import android.support.test.filters.SmallTest;

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;

/**
 * Unit tests for {@link com.android.server.wifi.SelfRecovery}.
 */
@SmallTest
public class SelfRecoveryTest {
    SelfRecovery mSelfRecovery;
    @Mock WifiController mWifiController;
    @Mock Clock mClock;

    @Before
    public void setUp() throws Exception {
        initMocks(this);
        mSelfRecovery = new SelfRecovery(mWifiController, mClock);
    }

    /**
     * Verifies that invocations of {@link SelfRecovery#trigger(int)} with valid reasons will send
     * the restart message to {@link WifiController}.
     */
    @Test
    public void testValidTriggerReasonsSendMessageToWifiController() {
        mSelfRecovery.trigger(SelfRecovery.REASON_LAST_RESORT_WATCHDOG);
        verify(mWifiController).sendMessage(eq(WifiController.CMD_RECOVERY_RESTART_WIFI), anyInt());
        reset(mWifiController);

        when(mClock.getElapsedSinceBootMillis())
                .thenReturn(SelfRecovery.MAX_RESTARTS_TIME_WINDOW_MILLIS + 1);
        mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE);
        verify(mWifiController).sendMessage(eq(WifiController.CMD_RECOVERY_RESTART_WIFI), anyInt());
        reset(mWifiController);
    }

    /**
     * Verifies that invocations of {@link SelfRecovery#trigger(int)} with invalid reasons will not
     * send the restart message to {@link WifiController}.
     */
    @Test
    public void testInvalidTriggerReasonsDoesNotSendMessageToWifiController() {
        mSelfRecovery.trigger(-1);
        verify(mWifiController, never()).sendMessage(anyInt(), anyString());

        mSelfRecovery.trigger(8);
        verify(mWifiController, never()).sendMessage(anyInt(), anyString());
    }

    /**
     * Verifies that a STA interface down event will trigger WifiController to disable wifi.
     */
    @Test
    public void testStaIfaceDownDisablesWifi() {
        mSelfRecovery.trigger(SelfRecovery.REASON_STA_IFACE_DOWN);
        verify(mWifiController).sendMessage(eq(WifiController.CMD_RECOVERY_DISABLE_WIFI));
    }

    /**
     * Verifies that invocations of {@link SelfRecovery#trigger(int)} for REASON_HAL_CRASH &
     * REASON_WIFICOND_CRASH are limited to {@link SelfRecovery#MAX_RESTARTS_IN_TIME_WINDOW} in a
     * {@link SelfRecovery#MAX_RESTARTS_TIME_WINDOW_MILLIS} millisecond time window.
     */
    @Test
    public void testTimeWindowLimiting_typicalUse() {
        when(mClock.getElapsedSinceBootMillis()).thenReturn(0L);
        // Fill up the SelfRecovery's restart time window buffer, ensure all the restart triggers
        // aren't ignored
        for (int i = 0; i < SelfRecovery.MAX_RESTARTS_IN_TIME_WINDOW / 2; i++) {
            mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE);
            verify(mWifiController).sendMessage(eq(WifiController.CMD_RECOVERY_RESTART_WIFI),
                                                anyInt());
            reset(mWifiController);

            mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE);
            verify(mWifiController).sendMessage(eq(WifiController.CMD_RECOVERY_RESTART_WIFI),
                                                anyInt());
            reset(mWifiController);
        }
        if ((SelfRecovery.MAX_RESTARTS_IN_TIME_WINDOW % 2) == 1) {
            mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE);
            verify(mWifiController).sendMessage(eq(WifiController.CMD_RECOVERY_RESTART_WIFI),
                                                anyInt());
            reset(mWifiController);
        }

        // Verify that further attempts to trigger restarts disable wifi
        mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE);
        verify(mWifiController, never()).sendMessage(eq(WifiController.CMD_RECOVERY_RESTART_WIFI),
                anyString());
        verify(mWifiController).sendMessage(eq(WifiController.CMD_RECOVERY_DISABLE_WIFI));
        reset(mWifiController);

        mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE);
        verify(mWifiController, never()).sendMessage(eq(WifiController.CMD_RECOVERY_RESTART_WIFI),
                anyString());
        verify(mWifiController).sendMessage(eq(WifiController.CMD_RECOVERY_DISABLE_WIFI));
        reset(mWifiController);

        // Verify L.R.Watchdog can still restart things (It has its own complex limiter)
        mSelfRecovery.trigger(SelfRecovery.REASON_LAST_RESORT_WATCHDOG);
        verify(mWifiController).sendMessage(eq(WifiController.CMD_RECOVERY_RESTART_WIFI),
                                            anyInt());
        reset(mWifiController);

        // Verify Sta Interface Down will still disable wifi
        mSelfRecovery.trigger(SelfRecovery.REASON_STA_IFACE_DOWN);
        verify(mWifiController).sendMessage(eq(WifiController.CMD_RECOVERY_DISABLE_WIFI));
        reset(mWifiController);

        // now TRAVEL FORWARDS IN TIME and ensure that more restarts can occur
        when(mClock.getElapsedSinceBootMillis())
                .thenReturn(SelfRecovery.MAX_RESTARTS_TIME_WINDOW_MILLIS + 1);
        mSelfRecovery.trigger(SelfRecovery.REASON_LAST_RESORT_WATCHDOG);
        verify(mWifiController).sendMessage(eq(WifiController.CMD_RECOVERY_RESTART_WIFI), anyInt());
        reset(mWifiController);

        when(mClock.getElapsedSinceBootMillis())
                .thenReturn(SelfRecovery.MAX_RESTARTS_TIME_WINDOW_MILLIS + 1);
        mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE);
        verify(mWifiController).sendMessage(eq(WifiController.CMD_RECOVERY_RESTART_WIFI), anyInt());
        reset(mWifiController);
    }

    /**
     * Verifies that invocations of {@link SelfRecovery#trigger(int)} for
     * REASON_LAST_RESORT_WATCHDOG are NOT limited to
     * {@link SelfRecovery#MAX_RESTARTS_IN_TIME_WINDOW} in a
     * {@link SelfRecovery#MAX_RESTARTS_TIME_WINDOW_MILLIS} millisecond time window.
     */
    @Test
    public void testTimeWindowLimiting_lastResortWatchdog_noEffect() {
        for (int i = 0; i < SelfRecovery.MAX_RESTARTS_IN_TIME_WINDOW * 2; i++) {
            // Verify L.R.Watchdog can still restart things (It has it's own complex limiter)
            mSelfRecovery.trigger(SelfRecovery.REASON_LAST_RESORT_WATCHDOG);
            verify(mWifiController).sendMessage(eq(WifiController.CMD_RECOVERY_RESTART_WIFI),
                                                anyInt());
            reset(mWifiController);
        }
    }

    /**
     * Verifies that invocations of {@link SelfRecovery#trigger(int)} for
     * REASON_STA_IFACE_DOWN are NOT limited to
     * {@link SelfRecovery#MAX_RESTARTS_IN_TIME_WINDOW} in a
     * {@link SelfRecovery#MAX_RESTARTS_TIME_WINDOW_MILLIS} millisecond time window.
     */
    @Test
    public void testTimeWindowLimiting_staIfaceDown_noEffect() {
        for (int i = 0; i < SelfRecovery.MAX_RESTARTS_IN_TIME_WINDOW * 2; i++) {
            mSelfRecovery.trigger(SelfRecovery.REASON_STA_IFACE_DOWN);
            verify(mWifiController).sendMessage(eq(WifiController.CMD_RECOVERY_DISABLE_WIFI));
            verify(mWifiController, never())
                    .sendMessage(eq(WifiController.CMD_RECOVERY_RESTART_WIFI), anyInt());
            reset(mWifiController);
        }
    }
}
