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.hotspot2;
18
19import static org.junit.Assert.assertEquals;
20import static org.junit.Assert.assertFalse;
21import static org.junit.Assert.assertTrue;
22import static org.mockito.Mockito.anyLong;
23import static org.mockito.Mockito.anyObject;
24import static org.mockito.Mockito.never;
25import static org.mockito.Mockito.reset;
26import static org.mockito.Mockito.verify;
27import static org.mockito.Mockito.when;
28import static org.mockito.MockitoAnnotations.initMocks;
29
30import android.test.suitebuilder.annotation.SmallTest;
31
32import com.android.server.wifi.Clock;
33import com.android.server.wifi.hotspot2.anqp.Constants;
34
35import org.junit.Before;
36import org.junit.Test;
37import org.mockito.Mock;
38
39import java.util.Arrays;
40import java.util.List;
41
42/**
43 * Unit tests for {@link com.android.server.wifi.hotspot2.ANQPRequestManager}.
44 */
45@SmallTest
46public class ANQPRequestManagerTest {
47    private static final long TEST_BSSID = 0x123456L;
48    private static final ANQPNetworkKey TEST_ANQP_KEY =
49            new ANQPNetworkKey("TestSSID", TEST_BSSID, 0, 0);
50
51    private static final List<Constants.ANQPElementType> R1_ANQP_WITHOUT_RC = Arrays.asList(
52            Constants.ANQPElementType.ANQPVenueName,
53            Constants.ANQPElementType.ANQPIPAddrAvailability,
54            Constants.ANQPElementType.ANQPNAIRealm,
55            Constants.ANQPElementType.ANQP3GPPNetwork,
56            Constants.ANQPElementType.ANQPDomName);
57
58    private static final List<Constants.ANQPElementType> R1_ANQP_WITH_RC = Arrays.asList(
59            Constants.ANQPElementType.ANQPVenueName,
60            Constants.ANQPElementType.ANQPIPAddrAvailability,
61            Constants.ANQPElementType.ANQPNAIRealm,
62            Constants.ANQPElementType.ANQP3GPPNetwork,
63            Constants.ANQPElementType.ANQPDomName,
64            Constants.ANQPElementType.ANQPRoamingConsortium);
65
66    private static final List<Constants.ANQPElementType> R1R2_ANQP_WITHOUT_RC = Arrays.asList(
67            Constants.ANQPElementType.ANQPVenueName,
68            Constants.ANQPElementType.ANQPIPAddrAvailability,
69            Constants.ANQPElementType.ANQPNAIRealm,
70            Constants.ANQPElementType.ANQP3GPPNetwork,
71            Constants.ANQPElementType.ANQPDomName,
72            Constants.ANQPElementType.HSFriendlyName,
73            Constants.ANQPElementType.HSWANMetrics,
74            Constants.ANQPElementType.HSConnCapability,
75            Constants.ANQPElementType.HSOSUProviders);
76
77    private static final List<Constants.ANQPElementType> R1R2_ANQP_WITH_RC = Arrays.asList(
78            Constants.ANQPElementType.ANQPVenueName,
79            Constants.ANQPElementType.ANQPIPAddrAvailability,
80            Constants.ANQPElementType.ANQPNAIRealm,
81            Constants.ANQPElementType.ANQP3GPPNetwork,
82            Constants.ANQPElementType.ANQPDomName,
83            Constants.ANQPElementType.ANQPRoamingConsortium,
84            Constants.ANQPElementType.HSFriendlyName,
85            Constants.ANQPElementType.HSWANMetrics,
86            Constants.ANQPElementType.HSConnCapability,
87            Constants.ANQPElementType.HSOSUProviders);
88
89    @Mock PasspointEventHandler mHandler;
90    @Mock Clock mClock;
91    ANQPRequestManager mManager;
92
93    /**
94     * Test setup.
95     */
96    @Before
97    public void setUp() throws Exception {
98        initMocks(this);
99        mManager = new ANQPRequestManager(mHandler, mClock);
100    }
101
102    /**
103     * Verify that the expected set of ANQP elements are being requested when the targeted AP
104     * doesn't provide roaming consortium OIs and doesn't support Hotspot 2.0 Release 2 ANQP
105     * elements, based on the IEs in the scan result .
106     *
107     * @throws Exception
108     */
109    @Test
110    public void requestR1ANQPElementsWithoutRC() throws Exception {
111        when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITHOUT_RC)).thenReturn(true);
112        assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, false));
113    }
114
115    /**
116     * Verify that the expected set of ANQP elements are being requested when the targeted AP
117     * does provide roaming consortium OIs and doesn't support Hotspot 2.0 Release ANQP elements,
118     * based on the IEs in the scan result.
119     *
120     * @throws Exception
121     */
122    @Test
123    public void requestR1ANQPElementsWithRC() throws Exception {
124        when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITH_RC)).thenReturn(true);
125        assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, true, false));
126    }
127
128    /**
129     * Verify that the expected set of ANQP elements are being requested when the targeted AP
130     * doesn't provide roaming consortium OIs and does support Hotspot 2.0 Release ANQP elements,
131     * based on the IEs in the scan result.
132     *
133     * @throws Exception
134     */
135    @Test
136    public void requestR1R2ANQPElementsWithoutRC() throws Exception {
137        when(mHandler.requestANQP(TEST_BSSID, R1R2_ANQP_WITHOUT_RC)).thenReturn(true);
138        assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, true));
139    }
140
141    /**
142     * Verify that the expected set of ANQP elements are being requested when the targeted AP
143     * does provide roaming consortium OIs and support Hotspot 2.0 Release ANQP elements,
144     * based on the IEs in the scan result.
145     *
146     * @throws Exception
147     */
148    @Test
149    public void requestR1R2ANQPElementsWithRC() throws Exception {
150        when(mHandler.requestANQP(TEST_BSSID, R1R2_ANQP_WITH_RC)).thenReturn(true);
151        assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, true, true));
152    }
153
154    /**
155     * Verify that attempt to request ANQP elements from an AP will fail when there is a request
156     * already pending.  The request will succeed when the hold off time is up.
157     *
158     * @throws Exception
159     */
160    @Test
161    public void requestANQPElementsWithPendingRequest() throws Exception {
162        // Send the initial request.
163        long startTime = 0;
164        when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITHOUT_RC)).thenReturn(true);
165        when(mClock.getElapsedSinceBootMillis()).thenReturn(startTime);
166        assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, false));
167        reset(mHandler);
168
169        // Attempt another request will fail while one is still pending and hold off time is not up
170        // yet.
171        when(mClock.getElapsedSinceBootMillis()).thenReturn(startTime + 1);
172        assertFalse(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, false));
173        verify(mHandler, never()).requestANQP(anyLong(), anyObject());
174        reset(mHandler);
175
176        // Attempt other request will succeed after the hold off time is up.
177        when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITHOUT_RC)).thenReturn(true);
178        when(mClock.getElapsedSinceBootMillis())
179                .thenReturn(startTime + ANQPRequestManager.BASE_HOLDOFF_TIME_MILLISECONDS);
180        assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, false));
181    }
182
183    /**
184     * Verify that an immediate attempt to request ANQP elements from an AP will succeed when
185     * the previous request is failed on sending.
186     *
187     * @throws Exception
188     */
189    @Test
190    public void requestANQPElementsAfterRequestSendFailure() throws Exception {
191        // Initial request failed to send.
192        long startTime = 0;
193        when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITHOUT_RC)).thenReturn(false);
194        when(mClock.getElapsedSinceBootMillis()).thenReturn(startTime);
195        assertFalse(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, false));
196        reset(mHandler);
197
198        // Verify that new request is not being held off after previous send failure.
199        when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITHOUT_RC)).thenReturn(true);
200        when(mClock.getElapsedSinceBootMillis()).thenReturn(startTime);
201        assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, false));
202    }
203
204    /**
205     * Verify that an immediate attempt to request ANQP elements from an AP will succeed when
206     * the previous request is completed with success.
207     *
208     * @throws Exception
209     */
210    @Test
211    public void requestANQPElementsAfterRequestSucceeded() throws Exception {
212        // Send the initial request.
213        long startTime = 0;
214        when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITHOUT_RC)).thenReturn(true);
215        when(mClock.getElapsedSinceBootMillis()).thenReturn(startTime);
216        assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, false));
217        reset(mHandler);
218
219        // Request completed with success. Verify that the key associated with the request
220        // is returned.
221        assertEquals(TEST_ANQP_KEY, mManager.onRequestCompleted(TEST_BSSID, true));
222
223        when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITHOUT_RC)).thenReturn(true);
224        when(mClock.getElapsedSinceBootMillis()).thenReturn(startTime + 1);
225        assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, false));
226    }
227
228    /**
229     * Verify that an immediate attempt to request ANQP elements from an AP will fail when
230     * the previous request is completed with failure.  The request will succeed after the
231     * hold off time is up.
232     *
233     * @throws Exception
234     */
235    @Test
236    public void requestANQPElementsAfterRequestFailed() throws Exception {
237        // Send the initial request.
238        long startTime = 0;
239        when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITHOUT_RC)).thenReturn(true);
240        when(mClock.getElapsedSinceBootMillis()).thenReturn(startTime);
241        assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, false));
242        reset(mHandler);
243
244        // Request completed with failure.  Verify that the key associated with the request
245        // is returned
246        assertEquals(TEST_ANQP_KEY, mManager.onRequestCompleted(TEST_BSSID, false));
247
248        // Attempt another request will fail since the hold off time is not up yet.
249        when(mClock.getElapsedSinceBootMillis()).thenReturn(startTime + 1);
250        assertFalse(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, false));
251        verify(mHandler, never()).requestANQP(anyLong(), anyObject());
252
253        // Attempt another request will succeed after the hold off time is up.
254        when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITHOUT_RC)).thenReturn(true);
255        when(mClock.getElapsedSinceBootMillis())
256                .thenReturn(startTime + ANQPRequestManager.BASE_HOLDOFF_TIME_MILLISECONDS);
257        assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, false));
258    }
259
260    /**
261     * Verify the hold off time for each unanswered query, and that it will stay the same after
262     * reaching the max hold off count {@link ANQPRequestManager#MAX_HOLDOFF_COUNT}.
263     *
264     * @throws Exception
265     */
266    @Test
267    public void requestANQPElementsWithMaxRetries() throws Exception {
268        long currentTime = 0;
269
270        // Initial request.
271        when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITHOUT_RC)).thenReturn(true);
272        when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTime);
273        assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, false));
274        reset(mHandler);
275
276        // Sending the request with the hold off time based on the current hold off count.
277        for (int i = 0; i <= ANQPRequestManager.MAX_HOLDOFF_COUNT; i++) {
278            long currentHoldOffTime = ANQPRequestManager.BASE_HOLDOFF_TIME_MILLISECONDS * (1 << i);
279            currentTime += (currentHoldOffTime - 1);
280
281            // Request will fail before the hold off time is up.
282            when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTime);
283            assertFalse(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, false));
284            verify(mHandler, never()).requestANQP(anyLong(), anyObject());
285
286            // Request will succeed when the hold off time is up.
287            currentTime += 1;
288            when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITHOUT_RC)).thenReturn(true);
289            when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTime);
290            assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, false));
291            reset(mHandler);
292        }
293
294        // Verify that the hold off time is max out at the maximum hold off count.
295        currentTime += (ANQPRequestManager.BASE_HOLDOFF_TIME_MILLISECONDS
296                * (1 << ANQPRequestManager.MAX_HOLDOFF_COUNT) - 1);
297
298        when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTime);
299        assertFalse(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, false));
300        verify(mHandler, never()).requestANQP(anyLong(), anyObject());
301
302        currentTime += 1;
303        when(mHandler.requestANQP(TEST_BSSID, R1_ANQP_WITHOUT_RC)).thenReturn(true);
304        when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTime);
305        assertTrue(mManager.requestANQPElements(TEST_BSSID, TEST_ANQP_KEY, false, false));
306        reset(mHandler);
307    }
308}
309