/*
 * Copyright (C) 2016 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.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.AdditionalMatchers.gt;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.contains;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyObject;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.test.MockAnswerUtil.AnswerWithArguments;
import android.content.Context;
import android.os.BugreportManager;

import androidx.test.filters.SmallTest;

import com.android.wifi.resources.R;

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

import java.io.ByteArrayInputStream;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.regex.Pattern;

/**
 * Unit tests for {@link WifiDiagnostics}.
 */
@SmallTest
public class WifiDiagnosticsTest extends WifiBaseTest {
    @Mock WifiNative mWifiNative;
    @Mock BuildProperties mBuildProperties;
    @Mock Context mContext;
    @Mock WifiInjector mWifiInjector;
    @Mock DeviceConfigFacade mDeviceConfigFacade;
    @Spy FakeWifiLog mLog;
    @Mock LastMileLogger mLastMileLogger;
    @Mock Runtime mJavaRuntime;
    @Mock Process mExternalProcess;
    @Mock WifiMetrics mWifiMetrics;
    @Mock Clock mClock;
    @Mock BugreportManager mBugreportManager;
    @Mock WifiScoreCard mWifiScoreCard;
    private long mBootTimeMs = 0L;
    MockResources mResources;
    WifiDiagnostics mWifiDiagnostics;

    private static final String FAKE_RING_BUFFER_NAME = "fake-ring-buffer";
    private static final String STA_IF_NAME = "wlan0";
    private static final String AP_IF_NAME = "wlan1";
    private static final int SMALL_RING_BUFFER_SIZE_KB = 32;
    private static final int LARGE_RING_BUFFER_SIZE_KB = 1024;
    private static final int BYTES_PER_KBYTE = 1024;
    private static final int ALERT_REASON_CODE = 1;
    private static final byte[] ALERT_DATA = {0 , 4, 5};
    /** Mock resource for fatal firmware alert list */
    private static final int[] FATAL_FW_ALERT_LIST = {256, 257, 258};
    /** Mock a non fatal firmware alert */
    private static final int NON_FATAL_FW_ALERT = 0;
    private static final int BUG_REPORT_MIN_WINDOW_MS = 3600_000;

    private WifiNative.RingBufferStatus mFakeRbs;
    /**
     * Returns the data that we would dump in a bug report, for our ring buffer.
     * @return a 2-D byte array, where the first dimension is the record number, and the second
     * dimension is the byte index within that record.
     */
    private final byte[][] getLoggerRingBufferData() throws Exception {
        return mWifiDiagnostics.getBugReports().get(0).ringBuffers.get(FAKE_RING_BUFFER_NAME);
    }

