| /* |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.server.wifi; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.mockito.Matchers.any; |
| import static org.mockito.Matchers.anyInt; |
| import static org.mockito.Mockito.atLeastOnce; |
| import static org.mockito.Mockito.mock; |
| import static org.mockito.Mockito.times; |
| import static org.mockito.Mockito.validateMockitoUsage; |
| import static org.mockito.Mockito.verify; |
| import static org.mockito.Mockito.verifyNoMoreInteractions; |
| import static org.mockito.Mockito.when; |
| |
| import android.content.BroadcastReceiver; |
| import android.content.Context; |
| import android.content.IntentFilter; |
| import android.net.wifi.RttManager; |
| import android.net.wifi.RttManager.ParcelableRttParams; |
| import android.net.wifi.RttManager.ResponderConfig; |
| import android.net.wifi.WifiManager; |
| import android.os.Handler; |
| import android.os.Message; |
| import android.test.suitebuilder.annotation.SmallTest; |
| |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.mockito.ArgumentCaptor; |
| import org.mockito.Mock; |
| import org.mockito.MockitoAnnotations; |
| |
| /** |
| * Unit test for {@link com.android.server.wifi.RttService} |
| */ |
| @SmallTest |
| public class RttServiceTest { |
| |
| // Some constants for running Rtt tests. |
| private static final String MAC = "12:34:56:78:9A:BC"; |
| private static final int CLIENT_KEY1 = 1; |
| private static final int CLIENT_KEY2 = 2; |
| |
| @Mock |
| Context mContext; |
| @Mock |
| WifiNative mWifiNative; |
| MockLooper mLooper; |
| |
| RttService.RttServiceImpl mRttServiceImpl; |
| ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor = ArgumentCaptor |
| .forClass(BroadcastReceiver.class); |
| |
| @Before |
| public void setUp() throws Exception { |
| MockitoAnnotations.initMocks(this); |
| TestUtil.installWlanWifiNative(mWifiNative); |
| mLooper = new MockLooper(); |
| mRttServiceImpl = new RttService.RttServiceImpl(mContext, mLooper.getLooper()); |
| mRttServiceImpl.startService(); |
| } |
| |
| @After |
| public void cleanup() { |
| validateMockitoUsage(); |
| } |
| |
| private void startWifi() { |
| verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(), |
| any(IntentFilter.class)); |
| TestUtil.sendWifiScanAvailable(mBroadcastReceiverCaptor.getValue(), |
| mContext, WifiManager.WIFI_STATE_ENABLED); |
| } |
| |
| // Create and connect a bi-directional async channel. |
| private BidirectionalAsyncChannel connectChannel(Handler handler) { |
| BidirectionalAsyncChannel channel = new BidirectionalAsyncChannel(); |
| channel.connect(mLooper.getLooper(), mRttServiceImpl.getMessenger(), |
| handler); |
| mLooper.dispatchAll(); |
| channel.assertConnected(); |
| return channel; |
| } |
| |
| private void sendRangingRequestFailed(BidirectionalAsyncChannel channel, Handler handler, |
| int clientKey, ParcelableRttParams params) { |
| Message message = sendRangingRequest(channel, handler, clientKey, params); |
| assertEquals("ranging request did not fail", |
| RttManager.CMD_OP_FAILED, message.what); |
| verifyNoMoreInteractions(mWifiNative); |
| } |
| |
| // Send rtt ranging request message and verify failure. |
| private Message sendRangingRequest(BidirectionalAsyncChannel channel, Handler handler, |
| int clientKey, ParcelableRttParams params) { |
| Message message = new Message(); |
| message.what = RttManager.CMD_OP_START_RANGING; |
| message.arg2 = clientKey; |
| message.obj = params; |
| channel.sendMessage(message); |
| mLooper.dispatchAll(); |
| ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); |
| verify(handler, atLeastOnce()).handleMessage(messageCaptor.capture()); |
| return messageCaptor.getValue(); |
| } |
| |
| // Send enable responder message and verify success. |
| private void sendEnableResponderSucceed(BidirectionalAsyncChannel channel, |
| Handler handler, int clientKey) { |
| Message message = sendEnableResponder(channel, handler, clientKey, |
| createResponderConfig()); |
| verify(mWifiNative).enableRttResponder(anyInt()); |
| assertEquals("reponse status is not success", |
| RttManager.CMD_OP_ENALBE_RESPONDER_SUCCEEDED, message.what); |
| String actualMac = ((ResponderConfig) message.obj).macAddress; |
| assertEquals("mac address mismatch", MAC, actualMac); |
| } |
| |
| // Send enable responder message and verify failure. |
| private void sendEnableResponderFailed(BidirectionalAsyncChannel channel, |
| Handler handler, int clientKey, int reason) { |
| Message message = sendEnableResponder(channel, handler, clientKey, null); |
| assertEquals("reponse status is not failure", |
| RttManager.CMD_OP_ENALBE_RESPONDER_FAILED, message.what); |
| assertEquals("failure reason is not " + reason, |
| reason, message.arg1); |
| } |
| |
| private Message sendEnableResponder(BidirectionalAsyncChannel channel, Handler handler, |
| int clientKey, ResponderConfig config) { |
| when(mWifiNative.enableRttResponder(anyInt())).thenReturn(config); |
| when(mWifiNative.getMacAddress()).thenReturn(MAC); |
| Message message = new Message(); |
| message.what = RttManager.CMD_OP_ENABLE_RESPONDER; |
| message.arg2 = clientKey; |
| channel.sendMessage(message); |
| mLooper.dispatchAll(); |
| ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); |
| verify(handler, atLeastOnce()).handleMessage(messageCaptor.capture()); |
| return messageCaptor.getValue(); |
| } |
| |
| private void sendDisableResponder(BidirectionalAsyncChannel channel, int key, boolean success) { |
| when(mWifiNative.disableRttResponder()).thenReturn(success); |
| Message message = new Message(); |
| message.what = RttManager.CMD_OP_DISABLE_RESPONDER; |
| message.arg2 = key; |
| channel.sendMessage(message); |
| mLooper.dispatchAll(); |
| } |
| |
| private ResponderConfig createResponderConfig() { |
| ResponderConfig config = new ResponderConfig(); |
| config.macAddress = MAC; |
| return config; |
| } |
| |
| @Test |
| public void testEnableResponderSuccess() throws Exception { |
| startWifi(); |
| Handler handler = mock(Handler.class); |
| BidirectionalAsyncChannel channel = connectChannel(handler); |
| // Successfully enabled responder. |
| sendEnableResponderSucceed(channel, handler, CLIENT_KEY1); |
| } |
| |
| @Test |
| public void testEnableResponderSecondTime() throws Exception { |
| startWifi(); |
| Handler handler = mock(Handler.class); |
| BidirectionalAsyncChannel channel = connectChannel(handler); |
| sendEnableResponderSucceed(channel, handler, CLIENT_KEY1); |
| // Calling enabling responder with the same key should succeed. |
| sendEnableResponderSucceed(channel, handler, CLIENT_KEY1); |
| } |
| |
| @Test |
| public void testEnableResponderMultiClient() throws Exception { |
| startWifi(); |
| Handler handler = mock(Handler.class); |
| BidirectionalAsyncChannel channel = connectChannel(handler); |
| sendEnableResponderSucceed(channel, handler, CLIENT_KEY1); |
| sendEnableResponderSucceed(channel, handler, CLIENT_KEY2); |
| // Native method should be called only once when multiple clients enabled responder. |
| verify(mWifiNative, times(1)).enableRttResponder(anyInt()); |
| } |
| |
| @Test |
| public void testDisableResponderSuccess() throws Exception { |
| startWifi(); |
| Handler handler = mock(Handler.class); |
| BidirectionalAsyncChannel channel = connectChannel(handler); |
| sendEnableResponderSucceed(channel, handler, CLIENT_KEY1); |
| // Disable after successfully enabling. |
| sendDisableResponder(channel, CLIENT_KEY1, false); |
| verify(mWifiNative).disableRttResponder(); |
| } |
| |
| /** |
| * Enable responder failed because of internal error. |
| */ |
| @Test |
| public void testEnableResponderFailure() throws Exception { |
| startWifi(); |
| Handler handler = mock(Handler.class); |
| when(mWifiNative.enableRttResponder(anyInt())).thenReturn(null); |
| BidirectionalAsyncChannel channel = connectChannel(handler); |
| // Disable failed. |
| sendEnableResponderFailed(channel, handler, CLIENT_KEY1, RttManager.REASON_UNSPECIFIED); |
| } |
| |
| @Test |
| public void testDisableResponderNotStarted() throws Exception { |
| startWifi(); |
| Handler handler = mock(Handler.class); |
| BidirectionalAsyncChannel channel = connectChannel(handler); |
| // Disable without enabling should fail. |
| sendDisableResponder(channel, CLIENT_KEY1, false); |
| // Native disable method shouldn't be called. |
| verifyNoMoreInteractions(mWifiNative); |
| } |
| |
| @Test |
| public void testDisableResponderMultiClient() throws Exception { |
| startWifi(); |
| Handler handler = mock(Handler.class); |
| BidirectionalAsyncChannel channel = connectChannel(handler); |
| sendEnableResponderSucceed(channel, handler, CLIENT_KEY1); |
| sendEnableResponderSucceed(channel, handler, CLIENT_KEY2); |
| // Two clients enabled, one client disabled. |
| sendDisableResponder(channel, CLIENT_KEY1, true); |
| verify(mWifiNative, times(1)).getMacAddress(); |
| verifyNoMoreInteractions(mWifiNative); |
| } |
| |
| /** |
| * Enable responder failed because wifi is not enabled. |
| */ |
| @Test |
| public void testEnableResponderFailedWifiDisabled() throws Exception { |
| Handler handler = mock(Handler.class); |
| BidirectionalAsyncChannel channel = connectChannel(handler); |
| // Wifi is disabled as startWifi() is not invoked. |
| sendEnableResponderFailed(channel, handler, CLIENT_KEY1, RttManager.REASON_NOT_AVAILABLE); |
| verifyNoMoreInteractions(mWifiNative); |
| } |
| |
| /** |
| * Test RTT ranging with empty RttParams. |
| */ |
| @Test |
| public void testInitiatorEmptyParams() throws Exception { |
| startWifi(); |
| Handler handler = mock(Handler.class); |
| BidirectionalAsyncChannel channel = connectChannel(handler); |
| sendRangingRequestFailed(channel, handler, CLIENT_KEY1, new ParcelableRttParams(null)); |
| } |
| } |