WifiScoreReportTest.java revision 9b256a5cb87062b7ae1696324e2bd7c9b1ceca27
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.assertFalse; 21import static org.junit.Assert.assertTrue; 22import static org.mockito.Mockito.anyInt; 23import static org.mockito.Mockito.atLeast; 24import static org.mockito.Mockito.times; 25import static org.mockito.Mockito.verify; 26import static org.mockito.Mockito.when; 27 28import android.content.Context; 29import android.content.res.Resources; 30import android.net.NetworkAgent; 31import android.net.wifi.WifiConfiguration; 32import android.net.wifi.WifiInfo; 33 34import com.android.internal.R; 35 36import org.junit.After; 37import org.junit.Before; 38import org.junit.Test; 39import org.mockito.Mock; 40import org.mockito.MockitoAnnotations; 41 42import java.util.Arrays; 43 44/** 45 * Unit tests for {@link com.android.server.wifi.WifiScoreReport}. 46 */ 47public class WifiScoreReportTest { 48 49 private static final int CELLULAR_THRESHOLD_SCORE = 50; 50 51 WifiConfiguration mWifiConfiguration; 52 WifiScoreReport mWifiScoreReport; 53 ScanDetailCache mScanDetailCache; 54 WifiInfo mWifiInfo; 55 @Mock Context mContext; 56 @Mock NetworkAgent mNetworkAgent; 57 @Mock Resources mResources; 58 @Mock WifiConfigManager mWifiConfigManager; 59 @Mock WifiMetrics mWifiMetrics; 60 61 /** 62 * Sets up resource values for testing 63 * 64 * See frameworks/base/core/res/res/values/config.xml 65 */ 66 private void setUpResources(Resources resources) { 67 when(resources.getInteger( 68 R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz)) 69 .thenReturn(-82); 70 when(resources.getInteger( 71 R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz)) 72 .thenReturn(-70); 73 when(resources.getInteger( 74 R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_5GHz)) 75 .thenReturn(-57); 76 when(resources.getInteger( 77 R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz)) 78 .thenReturn(-85); 79 when(resources.getInteger( 80 R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz)) 81 .thenReturn(-73); 82 when(resources.getInteger( 83 R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_24GHz)) 84 .thenReturn(-60); 85 when(resources.getInteger( 86 R.integer.config_wifi_framework_wifi_score_bad_link_speed_24)) 87 .thenReturn(6); // Mbps 88 when(resources.getInteger( 89 R.integer.config_wifi_framework_wifi_score_bad_link_speed_5)) 90 .thenReturn(12); 91 when(resources.getInteger( 92 R.integer.config_wifi_framework_wifi_score_good_link_speed_24)) 93 .thenReturn(24); 94 when(resources.getInteger( 95 R.integer.config_wifi_framework_wifi_score_good_link_speed_5)) 96 .thenReturn(36); 97 when(resources.getBoolean( 98 R.bool.config_wifi_framework_cellular_handover_enable_user_triggered_adjustment)) 99 .thenReturn(true); 100 } 101 102 /** 103 * Pulls the final score from a report string 104 * 105 * The report string is essentially free-form, intended for debugging, 106 * but we would like to know that the score is in there somewhere. 107 * 108 * Currently, the score is found as the last value in a comma-separated 109 * list enclosed in square brackets. 110 */ 111 private int fishScoreFromReportString(String report) { 112 int score = 0; 113 if (report != null) { 114 String[] f = report.split("]"); 115 assertTrue(f.length > 1); 116 f = f[f.length - 2].split(","); 117 score = Integer.parseInt(f[f.length - 1]); 118 // clipping happens after stashing in report string, so do that here. 119 score = Integer.min(score, NetworkAgent.WIFI_BASE_SCORE); 120 } 121 return score; 122 } 123 124 /** 125 * Sets up for unit test 126 */ 127 @Before 128 public void setUp() throws Exception { 129 MockitoAnnotations.initMocks(this); 130 setUpResources(mResources); 131 WifiConfiguration config = new WifiConfiguration(); 132 config.SSID = "nooooooooooo"; 133 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 134 config.hiddenSSID = false; 135 mWifiInfo = new WifiInfo(); 136 mWifiInfo.setFrequency(2410); 137 when(mWifiConfigManager.getSavedNetworks()).thenReturn(Arrays.asList(config)); 138 when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config); 139 mWifiConfiguration = config; 140 int maxSize = 10; 141 int trimSize = 5; 142 mScanDetailCache = new ScanDetailCache(config, maxSize, trimSize); 143 // TODO: populate the cache, but probably in the test cases, not here. 144 when(mWifiConfigManager.getScanDetailCacheForNetwork(anyInt())) 145 .thenReturn(mScanDetailCache); 146 when(mContext.getResources()).thenReturn(mResources); 147 mWifiScoreReport = new WifiScoreReport(mContext, mWifiConfigManager); 148 } 149 150 /** 151 * Cleans up after test 152 */ 153 @After 154 public void tearDown() throws Exception { 155 mResources = null; 156 mWifiScoreReport = null; 157 mWifiConfigManager = null; 158 mWifiMetrics = null; 159 } 160 161 /** 162 * Test for score reporting 163 * 164 * The score should be sent to both the NetworkAgent and the 165 * WifiMetrics 166 */ 167 @Test 168 public void calculateAndReportScoreSucceeds() throws Exception { 169 int aggressiveHandover = 0; 170 mWifiInfo.setRssi(-77); 171 mWifiScoreReport.calculateAndReportScore(mWifiInfo, 172 mNetworkAgent, aggressiveHandover, mWifiMetrics); 173 verify(mNetworkAgent).sendNetworkScore(anyInt()); 174 verify(mWifiMetrics).incrementWifiScoreCount(anyInt()); 175 } 176 177 /** 178 * Test for operation with null NetworkAgent 179 * 180 * Expect to not die, and to calculate the score and report to metrics. 181 */ 182 @Test 183 public void networkAgentMayBeNull() throws Exception { 184 mWifiInfo.setRssi(-33); 185 mWifiScoreReport.enableVerboseLogging(true); 186 mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics); 187 verify(mWifiMetrics).incrementWifiScoreCount(anyInt()); 188 } 189 190 /** 191 * Test operation of saved last report 192 * 193 * One score is calculated 194 * Expect: last report is not valid before any score is calculated 195 * Expect: last report is valid after a score is calculated 196 * Expect: the score in the last report string matches the reported score 197 * Expect: reset makes the last report invalid again 198 */ 199 @Test 200 public void makeSureLastReportWorks() throws Exception { 201 mWifiInfo.setRssi(-33); 202 assertFalse(mWifiScoreReport.isLastReportValid()); 203 mWifiScoreReport.enableVerboseLogging(true); 204 mWifiScoreReport.calculateAndReportScore(mWifiInfo, mNetworkAgent, 0, mWifiMetrics); 205 assertTrue(mWifiScoreReport.isLastReportValid()); 206 String report = mWifiScoreReport.getLastReport(); 207 int score = fishScoreFromReportString(report); 208 verify(mWifiMetrics).incrementWifiScoreCount(score); 209 verify(mNetworkAgent).sendNetworkScore(score); 210 mWifiScoreReport.reset(); 211 assertFalse(mWifiScoreReport.isLastReportValid()); 212 assertTrue(mWifiScoreReport.getLastReport().equals("")); 213 } 214 215 /** 216 * Test bad linkspeed counter 217 * 218 * Expect badLinkspeed count to be incemented based on bad link speed. 219 * Expect counter to be pinned at a maximum value. 220 * Expect counter to be cleared by reset. 221 */ 222 @Test 223 public void badLinkspeedCounter() throws Exception { 224 mWifiInfo.setRssi(-123); 225 mWifiInfo.setLinkSpeed(1); 226 mWifiInfo.setFrequency(2410); 227 assertFalse(mWifiScoreReport.isLastReportValid()); 228 mWifiScoreReport.enableVerboseLogging(true); 229 assertEquals(0, mWifiScoreReport.getLastBadLinkspeedcount()); 230 mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics); 231 assertEquals(1, mWifiScoreReport.getLastBadLinkspeedcount()); 232 mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics); 233 assertEquals(2, mWifiScoreReport.getLastBadLinkspeedcount()); 234 mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics); 235 assertEquals(3, mWifiScoreReport.getLastBadLinkspeedcount()); 236 mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 1, mWifiMetrics); 237 mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics); 238 mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 1, mWifiMetrics); 239 mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics); 240 mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics); 241 mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics); 242 assertEquals(6, mWifiScoreReport.getLastBadLinkspeedcount()); // pinned at limit 243 verify(mWifiMetrics, times(9)).incrementWifiScoreCount(anyInt()); 244 assertTrue(mWifiScoreReport.isLastReportValid()); 245 mWifiScoreReport.reset(); 246 assertEquals(0, mWifiScoreReport.getLastBadLinkspeedcount()); 247 } 248 249 /** 250 * Exercise the rates with low RSSI 251 * 252 * The setup has a low (not bad) RSSI, and data movement (txSuccessRate) above 253 * the threshold. 254 * 255 * Expect a score above threshold. 256 */ 257 @Test 258 public void allowLowRssiIfDataIsMoving() throws Exception { 259 mWifiInfo.setRssi(-80); 260 mWifiInfo.setLinkSpeed(6); // Mbps 261 mWifiInfo.txSuccessRate = 5.1; // proportional to pps 262 mWifiInfo.rxSuccessRate = 5.1; 263 for (int i = 0; i < 10; i++) { 264 mWifiScoreReport.calculateAndReportScore(mWifiInfo, mNetworkAgent, 0, mWifiMetrics); 265 } 266 assertTrue(mWifiScoreReport.isLastReportValid()); 267 int score = fishScoreFromReportString(mWifiScoreReport.getLastReport()); 268 assertTrue(score > CELLULAR_THRESHOLD_SCORE); 269 } 270 271 /** 272 * Bad RSSI without data moving should allow handoff 273 * 274 * The setup has a bad RSSI, and the txSuccessRate is below threshold; several 275 * scoring iterations are performed. 276 * 277 * Expect the score to drop below the handoff threshold. 278 */ 279 @Test 280 public void giveUpOnBadRssiWhenDataIsNotMoving() throws Exception { 281 mWifiInfo.setRssi(-100); 282 mWifiInfo.setLinkSpeed(6); // Mbps 283 mWifiInfo.setFrequency(5010); 284 mWifiScoreReport.enableVerboseLogging(true); 285 mWifiInfo.txSuccessRate = 0.1; 286 mWifiInfo.rxSuccessRate = 0.1; 287 for (int i = 0; i < 10; i++) { 288 mWifiScoreReport.calculateAndReportScore(mWifiInfo, mNetworkAgent, 0, mWifiMetrics); 289 String report = mWifiScoreReport.getLastReport(); 290 assertTrue(report.contains(" br ")); 291 } 292 assertTrue(mWifiScoreReport.isLastReportValid()); 293 int score = fishScoreFromReportString(mWifiScoreReport.getLastReport()); 294 assertTrue(score < CELLULAR_THRESHOLD_SCORE); 295 verify(mNetworkAgent, atLeast(1)).sendNetworkScore(score); 296 } 297} 298