    /**
     * Initializes common state (e.g. mocks) needed by test cases.
     */
    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);

        mFakeRbs = new WifiNative.RingBufferStatus();
        mFakeRbs.name = FAKE_RING_BUFFER_NAME;
        WifiNative.RingBufferStatus[] ringBufferStatuses = new WifiNative.RingBufferStatus[] {
                mFakeRbs
        };

        when(mWifiNative.getRingBufferStatus()).thenReturn(ringBufferStatuses);
        when(mBuildProperties.isEngBuild()).thenReturn(false);
        when(mBuildProperties.isUserdebugBuild()).thenReturn(false);
        when(mBuildProperties.isUserBuild()).thenReturn(true);
        when(mExternalProcess.getInputStream()).thenReturn(new ByteArrayInputStream(new byte[0]));
        when(mExternalProcess.getErrorStream()).thenReturn(new ByteArrayInputStream(new byte[0]));
        when(mJavaRuntime.exec(anyString())).thenReturn(mExternalProcess);

        mResources = new MockResources();
        mResources.setInteger(R.integer.config_wifi_logger_ring_buffer_default_size_limit_kb,
                SMALL_RING_BUFFER_SIZE_KB);
        mResources.setInteger(R.integer.config_wifi_logger_ring_buffer_verbose_size_limit_kb,
                LARGE_RING_BUFFER_SIZE_KB);
        mResources.setIntArray(R.array.config_wifi_fatal_firmware_alert_error_code_list,
                FATAL_FW_ALERT_LIST);
        mResources.setBoolean(R.bool.config_wifi_diagnostics_bugreport_enabled, true);
        when(mContext.getResources()).thenReturn(mResources);
        when(mContext.getSystemService(BugreportManager.class)).thenReturn(mBugreportManager);
        when(mWifiInjector.makeLog(anyString())).thenReturn(mLog);
        when(mWifiInjector.getJavaRuntime()).thenReturn(mJavaRuntime);
        when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics);
        when(mWifiInjector.getDeviceConfigFacade()).thenReturn(mDeviceConfigFacade);
        when(mWifiInjector.getWifiScoreCard()).thenReturn(mWifiScoreCard);
        when(mDeviceConfigFacade.getBugReportMinWindowMs()).thenReturn(BUG_REPORT_MIN_WINDOW_MS);
        // needed to for the loop in WifiDiagnostics.readLogcatStreamLinesWithTimeout().
        doAnswer(new AnswerWithArguments() {
            public long answer() throws Exception {
                mBootTimeMs += WifiDiagnostics.LOGCAT_READ_TIMEOUT_MILLIS / 2;
                return mBootTimeMs;
            }
        }).when(mClock).getElapsedSinceBootMillis();
        mWifiDiagnostics = new WifiDiagnostics(
                mContext, mWifiInjector, mWifiNative, mBuildProperties, mLastMileLogger, mClock);
        mWifiNative.enableVerboseLogging(0);
    }

    /** Verifies that startLogging() registers a logging event handler. */
    @Test
    public void startLoggingRegistersLogEventHandler() throws Exception {
        mWifiDiagnostics.enableVerboseLogging(false);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        verify(mWifiNative).setLoggingEventHandler(anyObject());
    }

    /**
     * Verifies that a failure to set the logging event handler does not prevent a future
     * startLogging() from setting the logging event handler.
     */
    @Test
    public void startLoggingRegistersLogEventHandlerIfPriorAttemptFailed()
            throws Exception {
        final boolean verbosityToggle = false;  // even default mode registers handler

        when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(false);
        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        verify(mWifiNative).setLoggingEventHandler(anyObject());
        mWifiDiagnostics.stopLogging(STA_IF_NAME);
        reset(mWifiNative);

        when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(true);
        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        verify(mWifiNative).setLoggingEventHandler(anyObject());
    }

    /** Verifies that startLogging() does not make redundant calls to setLoggingEventHandler(). */
    @Test
    public void startLoggingDoesNotRegisterLogEventHandlerIfPriorAttemptSucceeded()
            throws Exception {
        when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(true);
        mWifiDiagnostics.enableVerboseLogging(false);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        verify(mWifiNative).setLoggingEventHandler(anyObject());
        reset(mWifiNative);

        mWifiDiagnostics.enableVerboseLogging(false);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        verify(mWifiNative, never()).setLoggingEventHandler(anyObject());
    }

    /**
     * Verifies that startLogging() restarts HAL ringbuffers.
     *
     * Specifically: verifies that startLogging()
     * a) stops any ring buffer logging that might be already running,
     * b) instructs WifiNative to enable ring buffers of the appropriate log level.
     */
    @Test
    public void startLoggingStopsAndRestartsRingBufferLoggingInVerboseMode() throws Exception {
        final boolean verbosityToggle = true;
        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        verify(mWifiNative).startLoggingRingBuffer(
                eq(WifiDiagnostics.VERBOSE_NO_LOG), anyInt(), anyInt(), anyInt(),
                eq(FAKE_RING_BUFFER_NAME));
        verify(mWifiNative).startLoggingRingBuffer(
                eq(WifiDiagnostics.VERBOSE_LOG_WITH_WAKEUP), anyInt(), anyInt(), anyInt(),
                eq(FAKE_RING_BUFFER_NAME));
    }

    @Test
    public void startLoggingStopsAndThenStartRingBufferLoggingInNormalMode() throws Exception {
        final boolean verbosityToggle = false;
        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        verify(mWifiNative).startLoggingRingBuffer(
                eq(WifiDiagnostics.VERBOSE_NO_LOG), anyInt(), anyInt(), anyInt(),
                eq(FAKE_RING_BUFFER_NAME));
        verify(mWifiNative).startLoggingRingBuffer(
                gt(WifiDiagnostics.VERBOSE_NO_LOG), anyInt(), anyInt(), anyInt(),
                anyString());
    }

    /** Verifies that, if a log handler was registered, then stopLogging() resets it. */
    @Test
    public void stopLoggingResetsLogHandlerIfHandlerWasRegistered() throws Exception {
        final boolean verbosityToggle = false;  // even default mode registers handler

        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(true);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        reset(mWifiNative);

        mWifiDiagnostics.stopLogging(STA_IF_NAME);
        verify(mWifiNative).resetLogHandler();
    }

    /** Verifies that, if a log handler is not registered, stopLogging() skips resetLogHandler(). */
    @Test
    public void stopLoggingOnlyResetsLogHandlerIfHandlerWasRegistered() throws Exception {
        mWifiDiagnostics.stopLogging(STA_IF_NAME);
        verify(mWifiNative, never()).resetLogHandler();
    }

    /** Verifies that stopLogging() remembers that we've reset the log handler. */
    @Test
    public void multipleStopLoggingCallsOnlyResetLogHandlerOnce() throws Exception {
        final boolean verbosityToggle = false;  // even default mode registers handler

        when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(true);
        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        reset(mWifiNative);

        when(mWifiNative.resetLogHandler()).thenReturn(true);
        mWifiDiagnostics.stopLogging(STA_IF_NAME);
        verify(mWifiNative).resetLogHandler();
        reset(mWifiNative);

        mWifiDiagnostics.stopLogging(STA_IF_NAME);
        verify(mWifiNative, never()).resetLogHandler();
    }

    /**
     * Verifies that we capture ring-buffer data.
     */
    @Test
    public void canCaptureAndStoreRingBufferData() throws Exception {
        final boolean verbosityToggle = false;
        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startLogging(STA_IF_NAME);

        final byte[] data = new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE];
        mWifiDiagnostics.onRingBufferData(mFakeRbs, data);
        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);

        byte[][] ringBufferData = getLoggerRingBufferData();
        assertEquals(1, ringBufferData.length);
        assertArrayEquals(data, ringBufferData[0]);
    }

    /**
     * Verifies that we discard extraneous ring-buffer data.
     */
    @Ignore("TODO(b/36811399): re-enabled this @Test")
    @Test
    public void loggerDiscardsExtraneousData() throws Exception {
        final boolean verbosityToggle = false;
        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startLogging(STA_IF_NAME);

        final byte[] data1 = new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE];
        final byte[] data2 = {1, 2, 3};
        mWifiDiagnostics.onRingBufferData(mFakeRbs, data1);
        mWifiDiagnostics.onRingBufferData(mFakeRbs, data2);
        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);

        byte[][] ringBufferData = getLoggerRingBufferData();
        assertEquals(1, ringBufferData.length);
        assertArrayEquals(data2, ringBufferData[0]);
    }

    // Verifies that startPktFateMonitoring(any()) reports failure to start packet fate
    @Test
    public void startPktFateMonitoringReportsStartFailures() {
        when(mWifiNative.startPktFateMonitoring(any())).thenReturn(false);
        mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME);
        verify(mLog).wC(contains("Failed"));
    }

    /**
     * Verifies that, when verbose mode is not enabled,
     * reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED) still fetches packet fates.
     */
    @Test
    public void reportConnectionFailureIsIgnoredWithoutVerboseMode() {
        final boolean verbosityToggle = false;
        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME);
        mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED);
        verify(mWifiNative).getTxPktFates(any(), anyObject());
        verify(mWifiNative).getRxPktFates(any(), anyObject());
    }

    /**
     * Verifies that, when verbose mode is enabled, reportConnectionFailure() fetches packet fates.
     */
    @Test
    public void reportConnectionFailureFetchesFatesInVerboseMode() {
        final boolean verbosityToggle = true;
        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME);
        mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED);
        verify(mWifiNative).getTxPktFates(any(), anyObject());
        verify(mWifiNative).getRxPktFates(any(), anyObject());
    }

    @Test
    public void reportConnectionEventPropagatesStartToLastMileLogger() {
        final boolean verbosityToggle = false;
        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_STARTED);
        verify(mLastMileLogger).reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_STARTED);
    }

    @Test
    public void reportConnectionEventPropagatesSuccessToLastMileLogger() {
        final boolean verbosityToggle = false;
        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_SUCCEEDED);
        verify(mLastMileLogger).reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_SUCCEEDED);
    }

    @Test
    public void reportConnectionEventPropagatesFailureToLastMileLogger() {
        final boolean verbosityToggle = false;
        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED);
        verify(mLastMileLogger).reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED);
    }

    /**
     * Verifies that we are propagating the CONNECTION_EVENT_TIMEOUT event to LastMileLogger.
     */
    @Test
    public void reportConnectionEventPropagatesTimeoutToLastMileLogger() {
        final boolean verbosityToggle = true;
        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_TIMEOUT);
        verify(mLastMileLogger).reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_TIMEOUT);
    }

    /**
     * Verifies that we try to fetch TX fates, even if fetching RX fates failed.
     */
    @Test
    public void loggerFetchesTxFatesEvenIfFetchingRxFatesFails() {
        final boolean verbosityToggle = true;
        when(mWifiNative.getRxPktFates(any(), anyObject())).thenReturn(false);
        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME);
        mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED);
        verify(mWifiNative).getTxPktFates(any(), anyObject());
        verify(mWifiNative).getRxPktFates(any(), anyObject());
    }

    /**
     * Verifies that we try to fetch RX fates, even if fetching TX fates failed.
     */
    @Test
    public void loggerFetchesRxFatesEvenIfFetchingTxFatesFails() {
        final boolean verbosityToggle = true;
        when(mWifiNative.getTxPktFates(any(), anyObject())).thenReturn(false);
        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME);
        mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED);
        verify(mWifiNative).getTxPktFates(any(), anyObject());
        verify(mWifiNative).getRxPktFates(any(), anyObject());
    }

    /** Verifies that dump() fetches the latest fates. */
    @Test
    public void dumpFetchesFates() {
        final boolean verbosityToggle = false;
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME);
        mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"});
        verify(mWifiNative).getTxPktFates(any(), anyObject());
        verify(mWifiNative).getRxPktFates(any(), anyObject());
    }

    /**
     * Verifies that dump() doesn't crash, or generate garbage, in the case where we haven't fetched
     * any fates.
     */
    @Test
    public void dumpSucceedsWhenNoFatesHaveNotBeenFetched() {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"});

        String fateDumpString = sw.toString();
        assertTrue(fateDumpString.contains("Last failed"));
        // Verify dump terminator is present
        assertTrue(fateDumpString.contains(
                "--------------------------------------------------------------------"));
    }

    /**
     * Verifies that dump() doesn't crash, or generate garbage, in the case where the fates that
     * the HAL-provided fates are empty.
     */
    @Test
    public void dumpSucceedsWhenFatesHaveBeenFetchedButAreEmpty() {
        final boolean verbosityToggle = true;
        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME);
        mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED);
        verify(mWifiNative).getTxPktFates(any(), anyObject());
        verify(mWifiNative).getRxPktFates(any(), anyObject());

        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"});

        String fateDumpString = sw.toString();
        assertTrue(fateDumpString.contains("Last failed"));
        // Verify dump terminator is present
        assertTrue(fateDumpString.contains(
                "--------------------------------------------------------------------"));
    }

    private String getDumpString(boolean verbose) {
        mWifiDiagnostics.enableVerboseLogging(verbose);
        mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        mWifiNative.enableVerboseLogging(verbose ? 1 : 0);
        when(mWifiNative.getTxPktFates(any(), anyObject())).then(new AnswerWithArguments() {
            public boolean answer(String ifaceName, WifiNative.TxFateReport[] fates) {
                fates[0] = new WifiNative.TxFateReport(
                        WifiLoggerHal.TX_PKT_FATE_ACKED, 2, WifiLoggerHal.FRAME_TYPE_ETHERNET_II,
                        new byte[0]
                );
                fates[1] = new WifiNative.TxFateReport(
                        WifiLoggerHal.TX_PKT_FATE_ACKED, 0, WifiLoggerHal.FRAME_TYPE_ETHERNET_II,
                        new byte[0]
                );
                return true;
            }
        });
        when(mWifiNative.getRxPktFates(any(), anyObject())).then(new AnswerWithArguments() {
            public boolean answer(String ifaceName, WifiNative.RxFateReport[] fates) {
                fates[0] = new WifiNative.RxFateReport(
                        WifiLoggerHal.RX_PKT_FATE_SUCCESS, 3, WifiLoggerHal.FRAME_TYPE_ETHERNET_II,
                        new byte[0]
                );
                fates[1] = new WifiNative.RxFateReport(
                        WifiLoggerHal.RX_PKT_FATE_SUCCESS, 1, WifiLoggerHal.FRAME_TYPE_ETHERNET_II,
                        new byte[0]
                );
                return true;
            }
        });
        mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED);

        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"});
        return sw.toString();
    }

      /**
     * Verifies that dump() shows both TX, and RX fates in only table form, when verbose
     * logging is not enabled.
     */
    @Test
    public void dumpShowsTxAndRxFates() {
        final boolean verbosityToggle = false;
        String dumpString = getDumpString(verbosityToggle);
        assertTrue(dumpString.contains(WifiNative.FateReport.getTableHeader()));
        assertTrue(Pattern.compile("0 .* TX ").matcher(dumpString).find());
        assertTrue(Pattern.compile("1 .* RX ").matcher(dumpString).find());
        assertTrue(Pattern.compile("2 .* TX ").matcher(dumpString).find());
        assertTrue(Pattern.compile("3 .* RX ").matcher(dumpString).find());
        assertFalse(dumpString.contains("VERBOSE PACKET FATE DUMP"));
        assertFalse(dumpString.contains("Frame bytes"));
    }

    /**
     * Verifies that dump() shows both TX, and RX fates in table and verbose forms, when verbose
     * logging is enabled.
     */
    @Test
    public void dumpShowsTxAndRxFatesVerbose() {
        final boolean verbosityToggle = true;
        String dumpString = getDumpString(verbosityToggle);
        assertTrue(dumpString.contains(WifiNative.FateReport.getTableHeader()));
        assertTrue(Pattern.compile("0 .* TX ").matcher(dumpString).find());
        assertTrue(Pattern.compile("1 .* RX ").matcher(dumpString).find());
        assertTrue(Pattern.compile("2 .* TX ").matcher(dumpString).find());
        assertTrue(Pattern.compile("3 .* RX ").matcher(dumpString).find());
        assertTrue(dumpString.contains("VERBOSE PACKET FATE DUMP"));
        assertTrue(dumpString.contains("Frame bytes"));
    }

    /**
     * Verifies that dump() outputs frames in timestamp order, even though the HAL provided the
     * data out-of-order (order is specified in getDumpString()).
     */
    @Test
    public void dumpIsSortedByTimestamp() {
        final boolean verbosityToggle = true;
        String dumpString = getDumpString(verbosityToggle);
        assertTrue(dumpString.contains(WifiNative.FateReport.getTableHeader()));
        assertTrue(Pattern.compile(
                "0 .* TX .*\n" +
                "1 .* RX .*\n" +
                "2 .* TX .*\n" +
                "3 .* RX "
        ).matcher(dumpString).find());

        int expected_index_of_verbose_frame_0 = dumpString.indexOf(
                "Frame direction: TX\nFrame timestamp: 0\n");
        int expected_index_of_verbose_frame_1 = dumpString.indexOf(
                "Frame direction: RX\nFrame timestamp: 1\n");
        int expected_index_of_verbose_frame_2 = dumpString.indexOf(
                "Frame direction: TX\nFrame timestamp: 2\n");
        int expected_index_of_verbose_frame_3 = dumpString.indexOf(
                "Frame direction: RX\nFrame timestamp: 3\n");
        assertFalse(-1 == expected_index_of_verbose_frame_0);
        assertFalse(-1 == expected_index_of_verbose_frame_1);
        assertFalse(-1 == expected_index_of_verbose_frame_2);
        assertFalse(-1 == expected_index_of_verbose_frame_3);
        assertTrue(expected_index_of_verbose_frame_0 < expected_index_of_verbose_frame_1);
        assertTrue(expected_index_of_verbose_frame_1 < expected_index_of_verbose_frame_2);
        assertTrue(expected_index_of_verbose_frame_2 < expected_index_of_verbose_frame_3);
    }

    /** Verifies that eng builds do not show fate detail outside of verbose mode. */
    @Test
    public void dumpOmitsFateDetailInEngBuildsOutsideOfVerboseMode() throws Exception {
        final boolean verbosityToggle = false;
        when(mBuildProperties.isEngBuild()).thenReturn(true);
        when(mBuildProperties.isUserdebugBuild()).thenReturn(false);
        when(mBuildProperties.isUserBuild()).thenReturn(false);
        String dumpString = getDumpString(verbosityToggle);
        assertFalse(dumpString.contains("VERBOSE PACKET FATE DUMP"));
        assertFalse(dumpString.contains("Frame bytes"));
    }

    /** Verifies that userdebug builds do not show fate detail outside of verbose mode. */
    @Test
    public void dumpOmitsFateDetailInUserdebugBuildsOutsideOfVerboseMode() throws Exception {
        final boolean verbosityToggle = false;
        when(mBuildProperties.isUserdebugBuild()).thenReturn(true);
        when(mBuildProperties.isEngBuild()).thenReturn(false);
        when(mBuildProperties.isUserBuild()).thenReturn(false);
        String dumpString = getDumpString(verbosityToggle);
        assertFalse(dumpString.contains("VERBOSE PACKET FATE DUMP"));
        assertFalse(dumpString.contains("Frame bytes"));
    }

    /**
     * Verifies that, if verbose is disabled after fetching fates, the dump does not include
     * verbose fate logs.
     */
    @Test
    public void dumpOmitsFatesIfVerboseIsDisabledAfterFetch() {
        final boolean verbosityToggle = true;
        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME);
        when(mWifiNative.getTxPktFates(any(), anyObject())).then(new AnswerWithArguments() {
            public boolean answer(String ifaceName, WifiNative.TxFateReport[] fates) {
                fates[0] = new WifiNative.TxFateReport(
                        WifiLoggerHal.TX_PKT_FATE_ACKED, 0, WifiLoggerHal.FRAME_TYPE_ETHERNET_II,
                        new byte[0]
                );
                return true;
            }
        });
        when(mWifiNative.getRxPktFates(any(), anyObject())).then(new AnswerWithArguments() {
            public boolean answer(String ifaceName, WifiNative.RxFateReport[] fates) {
                fates[0] = new WifiNative.RxFateReport(
                        WifiLoggerHal.RX_PKT_FATE_SUCCESS, 1, WifiLoggerHal.FRAME_TYPE_ETHERNET_II,
                        new byte[0]
                );
                return true;
            }
        });
        mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED);
        verify(mWifiNative).getTxPktFates(any(), anyObject());
        verify(mWifiNative).getRxPktFates(any(), anyObject());

        final boolean newVerbosityToggle = false;
        mWifiDiagnostics.enableVerboseLogging(newVerbosityToggle);
        mWifiDiagnostics.startLogging(STA_IF_NAME);

        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"});

        String fateDumpString = sw.toString();
        assertFalse(fateDumpString.contains("VERBOSE PACKET FATE DUMP"));
        assertFalse(fateDumpString.contains("Frame bytes"));
    }

    /** Verifies that the default size of our ring buffers is small. */
    @Ignore("TODO(b/36811399): re-enable this @Test")
    @Test
    public void ringBufferSizeIsSmallByDefault() throws Exception {
        final boolean verbosityToggle = false;
        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        mWifiDiagnostics.onRingBufferData(
                mFakeRbs, new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE + 1]);
        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
        assertEquals(0, getLoggerRingBufferData().length);
    }

    /** Verifies that we use small ring buffers by default, on userdebug builds. */
    @Ignore("TODO(b/36811399): re-enable this @Test")
    @Test
    public void ringBufferSizeIsSmallByDefaultOnUserdebugBuilds() throws Exception {
        final boolean verbosityToggle = false;
        when(mBuildProperties.isUserdebugBuild()).thenReturn(true);
        when(mBuildProperties.isEngBuild()).thenReturn(false);
        when(mBuildProperties.isUserBuild()).thenReturn(false);
        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        mWifiDiagnostics.onRingBufferData(
                mFakeRbs, new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE + 1]);
        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
        assertEquals(0, getLoggerRingBufferData().length);
    }

    /** Verifies that we use small ring buffers by default, on eng builds. */
    @Ignore("TODO(b/36811399): re-enable this @Test")
    @Test
    public void ringBufferSizeIsSmallByDefaultOnEngBuilds() throws Exception {
        final boolean verbosityToggle = false;
        when(mBuildProperties.isEngBuild()).thenReturn(true);
        when(mBuildProperties.isUserdebugBuild()).thenReturn(false);
        when(mBuildProperties.isUserBuild()).thenReturn(false);
        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        mWifiDiagnostics.onRingBufferData(
                mFakeRbs, new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE + 1]);
        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
        assertEquals(0, getLoggerRingBufferData().length);
    }

    /** Verifies that we use large ring buffers when initially started in verbose mode. */
    @Test
    public void ringBufferSizeIsLargeInVerboseMode() throws Exception {
        final boolean verbosityToggle = true;

        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        mWifiDiagnostics.onRingBufferData(
                mFakeRbs, new byte[LARGE_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE]);
        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
        assertEquals(1, getLoggerRingBufferData().length);
    }

    /** Verifies that we use large ring buffers when switched from normal to verbose mode. */
    @Test
    public void startLoggingGrowsRingBuffersIfNeeded() throws Exception {
        mWifiDiagnostics.enableVerboseLogging(false /* verbose disabled */);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        mWifiDiagnostics.onRingBufferData(
                mFakeRbs, new byte[LARGE_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE]);
        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
        assertEquals(1, getLoggerRingBufferData().length);
    }

    /** Verifies that we use small ring buffers when switched from verbose to normal mode. */
    @Ignore("TODO(b/36811399): re-enabled this @Test")
    @Test
    public void startLoggingShrinksRingBuffersIfNeeded() throws Exception {

        mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        mWifiDiagnostics.onRingBufferData(
                mFakeRbs, new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE + 1]);

        // Existing data is nuked (too large).
        mWifiDiagnostics.enableVerboseLogging(false /* verbose disabled */);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
        assertEquals(0, getLoggerRingBufferData().length);

        // New data must obey limit as well.
        mWifiDiagnostics.onRingBufferData(
                mFakeRbs, new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE + 1]);
        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
        assertEquals(0, getLoggerRingBufferData().length);
    }

    /**
     * Verifies that we capture a bugreport & store alert data when WifiNative invokes
     * the alert callback.
     */
    @Test
    public void onWifiAlertCapturesBugreportAndLogsMetrics() throws Exception {
        mWifiDiagnostics.onWifiAlert(ALERT_REASON_CODE, ALERT_DATA);

        assertEquals(1, mWifiDiagnostics.getAlertReports().size());
        WifiDiagnostics.BugReport alertReport = mWifiDiagnostics.getAlertReports().get(0);
        assertEquals(ALERT_REASON_CODE, alertReport.errorCode);
        assertArrayEquals(ALERT_DATA, alertReport.alertData);

        verify(mWifiMetrics).logFirmwareAlert(ALERT_REASON_CODE);
        verify(mWifiScoreCard).noteFirmwareAlert(ALERT_REASON_CODE);
    }

    /** Verifies that we skip the firmware and driver dumps if verbose is not enabled. */
    @Test
    public void captureBugReportSkipsFirmwareAndDriverDumpsByDefault() {
        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
        verify(mWifiNative, never()).getFwMemoryDump();
        verify(mWifiNative, never()).getDriverStateDump();
    }

    /** Verifies that we capture the firmware and driver dumps if verbose is enabled. */
    @Test
    public void captureBugReportTakesFirmwareAndDriverDumpsInVerboseMode() {
        mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
        verify(mWifiNative).getFwMemoryDump();
        verify(mWifiNative).getDriverStateDump();
    }

    /** Verifies that the dump includes driver state, if driver state was provided by HAL. */
    @Test
    public void dumpIncludesDriverStateDumpIfAvailable() {
        when(mWifiNative.getDriverStateDump()).thenReturn(new byte[]{0, 1, 2});

        mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
        verify(mWifiNative).getDriverStateDump();

        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{});
        assertTrue(sw.toString().contains(WifiDiagnostics.DRIVER_DUMP_SECTION_HEADER));
    }

    /** Verifies that the dump skips driver state, if driver state was not provided by HAL. */
    @Test
    public void dumpOmitsDriverStateDumpIfUnavailable() {
        mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
        verify(mWifiNative).getDriverStateDump();

        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{});
        assertFalse(sw.toString().contains(WifiDiagnostics.DRIVER_DUMP_SECTION_HEADER));
    }

    /** Verifies that the dump omits driver state, if verbose was disabled after capture. */
    @Test
    public void dumpOmitsDriverStateDumpIfVerboseDisabledAfterCapture() {
        when(mWifiNative.getDriverStateDump()).thenReturn(new byte[]{0, 1, 2});

        mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
        verify(mWifiNative).getDriverStateDump();

        mWifiDiagnostics.enableVerboseLogging(false /* verbose disabled */);
        mWifiDiagnostics.startLogging(STA_IF_NAME);

        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{});
        assertFalse(sw.toString().contains(WifiDiagnostics.DRIVER_DUMP_SECTION_HEADER));
    }

    /** Verifies that the dump includes firmware dump, if firmware dump was provided by HAL. */
    @Test
    public void dumpIncludesFirmwareMemoryDumpIfAvailable() {
        when(mWifiNative.getFwMemoryDump()).thenReturn(new byte[]{0, 1, 2});

        mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
        verify(mWifiNative).getFwMemoryDump();

        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{});
        assertTrue(sw.toString().contains(WifiDiagnostics.FIRMWARE_DUMP_SECTION_HEADER));
    }

    /** Verifies that the dump skips firmware memory, if firmware memory was not provided by HAL. */
    @Test
    public void dumpOmitsFirmwareMemoryDumpIfUnavailable() {
        mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
        verify(mWifiNative).getFwMemoryDump();

        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{});
        assertFalse(sw.toString().contains(WifiDiagnostics.FIRMWARE_DUMP_SECTION_HEADER));
    }

    /** Verifies that the dump omits firmware memory, if verbose was disabled after capture. */
    @Test
    public void dumpOmitsFirmwareMemoryDumpIfVerboseDisabledAfterCapture() {
        when(mWifiNative.getFwMemoryDump()).thenReturn(new byte[]{0, 1, 2});

        mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
        verify(mWifiNative).getFwMemoryDump();

        mWifiDiagnostics.enableVerboseLogging(false /* verbose disabled */);
        mWifiDiagnostics.startLogging(STA_IF_NAME);

        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{});
        assertFalse(sw.toString().contains(WifiDiagnostics.FIRMWARE_DUMP_SECTION_HEADER));
    }

    @Test
    public void dumpRequestsLastMileLoggerDump() {
        mWifiDiagnostics.dump(
                new FileDescriptor(), new PrintWriter(new StringWriter()), new String[]{});
        verify(mLastMileLogger).dump(anyObject());
    }

    @Test
    public void takeBugReportCallsActivityManagerOnUserDebug() {
        when(mBuildProperties.isUserBuild()).thenReturn(false);
        mWifiDiagnostics.takeBugReport("", "");
        verify(mBugreportManager, times(1)).requestBugreport(any(), any(), any());
    }

    @Test
    public void takeBugReportSwallowsExceptions() {
        when(mBuildProperties.isUserBuild()).thenReturn(false);
        doThrow(new RuntimeException()).when(mBugreportManager).requestBugreport(
                any(), any(), any());
        mWifiDiagnostics.takeBugReport("", "");
        verify(mBugreportManager, times(1)).requestBugreport(any(), any(), any());
    }

    @Test
    public void takeBugReportDoesNothingOnUserBuild() {
        when(mBuildProperties.isUserBuild()).thenReturn(true);
        mWifiDiagnostics.takeBugReport("", "");
        verify(mBugreportManager, never()).requestBugreport(any(), any(), any());
    }

    @Test
    public void tryTakeBugReportTwiceWithInsufficientTimeGap() {
        when(mBuildProperties.isUserBuild()).thenReturn(false);
        // 1st attempt should succeed
        when(mClock.getWallClockMillis()).thenReturn(10L);
        mWifiDiagnostics.takeBugReport("", "");
        verify(mBugreportManager, times(1)).requestBugreport(any(), any(), any());
        // 2nd attempt should fail
        when(mClock.getWallClockMillis()).thenReturn(BUG_REPORT_MIN_WINDOW_MS - 20L);
        mWifiDiagnostics.takeBugReport("", "");
        verify(mBugreportManager, times(1)).requestBugreport(any(), any(), any());
    }

    @Test
    public void takeBugReportDoesNothingWhenConfigOverlayDisabled() {
        when(mBuildProperties.isUserBuild()).thenReturn(false);
        mResources.setBoolean(R.bool.config_wifi_diagnostics_bugreport_enabled, false);
        mWifiDiagnostics = new WifiDiagnostics(
                mContext, mWifiInjector, mWifiNative, mBuildProperties, mLastMileLogger, mClock);

        mWifiDiagnostics.takeBugReport("", "");
        verify(mBugreportManager, never()).requestBugreport(any(), any(), any());
    }

    /** Verifies that we flush HAL ringbuffer when capture bugreport. */
    @Test
    public void captureBugReportFlushRingBufferData() {
        when(mBuildProperties.isUserBuild()).thenReturn(false);
        when(mWifiNative.flushRingBufferData()).thenReturn(true);
        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
        verify(mWifiNative).flushRingBufferData();
    }

    /** Verifies that we flush HAL ringbuffer when detecting fatal firmware alert. */
    @Test
    public void captureAlertFlushRingBufferData() {
        when(mBuildProperties.isUserBuild()).thenReturn(false);
        when(mWifiNative.flushRingBufferData()).thenReturn(true);
        /** captureAlertData with mock fatal firmware alert*/
        mWifiDiagnostics.captureAlertData(FATAL_FW_ALERT_LIST[0], ALERT_DATA);
        verify(mWifiNative).flushRingBufferData();
    }

    /** Verifies that we don't flush HAL ringbuffer when detecting non fatal firmware alert. */
    @Test
    public void captureNonAlertFlushRingBufferData() {
        when(mBuildProperties.isUserBuild()).thenReturn(false);
        when(mWifiNative.flushRingBufferData()).thenReturn(true);
        /** captureAlertData with mock non fatal firmware alert*/
        mWifiDiagnostics.captureAlertData(NON_FATAL_FW_ALERT, ALERT_DATA);
        verify(mWifiNative, never()).flushRingBufferData();
    }

    /**
     * Verifies that we can capture ring-buffer data in SoftAp mode
     */
    @Test
    public void canCaptureAndStoreRingBufferDataInSoftApMode() throws Exception {
        final boolean verbosityToggle = false;

        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startLogging(AP_IF_NAME);

        final byte[] data = new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE];
        mWifiDiagnostics.onRingBufferData(mFakeRbs, data);
        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);

        byte[][] ringBufferData = getLoggerRingBufferData();
        assertEquals(1, ringBufferData.length);
        assertArrayEquals(data, ringBufferData[0]);
    }

    /**
     * Verifies that we capture ring-buffer data in Station + SoftAp
     * Concurrency mode.
     */
    @Test
    public void canCaptureAndStoreRingBufferDataInConcurrencyMode() throws Exception {
        final boolean verbosityToggle = false;

        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        mWifiDiagnostics.startLogging(AP_IF_NAME);

        final byte[] data = new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE];
        mWifiDiagnostics.onRingBufferData(mFakeRbs, data);
        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);

        byte[][] ringBufferData = getLoggerRingBufferData();
        assertEquals(1, ringBufferData.length);
        assertArrayEquals(data, ringBufferData[0]);
    }

    /**
     * Verifies that we can continue to capture ring-buffer data
     * after WiFi station is turned off in concurrency mode.
     */
    @Test
    public void canCaptureAndStoreRingBufferDataAfterStaIsTurnedOffInConcurrencyMode()
            throws Exception {
        final boolean verbosityToggle = false;
        final byte[] data = new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE];

        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        mWifiDiagnostics.startLogging(AP_IF_NAME);

        mWifiDiagnostics.onRingBufferData(mFakeRbs, data);
        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);

        byte[][] ringBufferData0 = getLoggerRingBufferData();
        assertEquals(1, ringBufferData0.length);
        assertArrayEquals(data, ringBufferData0[0]);

        mWifiDiagnostics.stopLogging(STA_IF_NAME);

        mWifiDiagnostics.onRingBufferData(mFakeRbs, data);
        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);

        byte[][] ringBufferData1 = getLoggerRingBufferData();
        assertEquals(1, ringBufferData1.length);
        assertArrayEquals(data, ringBufferData1[0]);
    }

    /**
     * Verifies that we can continue to capture ring-buffer data
     * after SoftAp is turned off in concurrency mode.
     */
    @Test
    public void canCaptureAndStoreRingBufferDataAfterSoftApIsTurnedOffInConcurrencyMode()
            throws Exception {
        final boolean verbosityToggle = false;
        final byte[] data = new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE];

        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        mWifiDiagnostics.startLogging(STA_IF_NAME);
        mWifiDiagnostics.startLogging(AP_IF_NAME);

        mWifiDiagnostics.onRingBufferData(mFakeRbs, data);
        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);

        byte[][] ringBufferData0 = getLoggerRingBufferData();
        assertEquals(1, ringBufferData0.length);
        assertArrayEquals(data, ringBufferData0[0]);

        mWifiDiagnostics.stopLogging(AP_IF_NAME);

        mWifiDiagnostics.onRingBufferData(mFakeRbs, data);
        mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);

        byte[][] ringBufferData1 = getLoggerRingBufferData();
        assertEquals(1, ringBufferData1.length);
        assertArrayEquals(data, ringBufferData1[0]);
    }

    /** Verifies that stoplogging on both the interfaces clean up
     *  all the resources.
     */
    @Test
    public void verifyStopLoggingOnAllInterfacesClearTheResources() throws Exception {
        final boolean verbosityToggle = false;

        mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
        when(mWifiNative.setLoggingEventHandler(any())).thenReturn(true);
        when(mWifiNative.resetLogHandler()).thenReturn(true);

        mWifiDiagnostics.startLogging(STA_IF_NAME);
        verify(mWifiNative).setLoggingEventHandler(any());

        mWifiDiagnostics.startLogging(AP_IF_NAME);

        mWifiDiagnostics.stopLogging(STA_IF_NAME);
        verify(mWifiNative, never()).resetLogHandler();

        mWifiDiagnostics.stopLogging(AP_IF_NAME);

        verify(mWifiNative).resetLogHandler();
    }
}
