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