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 android.net.wifi; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.junit.Assert.fail; 22 import static org.mockito.Mockito.when; 23 24 import android.content.Context; 25 import android.net.NetworkKey; 26 import android.net.RssiCurve; 27 import android.net.ScoredNetwork; 28 import android.net.WifiKey; 29 import android.net.wifi.WifiNetworkScoreCache.CacheListener; 30 import android.os.Handler; 31 import android.os.HandlerThread; 32 33 import androidx.test.filters.SmallTest; 34 import androidx.test.runner.AndroidJUnit4; 35 36 import com.google.common.collect.ImmutableList; 37 38 import org.junit.Before; 39 import org.junit.Test; 40 import org.junit.runner.RunWith; 41 import org.mockito.Mock; 42 import org.mockito.MockitoAnnotations; 43 44 import java.util.List; 45 import java.util.concurrent.CountDownLatch; 46 import java.util.concurrent.TimeUnit; 47 48 /** Unit tests for {@link WifiNetworkScoreCache}. */ 49 @RunWith(AndroidJUnit4.class) 50 @SmallTest 51 public class WifiNetworkScoreCacheTest { 52 53 public static final String SSID = "ssid"; 54 public static final String SSID2 = "ssid2"; 55 public static final String SSID3 = "ssid3"; 56 public static final String FORMATTED_SSID = "\"" + SSID + "\""; 57 public static final String FORMATTED_SSID2 = "\"" + SSID2 + "\""; 58 public static final String FORMATTED_SSID3 = "\"" + SSID3 + "\""; 59 public static final String BSSID = "AA:AA:AA:AA:AA:AA"; 60 61 public static final WifiKey VALID_KEY = new WifiKey(FORMATTED_SSID, BSSID); 62 63 public static final ScanResult VALID_SCAN_RESULT = buildScanResult(SSID, BSSID); 64 65 @Mock private Context mockApplicationContext; 66 @Mock private Context mockContext; // isn't used, can be null 67 @Mock private RssiCurve mockRssiCurve; 68 69 70 private CacheListener mCacheListener; 71 private CountDownLatch mLatch; 72 private Handler mHandler; 73 private List<ScoredNetwork> mUpdatedNetworksCaptor; 74 private ScoredNetwork mValidScoredNetwork; 75 private WifiNetworkScoreCache mScoreCache; 76 buildScanResult(String ssid, String bssid)77 private static ScanResult buildScanResult(String ssid, String bssid) { 78 return new ScanResult( 79 WifiSsid.fromUtf8Text(ssid), 80 bssid, 81 "" /* caps */, 82 0 /* level */, 83 0 /* frequency */, 84 0 /* tsf */, 85 0 /* distCm */, 86 0 /* distSdCm*/); 87 } 88 buildScoredNetwork(WifiKey key, RssiCurve curve)89 private static ScoredNetwork buildScoredNetwork(WifiKey key, RssiCurve curve) { 90 return new ScoredNetwork(new NetworkKey(key), curve); 91 } 92 93 // Called from setup initializeCacheWithValidScoredNetwork()94 private void initializeCacheWithValidScoredNetwork() { 95 mScoreCache.updateScores(ImmutableList.of(mValidScoredNetwork)); 96 } 97 98 @Before setUp()99 public void setUp() { 100 MockitoAnnotations.initMocks(this); 101 102 when(mockContext.getApplicationContext()).thenReturn(mockApplicationContext); 103 104 mValidScoredNetwork = buildScoredNetwork(VALID_KEY, mockRssiCurve); 105 mScoreCache = new WifiNetworkScoreCache(mockContext); 106 initializeCacheWithValidScoredNetwork(); 107 108 HandlerThread thread = new HandlerThread("WifiNetworkScoreCacheTest Handler Thread"); 109 thread.start(); 110 mHandler = new Handler(thread.getLooper()); 111 mLatch = new CountDownLatch(1); 112 mCacheListener = new CacheListener(mHandler) { 113 @Override 114 public void networkCacheUpdated(List<ScoredNetwork> updatedNetworks) { 115 mUpdatedNetworksCaptor = updatedNetworks; 116 mLatch.countDown(); 117 } 118 }; 119 } 120 121 122 @Test isScoredNetworkShouldReturnTrueAfterUpdateScoresIsCalled()123 public void isScoredNetworkShouldReturnTrueAfterUpdateScoresIsCalled() { 124 assertThat(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT)).isTrue(); 125 } 126 127 @Test isScoredNetworkShouldReturnFalseAfterClearScoresIsCalled()128 public void isScoredNetworkShouldReturnFalseAfterClearScoresIsCalled() { 129 mScoreCache.clearScores(); 130 assertThat(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT)).isFalse(); 131 } 132 133 @Test updateScoresShouldAddNewNetwork()134 public void updateScoresShouldAddNewNetwork() { 135 WifiKey key2 = new WifiKey("\"ssid2\"", BSSID); 136 ScoredNetwork network2 = buildScoredNetwork(key2, mockRssiCurve); 137 ScanResult result2 = buildScanResult("ssid2", BSSID); 138 139 mScoreCache.updateScores(ImmutableList.of(network2)); 140 141 assertThat(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT)).isTrue(); 142 assertThat(mScoreCache.isScoredNetwork(result2)).isTrue(); 143 } 144 145 @Test hasScoreCurveShouldReturnTrue()146 public void hasScoreCurveShouldReturnTrue() { 147 assertThat(mScoreCache.hasScoreCurve(VALID_SCAN_RESULT)).isTrue(); 148 } 149 150 @Test hasScoreCurveShouldReturnFalseWhenNoCachedNetwork()151 public void hasScoreCurveShouldReturnFalseWhenNoCachedNetwork() { 152 ScanResult unscored = buildScanResult("fake", BSSID); 153 assertThat(mScoreCache.hasScoreCurve(unscored)).isFalse(); 154 } 155 156 @Test hasScoreCurveShouldReturnFalseWhenScoredNetworkHasNoCurve()157 public void hasScoreCurveShouldReturnFalseWhenScoredNetworkHasNoCurve() { 158 ScoredNetwork noCurve = buildScoredNetwork(VALID_KEY, null /* rssiCurve */); 159 mScoreCache.updateScores(ImmutableList.of(noCurve)); 160 161 assertThat(mScoreCache.hasScoreCurve(VALID_SCAN_RESULT)).isFalse(); 162 } 163 164 @Test getNetworkScoreShouldReturnScore()165 public void getNetworkScoreShouldReturnScore() { 166 final byte score = 50; 167 final int rssi = -70; 168 ScanResult result = new ScanResult(VALID_SCAN_RESULT); 169 result.level = rssi; 170 171 when(mockRssiCurve.lookupScore(rssi)).thenReturn(score); 172 173 assertThat(mScoreCache.getNetworkScore(result)).isEqualTo(score); 174 } 175 176 @Test getMeteredHintShouldReturnFalse()177 public void getMeteredHintShouldReturnFalse() { 178 assertThat(mScoreCache.getMeteredHint(VALID_SCAN_RESULT)).isFalse(); 179 } 180 181 @Test getMeteredHintShouldReturnTrue()182 public void getMeteredHintShouldReturnTrue() { 183 ScoredNetwork network = 184 new ScoredNetwork( 185 new NetworkKey(VALID_KEY), mockRssiCurve, true /* metered Hint */); 186 mScoreCache.updateScores(ImmutableList.of(network)); 187 188 assertThat(mScoreCache.getMeteredHint(VALID_SCAN_RESULT)).isTrue(); 189 } 190 191 @Test updateScoresShouldInvokeCacheListener_networkCacheUpdated()192 public void updateScoresShouldInvokeCacheListener_networkCacheUpdated() { 193 mScoreCache = new WifiNetworkScoreCache(mockContext, mCacheListener); 194 initializeCacheWithValidScoredNetwork(); 195 196 try { 197 mLatch.await(1, TimeUnit.SECONDS); // wait for listener to be executed 198 } catch (InterruptedException e) { 199 fail("Interrupted Exception while waiting for listener to be invoked."); 200 } 201 // One network should be updated. 202 assertThat(mUpdatedNetworksCaptor.size()).isEqualTo(1); 203 assertThat(mUpdatedNetworksCaptor.get(0)).isEqualTo(mValidScoredNetwork); 204 } 205 206 @Test leastRecentlyUsedScore_shouldBeEvictedFromCache()207 public void leastRecentlyUsedScore_shouldBeEvictedFromCache() { 208 mScoreCache = new WifiNetworkScoreCache(mockContext, mCacheListener, 2 /* maxCacheSize */); 209 210 ScoredNetwork network1 = mValidScoredNetwork; 211 ScoredNetwork network2 = buildScoredNetwork( 212 new WifiKey(FORMATTED_SSID2, BSSID), mockRssiCurve); 213 ScoredNetwork network3 = buildScoredNetwork( 214 new WifiKey(FORMATTED_SSID3, BSSID), mockRssiCurve); 215 mScoreCache.updateScores(ImmutableList.of(network1)); 216 mScoreCache.updateScores(ImmutableList.of(network2)); 217 218 // First score should be evicted because max cache size has been reached. 219 mScoreCache.updateScores(ImmutableList.of(network3)); 220 221 assertThat(mScoreCache.hasScoreCurve(buildScanResult(SSID2, BSSID))).isTrue(); 222 assertThat(mScoreCache.hasScoreCurve(buildScanResult(SSID3, BSSID))).isTrue(); 223 assertThat(mScoreCache.hasScoreCurve(VALID_SCAN_RESULT)).isFalse(); 224 } 225 } 226