WifiNativeTest.java revision fc83b303a3382329c28d631b1e0fb2bb35969f85
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 static org.junit.Assert.assertArrayEquals;
20import static org.junit.Assert.assertEquals;
21import static org.junit.Assert.assertFalse;
22import static org.junit.Assert.assertTrue;
23import static org.mockito.Mockito.anyInt;
24import static org.mockito.Mockito.anyString;
25import static org.mockito.Mockito.eq;
26import static org.mockito.Mockito.mock;
27import static org.mockito.Mockito.spy;
28import static org.mockito.Mockito.verify;
29import static org.mockito.Mockito.when;
30
31import android.net.wifi.IApInterface;
32import android.net.wifi.IClientInterface;
33import android.net.wifi.IWificond;
34import android.test.suitebuilder.annotation.SmallTest;
35
36import org.junit.Before;
37import org.junit.Test;
38
39import java.lang.reflect.Constructor;
40import java.util.Arrays;
41import java.util.HashMap;
42import java.util.Map;
43import java.util.Set;
44import java.util.TreeSet;
45import java.util.regex.Pattern;
46
47/**
48 * Unit tests for {@link com.android.server.wifi.WifiNative}.
49 */
50@SmallTest
51public class WifiNativeTest {
52    private static final int NETWORK_ID = 0;
53    private static final String NETWORK_EXTRAS_VARIABLE = "test";
54    private static final Map<String, String> NETWORK_EXTRAS_VALUES = new HashMap<>();
55    static {
56        NETWORK_EXTRAS_VALUES.put("key1", "value1");
57        NETWORK_EXTRAS_VALUES.put("key2", "value2");
58    }
59    private static final String NETWORK_EXTRAS_SERIALIZED =
60            "\"%7B%22key1%22%3A%22value1%22%2C%22key2%22%3A%22value2%22%7D\"";
61
62    private static final long FATE_REPORT_DRIVER_TIMESTAMP_USEC = 12345;
63    private static final byte[] FATE_REPORT_FRAME_BYTES = new byte[] {
64            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 0, 1, 2, 3, 4, 5, 6, 7};
65    private static final WifiNative.TxFateReport TX_FATE_REPORT = new WifiNative.TxFateReport(
66            WifiLoggerHal.TX_PKT_FATE_SENT,
67            FATE_REPORT_DRIVER_TIMESTAMP_USEC,
68            WifiLoggerHal.FRAME_TYPE_ETHERNET_II,
69            FATE_REPORT_FRAME_BYTES
70    );
71    private static final WifiNative.RxFateReport RX_FATE_REPORT = new WifiNative.RxFateReport(
72            WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID,
73            FATE_REPORT_DRIVER_TIMESTAMP_USEC,
74            WifiLoggerHal.FRAME_TYPE_ETHERNET_II,
75            FATE_REPORT_FRAME_BYTES
76    );
77    private static final FrameTypeMapping[] FRAME_TYPE_MAPPINGS = new FrameTypeMapping[] {
78            new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_UNKNOWN, "unknown", "N/A"),
79            new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, "data", "Ethernet"),
80            new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_80211_MGMT, "802.11 management",
81                    "802.11 Mgmt"),
82            new FrameTypeMapping((byte) 42, "42", "N/A")
83    };
84    private static final FateMapping[] TX_FATE_MAPPINGS = new FateMapping[] {
85            new FateMapping(WifiLoggerHal.TX_PKT_FATE_ACKED, "acked"),
86            new FateMapping(WifiLoggerHal.TX_PKT_FATE_SENT, "sent"),
87            new FateMapping(WifiLoggerHal.TX_PKT_FATE_FW_QUEUED, "firmware queued"),
88            new FateMapping(WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID,
89                    "firmware dropped (invalid frame)"),
90            new FateMapping(
91                    WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS,  "firmware dropped (no bufs)"),
92            new FateMapping(
93                    WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER, "firmware dropped (other)"),
94            new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED, "driver queued"),
95            new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID,
96                    "driver dropped (invalid frame)"),
97            new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS,
98                    "driver dropped (no bufs)"),
99            new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER, "driver dropped (other)"),
100            new FateMapping((byte) 42, "42")
101    };
102    private static final FateMapping[] RX_FATE_MAPPINGS = new FateMapping[] {
103            new FateMapping(WifiLoggerHal.RX_PKT_FATE_SUCCESS, "success"),
104            new FateMapping(WifiLoggerHal.RX_PKT_FATE_FW_QUEUED, "firmware queued"),
105            new FateMapping(
106                    WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER, "firmware dropped (filter)"),
107            new FateMapping(WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID,
108                    "firmware dropped (invalid frame)"),
109            new FateMapping(
110                    WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS, "firmware dropped (no bufs)"),
111            new FateMapping(
112                    WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER, "firmware dropped (other)"),
113            new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED, "driver queued"),
114            new FateMapping(
115                    WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER, "driver dropped (filter)"),
116            new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID,
117                    "driver dropped (invalid frame)"),
118            new FateMapping(
119                    WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS, "driver dropped (no bufs)"),
120            new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER, "driver dropped (other)"),
121            new FateMapping((byte) 42, "42")
122    };
123    private static final WifiNative.SignalPollResult SIGNAL_POLL_RESULT =
124            new WifiNative.SignalPollResult() {{
125                currentRssi = -60;
126                txBitrate = 12;
127                associationFrequency = 5240;
128            }};
129    private static final WifiNative.TxPacketCounters PACKET_COUNTERS_RESULT =
130            new WifiNative.TxPacketCounters() {{
131                txSucceeded = 2000;
132                txFailed = 120;
133            }};
134
135
136    private WifiNative mWifiNative;
137
138    @Before
139    public void setUp() throws Exception {
140        final Constructor<WifiNative> wifiNativeConstructor =
141                WifiNative.class.getDeclaredConstructor(String.class, Boolean.TYPE);
142        wifiNativeConstructor.setAccessible(true);
143        mWifiNative = spy(wifiNativeConstructor.newInstance("test", true));
144    }
145
146    /**
147     * Verifies that setNetworkExtra() correctly writes a serialized and URL-encoded JSON object.
148     */
149    @Test
150    public void testSetNetworkExtra() {
151        when(mWifiNative.setNetworkVariable(anyInt(), anyString(), anyString())).thenReturn(true);
152        assertTrue(mWifiNative.setNetworkExtra(NETWORK_ID, NETWORK_EXTRAS_VARIABLE,
153                NETWORK_EXTRAS_VALUES));
154        verify(mWifiNative).setNetworkVariable(NETWORK_ID, NETWORK_EXTRAS_VARIABLE,
155                NETWORK_EXTRAS_SERIALIZED);
156    }
157
158    /**
159     * Verifies that getNetworkExtra() correctly reads a serialized and URL-encoded JSON object.
160     */
161    @Test
162    public void testGetNetworkExtra() {
163        when(mWifiNative.getNetworkVariable(NETWORK_ID, NETWORK_EXTRAS_VARIABLE))
164                .thenReturn(NETWORK_EXTRAS_SERIALIZED);
165        final Map<String, String> actualValues =
166                mWifiNative.getNetworkExtra(NETWORK_ID, NETWORK_EXTRAS_VARIABLE);
167        assertEquals(NETWORK_EXTRAS_VALUES, actualValues);
168    }
169
170    /**
171     * Verifies that TxFateReport's constructor sets all of the TxFateReport fields.
172     */
173    @Test
174    public void testTxFateReportCtorSetsFields() {
175        WifiNative.TxFateReport fateReport = new WifiNative.TxFateReport(
176                WifiLoggerHal.TX_PKT_FATE_SENT,  // non-zero value
177                FATE_REPORT_DRIVER_TIMESTAMP_USEC,
178                WifiLoggerHal.FRAME_TYPE_ETHERNET_II,  // non-zero value
179                FATE_REPORT_FRAME_BYTES
180        );
181        assertEquals(WifiLoggerHal.TX_PKT_FATE_SENT, fateReport.mFate);
182        assertEquals(FATE_REPORT_DRIVER_TIMESTAMP_USEC, fateReport.mDriverTimestampUSec);
183        assertEquals(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, fateReport.mFrameType);
184        assertArrayEquals(FATE_REPORT_FRAME_BYTES, fateReport.mFrameBytes);
185    }
186
187    /**
188     * Verifies that RxFateReport's constructor sets all of the RxFateReport fields.
189     */
190    @Test
191    public void testRxFateReportCtorSetsFields() {
192        WifiNative.RxFateReport fateReport = new WifiNative.RxFateReport(
193                WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID,  // non-zero value
194                FATE_REPORT_DRIVER_TIMESTAMP_USEC,
195                WifiLoggerHal.FRAME_TYPE_ETHERNET_II,  // non-zero value
196                FATE_REPORT_FRAME_BYTES
197        );
198        assertEquals(WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID, fateReport.mFate);
199        assertEquals(FATE_REPORT_DRIVER_TIMESTAMP_USEC, fateReport.mDriverTimestampUSec);
200        assertEquals(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, fateReport.mFrameType);
201        assertArrayEquals(FATE_REPORT_FRAME_BYTES, fateReport.mFrameBytes);
202    }
203
204    // Support classes for test{Tx,Rx}FateReportToString.
205    private static class FrameTypeMapping {
206        byte mTypeNumber;
207        String mExpectedTypeText;
208        String mExpectedProtocolText;
209        FrameTypeMapping(byte typeNumber, String expectedTypeText, String expectedProtocolText) {
210            this.mTypeNumber = typeNumber;
211            this.mExpectedTypeText = expectedTypeText;
212            this.mExpectedProtocolText = expectedProtocolText;
213        }
214    }
215    private static class FateMapping {
216        byte mFateNumber;
217        String mExpectedText;
218        FateMapping(byte fateNumber, String expectedText) {
219            this.mFateNumber = fateNumber;
220            this.mExpectedText = expectedText;
221        }
222    }
223
224    /**
225     * Verifies that FateReport.getTableHeader() prints the right header.
226     */
227    @Test
228    public void testFateReportTableHeader() {
229        final String header = WifiNative.FateReport.getTableHeader();
230        assertEquals(
231                "\nTime usec        Walltime      Direction  Fate                              "
232                + "Protocol      Type                     Result\n"
233                + "---------        --------      ---------  ----                              "
234                + "--------      ----                     ------\n", header);
235    }
236
237    /**
238     * Verifies that TxFateReport.toTableRowString() includes the information we care about.
239     */
240    @Test
241    public void testTxFateReportToTableRowString() {
242        WifiNative.TxFateReport fateReport = TX_FATE_REPORT;
243        assertTrue(
244                fateReport.toTableRowString().replaceAll("\\s+", " ").trim().matches(
245                    FATE_REPORT_DRIVER_TIMESTAMP_USEC + " "  // timestamp
246                            + "\\d{2}:\\d{2}:\\d{2}\\.\\d{3} "  // walltime
247                            + "TX "  // direction
248                            + "sent "  // fate
249                            + "Ethernet "  // type
250                            + "N/A "  // protocol
251                            + "N/A"  // result
252                )
253        );
254
255        for (FrameTypeMapping frameTypeMapping : FRAME_TYPE_MAPPINGS) {
256            fateReport = new WifiNative.TxFateReport(
257                    WifiLoggerHal.TX_PKT_FATE_SENT,
258                    FATE_REPORT_DRIVER_TIMESTAMP_USEC,
259                    frameTypeMapping.mTypeNumber,
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                                    + "sent "  // fate
268                                    + frameTypeMapping.mExpectedProtocolText + " "  // type
269                                    + "N/A "  // protocol
270                                    + "N/A"  // result
271                    )
272            );
273        }
274
275        for (FateMapping fateMapping : TX_FATE_MAPPINGS) {
276            fateReport = new WifiNative.TxFateReport(
277                    fateMapping.mFateNumber,
278                    FATE_REPORT_DRIVER_TIMESTAMP_USEC,
279                    WifiLoggerHal.FRAME_TYPE_80211_MGMT,
280                    FATE_REPORT_FRAME_BYTES
281            );
282            assertTrue(
283                    fateReport.toTableRowString().replaceAll("\\s+", " ").trim().matches(
284                            FATE_REPORT_DRIVER_TIMESTAMP_USEC + " "  // timestamp
285                                    + "\\d{2}:\\d{2}:\\d{2}\\.\\d{3} "  // walltime
286                                    + "TX "  // direction
287                                    + Pattern.quote(fateMapping.mExpectedText) + " "  // fate
288                                    + "802.11 Mgmt "  // type
289                                    + "N/A "  // protocol
290                                    + "N/A"  // result
291                    )
292            );
293        }
294    }
295
296    /**
297     * Verifies that TxFateReport.toVerboseStringWithPiiAllowed() includes the information we care
298     * about.
299     */
300    @Test
301    public void testTxFateReportToVerboseStringWithPiiAllowed() {
302        WifiNative.TxFateReport fateReport = TX_FATE_REPORT;
303
304        String verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
305        assertTrue(verboseFateString.contains("Frame direction: TX"));
306        assertTrue(verboseFateString.contains("Frame timestamp: 12345"));
307        assertTrue(verboseFateString.contains("Frame fate: sent"));
308        assertTrue(verboseFateString.contains("Frame type: data"));
309        assertTrue(verboseFateString.contains("Frame protocol: Ethernet"));
310        assertTrue(verboseFateString.contains("Frame protocol type: N/A"));
311        assertTrue(verboseFateString.contains("Frame length: 16"));
312        assertTrue(verboseFateString.contains(
313                "61 62 63 64 65 66 67 68 00 01 02 03 04 05 06 07")); // hex dump
314        // TODO(quiche): uncomment this, once b/27975149 is fixed.
315        // assertTrue(verboseFateString.contains("abcdefgh........"));  // hex dump
316
317        for (FrameTypeMapping frameTypeMapping : FRAME_TYPE_MAPPINGS) {
318            fateReport = new WifiNative.TxFateReport(
319                    WifiLoggerHal.TX_PKT_FATE_SENT,
320                    FATE_REPORT_DRIVER_TIMESTAMP_USEC,
321                    frameTypeMapping.mTypeNumber,
322                    FATE_REPORT_FRAME_BYTES
323            );
324            verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
325            assertTrue(verboseFateString.contains("Frame type: "
326                    + frameTypeMapping.mExpectedTypeText));
327        }
328
329        for (FateMapping fateMapping : TX_FATE_MAPPINGS) {
330            fateReport = new WifiNative.TxFateReport(
331                    fateMapping.mFateNumber,
332                    FATE_REPORT_DRIVER_TIMESTAMP_USEC,
333                    WifiLoggerHal.FRAME_TYPE_80211_MGMT,
334                    FATE_REPORT_FRAME_BYTES
335            );
336            verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
337            assertTrue(verboseFateString.contains("Frame fate: " + fateMapping.mExpectedText));
338        }
339    }
340
341    /**
342     * Verifies that RxFateReport.toTableRowString() includes the information we care about.
343     */
344    @Test
345    public void testRxFateReportToTableRowString() {
346        WifiNative.RxFateReport fateReport = RX_FATE_REPORT;
347        assertTrue(
348                fateReport.toTableRowString().replaceAll("\\s+", " ").trim().matches(
349                        FATE_REPORT_DRIVER_TIMESTAMP_USEC + " "  // timestamp
350                                + "\\d{2}:\\d{2}:\\d{2}\\.\\d{3} "  // walltime
351                                + "RX "  // direction
352                                + Pattern.quote("firmware dropped (invalid frame) ")  // fate
353                                + "Ethernet "  // type
354                                + "N/A "  // protocol
355                                + "N/A"  // result
356                )
357        );
358
359        // FrameTypeMappings omitted, as they're the same as for TX.
360
361        for (FateMapping fateMapping : RX_FATE_MAPPINGS) {
362            fateReport = new WifiNative.RxFateReport(
363                    fateMapping.mFateNumber,
364                    FATE_REPORT_DRIVER_TIMESTAMP_USEC,
365                    WifiLoggerHal.FRAME_TYPE_80211_MGMT,
366                    FATE_REPORT_FRAME_BYTES
367            );
368            assertTrue(
369                    fateReport.toTableRowString().replaceAll("\\s+", " ").trim().matches(
370                            FATE_REPORT_DRIVER_TIMESTAMP_USEC + " "  // timestamp
371                                    + "\\d{2}:\\d{2}:\\d{2}\\.\\d{3} "  // walltime
372                                    + "RX "  // direction
373                                    + Pattern.quote(fateMapping.mExpectedText) + " " // fate
374                                    + "802.11 Mgmt "  // type
375                                    + "N/A " // protocol
376                                    + "N/A"  // result
377                    )
378            );
379        }
380    }
381
382    /**
383     * Verifies that RxFateReport.toVerboseStringWithPiiAllowed() includes the information we care
384     * about.
385     */
386    @Test
387    public void testRxFateReportToVerboseStringWithPiiAllowed() {
388        WifiNative.RxFateReport fateReport = RX_FATE_REPORT;
389
390        String verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
391        assertTrue(verboseFateString.contains("Frame direction: RX"));
392        assertTrue(verboseFateString.contains("Frame timestamp: 12345"));
393        assertTrue(verboseFateString.contains("Frame fate: firmware dropped (invalid frame)"));
394        assertTrue(verboseFateString.contains("Frame type: data"));
395        assertTrue(verboseFateString.contains("Frame protocol: Ethernet"));
396        assertTrue(verboseFateString.contains("Frame protocol type: N/A"));
397        assertTrue(verboseFateString.contains("Frame length: 16"));
398        assertTrue(verboseFateString.contains(
399                "61 62 63 64 65 66 67 68 00 01 02 03 04 05 06 07")); // hex dump
400        // TODO(quiche): uncomment this, once b/27975149 is fixed.
401        // assertTrue(verboseFateString.contains("abcdefgh........"));  // hex dump
402
403        // FrameTypeMappings omitted, as they're the same as for TX.
404
405        for (FateMapping fateMapping : RX_FATE_MAPPINGS) {
406            fateReport = new WifiNative.RxFateReport(
407                    fateMapping.mFateNumber,
408                    FATE_REPORT_DRIVER_TIMESTAMP_USEC,
409                    WifiLoggerHal.FRAME_TYPE_80211_MGMT,
410                    FATE_REPORT_FRAME_BYTES
411            );
412            verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
413            assertTrue(verboseFateString.contains("Frame fate: " + fateMapping.mExpectedText));
414        }
415    }
416
417    /**
418     * Verifies that startPktFateMonitoring returns false when HAL is not started.
419     */
420    @Test
421    public void testStartPktFateMonitoringReturnsFalseWhenHalIsNotStarted() {
422        assertFalse(mWifiNative.isHalStarted());
423        assertFalse(mWifiNative.startPktFateMonitoring());
424    }
425
426    /**
427     * Verifies that getTxPktFates returns error when HAL is not started.
428     */
429    @Test
430    public void testGetTxPktFatesReturnsErrorWhenHalIsNotStarted() {
431        WifiNative.TxFateReport[] fateReports = null;
432        assertFalse(mWifiNative.isHalStarted());
433        assertFalse(mWifiNative.getTxPktFates(fateReports));
434    }
435
436    /**
437     * Verifies that getRxPktFates returns error when HAL is not started.
438     */
439    @Test
440    public void testGetRxPktFatesReturnsErrorWhenHalIsNotStarted() {
441        WifiNative.RxFateReport[] fateReports = null;
442        assertFalse(mWifiNative.isHalStarted());
443        assertFalse(mWifiNative.getRxPktFates(fateReports));
444    }
445
446    // TODO(quiche): Add tests for the success cases (when HAL has been started). Specifically:
447    // - testStartPktFateMonitoringCallsHalIfHalIsStarted()
448    // - testGetTxPktFatesCallsHalIfHalIsStarted()
449    // - testGetRxPktFatesCallsHalIfHalIsStarted()
450    //
451    // Adding these tests is difficult to do at the moment, because we can't mock out the HAL
452    // itself. Also, we can't mock out the native methods, because those methods are private.
453    // b/28005116.
454
455    /** Verifies that getDriverStateDumpNative returns null when HAL is not started. */
456    @Test
457    public void testGetDriverStateDumpReturnsNullWhenHalIsNotStarted() {
458        assertEquals(null, mWifiNative.getDriverStateDump());
459    }
460
461    // TODO(b/28005116): Add test for the success case of getDriverStateDump().
462
463    /**
464     * Verifies that setupDriverForClientMode() calls underlying WificondControl.
465     */
466    @Test
467    public void testSetupDriverForClientMode() {
468        WificondControl wificondControl = mock(WificondControl.class);
469        IWificond wificond = mock(IWificond.class);
470        IClientInterface clientInterface = mock(IClientInterface.class);
471
472        when(wificondControl.setupDriverForClientMode()).thenReturn(clientInterface);
473        mWifiNative.setWificondControl(wificondControl);
474
475        IClientInterface returnedClientInterface = mWifiNative.setupDriverForClientMode();
476        assertEquals(clientInterface, returnedClientInterface);
477        verify(wificondControl).setupDriverForClientMode();
478        verify(mWifiNative).startHal(eq(true));
479    }
480
481    /**
482     * Verifies that setupDriverForClientMode() returns null when underlying WificondControl
483     * call fails.
484     */
485    @Test
486    public void testSetupDriverForClientModeError() {
487        WificondControl wificondControl = mock(WificondControl.class);
488        IWificond wificond = mock(IWificond.class);
489
490        when(wificondControl.setupDriverForClientMode()).thenReturn(null);
491        mWifiNative.setWificondControl(wificondControl);
492
493        IClientInterface returnedClientInterface = mWifiNative.setupDriverForClientMode();
494        assertEquals(null, returnedClientInterface);
495        verify(wificondControl).setupDriverForClientMode();
496    }
497
498    /**
499     * Verifies that setupDriverForSoftApMode() calls underlying WificondControl.
500     */
501    @Test
502    public void testSetupDriverForSoftApMode() {
503        WificondControl wificondControl = mock(WificondControl.class);
504        IWificond wificond = mock(IWificond.class);
505        IApInterface apInterface = mock(IApInterface.class);
506
507        when(wificondControl.setupDriverForSoftApMode()).thenReturn(apInterface);
508        mWifiNative.setWificondControl(wificondControl);
509
510        IApInterface returnedApInterface = mWifiNative.setupDriverForSoftApMode();
511        assertEquals(apInterface, returnedApInterface);
512        verify(wificondControl).setupDriverForSoftApMode();
513        verify(mWifiNative).startHal(eq(false));
514    }
515
516    /**
517     * Verifies that setupDriverForSoftApMode() returns null when underlying WificondControl
518     * call fails.
519     */
520    @Test
521    public void testSetupDriverForSoftApModeError() {
522        WificondControl wificondControl = mock(WificondControl.class);
523        IWificond wificond = mock(IWificond.class);
524
525        when(wificondControl.setupDriverForSoftApMode()).thenReturn(null);
526        mWifiNative.setWificondControl(wificondControl);
527
528        IApInterface returnedApInterface = mWifiNative.setupDriverForSoftApMode();
529        assertEquals(null, returnedApInterface);
530        verify(wificondControl).setupDriverForSoftApMode();
531    }
532
533    /**
534     * Verifies that enableSupplicant() calls underlying WificondControl.
535     */
536    @Test
537    public void testEnableSupplicant() {
538        WificondControl wificondControl = mock(WificondControl.class);
539        IWificond wificond = mock(IWificond.class);
540
541        mWifiNative.setWificondControl(wificondControl);
542
543        mWifiNative.enableSupplicant();
544        verify(wificondControl).enableSupplicant();
545    }
546
547    /**
548     * Verifies that disableSupplicant() calls underlying WificondControl.
549     */
550    @Test
551    public void testDisableSupplicant() {
552        WificondControl wificondControl = mock(WificondControl.class);
553        IWificond wificond = mock(IWificond.class);
554
555        mWifiNative.setWificondControl(wificondControl);
556
557        mWifiNative.disableSupplicant();
558        verify(wificondControl).disableSupplicant();
559    }
560
561    /**
562     * Verifies that tearDownInterfaces() calls underlying WificondControl.
563     */
564    @Test
565    public void testTearDownInterfaces() {
566        WificondControl wificondControl = mock(WificondControl.class);
567
568        when(wificondControl.tearDownInterfaces()).thenReturn(true);
569        mWifiNative.setWificondControl(wificondControl);
570
571        assertTrue(mWifiNative.tearDownInterfaces());
572        verify(wificondControl).tearDownInterfaces();
573    }
574
575    /**
576     * Verifies that signalPoll() calls underlying WificondControl.
577     */
578    @Test
579    public void testSignalPoll() throws Exception {
580        WificondControl wificondControl = mock(WificondControl.class);
581
582        when(wificondControl.signalPoll()).thenReturn(SIGNAL_POLL_RESULT);
583        mWifiNative.setWificondControl(wificondControl);
584
585        assertEquals(SIGNAL_POLL_RESULT, mWifiNative.signalPoll());
586        verify(wificondControl).signalPoll();
587    }
588
589    /**
590     * Verifies that getTxPacketCounters() calls underlying WificondControl.
591     */
592    @Test
593    public void testGetTxPacketCounters() throws Exception {
594        WificondControl wificondControl = mock(WificondControl.class);
595
596        when(wificondControl.getTxPacketCounters()).thenReturn(PACKET_COUNTERS_RESULT);
597        mWifiNative.setWificondControl(wificondControl);
598
599        assertEquals(PACKET_COUNTERS_RESULT, mWifiNative.getTxPacketCounters());
600        verify(wificondControl).getTxPacketCounters();
601    }
602
603    /**
604     * Verifies that the ANQP query command is correctly created.
605     */
606    @Test
607    public void testbuildAnqpQueryCommandWithOnlyHsSubtypes() {
608        String bssid = "34:12:ac:45:21:12";
609        Set<Integer> anqpIds = new TreeSet<>();
610        Set<Integer> hs20Subtypes = new TreeSet<>(Arrays.asList(3, 7));
611
612        String expectedCommand = "HS20_ANQP_GET " + bssid + " 3,7";
613        assertEquals(expectedCommand,
614                WifiNative.buildAnqpQueryCommand(bssid, anqpIds, hs20Subtypes));
615    }
616
617    /**
618     * Verifies that the ANQP query command is correctly created.
619     */
620    @Test
621    public void testbuildAnqpQueryCommandWithMixedTypes() {
622        String bssid = "34:12:ac:45:21:12";
623        Set<Integer> anqpIds = new TreeSet<>(Arrays.asList(1, 2, 5));
624        Set<Integer> hs20Subtypes = new TreeSet<>(Arrays.asList(3, 7));
625
626        String expectedCommand = "ANQP_GET " + bssid + " 1,2,5,hs20:3,hs20:7";
627        assertEquals(expectedCommand,
628                WifiNative.buildAnqpQueryCommand(bssid, anqpIds, hs20Subtypes));
629    }
630}
631