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.assertEquals;
20import static org.junit.Assert.assertNotNull;
21import static org.junit.Assert.assertNull;
22import static org.mockito.Mockito.when;
23import static org.mockito.MockitoAnnotations.initMocks;
24
25import android.net.wifi.ScanResult;
26import android.net.wifi.WifiSsid;
27import android.test.suitebuilder.annotation.SmallTest;
28import android.util.Log;
29
30import com.android.server.wifi.anqp.ANQPElement;
31import com.android.server.wifi.anqp.Constants;
32import com.android.server.wifi.hotspot2.ANQPData;
33import com.android.server.wifi.hotspot2.AnqpCache;
34import com.android.server.wifi.hotspot2.NetworkDetail;
35
36import org.junit.Test;
37import org.mockito.Mock;
38
39import java.util.ArrayList;
40import java.util.Arrays;
41import java.util.HashMap;
42import java.util.List;
43import java.util.Map;
44
45
46/**
47 * Unit tests for {@link com.android.server.wifi.hotspot2.AnqpCache}.
48 */
49@SmallTest
50public class AnqpCacheTest {
51
52    private static final String TAG = "AnqpCacheTest";
53
54    private static class NetworkDescription {
55        ScanDetail[] mScanDetails;
56        static int[] sChannels = new int[]{2412, 2437, 2462, 5180, 5220, 5745, 5825};
57        static int[] sRSSIs = new int[]{ -50, -80, -60, -80, -55, -90, -75};
58
59        NetworkDescription(String ssid, String bssidPrefix) {
60            WifiSsid wifiSsid = WifiSsid.createFromAsciiEncoded(ssid);
61            mScanDetails = new ScanDetail[sChannels.length];
62            for (int i = 0; i < sChannels.length; i++) {
63                String bssid = String.format("%s:%02x", bssidPrefix, i);
64                ScanResult.InformationElement[] ie = new ScanResult.InformationElement[1];
65                ie[0] = ScanResults.generateSsidIe(ssid);
66                List<String> anqpLines = new ArrayList<String>();
67                NetworkDetail nd = new NetworkDetail(bssid, ie,
68                        new ArrayList<String>(), sChannels[i]);
69                mScanDetails[i] = new ScanDetail(nd, wifiSsid,
70                        bssid, "", sRSSIs[i], sChannels[i], Long.MAX_VALUE, ie, anqpLines);
71            }
72        }
73    }
74
75    private static final String ATT_SSID         = "att_wifi";
76    private static final String ATT_BSSID_PREFIX = "aa:44:bb:55:cc";
77    private static final String TWC_SSID         = "TWCWIFI";
78    private static final String TWC_BSSID_PREFIX = "11:aa:22:bb:33";
79
80    private static ScanDetail[] getAttWifiNetworkDescription() {
81        NetworkDescription network = new NetworkDescription(ATT_SSID, ATT_BSSID_PREFIX);
82        return network.mScanDetails;
83    }
84
85    private static ScanDetail[] getTwcWifiNetworkDescription() {
86        NetworkDescription network = new NetworkDescription(TWC_SSID, TWC_BSSID_PREFIX);
87        return network.mScanDetails;
88    }
89
90    private static List<Constants.ANQPElementType> buildQueryList() {
91        List<Constants.ANQPElementType> list = Arrays.asList(
92                Constants.ANQPElementType.class.getEnumConstants());
93        return list;
94    }
95
96    private static Map<Constants.ANQPElementType, ANQPElement> buildAnqpResult() {
97        Map<Constants.ANQPElementType, ANQPElement> elements = new HashMap<>();
98        List<Constants.ANQPElementType> list = Arrays.asList(
99                Constants.ANQPElementType.class.getEnumConstants());
100        for (final Constants.ANQPElementType type : list) {
101            ANQPElement element = new ANQPElement(type) {
102                @Override
103                public Constants.ANQPElementType getID() {
104                    return super.getID();
105                }
106            };
107            elements.put(type, element);
108        }
109
110        return elements;
111    }
112
113    private void advanceTimeAndTrimCache(long howManyMillis) {
114        mCurrentTimeMillis += howManyMillis;
115        Log.d(TAG, "Time set to " + mCurrentTimeMillis);
116        when(mClock.currentTimeMillis()).thenReturn(mCurrentTimeMillis);
117        mCache.clear(false, true);
118    }
119
120    public AnqpCacheTest() {}
121
122    private static final long SECOND_MS = 1000;
123    private static final long MINUTE_MS = 60 * SECOND_MS;
124
125    @Mock Clock mClock;
126    long mCurrentTimeMillis = 1000000000;
127    AnqpCache mCache;
128
129    /** verify that ANQP data is cached per the (rather abstract) spec */
130    @Test
131    public void basicAddQueryAndExpiry() {
132        initMocks(this);
133
134        AnqpCache cache = mCache = new AnqpCache(mClock);
135        advanceTimeAndTrimCache(0);
136
137        List<Constants.ANQPElementType> queryList = buildQueryList();
138
139        ScanDetail[] attScanDetails = getAttWifiNetworkDescription();
140        ScanDetail[] twcScanDetails = getTwcWifiNetworkDescription();
141
142        /* query att network at time 0 */
143        for (ScanDetail scanDetail : attScanDetails) {
144            cache.initiate(scanDetail.getNetworkDetail(), queryList);
145        }
146
147        /* verify that no data can be returned */
148        for (ScanDetail scanDetail : attScanDetails) {
149            ANQPData data = cache.getEntry(scanDetail.getNetworkDetail());
150            assertNull(data);
151        }
152
153        /* update ANQP results after 1 min */
154        advanceTimeAndTrimCache(1 * MINUTE_MS);
155
156        Map<Constants.ANQPElementType, ANQPElement> anqpResults = buildAnqpResult();
157
158        for (ScanDetail scanDetail : attScanDetails) {
159            cache.update(scanDetail.getNetworkDetail(), anqpResults);
160        }
161
162        /* check ANQP results after another 1 min */
163        advanceTimeAndTrimCache(1 * MINUTE_MS);
164
165        for (ScanDetail scanDetail : attScanDetails) {
166            ANQPData data = cache.getEntry(scanDetail.getNetworkDetail());
167            assertNotNull(data);
168            NetworkDetail nd = data.getNetwork();
169            Map<Constants.ANQPElementType, ANQPElement> anqp = data.getANQPElements();
170            assertEquals(scanDetail.getBSSIDString(), nd.getBSSIDString());
171            assertEquals(anqpResults.size(), anqp.size());
172        }
173
174        /* query ANQP results for twcwifi after another 10 min */
175        advanceTimeAndTrimCache(10 * MINUTE_MS);
176
177        for (ScanDetail scanDetail : twcScanDetails) {
178            cache.initiate(scanDetail.getNetworkDetail(), queryList);
179        }
180
181        /* update ANQP results for twcwifi after another 10 min */
182        advanceTimeAndTrimCache(1 * MINUTE_MS);
183
184        for (ScanDetail scanDetail : twcScanDetails) {
185            cache.update(scanDetail.getNetworkDetail(), anqpResults);
186        }
187
188        /* check all results after 1 minute */
189        advanceTimeAndTrimCache(1 * MINUTE_MS);
190
191        for (ScanDetail scanDetail : attScanDetails) {
192            ANQPData data = cache.getEntry(scanDetail.getNetworkDetail());
193            assertNull(data);
194        }
195
196        for (ScanDetail scanDetail : twcScanDetails) {
197            ANQPData data = cache.getEntry(scanDetail.getNetworkDetail());
198            assertNotNull(data);
199            NetworkDetail nd = data.getNetwork();
200            Map<Constants.ANQPElementType, ANQPElement> anqp = data.getANQPElements();
201            assertEquals(scanDetail.getBSSIDString(), nd.getBSSIDString());
202            assertEquals(anqpResults.size(), anqp.size());
203        }
204    }
205}
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237