Home | History | Annotate | Download | only in wifi
      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 
     17 package com.android.server.wifi;
     18 
     19 import static org.junit.Assert.assertArrayEquals;
     20 import static org.junit.Assert.assertEquals;
     21 import static org.junit.Assert.assertFalse;
     22 import static org.junit.Assert.assertTrue;
     23 import static org.mockito.Mockito.anyInt;
     24 import static org.mockito.Mockito.anyString;
     25 import static org.mockito.Mockito.spy;
     26 import static org.mockito.Mockito.verify;
     27 import static org.mockito.Mockito.when;
     28 
     29 import android.test.suitebuilder.annotation.SmallTest;
     30 
     31 import org.junit.Before;
     32 import org.junit.Test;
     33 
     34 import java.lang.reflect.Constructor;
     35 import java.util.HashMap;
     36 import java.util.Map;
     37 import java.util.regex.Pattern;
     38 
     39 /**
     40  * Unit tests for {@link com.android.server.wifi.WifiNative}.
     41  */
     42 @SmallTest
     43 public class WifiNativeTest {
     44     private static final int NETWORK_ID = 0;
     45     private static final String NETWORK_EXTRAS_VARIABLE = "test";
     46     private static final Map<String, String> NETWORK_EXTRAS_VALUES = new HashMap<>();
     47     static {
     48         NETWORK_EXTRAS_VALUES.put("key1", "value1");
     49         NETWORK_EXTRAS_VALUES.put("key2", "value2");
     50     }
     51     private static final String NETWORK_EXTRAS_SERIALIZED =
     52             "\"%7B%22key2%22%3A%22value2%22%2C%22key1%22%3A%22value1%22%7D\"";
     53 
     54     private static final long FATE_REPORT_DRIVER_TIMESTAMP_USEC = 12345;
     55     private static final byte[] FATE_REPORT_FRAME_BYTES = new byte[] {
     56             'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 0, 1, 2, 3, 4, 5, 6, 7};
     57     private static final WifiNative.TxFateReport TX_FATE_REPORT = new WifiNative.TxFateReport(
     58             WifiLoggerHal.TX_PKT_FATE_SENT,
     59             FATE_REPORT_DRIVER_TIMESTAMP_USEC,
     60             WifiLoggerHal.FRAME_TYPE_ETHERNET_II,
     61             FATE_REPORT_FRAME_BYTES
     62     );
     63     private static final WifiNative.RxFateReport RX_FATE_REPORT = new WifiNative.RxFateReport(
     64             WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID,
     65             FATE_REPORT_DRIVER_TIMESTAMP_USEC,
     66             WifiLoggerHal.FRAME_TYPE_ETHERNET_II,
     67             FATE_REPORT_FRAME_BYTES
     68     );
     69     private static final FrameTypeMapping[] FRAME_TYPE_MAPPINGS = new FrameTypeMapping[] {
     70             new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_UNKNOWN, "unknown", "N/A"),
     71             new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, "data", "Ethernet"),
     72             new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_80211_MGMT, "802.11 management",
     73                     "802.11 Mgmt"),
     74             new FrameTypeMapping((byte) 42, "42", "N/A")
     75     };
     76     private static final FateMapping[] TX_FATE_MAPPINGS = new FateMapping[] {
     77             new FateMapping(WifiLoggerHal.TX_PKT_FATE_ACKED, "acked"),
     78             new FateMapping(WifiLoggerHal.TX_PKT_FATE_SENT, "sent"),
     79             new FateMapping(WifiLoggerHal.TX_PKT_FATE_FW_QUEUED, "firmware queued"),
     80             new FateMapping(WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID,
     81                     "firmware dropped (invalid frame)"),
     82             new FateMapping(
     83                     WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS,  "firmware dropped (no bufs)"),
     84             new FateMapping(
     85                     WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER, "firmware dropped (other)"),
     86             new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED, "driver queued"),
     87             new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID,
     88                     "driver dropped (invalid frame)"),
     89             new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS,
     90                     "driver dropped (no bufs)"),
     91             new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER, "driver dropped (other)"),
     92             new FateMapping((byte) 42, "42")
     93     };
     94     private static final FateMapping[] RX_FATE_MAPPINGS = new FateMapping[] {
     95             new FateMapping(WifiLoggerHal.RX_PKT_FATE_SUCCESS, "success"),
     96             new FateMapping(WifiLoggerHal.RX_PKT_FATE_FW_QUEUED, "firmware queued"),
     97             new FateMapping(
     98                     WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER, "firmware dropped (filter)"),
     99             new FateMapping(WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID,
    100                     "firmware dropped (invalid frame)"),
    101             new FateMapping(
    102                     WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS, "firmware dropped (no bufs)"),
    103             new FateMapping(
    104                     WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER, "firmware dropped (other)"),
    105             new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED, "driver queued"),
    106             new FateMapping(
    107                     WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER, "driver dropped (filter)"),
    108             new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID,
    109                     "driver dropped (invalid frame)"),
    110             new FateMapping(
    111                     WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS, "driver dropped (no bufs)"),
    112             new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER, "driver dropped (other)"),
    113             new FateMapping((byte) 42, "42")
    114     };
    115 
    116     private WifiNative mWifiNative;
    117 
    118     @Before
    119     public void setUp() throws Exception {
    120         final Constructor<WifiNative> wifiNativeConstructor =
    121                 WifiNative.class.getDeclaredConstructor(String.class, Boolean.TYPE);
    122         wifiNativeConstructor.setAccessible(true);
    123         mWifiNative = spy(wifiNativeConstructor.newInstance("test", true));
    124     }
    125 
    126     /**
    127      * Verifies that setNetworkExtra() correctly writes a serialized and URL-encoded JSON object.
    128      */
    129     @Test
    130     public void testSetNetworkExtra() {
    131         when(mWifiNative.setNetworkVariable(anyInt(), anyString(), anyString())).thenReturn(true);
    132         assertTrue(mWifiNative.setNetworkExtra(NETWORK_ID, NETWORK_EXTRAS_VARIABLE,
    133                 NETWORK_EXTRAS_VALUES));
    134         verify(mWifiNative).setNetworkVariable(NETWORK_ID, NETWORK_EXTRAS_VARIABLE,
    135                 NETWORK_EXTRAS_SERIALIZED);
    136     }
    137 
    138     /**
    139      * Verifies that getNetworkExtra() correctly reads a serialized and URL-encoded JSON object.
    140      */
    141     @Test
    142     public void testGetNetworkExtra() {
    143         when(mWifiNative.getNetworkVariable(NETWORK_ID, NETWORK_EXTRAS_VARIABLE))
    144                 .thenReturn(NETWORK_EXTRAS_SERIALIZED);
    145         final Map<String, String> actualValues =
    146                 mWifiNative.getNetworkExtra(NETWORK_ID, NETWORK_EXTRAS_VARIABLE);
    147         assertEquals(NETWORK_EXTRAS_VALUES, actualValues);
    148     }
    149 
    150     /**
    151      * Verifies that TxFateReport's constructor sets all of the TxFateReport fields.
    152      */
    153     @Test
    154     public void testTxFateReportCtorSetsFields() {
    155         WifiNative.TxFateReport fateReport = new WifiNative.TxFateReport(
    156                 WifiLoggerHal.TX_PKT_FATE_SENT,  // non-zero value
    157                 FATE_REPORT_DRIVER_TIMESTAMP_USEC,
    158                 WifiLoggerHal.FRAME_TYPE_ETHERNET_II,  // non-zero value
    159                 FATE_REPORT_FRAME_BYTES
    160         );
    161         assertEquals(WifiLoggerHal.TX_PKT_FATE_SENT, fateReport.mFate);
    162         assertEquals(FATE_REPORT_DRIVER_TIMESTAMP_USEC, fateReport.mDriverTimestampUSec);
    163         assertEquals(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, fateReport.mFrameType);
    164         assertArrayEquals(FATE_REPORT_FRAME_BYTES, fateReport.mFrameBytes);
    165     }
    166 
    167     /**
    168      * Verifies that RxFateReport's constructor sets all of the RxFateReport fields.
    169      */
    170     @Test
    171     public void testRxFateReportCtorSetsFields() {
    172         WifiNative.RxFateReport fateReport = new WifiNative.RxFateReport(
    173                 WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID,  // non-zero value
    174                 FATE_REPORT_DRIVER_TIMESTAMP_USEC,
    175                 WifiLoggerHal.FRAME_TYPE_ETHERNET_II,  // non-zero value
    176                 FATE_REPORT_FRAME_BYTES
    177         );
    178         assertEquals(WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID, fateReport.mFate);
    179         assertEquals(FATE_REPORT_DRIVER_TIMESTAMP_USEC, fateReport.mDriverTimestampUSec);
    180         assertEquals(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, fateReport.mFrameType);
    181         assertArrayEquals(FATE_REPORT_FRAME_BYTES, fateReport.mFrameBytes);
    182     }
    183 
    184     // Support classes for test{Tx,Rx}FateReportToString.
    185     private static class FrameTypeMapping {
    186         byte mTypeNumber;
    187         String mExpectedTypeText;
    188         String mExpectedProtocolText;
    189         FrameTypeMapping(byte typeNumber, String expectedTypeText, String expectedProtocolText) {
    190             this.mTypeNumber = typeNumber;
    191             this.mExpectedTypeText = expectedTypeText;
    192             this.mExpectedProtocolText = expectedProtocolText;
    193         }
    194     }
    195     private static class FateMapping {
    196         byte mFateNumber;
    197         String mExpectedText;
    198         FateMapping(byte fateNumber, String expectedText) {
    199             this.mFateNumber = fateNumber;
    200             this.mExpectedText = expectedText;
    201         }
    202     }
    203 
    204     /**
    205      * Verifies that FateReport.getTableHeader() prints the right header.
    206      */
    207     @Test
    208     public void testFateReportTableHeader() {
    209         final String header = WifiNative.FateReport.getTableHeader();
    210         assertEquals(
    211                 "\nTime usec        Walltime      Direction  Fate                              "
    212                 + "Protocol      Type                     Result\n"
    213                 + "---------        --------      ---------  ----                              "
    214                 + "--------      ----                     ------\n", header);
    215     }
    216 
    217     /**
    218      * Verifies that TxFateReport.toTableRowString() includes the information we care about.
    219      */
    220     @Test
    221     public void testTxFateReportToTableRowString() {
    222         WifiNative.TxFateReport fateReport = TX_FATE_REPORT;
    223         assertTrue(
    224                 fateReport.toTableRowString().replaceAll("\\s+", " ").trim().matches(
    225                     FATE_REPORT_DRIVER_TIMESTAMP_USEC + " "  // timestamp
    226                             + "\\d{2}:\\d{2}:\\d{2}\\.\\d{3} "  // walltime
    227                             + "TX "  // direction
    228                             + "sent "  // fate
    229                             + "Ethernet "  // type
    230                             + "N/A "  // protocol
    231                             + "N/A"  // result
    232                 )
    233         );
    234 
    235         for (FrameTypeMapping frameTypeMapping : FRAME_TYPE_MAPPINGS) {
    236             fateReport = new WifiNative.TxFateReport(
    237                     WifiLoggerHal.TX_PKT_FATE_SENT,
    238                     FATE_REPORT_DRIVER_TIMESTAMP_USEC,
    239                     frameTypeMapping.mTypeNumber,
    240                     FATE_REPORT_FRAME_BYTES
    241             );
    242             assertTrue(
    243                     fateReport.toTableRowString().replaceAll("\\s+", " ").trim().matches(
    244                             FATE_REPORT_DRIVER_TIMESTAMP_USEC + " "  // timestamp
    245                                     + "\\d{2}:\\d{2}:\\d{2}\\.\\d{3} "  // walltime
    246                                     + "TX "  // direction
    247                                     + "sent "  // fate
    248                                     + frameTypeMapping.mExpectedProtocolText + " "  // type
    249                                     + "N/A "  // protocol
    250                                     + "N/A"  // result
    251                     )
    252             );
    253         }
    254 
    255         for (FateMapping fateMapping : TX_FATE_MAPPINGS) {
    256             fateReport = new WifiNative.TxFateReport(
    257                     fateMapping.mFateNumber,
    258                     FATE_REPORT_DRIVER_TIMESTAMP_USEC,
    259                     WifiLoggerHal.FRAME_TYPE_80211_MGMT,
    260                     FATE_REPORT_FRAME_BYTES
    261             );
    262             assertTrue(
    263                     fateReport.toTableRowString().replaceAll("\\s+", " ").trim().matches(
    264                             FATE_REPORT_DRIVER_TIMESTAMP_USEC + " "  // timestamp
    265                                     + "\\d{2}:\\d{2}:\\d{2}\\.\\d{3} "  // walltime
    266                                     + "TX "  // direction
    267                                     + Pattern.quote(fateMapping.mExpectedText) + " "  // fate
    268                                     + "802.11 Mgmt "  // type
    269                                     + "N/A "  // protocol
    270                                     + "N/A"  // result
    271                     )
    272             );
    273         }
    274     }
    275 
    276     /**
    277      * Verifies that TxFateReport.toVerboseStringWithPiiAllowed() includes the information we care
    278      * about.
    279      */
    280     @Test
    281     public void testTxFateReportToVerboseStringWithPiiAllowed() {
    282         WifiNative.TxFateReport fateReport = TX_FATE_REPORT;
    283 
    284         String verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
    285         assertTrue(verboseFateString.contains("Frame direction: TX"));
    286         assertTrue(verboseFateString.contains("Frame timestamp: 12345"));
    287         assertTrue(verboseFateString.contains("Frame fate: sent"));
    288         assertTrue(verboseFateString.contains("Frame type: data"));
    289         assertTrue(verboseFateString.contains("Frame protocol: Ethernet"));
    290         assertTrue(verboseFateString.contains("Frame protocol type: N/A"));
    291         assertTrue(verboseFateString.contains("Frame length: 16"));
    292         assertTrue(verboseFateString.contains(
    293                 "61 62 63 64 65 66 67 68 00 01 02 03 04 05 06 07")); // hex dump
    294         // TODO(quiche): uncomment this, once b/27975149 is fixed.
    295         // assertTrue(verboseFateString.contains("abcdefgh........"));  // hex dump
    296 
    297         for (FrameTypeMapping frameTypeMapping : FRAME_TYPE_MAPPINGS) {
    298             fateReport = new WifiNative.TxFateReport(
    299                     WifiLoggerHal.TX_PKT_FATE_SENT,
    300                     FATE_REPORT_DRIVER_TIMESTAMP_USEC,
    301                     frameTypeMapping.mTypeNumber,
    302                     FATE_REPORT_FRAME_BYTES
    303             );
    304             verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
    305             assertTrue(verboseFateString.contains("Frame type: "
    306                     + frameTypeMapping.mExpectedTypeText));
    307         }
    308 
    309         for (FateMapping fateMapping : TX_FATE_MAPPINGS) {
    310             fateReport = new WifiNative.TxFateReport(
    311                     fateMapping.mFateNumber,
    312                     FATE_REPORT_DRIVER_TIMESTAMP_USEC,
    313                     WifiLoggerHal.FRAME_TYPE_80211_MGMT,
    314                     FATE_REPORT_FRAME_BYTES
    315             );
    316             verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
    317             assertTrue(verboseFateString.contains("Frame fate: " + fateMapping.mExpectedText));
    318         }
    319     }
    320 
    321     /**
    322      * Verifies that RxFateReport.toTableRowString() includes the information we care about.
    323      */
    324     @Test
    325     public void testRxFateReportToTableRowString() {
    326         WifiNative.RxFateReport fateReport = RX_FATE_REPORT;
    327         assertTrue(
    328                 fateReport.toTableRowString().replaceAll("\\s+", " ").trim().matches(
    329                         FATE_REPORT_DRIVER_TIMESTAMP_USEC + " "  // timestamp
    330                                 + "\\d{2}:\\d{2}:\\d{2}\\.\\d{3} "  // walltime
    331                                 + "RX "  // direction
    332                                 + Pattern.quote("firmware dropped (invalid frame) ")  // fate
    333                                 + "Ethernet "  // type
    334                                 + "N/A "  // protocol
    335                                 + "N/A"  // result
    336                 )
    337         );
    338 
    339         // FrameTypeMappings omitted, as they're the same as for TX.
    340 
    341         for (FateMapping fateMapping : RX_FATE_MAPPINGS) {
    342             fateReport = new WifiNative.RxFateReport(
    343                     fateMapping.mFateNumber,
    344                     FATE_REPORT_DRIVER_TIMESTAMP_USEC,
    345                     WifiLoggerHal.FRAME_TYPE_80211_MGMT,
    346                     FATE_REPORT_FRAME_BYTES
    347             );
    348             assertTrue(
    349                     fateReport.toTableRowString().replaceAll("\\s+", " ").trim().matches(
    350                             FATE_REPORT_DRIVER_TIMESTAMP_USEC + " "  // timestamp
    351                                     + "\\d{2}:\\d{2}:\\d{2}\\.\\d{3} "  // walltime
    352                                     + "RX "  // direction
    353                                     + Pattern.quote(fateMapping.mExpectedText) + " " // fate
    354                                     + "802.11 Mgmt "  // type
    355                                     + "N/A " // protocol
    356                                     + "N/A"  // result
    357                     )
    358             );
    359         }
    360     }
    361 
    362     /**
    363      * Verifies that RxFateReport.toVerboseStringWithPiiAllowed() includes the information we care
    364      * about.
    365      */
    366     @Test
    367     public void testRxFateReportToVerboseStringWithPiiAllowed() {
    368         WifiNative.RxFateReport fateReport = RX_FATE_REPORT;
    369 
    370         String verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
    371         assertTrue(verboseFateString.contains("Frame direction: RX"));
    372         assertTrue(verboseFateString.contains("Frame timestamp: 12345"));
    373         assertTrue(verboseFateString.contains("Frame fate: firmware dropped (invalid frame)"));
    374         assertTrue(verboseFateString.contains("Frame type: data"));
    375         assertTrue(verboseFateString.contains("Frame protocol: Ethernet"));
    376         assertTrue(verboseFateString.contains("Frame protocol type: N/A"));
    377         assertTrue(verboseFateString.contains("Frame length: 16"));
    378         assertTrue(verboseFateString.contains(
    379                 "61 62 63 64 65 66 67 68 00 01 02 03 04 05 06 07")); // hex dump
    380         // TODO(quiche): uncomment this, once b/27975149 is fixed.
    381         // assertTrue(verboseFateString.contains("abcdefgh........"));  // hex dump
    382 
    383         // FrameTypeMappings omitted, as they're the same as for TX.
    384 
    385         for (FateMapping fateMapping : RX_FATE_MAPPINGS) {
    386             fateReport = new WifiNative.RxFateReport(
    387                     fateMapping.mFateNumber,
    388                     FATE_REPORT_DRIVER_TIMESTAMP_USEC,
    389                     WifiLoggerHal.FRAME_TYPE_80211_MGMT,
    390                     FATE_REPORT_FRAME_BYTES
    391             );
    392             verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
    393             assertTrue(verboseFateString.contains("Frame fate: " + fateMapping.mExpectedText));
    394         }
    395     }
    396 
    397     /**
    398      * Verifies that startPktFateMonitoring returns false when HAL is not started.
    399      */
    400     @Test
    401     public void testStartPktFateMonitoringReturnsFalseWhenHalIsNotStarted() {
    402         assertFalse(mWifiNative.isHalStarted());
    403         assertFalse(mWifiNative.startPktFateMonitoring());
    404     }
    405 
    406     /**
    407      * Verifies that getTxPktFates returns error when HAL is not started.
    408      */
    409     @Test
    410     public void testGetTxPktFatesReturnsErrorWhenHalIsNotStarted() {
    411         WifiNative.TxFateReport[] fateReports = null;
    412         assertFalse(mWifiNative.isHalStarted());
    413         assertFalse(mWifiNative.getTxPktFates(fateReports));
    414     }
    415 
    416     /**
    417      * Verifies that getRxPktFates returns error when HAL is not started.
    418      */
    419     @Test
    420     public void testGetRxPktFatesReturnsErrorWhenHalIsNotStarted() {
    421         WifiNative.RxFateReport[] fateReports = null;
    422         assertFalse(mWifiNative.isHalStarted());
    423         assertFalse(mWifiNative.getRxPktFates(fateReports));
    424     }
    425 
    426     // TODO(quiche): Add tests for the success cases (when HAL has been started). Specifically:
    427     // - testStartPktFateMonitoringCallsHalIfHalIsStarted()
    428     // - testGetTxPktFatesCallsHalIfHalIsStarted()
    429     // - testGetRxPktFatesCallsHalIfHalIsStarted()
    430     //
    431     // Adding these tests is difficult to do at the moment, because we can't mock out the HAL
    432     // itself. Also, we can't mock out the native methods, because those methods are private.
    433     // b/28005116.
    434 
    435     /** Verifies that getDriverStateDumpNative returns null when HAL is not started. */
    436     @Test
    437     public void testGetDriverStateDumpReturnsNullWhenHalIsNotStarted() {
    438         assertEquals(null, mWifiNative.getDriverStateDump());
    439     }
    440 
    441     // TODO(b/28005116): Add test for the success case of getDriverStateDump().
    442 }
    443