WifiDiagnosticsTest.java revision 019fda2109ea79daee3fb4442080b1b83be2e7b3
1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.wifi; 18 19import android.app.test.MockAnswerUtil.AnswerWithArguments; 20import android.content.Context; 21import android.test.suitebuilder.annotation.SmallTest; 22import com.android.internal.R; 23import android.util.LocalLog; 24 25import static org.junit.Assert.assertArrayEquals; 26import static org.junit.Assert.assertEquals; 27import static org.junit.Assert.assertFalse; 28import static org.junit.Assert.assertTrue; 29import static org.mockito.Mockito.anyInt; 30import static org.mockito.Mockito.anyObject; 31import static org.mockito.Mockito.eq; 32import static org.mockito.Mockito.never; 33import static org.mockito.Mockito.reset; 34import static org.mockito.Mockito.verify; 35import static org.mockito.Mockito.when; 36 37import org.junit.Before; 38import org.junit.Test; 39import org.mockito.Mock; 40import org.mockito.MockitoAnnotations; 41 42import java.io.FileDescriptor; 43import java.io.PrintWriter; 44import java.io.StringWriter; 45import java.util.regex.Pattern; 46 47/** 48 * Unit tests for {@link WifiDiagnostics}. 49 */ 50@SmallTest 51public class WifiDiagnosticsTest { 52 public static final String TAG = "WifiDiagsTest"; 53 54 @Mock WifiStateMachine mWsm; 55 @Mock WifiNative mWifiNative; 56 @Mock BuildProperties mBuildProperties; 57 @Mock Context mContext; 58 WifiDiagnostics mWifiDiagnostics; 59 60 private static final String FAKE_RING_BUFFER_NAME = "fake-ring-buffer"; 61 private static final int SMALL_RING_BUFFER_SIZE_KB = 32; 62 private static final int LARGE_RING_BUFFER_SIZE_KB = 1024; 63 private static final int BYTES_PER_KBYTE = 1024; 64 private LocalLog mWifiNativeLocalLog; 65 66 private WifiNative.RingBufferStatus mFakeRbs; 67 /** 68 * Returns the data that we would dump in a bug report, for our ring buffer. 69 * @return a 2-D byte array, where the first dimension is the record number, and the second 70 * dimension is the byte index within that record. 71 */ 72 private final byte[][] getLoggerRingBufferData() throws Exception { 73 return mWifiDiagnostics.getBugReports().get(0).ringBuffers.get(FAKE_RING_BUFFER_NAME); 74 } 75 76 /** 77 * Initializes common state (e.g. mocks) needed by test cases. 78 */ 79 @Before 80 public void setUp() throws Exception { 81 MockitoAnnotations.initMocks(this); 82 83 mFakeRbs = new WifiNative.RingBufferStatus(); 84 mFakeRbs.name = FAKE_RING_BUFFER_NAME; 85 WifiNative.RingBufferStatus[] ringBufferStatuses = new WifiNative.RingBufferStatus[] { 86 mFakeRbs 87 }; 88 mWifiNativeLocalLog = new LocalLog(8192); 89 90 when(mWifiNative.getRingBufferStatus()).thenReturn(ringBufferStatuses); 91 when(mWifiNative.readKernelLog()).thenReturn(""); 92 when(mWifiNative.getLocalLog()).thenReturn(mWifiNativeLocalLog); 93 when(mBuildProperties.isEngBuild()).thenReturn(false); 94 when(mBuildProperties.isUserdebugBuild()).thenReturn(false); 95 when(mBuildProperties.isUserBuild()).thenReturn(true); 96 97 MockResources resources = new MockResources(); 98 resources.setInteger(R.integer.config_wifi_logger_ring_buffer_default_size_limit_kb, 99 SMALL_RING_BUFFER_SIZE_KB); 100 resources.setInteger(R.integer.config_wifi_logger_ring_buffer_verbose_size_limit_kb, 101 LARGE_RING_BUFFER_SIZE_KB); 102 when(mContext.getResources()).thenReturn(resources); 103 104 mWifiDiagnostics = new WifiDiagnostics(mContext, mWsm, mWifiNative, mBuildProperties); 105 mWifiNative.enableVerboseLogging(0); 106 } 107 108 /** Verifies that startLogging() registers a logging event handler. */ 109 @Test 110 public void startLoggingRegistersLogEventHandler() throws Exception { 111 final boolean verbosityToggle = false; // even default mode wants log events from HAL 112 mWifiDiagnostics.startLogging(verbosityToggle); 113 verify(mWifiNative).setLoggingEventHandler(anyObject()); 114 } 115 116 /** 117 * Verifies that a failure to set the logging event handler does not prevent a future 118 * startLogging() from setting the logging event handler. 119 */ 120 @Test 121 public void startLoggingRegistersLogEventHandlerIfPriorAttemptFailed() 122 throws Exception { 123 final boolean verbosityToggle = false; // even default mode wants log events from HAL 124 125 when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(false); 126 mWifiDiagnostics.startLogging(verbosityToggle); 127 verify(mWifiNative).setLoggingEventHandler(anyObject()); 128 reset(mWifiNative); 129 130 when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(true); 131 mWifiDiagnostics.startLogging(verbosityToggle); 132 verify(mWifiNative).setLoggingEventHandler(anyObject()); 133 } 134 135 /** Verifies that startLogging() does not make redundant calls to setLoggingEventHandler(). */ 136 @Test 137 public void startLoggingDoesNotRegisterLogEventHandlerIfPriorAttemptSucceeded() 138 throws Exception { 139 final boolean verbosityToggle = false; // even default mode wants log events from HAL 140 141 when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(true); 142 mWifiDiagnostics.startLogging(verbosityToggle); 143 verify(mWifiNative).setLoggingEventHandler(anyObject()); 144 reset(mWifiNative); 145 146 mWifiDiagnostics.startLogging(verbosityToggle); 147 verify(mWifiNative, never()).setLoggingEventHandler(anyObject()); 148 } 149 150 /** 151 * Verifies that startLogging() restarts HAL ringbuffers. 152 * 153 * Specifically: verifies that startLogging() 154 * a) stops any ring buffer logging that might be already running, 155 * b) instructs WifiNative to enable ring buffers of the appropriate log level. 156 */ 157 @Test 158 public void startLoggingStopsAndRestartsRingBufferLogging() throws Exception { 159 final boolean verbosityToggle = false; 160 mWifiDiagnostics.startLogging(verbosityToggle); 161 verify(mWifiNative).startLoggingRingBuffer( 162 eq(WifiDiagnostics.VERBOSE_NO_LOG), anyInt(), anyInt(), anyInt(), 163 eq(FAKE_RING_BUFFER_NAME)); 164 verify(mWifiNative).startLoggingRingBuffer( 165 eq(WifiDiagnostics.VERBOSE_NORMAL_LOG), anyInt(), anyInt(), anyInt(), 166 eq(FAKE_RING_BUFFER_NAME)); 167 } 168 169 /** Verifies that, if a log handler was registered, then stopLogging() resets it. */ 170 @Test 171 public void stopLoggingResetsLogHandlerIfHandlerWasRegistered() throws Exception { 172 final boolean verbosityToggle = false; // even default mode wants log events from HAL 173 174 when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(true); 175 mWifiDiagnostics.startLogging(verbosityToggle); 176 reset(mWifiNative); 177 178 mWifiDiagnostics.stopLogging(); 179 verify(mWifiNative).resetLogHandler(); 180 } 181 182 /** Verifies that, if a log handler is not registered, stopLogging() skips resetLogHandler(). */ 183 @Test 184 public void stopLoggingOnlyResetsLogHandlerIfHandlerWasRegistered() throws Exception { 185 final boolean verbosityToggle = false; // even default mode wants log events from HAL 186 mWifiDiagnostics.stopLogging(); 187 verify(mWifiNative, never()).resetLogHandler(); 188 } 189 190 /** Verifies that stopLogging() remembers that we've reset the log handler. */ 191 @Test 192 public void multipleStopLoggingCallsOnlyResetLogHandlerOnce() throws Exception { 193 final boolean verbosityToggle = false; // even default mode wants log events from HAL 194 195 when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(true); 196 mWifiDiagnostics.startLogging(verbosityToggle); 197 reset(mWifiNative); 198 199 when(mWifiNative.resetLogHandler()).thenReturn(true); 200 mWifiDiagnostics.stopLogging(); 201 verify(mWifiNative).resetLogHandler(); 202 reset(mWifiNative); 203 204 mWifiDiagnostics.stopLogging(); 205 verify(mWifiNative, never()).resetLogHandler(); 206 } 207 208 /** 209 * Verifies that we capture ring-buffer data. 210 */ 211 @Test 212 public void canCaptureAndStoreRingBufferData() throws Exception { 213 final boolean verbosityToggle = false; 214 mWifiDiagnostics.startLogging(verbosityToggle); 215 216 final byte[] data = new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE]; 217 mWifiDiagnostics.onRingBufferData(mFakeRbs, data); 218 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); 219 220 byte[][] ringBufferData = getLoggerRingBufferData(); 221 assertEquals(1, ringBufferData.length); 222 assertArrayEquals(data, ringBufferData[0]); 223 } 224 225 /** 226 * Verifies that we discard extraneous ring-buffer data. 227 */ 228 @Test 229 public void loggerDiscardsExtraneousData() throws Exception { 230 final boolean verbosityToggle = false; 231 mWifiDiagnostics.startLogging(verbosityToggle); 232 233 final byte[] data1 = new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE]; 234 final byte[] data2 = {1, 2, 3}; 235 mWifiDiagnostics.onRingBufferData(mFakeRbs, data1); 236 mWifiDiagnostics.onRingBufferData(mFakeRbs, data2); 237 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); 238 239 byte[][] ringBufferData = getLoggerRingBufferData(); 240 assertEquals(1, ringBufferData.length); 241 assertArrayEquals(data2, ringBufferData[0]); 242 } 243 244 /** 245 * Verifies that, when verbose mode is not enabled, startLogging() calls 246 * startPktFateMonitoring(). 247 */ 248 @Test 249 public void startLoggingStartsPacketFateWithoutVerboseMode() { 250 final boolean verbosityToggle = false; 251 mWifiDiagnostics.startLogging(verbosityToggle); 252 verify(mWifiNative).startPktFateMonitoring(); 253 } 254 255 /** 256 * Verifies that, when verbose mode is enabled, startLogging() calls 257 * startPktFateMonitoring(). 258 */ 259 @Test 260 public void startLoggingStartsPacketFateInVerboseMode() { 261 final boolean verbosityToggle = true; 262 mWifiDiagnostics.startLogging(verbosityToggle); 263 verify(mWifiNative).startPktFateMonitoring(); 264 } 265 266 /** 267 * Verifies that, when verbose mode is not enabled, reportConnectionFailure() still 268 * fetches packet fates. 269 */ 270 @Test 271 public void reportConnectionFailureIsIgnoredWithoutVerboseMode() { 272 final boolean verbosityToggle = false; 273 mWifiDiagnostics.startLogging(verbosityToggle); 274 mWifiDiagnostics.reportConnectionFailure(); 275 verify(mWifiNative).getTxPktFates(anyObject()); 276 verify(mWifiNative).getRxPktFates(anyObject()); 277 } 278 279 /** 280 * Verifies that, when verbose mode is enabled, reportConnectionFailure() fetches packet fates. 281 */ 282 @Test 283 public void reportConnectionFailureFetchesFatesInVerboseMode() { 284 final boolean verbosityToggle = true; 285 mWifiDiagnostics.startLogging(verbosityToggle); 286 mWifiDiagnostics.reportConnectionFailure(); 287 verify(mWifiNative).getTxPktFates(anyObject()); 288 verify(mWifiNative).getRxPktFates(anyObject()); 289 } 290 291 /** 292 * Verifies that we try to fetch TX fates, even if fetching RX fates failed. 293 */ 294 @Test 295 public void loggerFetchesTxFatesEvenIfFetchingRxFatesFails() { 296 final boolean verbosityToggle = true; 297 when(mWifiNative.getRxPktFates(anyObject())).thenReturn(false); 298 mWifiDiagnostics.startLogging(verbosityToggle); 299 mWifiDiagnostics.reportConnectionFailure(); 300 verify(mWifiNative).getTxPktFates(anyObject()); 301 verify(mWifiNative).getRxPktFates(anyObject()); 302 } 303 304 /** 305 * Verifies that we try to fetch RX fates, even if fetching TX fates failed. 306 */ 307 @Test 308 public void loggerFetchesRxFatesEvenIfFetchingTxFatesFails() { 309 final boolean verbosityToggle = true; 310 when(mWifiNative.getTxPktFates(anyObject())).thenReturn(false); 311 mWifiDiagnostics.startLogging(verbosityToggle); 312 mWifiDiagnostics.reportConnectionFailure(); 313 verify(mWifiNative).getTxPktFates(anyObject()); 314 verify(mWifiNative).getRxPktFates(anyObject()); 315 } 316 317 /** Verifies that dump() fetches the latest fates. */ 318 @Test 319 public void dumpFetchesFates() { 320 final boolean verbosityToggle = false; 321 StringWriter sw = new StringWriter(); 322 PrintWriter pw = new PrintWriter(sw); 323 mWifiDiagnostics.startLogging(verbosityToggle); 324 mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"}); 325 verify(mWifiNative).getTxPktFates(anyObject()); 326 verify(mWifiNative).getRxPktFates(anyObject()); 327 } 328 329 /** 330 * Verifies that dump() doesn't crash, or generate garbage, in the case where we haven't fetched 331 * any fates. 332 */ 333 @Test 334 public void dumpSucceedsWhenNoFatesHaveNotBeenFetched() { 335 StringWriter sw = new StringWriter(); 336 PrintWriter pw = new PrintWriter(sw); 337 mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"}); 338 339 String fateDumpString = sw.toString(); 340 assertTrue(fateDumpString.contains("Last failed")); 341 // Verify dump terminator is present 342 assertTrue(fateDumpString.contains( 343 "--------------------------------------------------------------------")); 344 } 345 346 /** 347 * Verifies that dump() doesn't crash, or generate garbage, in the case where the fates that 348 * the HAL-provided fates are empty. 349 */ 350 @Test 351 public void dumpSucceedsWhenFatesHaveBeenFetchedButAreEmpty() { 352 final boolean verbosityToggle = true; 353 mWifiDiagnostics.startLogging(verbosityToggle); 354 mWifiDiagnostics.reportConnectionFailure(); 355 verify(mWifiNative).getTxPktFates(anyObject()); 356 verify(mWifiNative).getRxPktFates(anyObject()); 357 358 StringWriter sw = new StringWriter(); 359 PrintWriter pw = new PrintWriter(sw); 360 mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"}); 361 362 String fateDumpString = sw.toString(); 363 assertTrue(fateDumpString.contains("Last failed")); 364 // Verify dump terminator is present 365 assertTrue(fateDumpString.contains( 366 "--------------------------------------------------------------------")); 367 } 368 369 private String getDumpString(boolean verbose) { 370 mWifiDiagnostics.startLogging(verbose); 371 mWifiNative.enableVerboseLogging(verbose ? 1 : 0); 372 when(mWifiNative.getTxPktFates(anyObject())).then(new AnswerWithArguments() { 373 public boolean answer(WifiNative.TxFateReport[] fates) { 374 fates[0] = new WifiNative.TxFateReport( 375 WifiLoggerHal.TX_PKT_FATE_ACKED, 2, WifiLoggerHal.FRAME_TYPE_ETHERNET_II, 376 new byte[0] 377 ); 378 fates[1] = new WifiNative.TxFateReport( 379 WifiLoggerHal.TX_PKT_FATE_ACKED, 0, WifiLoggerHal.FRAME_TYPE_ETHERNET_II, 380 new byte[0] 381 ); 382 return true; 383 } 384 }); 385 when(mWifiNative.getRxPktFates(anyObject())).then(new AnswerWithArguments() { 386 public boolean answer(WifiNative.RxFateReport[] fates) { 387 fates[0] = new WifiNative.RxFateReport( 388 WifiLoggerHal.RX_PKT_FATE_SUCCESS, 3, WifiLoggerHal.FRAME_TYPE_ETHERNET_II, 389 new byte[0] 390 ); 391 fates[1] = new WifiNative.RxFateReport( 392 WifiLoggerHal.RX_PKT_FATE_SUCCESS, 1, WifiLoggerHal.FRAME_TYPE_ETHERNET_II, 393 new byte[0] 394 ); 395 return true; 396 } 397 }); 398 mWifiDiagnostics.reportConnectionFailure(); 399 400 StringWriter sw = new StringWriter(); 401 PrintWriter pw = new PrintWriter(sw); 402 mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"}); 403 return sw.toString(); 404 } 405 406 /** 407 * Verifies that dump() shows both TX, and RX fates in only table form, when verbose 408 * logging is not enabled. 409 */ 410 @Test 411 public void dumpShowsTxAndRxFates() { 412 final boolean verbosityToggle = false; 413 String dumpString = getDumpString(verbosityToggle); 414 assertTrue(dumpString.contains(WifiNative.FateReport.getTableHeader())); 415 assertTrue(Pattern.compile("0 .* TX ").matcher(dumpString).find()); 416 assertTrue(Pattern.compile("1 .* RX ").matcher(dumpString).find()); 417 assertTrue(Pattern.compile("2 .* TX ").matcher(dumpString).find()); 418 assertTrue(Pattern.compile("3 .* RX ").matcher(dumpString).find()); 419 assertFalse(dumpString.contains("VERBOSE PACKET FATE DUMP")); 420 assertFalse(dumpString.contains("Frame bytes")); 421 } 422 423 /** 424 * Verifies that dump() shows both TX, and RX fates in table and verbose forms, when verbose 425 * logging is enabled. 426 */ 427 @Test 428 public void dumpShowsTxAndRxFatesVerbose() { 429 final boolean verbosityToggle = true; 430 String dumpString = getDumpString(verbosityToggle); 431 assertTrue(dumpString.contains(WifiNative.FateReport.getTableHeader())); 432 assertTrue(Pattern.compile("0 .* TX ").matcher(dumpString).find()); 433 assertTrue(Pattern.compile("1 .* RX ").matcher(dumpString).find()); 434 assertTrue(Pattern.compile("2 .* TX ").matcher(dumpString).find()); 435 assertTrue(Pattern.compile("3 .* RX ").matcher(dumpString).find()); 436 assertTrue(dumpString.contains("VERBOSE PACKET FATE DUMP")); 437 assertTrue(dumpString.contains("Frame bytes")); 438 } 439 440 /** 441 * Verifies that dump() outputs frames in timestamp order, even though the HAL provided the 442 * data out-of-order (order is specified in getDumpString()). 443 */ 444 @Test 445 public void dumpIsSortedByTimestamp() { 446 final boolean verbosityToggle = true; 447 String dumpString = getDumpString(verbosityToggle); 448 assertTrue(dumpString.contains(WifiNative.FateReport.getTableHeader())); 449 assertTrue(Pattern.compile( 450 "0 .* TX .*\n" + 451 "1 .* RX .*\n" + 452 "2 .* TX .*\n" + 453 "3 .* RX " 454 ).matcher(dumpString).find()); 455 456 int expected_index_of_verbose_frame_0 = dumpString.indexOf( 457 "Frame direction: TX\nFrame timestamp: 0\n"); 458 int expected_index_of_verbose_frame_1 = dumpString.indexOf( 459 "Frame direction: RX\nFrame timestamp: 1\n"); 460 int expected_index_of_verbose_frame_2 = dumpString.indexOf( 461 "Frame direction: TX\nFrame timestamp: 2\n"); 462 int expected_index_of_verbose_frame_3 = dumpString.indexOf( 463 "Frame direction: RX\nFrame timestamp: 3\n"); 464 assertFalse(-1 == expected_index_of_verbose_frame_0); 465 assertFalse(-1 == expected_index_of_verbose_frame_1); 466 assertFalse(-1 == expected_index_of_verbose_frame_2); 467 assertFalse(-1 == expected_index_of_verbose_frame_3); 468 assertTrue(expected_index_of_verbose_frame_0 < expected_index_of_verbose_frame_1); 469 assertTrue(expected_index_of_verbose_frame_1 < expected_index_of_verbose_frame_2); 470 assertTrue(expected_index_of_verbose_frame_2 < expected_index_of_verbose_frame_3); 471 } 472 473 /** Verifies that eng builds do not show fate detail outside of verbose mode. */ 474 @Test 475 public void dumpOmitsFateDetailInEngBuildsOutsideOfVerboseMode() throws Exception { 476 final boolean verbosityToggle = false; 477 when(mBuildProperties.isEngBuild()).thenReturn(true); 478 when(mBuildProperties.isUserdebugBuild()).thenReturn(false); 479 when(mBuildProperties.isUserBuild()).thenReturn(false); 480 String dumpString = getDumpString(verbosityToggle); 481 assertFalse(dumpString.contains("VERBOSE PACKET FATE DUMP")); 482 assertFalse(dumpString.contains("Frame bytes")); 483 } 484 485 /** Verifies that userdebug builds do not show fate detail outside of verbose mode. */ 486 @Test 487 public void dumpOmitsFateDetailInUserdebugBuildsOutsideOfVerboseMode() throws Exception { 488 final boolean verbosityToggle = false; 489 when(mBuildProperties.isUserdebugBuild()).thenReturn(true); 490 when(mBuildProperties.isEngBuild()).thenReturn(false); 491 when(mBuildProperties.isUserBuild()).thenReturn(false); 492 String dumpString = getDumpString(verbosityToggle); 493 assertFalse(dumpString.contains("VERBOSE PACKET FATE DUMP")); 494 assertFalse(dumpString.contains("Frame bytes")); 495 } 496 497 /** 498 * Verifies that, if verbose is disabled after fetching fates, the dump does not include 499 * verbose fate logs. 500 */ 501 @Test 502 public void dumpOmitsFatesIfVerboseIsDisabledAfterFetch() { 503 final boolean verbosityToggle = true; 504 mWifiDiagnostics.startLogging(verbosityToggle); 505 when(mWifiNative.getTxPktFates(anyObject())).then(new AnswerWithArguments() { 506 public boolean answer(WifiNative.TxFateReport[] fates) { 507 fates[0] = new WifiNative.TxFateReport( 508 WifiLoggerHal.TX_PKT_FATE_ACKED, 0, WifiLoggerHal.FRAME_TYPE_ETHERNET_II, 509 new byte[0] 510 ); 511 return true; 512 } 513 }); 514 when(mWifiNative.getRxPktFates(anyObject())).then(new AnswerWithArguments() { 515 public boolean answer(WifiNative.RxFateReport[] fates) { 516 fates[0] = new WifiNative.RxFateReport( 517 WifiLoggerHal.RX_PKT_FATE_SUCCESS, 1, WifiLoggerHal.FRAME_TYPE_ETHERNET_II, 518 new byte[0] 519 ); 520 return true; 521 } 522 }); 523 mWifiDiagnostics.reportConnectionFailure(); 524 verify(mWifiNative).getTxPktFates(anyObject()); 525 verify(mWifiNative).getRxPktFates(anyObject()); 526 527 final boolean newVerbosityToggle = false; 528 mWifiDiagnostics.startLogging(newVerbosityToggle); 529 530 StringWriter sw = new StringWriter(); 531 PrintWriter pw = new PrintWriter(sw); 532 mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"}); 533 534 String fateDumpString = sw.toString(); 535 assertFalse(fateDumpString.contains("VERBOSE PACKET FATE DUMP")); 536 assertFalse(fateDumpString.contains("Frame bytes")); 537 } 538 539 /** Verifies that the default size of our ring buffers is small. */ 540 @Test 541 public void ringBufferSizeIsSmallByDefault() throws Exception { 542 final boolean verbosityToggle = false; 543 mWifiDiagnostics.startLogging(verbosityToggle); 544 mWifiDiagnostics.onRingBufferData( 545 mFakeRbs, new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE + 1]); 546 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); 547 assertEquals(0, getLoggerRingBufferData().length); 548 } 549 550 /** Verifies that we use small ring buffers by default, on userdebug builds. */ 551 @Test 552 public void ringBufferSizeIsSmallByDefaultOnUserdebugBuilds() throws Exception { 553 final boolean verbosityToggle = false; 554 when(mBuildProperties.isUserdebugBuild()).thenReturn(true); 555 when(mBuildProperties.isEngBuild()).thenReturn(false); 556 when(mBuildProperties.isUserBuild()).thenReturn(false); 557 mWifiDiagnostics.startLogging(verbosityToggle); 558 mWifiDiagnostics.onRingBufferData( 559 mFakeRbs, new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE + 1]); 560 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); 561 assertEquals(0, getLoggerRingBufferData().length); 562 } 563 564 /** Verifies that we use small ring buffers by default, on eng builds. */ 565 @Test 566 public void ringBufferSizeIsSmallByDefaultOnEngBuilds() throws Exception { 567 final boolean verbosityToggle = false; 568 when(mBuildProperties.isEngBuild()).thenReturn(true); 569 when(mBuildProperties.isUserdebugBuild()).thenReturn(false); 570 when(mBuildProperties.isUserBuild()).thenReturn(false); 571 mWifiDiagnostics.startLogging(verbosityToggle); 572 mWifiDiagnostics.onRingBufferData( 573 mFakeRbs, new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE + 1]); 574 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); 575 assertEquals(0, getLoggerRingBufferData().length); 576 } 577 578 /** Verifies that we use large ring buffers when initially started in verbose mode. */ 579 @Test 580 public void ringBufferSizeIsLargeInVerboseMode() throws Exception { 581 final boolean verbosityToggle = true; 582 mWifiDiagnostics.startLogging(verbosityToggle); 583 mWifiDiagnostics.onRingBufferData( 584 mFakeRbs, new byte[LARGE_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE]); 585 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); 586 assertEquals(1, getLoggerRingBufferData().length); 587 } 588 589 /** Verifies that we use large ring buffers when switched from normal to verbose mode. */ 590 @Test 591 public void startLoggingGrowsRingBuffersIfNeeded() throws Exception { 592 mWifiDiagnostics.startLogging(false /* verbose disabled */); 593 mWifiDiagnostics.startLogging(true /* verbose enabled */); 594 mWifiDiagnostics.onRingBufferData( 595 mFakeRbs, new byte[LARGE_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE]); 596 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); 597 assertEquals(1, getLoggerRingBufferData().length); 598 } 599 600 /** Verifies that we use small ring buffers when switched from verbose to normal mode. */ 601 @Test 602 public void startLoggingShrinksRingBuffersIfNeeded() throws Exception { 603 mWifiDiagnostics.startLogging(true /* verbose enabled */); 604 mWifiDiagnostics.onRingBufferData( 605 mFakeRbs, new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE + 1]); 606 607 // Existing data is nuked (too large). 608 mWifiDiagnostics.startLogging(false /* verbose disabled */); 609 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); 610 assertEquals(0, getLoggerRingBufferData().length); 611 612 // New data must obey limit as well. 613 mWifiDiagnostics.onRingBufferData( 614 mFakeRbs, new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE + 1]); 615 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); 616 assertEquals(0, getLoggerRingBufferData().length); 617 } 618 619 /** Verifies that we skip the firmware and driver dumps if verbose is not enabled. */ 620 @Test 621 public void captureBugReportSkipsFirmwareAndDriverDumpsByDefault() { 622 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); 623 verify(mWifiNative, never()).getFwMemoryDump(); 624 verify(mWifiNative, never()).getDriverStateDump(); 625 } 626 627 /** Verifies that we capture the firmware and driver dumps if verbose is enabled. */ 628 @Test 629 public void captureBugReportTakesFirmwareAndDriverDumpsInVerboseMode() { 630 mWifiDiagnostics.startLogging(true /* verbose enabled */); 631 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); 632 verify(mWifiNative).getFwMemoryDump(); 633 verify(mWifiNative).getDriverStateDump(); 634 } 635 636 /** Verifies that the dump includes driver state, if driver state was provided by HAL. */ 637 @Test 638 public void dumpIncludesDriverStateDumpIfAvailable() { 639 when(mWifiNative.getDriverStateDump()).thenReturn(new byte[]{0, 1, 2}); 640 641 mWifiDiagnostics.startLogging(true /* verbose enabled */); 642 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); 643 verify(mWifiNative).getDriverStateDump(); 644 645 StringWriter sw = new StringWriter(); 646 PrintWriter pw = new PrintWriter(sw); 647 mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{}); 648 assertTrue(sw.toString().contains(WifiDiagnostics.DRIVER_DUMP_SECTION_HEADER)); 649 } 650 651 /** Verifies that the dump skips driver state, if driver state was not provided by HAL. */ 652 @Test 653 public void dumpOmitsDriverStateDumpIfUnavailable() { 654 mWifiDiagnostics.startLogging(true /* verbose enabled */); 655 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); 656 verify(mWifiNative).getDriverStateDump(); 657 658 StringWriter sw = new StringWriter(); 659 PrintWriter pw = new PrintWriter(sw); 660 mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{}); 661 assertFalse(sw.toString().contains(WifiDiagnostics.DRIVER_DUMP_SECTION_HEADER)); 662 } 663 664 /** Verifies that the dump omits driver state, if verbose was disabled after capture. */ 665 @Test 666 public void dumpOmitsDriverStateDumpIfVerboseDisabledAfterCapture() { 667 when(mWifiNative.getDriverStateDump()).thenReturn(new byte[]{0, 1, 2}); 668 669 mWifiDiagnostics.startLogging(true /* verbose enabled */); 670 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); 671 verify(mWifiNative).getDriverStateDump(); 672 673 mWifiDiagnostics.startLogging(false /* verbose no longer enabled */); 674 675 StringWriter sw = new StringWriter(); 676 PrintWriter pw = new PrintWriter(sw); 677 mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{}); 678 assertFalse(sw.toString().contains(WifiDiagnostics.DRIVER_DUMP_SECTION_HEADER)); 679 } 680 681 /** Verifies that the dump includes firmware dump, if firmware dump was provided by HAL. */ 682 @Test 683 public void dumpIncludesFirmwareMemoryDumpIfAvailable() { 684 when(mWifiNative.getFwMemoryDump()).thenReturn(new byte[]{0, 1, 2}); 685 686 mWifiDiagnostics.startLogging(true /* verbose enabled */); 687 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); 688 verify(mWifiNative).getFwMemoryDump(); 689 690 StringWriter sw = new StringWriter(); 691 PrintWriter pw = new PrintWriter(sw); 692 mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{}); 693 assertTrue(sw.toString().contains(WifiDiagnostics.FIRMWARE_DUMP_SECTION_HEADER)); 694 } 695 696 /** Verifies that the dump skips firmware memory, if firmware memory was not provided by HAL. */ 697 @Test 698 public void dumpOmitsFirmwareMemoryDumpIfUnavailable() { 699 mWifiDiagnostics.startLogging(true /* verbose enabled */); 700 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); 701 verify(mWifiNative).getFwMemoryDump(); 702 703 StringWriter sw = new StringWriter(); 704 PrintWriter pw = new PrintWriter(sw); 705 mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{}); 706 assertFalse(sw.toString().contains(WifiDiagnostics.FIRMWARE_DUMP_SECTION_HEADER)); 707 } 708 709 /** Verifies that the dump omits firmware memory, if verbose was disabled after capture. */ 710 @Test 711 public void dumpOmitsFirmwareMemoryDumpIfVerboseDisabledAfterCapture() { 712 when(mWifiNative.getFwMemoryDump()).thenReturn(new byte[]{0, 1, 2}); 713 714 mWifiDiagnostics.startLogging(true /* verbose enabled */); 715 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE); 716 verify(mWifiNative).getFwMemoryDump(); 717 718 mWifiDiagnostics.startLogging(false /* verbose no longer enabled */); 719 720 StringWriter sw = new StringWriter(); 721 PrintWriter pw = new PrintWriter(sw); 722 mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{}); 723 assertFalse(sw.toString().contains(WifiDiagnostics.FIRMWARE_DUMP_SECTION_HEADER)); 724 } 725 726 /** Verifies that the dump() includes contents of WifiNative's LocalLog. */ 727 @Test 728 public void dumpIncludesContentOfWifiNativeLocalLog() { 729 final String wifiNativeLogMessage = "This is a message"; 730 mWifiNativeLocalLog.log(wifiNativeLogMessage); 731 732 mWifiDiagnostics.startLogging(false /* verbose disabled */); 733 StringWriter sw = new StringWriter(); 734 PrintWriter pw = new PrintWriter(sw); 735 mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{}); 736 assertTrue(sw.toString().contains(wifiNativeLogMessage)); 737 } 738} 739