/* * 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 android.test.suitebuilder.annotation.SmallTest; 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.Mockito.anyInt; import static org.mockito.Mockito.anyObject; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import com.android.server.wifi.MockAnswerUtil.AnswerWithArguments; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.io.FileDescriptor; import java.io.PrintWriter; import java.io.StringWriter; import java.util.regex.Pattern; /** * Unit tests for {@link com.android.server.wifi.WifiLogger}. */ @SmallTest public class WifiLoggerTest { public static final String TAG = "WifiLoggerTest"; @Mock WifiStateMachine mWsm; @Mock WifiNative mWifiNative; @Mock BuildProperties mBuildProperties; WifiLogger mWifiLogger; private static final String FAKE_RING_BUFFER_NAME = "fake-ring-buffer"; 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 mWifiLogger.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(mWifiNative.readKernelLog()).thenReturn(""); when(mBuildProperties.isEngBuild()).thenReturn(false); when(mBuildProperties.isUserdebugBuild()).thenReturn(false); when(mBuildProperties.isUserBuild()).thenReturn(true); mWifiLogger = new WifiLogger(mWsm, mWifiNative, mBuildProperties); mWifiNative.enableVerboseLogging(0); } /** Verifies that startLogging() registers a logging event handler. */ @Test public void startLoggingRegistersLogEventHandler() throws Exception { final boolean verbosityToggle = false; // even default mode wants log events from HAL mWifiLogger.startLogging(verbosityToggle); 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 wants log events from HAL when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(false); mWifiLogger.startLogging(verbosityToggle); verify(mWifiNative).setLoggingEventHandler(anyObject()); reset(mWifiNative); when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(true); mWifiLogger.startLogging(verbosityToggle); verify(mWifiNative).setLoggingEventHandler(anyObject()); } /** Verifies that startLogging() does not make redundant calls to setLoggingEventHandler(). */ @Test public void startLoggingDoesNotRegisterLogEventHandlerIfPriorAttemptSucceeded() throws Exception { final boolean verbosityToggle = false; // even default mode wants log events from HAL when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(true); mWifiLogger.startLogging(verbosityToggle); verify(mWifiNative).setLoggingEventHandler(anyObject()); reset(mWifiNative); mWifiLogger.startLogging(verbosityToggle); 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 startLoggingStopsAndRestartsRingBufferLogging() throws Exception { final boolean verbosityToggle = false; mWifiLogger.startLogging(verbosityToggle); verify(mWifiNative).startLoggingRingBuffer( eq(WifiLogger.VERBOSE_NO_LOG), anyInt(), anyInt(), anyInt(), eq(FAKE_RING_BUFFER_NAME)); verify(mWifiNative).startLoggingRingBuffer( eq(WifiLogger.VERBOSE_NORMAL_LOG), anyInt(), anyInt(), anyInt(), eq(FAKE_RING_BUFFER_NAME)); } /** 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 wants log events from HAL when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(true); mWifiLogger.startLogging(verbosityToggle); reset(mWifiNative); mWifiLogger.stopLogging(); verify(mWifiNative).resetLogHandler(); } /** Verifies that, if a log handler is not registered, stopLogging() skips resetLogHandler(). */ @Test public void stopLoggingOnlyResetsLogHandlerIfHandlerWasRegistered() throws Exception { final boolean verbosityToggle = false; // even default mode wants log events from HAL mWifiLogger.stopLogging(); 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 wants log events from HAL when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(true); mWifiLogger.startLogging(verbosityToggle); reset(mWifiNative); when(mWifiNative.resetLogHandler()).thenReturn(true); mWifiLogger.stopLogging(); verify(mWifiNative).resetLogHandler(); reset(mWifiNative); mWifiLogger.stopLogging(); verify(mWifiNative, never()).resetLogHandler(); } /** * Verifies that we capture ring-buffer data. */ @Test public void canCaptureAndStoreRingBufferData() throws Exception { final boolean verbosityToggle = false; mWifiLogger.startLogging(verbosityToggle); final byte[] data = new byte[WifiLogger.RING_BUFFER_BYTE_LIMIT_SMALL]; mWifiLogger.onRingBufferData(mFakeRbs, data); mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_NONE); byte[][] ringBufferData = getLoggerRingBufferData(); assertEquals(1, ringBufferData.length); assertArrayEquals(data, ringBufferData[0]); } /** * Verifies that we discard extraneous ring-buffer data. */ @Test public void loggerDiscardsExtraneousData() throws Exception { final boolean verbosityToggle = false; mWifiLogger.startLogging(verbosityToggle); final byte[] data1 = new byte[WifiLogger.RING_BUFFER_BYTE_LIMIT_SMALL]; final byte[] data2 = {1, 2, 3}; mWifiLogger.onRingBufferData(mFakeRbs, data1); mWifiLogger.onRingBufferData(mFakeRbs, data2); mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_NONE); byte[][] ringBufferData = getLoggerRingBufferData(); assertEquals(1, ringBufferData.length); assertArrayEquals(data2, ringBufferData[0]); } /** * Verifies that, when verbose mode is not enabled, startLogging() calls * startPktFateMonitoring(). */ @Test public void startLoggingStartsPacketFateWithoutVerboseMode() { final boolean verbosityToggle = false; mWifiLogger.startLogging(verbosityToggle); verify(mWifiNative).startPktFateMonitoring(); } /** * Verifies that, when verbose mode is enabled, startLogging() calls * startPktFateMonitoring(). */ @Test public void startLoggingStartsPacketFateInVerboseMode() { final boolean verbosityToggle = true; mWifiLogger.startLogging(verbosityToggle); verify(mWifiNative).startPktFateMonitoring(); } /** * Verifies that, when verbose mode is not enabled, reportConnectionFailure() still * fetches packet fates. */ @Test public void reportConnectionFailureIsIgnoredWithoutVerboseMode() { final boolean verbosityToggle = false; mWifiLogger.startLogging(verbosityToggle); mWifiLogger.reportConnectionFailure(); verify(mWifiNative).getTxPktFates(anyObject()); verify(mWifiNative).getRxPktFates(anyObject()); } /** * Verifies that, when verbose mode is enabled, reportConnectionFailure() fetches packet fates. */ @Test public void reportConnectionFailureFetchesFatesInVerboseMode() { final boolean verbosityToggle = true; mWifiLogger.startLogging(verbosityToggle); mWifiLogger.reportConnectionFailure(); verify(mWifiNative).getTxPktFates(anyObject()); verify(mWifiNative).getRxPktFates(anyObject()); } /** * 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(anyObject())).thenReturn(false); mWifiLogger.startLogging(verbosityToggle); mWifiLogger.reportConnectionFailure(); verify(mWifiNative).getTxPktFates(anyObject()); verify(mWifiNative).getRxPktFates(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(anyObject())).thenReturn(false); mWifiLogger.startLogging(verbosityToggle); mWifiLogger.reportConnectionFailure(); verify(mWifiNative).getTxPktFates(anyObject()); verify(mWifiNative).getRxPktFates(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); mWifiLogger.startLogging(verbosityToggle); mWifiLogger.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"}); verify(mWifiNative).getTxPktFates(anyObject()); verify(mWifiNative).getRxPktFates(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); mWifiLogger.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; mWifiLogger.startLogging(verbosityToggle); mWifiLogger.reportConnectionFailure(); verify(mWifiNative).getTxPktFates(anyObject()); verify(mWifiNative).getRxPktFates(anyObject()); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); mWifiLogger.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) { mWifiLogger.startLogging(verbose); mWifiNative.enableVerboseLogging(verbose ? 1 : 0); when(mWifiNative.getTxPktFates(anyObject())).then(new AnswerWithArguments() { public boolean answer(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(anyObject())).then(new AnswerWithArguments() { public boolean answer(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; } }); mWifiLogger.reportConnectionFailure(); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); mWifiLogger.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; mWifiLogger.startLogging(verbosityToggle); when(mWifiNative.getTxPktFates(anyObject())).then(new AnswerWithArguments() { public boolean answer(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(anyObject())).then(new AnswerWithArguments() { public boolean answer(WifiNative.RxFateReport[] fates) { fates[0] = new WifiNative.RxFateReport( WifiLoggerHal.RX_PKT_FATE_SUCCESS, 1, WifiLoggerHal.FRAME_TYPE_ETHERNET_II, new byte[0] ); return true; } }); mWifiLogger.reportConnectionFailure(); verify(mWifiNative).getTxPktFates(anyObject()); verify(mWifiNative).getRxPktFates(anyObject()); final boolean newVerbosityToggle = false; mWifiLogger.startLogging(newVerbosityToggle); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); mWifiLogger.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. */ @Test public void ringBufferSizeIsSmallByDefault() throws Exception { final boolean verbosityToggle = false; mWifiLogger.startLogging(verbosityToggle); mWifiLogger.onRingBufferData( mFakeRbs, new byte[WifiLogger.RING_BUFFER_BYTE_LIMIT_SMALL + 1]); mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_NONE); assertEquals(0, getLoggerRingBufferData().length); } /** Verifies that we use small ring buffers by default, on userdebug builds. */ @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); mWifiLogger.startLogging(verbosityToggle); mWifiLogger.onRingBufferData( mFakeRbs, new byte[WifiLogger.RING_BUFFER_BYTE_LIMIT_SMALL + 1]); mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_NONE); assertEquals(0, getLoggerRingBufferData().length); } /** Verifies that we use small ring buffers by default, on eng builds. */ @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); mWifiLogger.startLogging(verbosityToggle); mWifiLogger.onRingBufferData( mFakeRbs, new byte[WifiLogger.RING_BUFFER_BYTE_LIMIT_SMALL + 1]); mWifiLogger.captureBugReportData(WifiLogger.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; mWifiLogger.startLogging(verbosityToggle); mWifiLogger.onRingBufferData(mFakeRbs, new byte[WifiLogger.RING_BUFFER_BYTE_LIMIT_LARGE]); mWifiLogger.captureBugReportData(WifiLogger.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 { mWifiLogger.startLogging(false /* verbose disabled */); mWifiLogger.startLogging(true /* verbose enabled */); mWifiLogger.onRingBufferData(mFakeRbs, new byte[WifiLogger.RING_BUFFER_BYTE_LIMIT_LARGE]); mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_NONE); assertEquals(1, getLoggerRingBufferData().length); } /** Verifies that we use small ring buffers when switched from verbose to normal mode. */ @Test public void startLoggingShrinksRingBuffersIfNeeded() throws Exception { mWifiLogger.startLogging(true /* verbose enabled */); mWifiLogger.onRingBufferData( mFakeRbs, new byte[WifiLogger.RING_BUFFER_BYTE_LIMIT_SMALL + 1]); // Existing data is nuked (too large). mWifiLogger.startLogging(false /* verbose disabled */); mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_NONE); assertEquals(0, getLoggerRingBufferData().length); // New data must obey limit as well. mWifiLogger.onRingBufferData( mFakeRbs, new byte[WifiLogger.RING_BUFFER_BYTE_LIMIT_SMALL + 1]); mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_NONE); assertEquals(0, getLoggerRingBufferData().length); } /** Verifies that we skip the firmware and driver dumps if verbose is not enabled. */ @Test public void captureBugReportSkipsFirmwareAndDriverDumpsByDefault() { mWifiLogger.captureBugReportData(WifiLogger.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() { mWifiLogger.startLogging(true /* verbose enabled */); mWifiLogger.captureBugReportData(WifiLogger.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}); mWifiLogger.startLogging(true /* verbose enabled */); mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_NONE); verify(mWifiNative).getDriverStateDump(); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); mWifiLogger.dump(new FileDescriptor(), pw, new String[]{}); assertTrue(sw.toString().contains(WifiLogger.DRIVER_DUMP_SECTION_HEADER)); } /** Verifies that the dump skips driver state, if driver state was not provided by HAL. */ @Test public void dumpOmitsDriverStateDumpIfUnavailable() { mWifiLogger.startLogging(true /* verbose enabled */); mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_NONE); verify(mWifiNative).getDriverStateDump(); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); mWifiLogger.dump(new FileDescriptor(), pw, new String[]{}); assertFalse(sw.toString().contains(WifiLogger.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}); mWifiLogger.startLogging(true /* verbose enabled */); mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_NONE); verify(mWifiNative).getDriverStateDump(); mWifiLogger.startLogging(false /* verbose no longer enabled */); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); mWifiLogger.dump(new FileDescriptor(), pw, new String[]{}); assertFalse(sw.toString().contains(WifiLogger.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}); mWifiLogger.startLogging(true /* verbose enabled */); mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_NONE); verify(mWifiNative).getFwMemoryDump(); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); mWifiLogger.dump(new FileDescriptor(), pw, new String[]{}); assertTrue(sw.toString().contains(WifiLogger.FIRMWARE_DUMP_SECTION_HEADER)); } /** Verifies that the dump skips firmware memory, if firmware memory was not provided by HAL. */ @Test public void dumpOmitsFirmwareMemoryDumpIfUnavailable() { mWifiLogger.startLogging(true /* verbose enabled */); mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_NONE); verify(mWifiNative).getFwMemoryDump(); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); mWifiLogger.dump(new FileDescriptor(), pw, new String[]{}); assertFalse(sw.toString().contains(WifiLogger.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}); mWifiLogger.startLogging(true /* verbose enabled */); mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_NONE); verify(mWifiNative).getFwMemoryDump(); mWifiLogger.startLogging(false /* verbose no longer enabled */); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); mWifiLogger.dump(new FileDescriptor(), pw, new String[]{}); assertFalse(sw.toString().contains(WifiLogger.FIRMWARE_DUMP_SECTION_HEADER)); } }