blob: 55dc683c7215a1fadb53cfe1693896a9cf1c008d [file] [log] [blame]
/*
* 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));
}
}