HalDeviceManagerTest.java revision dd4dcab629d1045b08f58f699a4a09ecc8cd23e3
1/* 2 * Copyright (C) 2017 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.mockito.Matchers.any; 20import static org.mockito.Matchers.anyLong; 21import static org.mockito.Matchers.anyString; 22import static org.mockito.Matchers.eq; 23import static org.mockito.Mockito.inOrder; 24import static org.mockito.Mockito.mock; 25import static org.mockito.Mockito.verify; 26import static org.mockito.Mockito.verifyNoMoreInteractions; 27import static org.mockito.Mockito.when; 28 29import android.hardware.wifi.V1_0.IWifi; 30import android.hardware.wifi.V1_0.IWifiEventCallback; 31import android.hardware.wifi.V1_0.WifiStatus; 32import android.hardware.wifi.V1_0.WifiStatusCode; 33import android.hidl.manager.V1_0.IServiceManager; 34import android.hidl.manager.V1_0.IServiceNotification; 35import android.os.IHwBinder; 36import android.os.test.TestLooper; 37import android.util.Log; 38 39import org.junit.After; 40import org.junit.Before; 41import org.junit.Rule; 42import org.junit.Test; 43import org.junit.rules.ErrorCollector; 44import org.mockito.ArgumentCaptor; 45import org.mockito.InOrder; 46import org.mockito.Mock; 47import org.mockito.MockitoAnnotations; 48 49import java.io.PrintWriter; 50import java.io.StringWriter; 51 52/** 53 * Unit test harness for HalDeviceManagerTest. 54 */ 55public class HalDeviceManagerTest { 56 private HalDeviceManager mDut; 57 @Mock IServiceManager mServiceManagerMock; 58 @Mock IWifi mWifiMock; 59 @Mock HalDeviceManager.ManagerStatusCallback mManagerStatusCallbackMock; 60 TestLooper mTestLooper; 61 private ArgumentCaptor<IHwBinder.DeathRecipient> mDeathRecipientCaptor = 62 ArgumentCaptor.forClass(IHwBinder.DeathRecipient.class); 63 private ArgumentCaptor<IServiceNotification.Stub> mServiceNotificationCaptor = 64 ArgumentCaptor.forClass(IServiceNotification.Stub.class); 65 private ArgumentCaptor<IWifiEventCallback> mWifiEventCallbackCaptor = ArgumentCaptor.forClass( 66 IWifiEventCallback.class); 67 private InOrder mInOrder; 68 @Rule public ErrorCollector collector = new ErrorCollector(); 69 private WifiStatus mStatusOk; 70 private WifiStatus mStatusFail; 71 72 private class HalDeviceManagerSpy extends HalDeviceManager { 73 @Override 74 protected IWifi getWifiServiceMockable() { 75 return mWifiMock; 76 } 77 78 @Override 79 protected IServiceManager getServiceManagerMockable() { 80 return mServiceManagerMock; 81 } 82 } 83 84 @Before 85 public void before() throws Exception { 86 MockitoAnnotations.initMocks(this); 87 88 mTestLooper = new TestLooper(); 89 90 // initialize dummy status objects 91 mStatusOk = new WifiStatus(); 92 mStatusOk.code = WifiStatusCode.SUCCESS; 93 mStatusFail = new WifiStatus(); 94 mStatusFail.code = WifiStatusCode.ERROR_UNKNOWN; 95 96 when(mServiceManagerMock.linkToDeath(any(IHwBinder.DeathRecipient.class), 97 anyLong())).thenReturn(true); 98 when(mServiceManagerMock.registerForNotifications(anyString(), anyString(), 99 any(IServiceNotification.Stub.class))).thenReturn(true); 100 when(mWifiMock.linkToDeath(any(IHwBinder.DeathRecipient.class), anyLong())).thenReturn( 101 true); 102 when(mWifiMock.registerEventCallback(any(IWifiEventCallback.class))).thenReturn(mStatusOk); 103 when(mWifiMock.start()).thenReturn(mStatusOk); 104 when(mWifiMock.stop()).thenReturn(mStatusOk); 105 106 mInOrder = inOrder(mServiceManagerMock, mWifiMock, mManagerStatusCallbackMock); 107 108 mDut = new HalDeviceManagerSpy(); 109 executeAndValidateInitializationSequence(); 110 } 111 112 /** 113 * Print out the dump of the device manager after each test. Not used in test validation 114 * (internal state) - but can help in debugging failed tests. 115 */ 116 @After 117 public void after() throws Exception { 118 dumpDut("after: "); 119 } 120 121 /** 122 * Test basic startup flow: 123 * - IServiceManager registrations 124 * - IWifi registrations 125 * - IWifi startup delayed 126 * - Start Wi-Fi -> onStart 127 * - Stop Wi-Fi -> onStop 128 */ 129 @Test 130 public void testStartStopFlow() throws Exception { 131 executeAndValidateStartupSequence(); 132 133 // act: stop Wi-Fi 134 mDut.stop(); 135 mTestLooper.dispatchAll(); 136 137 // verify: onStop called 138 mInOrder.verify(mWifiMock).stop(); 139 mInOrder.verify(mManagerStatusCallbackMock).onStop(); 140 141 verifyNoMoreInteractions(mServiceManagerMock, mWifiMock, mManagerStatusCallbackMock); 142 } 143 144 /** 145 * Validate that multiple callback registrations are called and that duplicate ones are 146 * only called once. 147 */ 148 @Test 149 public void testMultipleCallbackRegistrations() throws Exception { 150 // register another 2 callbacks - one of them twice 151 HalDeviceManager.ManagerStatusCallback callback1 = mock( 152 HalDeviceManager.ManagerStatusCallback.class); 153 HalDeviceManager.ManagerStatusCallback callback2 = mock( 154 HalDeviceManager.ManagerStatusCallback.class); 155 mDut.registerStatusCallback(callback2, mTestLooper.getLooper()); 156 mDut.registerStatusCallback(callback1, mTestLooper.getLooper()); 157 mDut.registerStatusCallback(callback2, mTestLooper.getLooper()); 158 159 // startup 160 executeAndValidateStartupSequence(); 161 162 // verify 163 verify(callback1).onStart(); 164 verify(callback2).onStart(); 165 166 verifyNoMoreInteractions(mServiceManagerMock, mWifiMock, mManagerStatusCallbackMock, 167 callback1, callback2); 168 } 169 170 /** 171 * Validate IWifi death listener and registration flow. 172 */ 173 @Test 174 public void testWifiDeathAndRegistration() throws Exception { 175 executeAndValidateStartupSequence(); 176 177 // act: IWifi service death 178 mDeathRecipientCaptor.getValue().serviceDied(0); 179 mTestLooper.dispatchAll(); 180 181 // verify: getting onStop 182 mInOrder.verify(mManagerStatusCallbackMock).onStop(); 183 184 // act: service startup 185 mServiceNotificationCaptor.getValue().onRegistration(IWifi.kInterfaceName, "", false); 186 187 // verify: initialization of IWifi 188 mInOrder.verify(mWifiMock).linkToDeath(mDeathRecipientCaptor.capture(), anyLong()); 189 mInOrder.verify(mWifiMock).registerEventCallback(mWifiEventCallbackCaptor.capture()); 190 191 // act: start 192 mDut.start(); 193 mWifiEventCallbackCaptor.getValue().onStart(); 194 mTestLooper.dispatchAll(); 195 196 // verify: service and callback calls 197 mInOrder.verify(mWifiMock).start(); 198 mInOrder.verify(mManagerStatusCallbackMock).onStart(); 199 200 verifyNoMoreInteractions(mServiceManagerMock, mWifiMock, mManagerStatusCallbackMock); 201 } 202 203 /** 204 * Validate IWifi onFailure causes notification 205 */ 206 @Test 207 public void testWifiFail() throws Exception { 208 executeAndValidateStartupSequence(); 209 210 // act: IWifi failure 211 mWifiEventCallbackCaptor.getValue().onFailure(mStatusFail); 212 mTestLooper.dispatchAll(); 213 214 // verify: getting onStop 215 mInOrder.verify(mManagerStatusCallbackMock).onStop(); 216 217 // act: start again 218 mDut.start(); 219 mWifiEventCallbackCaptor.getValue().onStart(); 220 mTestLooper.dispatchAll(); 221 222 // verify: service and callback calls 223 mInOrder.verify(mWifiMock).start(); 224 mInOrder.verify(mManagerStatusCallbackMock).onStart(); 225 226 verifyNoMoreInteractions(mServiceManagerMock, mWifiMock, mManagerStatusCallbackMock); 227 } 228 229 230 // utilities 231 private void dumpDut(String prefix) { 232 StringWriter sw = new StringWriter(); 233 mDut.dump(null, new PrintWriter(sw), null); 234 Log.e("HalDeviceManager", prefix + sw.toString()); 235 } 236 237 private void executeAndValidateInitializationSequence() throws Exception { 238 // act: 239 mDut.initialize(); 240 241 // verify: service manager initialization sequence 242 mInOrder.verify(mServiceManagerMock).linkToDeath(any(IHwBinder.DeathRecipient.class), 243 anyLong()); 244 mInOrder.verify(mServiceManagerMock).registerForNotifications(eq(IWifi.kInterfaceName), 245 eq(""), mServiceNotificationCaptor.capture()); 246 247 // act: get the service started (which happens even when service was already up) 248 mServiceNotificationCaptor.getValue().onRegistration(IWifi.kInterfaceName, "", true); 249 250 // verify: wifi initialization sequence 251 mInOrder.verify(mWifiMock).linkToDeath(mDeathRecipientCaptor.capture(), anyLong()); 252 mInOrder.verify(mWifiMock).registerEventCallback(mWifiEventCallbackCaptor.capture()); 253 } 254 255 private void executeAndValidateStartupSequence() throws Exception { 256 // act: register listener & start Wi-Fi 257 mDut.registerStatusCallback(mManagerStatusCallbackMock, mTestLooper.getLooper()); 258 mDut.start(); 259 260 // verify 261 mInOrder.verify(mWifiMock).start(); 262 263 // act: trigger onStart callback of IWifiEventCallback 264 mWifiEventCallbackCaptor.getValue().onStart(); 265 mTestLooper.dispatchAll(); 266 267 // verify: onStart called on registered listener 268 mInOrder.verify(mManagerStatusCallbackMock).onStart(); 269 } 270} 271