blob: 177705cb973f7d8d633753799543f65f91e5f328 [file] [log] [blame]
/*
* 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));
}
}