diff options
| author | 2016-11-23 23:42:29 +0000 | |
|---|---|---|
| committer | 2016-11-23 23:42:30 +0000 | |
| commit | 018f6ec16fb13ad7568e43e8c7ff481104900ed6 (patch) | |
| tree | a448850df8034e56cbefd41b9ca8a2f2c216b95c | |
| parent | 99d6227782844e42d7060b14d320cfd66a536798 (diff) | |
| parent | b77b69545ea32f336a90ac9403ceb826d8798f1b (diff) | |
Merge "[AWARE] Move manager tests from service to manager directory"
| -rw-r--r-- | wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java | 225 | ||||
| -rw-r--r-- | wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java | 1054 |
2 files changed, 1279 insertions, 0 deletions
diff --git a/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java b/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java new file mode 100644 index 000000000000..4b6957bfa3f6 --- /dev/null +++ b/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java @@ -0,0 +1,225 @@ +/* + * 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 android.net.wifi.aware; + +import static org.hamcrest.core.IsEqual.equalTo; + +import android.test.suitebuilder.annotation.SmallTest; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ErrorCollector; + +/** + * Unit test harness for TlvBufferUtils class. + */ +@SmallTest +public class TlvBufferUtilsTest { + @Rule + public ErrorCollector collector = new ErrorCollector(); + + /* + * TlvBufferUtils Tests + */ + + @Test + public void testTlvBuild() { + TlvBufferUtils.TlvConstructor tlv11 = new TlvBufferUtils.TlvConstructor(1, 1); + tlv11.allocate(15); + tlv11.putByte(0, (byte) 2); + tlv11.putByteArray(2, new byte[] { + 0, 1, 2 }); + + collector.checkThat("tlv11-correct-construction", + tlv11.getArray(), equalTo(new byte[]{0, 1, 2, 2, 3, 0, 1, 2})); + + LvBufferUtils.LvConstructor tlv01 = new LvBufferUtils.LvConstructor(1); + tlv01.allocate(15); + tlv01.putByte((byte) 2); + tlv01.putByteArray(2, new byte[] { + 0, 1, 2 }); + + collector.checkThat("tlv01-correct-construction", + tlv01.getArray(), equalTo(new byte[] {1, 2, 3, 0, 1, 2 })); + + collector.checkThat("tlv11-valid", + TlvBufferUtils.isValid(tlv11.getArray(), 1, 1), + equalTo(true)); + collector.checkThat("tlv01-valid", + LvBufferUtils.isValid(tlv01.getArray(), 1), + equalTo(true)); + } + + @Test + public void testTlvIterate() { + final String ascii = "ABC"; + final String nonAscii = "何かもっと複雑な"; + + TlvBufferUtils.TlvConstructor tlv22 = new TlvBufferUtils.TlvConstructor(2, 2); + tlv22.allocate(18); + tlv22.putInt(0, 2); + tlv22.putShort(2, (short) 3); + tlv22.putZeroLengthElement(55); + + TlvBufferUtils.TlvIterable tlv22It = new TlvBufferUtils.TlvIterable(2, 2, tlv22.getArray()); + int count = 0; + for (TlvBufferUtils.TlvElement tlv : tlv22It) { + if (count == 0) { + collector.checkThat("tlv22-correct-iteration-mType", tlv.type, equalTo(0)); + collector.checkThat("tlv22-correct-iteration-mLength", tlv.length, equalTo(4)); + collector.checkThat("tlv22-correct-iteration-DATA", tlv.getInt(), equalTo(2)); + } else if (count == 1) { + collector.checkThat("tlv22-correct-iteration-mType", tlv.type, equalTo(2)); + collector.checkThat("tlv22-correct-iteration-mLength", tlv.length, equalTo(2)); + collector.checkThat("tlv22-correct-iteration-DATA", (int) tlv.getShort(), + equalTo(3)); + } else if (count == 2) { + collector.checkThat("tlv22-correct-iteration-mType", tlv.type, equalTo(55)); + collector.checkThat("tlv22-correct-iteration-mLength", tlv.length, equalTo(0)); + } else { + collector.checkThat("Invalid number of iterations in loop - tlv22", true, + equalTo(false)); + } + ++count; + } + if (count != 3) { + collector.checkThat("Invalid number of iterations outside loop - tlv22", true, + equalTo(false)); + } + + TlvBufferUtils.TlvConstructor tlv02 = new TlvBufferUtils.TlvConstructor(0, 2); + tlv02.allocate(100); + tlv02.putByte(0, (byte) 2); + tlv02.putString(0, ascii); + tlv02.putString(0, nonAscii); + + TlvBufferUtils.TlvIterable tlv02It = new TlvBufferUtils.TlvIterable(0, 2, tlv02.getArray()); + count = 0; + for (TlvBufferUtils.TlvElement tlv : tlv02It) { + if (count == 0) { + collector.checkThat("tlv02-correct-iteration-mLength", tlv.length, equalTo(1)); + collector.checkThat("tlv02-correct-iteration-DATA", (int) tlv.getByte(), + equalTo(2)); + } else if (count == 1) { + collector.checkThat("tlv02-correct-iteration-mLength", tlv.length, + equalTo(ascii.length())); + collector.checkThat("tlv02-correct-iteration-DATA", tlv.getString().equals(ascii), + equalTo(true)); + } else if (count == 2) { + collector.checkThat("tlv02-correct-iteration-mLength", tlv.length, + equalTo(nonAscii.getBytes().length)); + collector.checkThat("tlv02-correct-iteration-DATA", + tlv.getString().equals(nonAscii), equalTo(true)); + } else { + collector.checkThat("Invalid number of iterations in loop - tlv02", true, + equalTo(false)); + } + ++count; + } + collector.checkThat("Invalid number of iterations outside loop - tlv02", count, + equalTo(3)); + + collector.checkThat("tlv22-valid", + TlvBufferUtils.isValid(tlv22.getArray(), 2, 2), + equalTo(true)); + collector.checkThat("tlv02-valid", + LvBufferUtils.isValid(tlv02.getArray(), 2), + equalTo(true)); + } + + @Test(expected = IllegalArgumentException.class) + public void testTlvInvalidSizeT1L0() { + TlvBufferUtils.TlvConstructor tlv10 = new TlvBufferUtils.TlvConstructor(1, 0); + } + + @Test(expected = IllegalArgumentException.class) + public void testTlvInvalidSizeTm3L2() { + TlvBufferUtils.TlvConstructor tlv10 = new TlvBufferUtils.TlvConstructor(-3, 2); + } + + @Test(expected = IllegalArgumentException.class) + public void testTlvInvalidSizeT1Lm2() { + TlvBufferUtils.TlvConstructor tlv10 = new TlvBufferUtils.TlvConstructor(1, -2); + } + + @Test(expected = IllegalArgumentException.class) + public void testTlvInvalidSizeT1L3() { + TlvBufferUtils.TlvConstructor tlv10 = new TlvBufferUtils.TlvConstructor(1, 3); + } + + @Test(expected = IllegalArgumentException.class) + public void testTlvInvalidSizeT3L1() { + TlvBufferUtils.TlvConstructor tlv10 = new TlvBufferUtils.TlvConstructor(3, 1); + } + + @Test(expected = IllegalArgumentException.class) + public void testTlvItInvalidSizeT1L0() { + final byte[] dummy = { + 0, 1, 2 }; + final int dummyLength = 3; + TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(1, 0, dummy); + } + + @Test(expected = IllegalArgumentException.class) + public void testTlvItInvalidSizeTm3L2() { + final byte[] dummy = { + 0, 1, 2 }; + final int dummyLength = 3; + TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(-3, 2, dummy); + } + + @Test(expected = IllegalArgumentException.class) + public void testTlvItInvalidSizeT1Lm2() { + final byte[] dummy = { + 0, 1, 2 }; + final int dummyLength = 3; + TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(1, -2, dummy); + } + + @Test(expected = IllegalArgumentException.class) + public void testTlvItInvalidSizeT1L3() { + final byte[] dummy = { + 0, 1, 2 }; + final int dummyLength = 3; + TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(1, 3, dummy); + } + + @Test(expected = IllegalArgumentException.class) + public void testTlvItInvalidSizeT3L1() { + final byte[] dummy = { + 0, 1, 2 }; + final int dummyLength = 3; + TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(3, 1, dummy); + } + + /** + * Validate that a malformed byte array fails the TLV validity test. + */ + @Test + public void testTlvInvalidByteArray() { + LvBufferUtils.LvConstructor tlv01 = new LvBufferUtils.LvConstructor(1); + tlv01.allocate(15); + tlv01.putByte((byte) 2); + tlv01.putByteArray(2, new byte[]{0, 1, 2}); + + byte[] array = tlv01.getArray(); + array[0] = 10; + + collector.checkThat("tlv01-invalid", + LvBufferUtils.isValid(array, 1), equalTo(false)); + } +} diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java new file mode 100644 index 000000000000..b30ecf7ea5d1 --- /dev/null +++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java @@ -0,0 +1,1054 @@ +/* + * 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 android.net.wifi.aware; + +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.isNull; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.net.wifi.RttManager; +import android.os.Handler; +import android.os.IBinder; +import android.os.Parcel; +import android.os.test.TestLooper; +import android.test.suitebuilder.annotation.SmallTest; +import android.util.Base64; + +import libcore.util.HexEncoding; + +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ErrorCollector; +import org.mockito.ArgumentCaptor; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** + * Unit test harness for WifiAwareManager class. + */ +@SmallTest +public class WifiAwareManagerTest { + private WifiAwareManager mDut; + private TestLooper mMockLooper; + private Handler mMockLooperHandler; + + @Rule + public ErrorCollector collector = new ErrorCollector(); + + @Mock + public Context mockContext; + + @Mock + public WifiAwareAttachCallback mockCallback; + + @Mock + public WifiAwareDiscoverySessionCallback mockSessionCallback; + + @Mock + public IWifiAwareManager mockAwareService; + + @Mock + public WifiAwarePublishDiscoverySession mockPublishSession; + + @Mock + public WifiAwareSubscribeDiscoverySession mockSubscribeSession; + + @Mock + public RttManager.RttListener mockRttListener; + + private static final int AWARE_STATUS_ERROR = -1; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + + mDut = new WifiAwareManager(mockContext, mockAwareService); + mMockLooper = new TestLooper(); + mMockLooperHandler = new Handler(mMockLooper.getLooper()); + } + + /* + * Straight pass-through tests + */ + + /** + * Validate pass-through of enableUsage() API. + */ + @Test + public void testEnableUsage() throws Exception { + mDut.enableUsage(); + + verify(mockAwareService).enableUsage(); + } + + /** + * Validate pass-through of disableUsage() API. + */ + @Test + public void testDisableUsage() throws Exception { + mDut.disableUsage(); + + verify(mockAwareService).disableUsage(); + } + + /** + * Validate pass-through of isUsageEnabled() API. + */ + @Test + public void testIsUsageEnable() throws Exception { + mDut.isAvailable(); + + verify(mockAwareService).isUsageEnabled(); + } + + /** + * Validate pass-through of getCharacteristics() API. + */ + @Test + public void testGetCharacteristics() throws Exception { + mDut.getCharacteristics(); + + verify(mockAwareService).getCharacteristics(); + } + + /* + * WifiAwareEventCallbackProxy Tests + */ + + /** + * Validate the successful connect flow: (1) connect + success (2) publish, (3) disconnect + * (4) try publishing on old session (5) connect again + */ + @Test + public void testConnectFlow() throws Exception { + final int clientId = 4565; + + InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService); + ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor + .forClass(IWifiAwareEventCallback.class); + ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass( + WifiAwareSession.class); + ArgumentCaptor<IBinder> binder = ArgumentCaptor.forClass(IBinder.class); + + // (1) connect + success + mDut.attach(mockCallback, mMockLooperHandler); + inOrder.verify(mockAwareService).connect(binder.capture(), anyString(), + clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false)); + clientProxyCallback.getValue().onConnectSuccess(clientId); + mMockLooper.dispatchAll(); + inOrder.verify(mockCallback).onAttached(sessionCaptor.capture()); + WifiAwareSession session = sessionCaptor.getValue(); + + // (2) publish - should succeed + PublishConfig publishConfig = new PublishConfig.Builder().build(); + session.publish(publishConfig, mockSessionCallback, mMockLooperHandler); + inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig), + any(IWifiAwareDiscoverySessionCallback.class)); + + // (3) disconnect + session.destroy(); + inOrder.verify(mockAwareService).disconnect(eq(clientId), eq(binder.getValue())); + + // (4) try publishing again - fails silently + session.publish(new PublishConfig.Builder().build(), mockSessionCallback, + mMockLooperHandler); + + // (5) connect + mDut.attach(mockCallback, mMockLooperHandler); + inOrder.verify(mockAwareService).connect(binder.capture(), anyString(), + any(IWifiAwareEventCallback.class), (ConfigRequest) isNull(), eq(false)); + + verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService); + } + + /** + * Validate the failed connect flow: (1) connect + failure, (2) connect + success (3) subscribe + */ + @Test + public void testConnectFailure() throws Exception { + final int clientId = 4565; + final int reason = AWARE_STATUS_ERROR; + + InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService); + ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass( + WifiAwareSession.class); + ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor + .forClass(IWifiAwareEventCallback.class); + + // (1) connect + failure + mDut.attach(mockCallback, mMockLooperHandler); + inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(), + clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false)); + clientProxyCallback.getValue().onConnectFail(reason); + mMockLooper.dispatchAll(); + inOrder.verify(mockCallback).onAttachFailed(); + + // (2) connect + success + mDut.attach(mockCallback, mMockLooperHandler); + inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(), + clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false)); + clientProxyCallback.getValue().onConnectSuccess(clientId); + mMockLooper.dispatchAll(); + inOrder.verify(mockCallback).onAttached(sessionCaptor.capture()); + WifiAwareSession session = sessionCaptor.getValue(); + + // (4) subscribe: should succeed + SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); + session.subscribe(subscribeConfig, mockSessionCallback, mMockLooperHandler); + inOrder.verify(mockAwareService).subscribe(eq(clientId), eq(subscribeConfig), + any(IWifiAwareDiscoverySessionCallback.class)); + + verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService); + } + + /** + * Validate that can call connect to create multiple sessions: (1) connect + * + success, (2) try connect again + */ + @Test + public void testInvalidConnectSequence() throws Exception { + final int clientId = 4565; + + InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService); + ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor + .forClass(IWifiAwareEventCallback.class); + + // (1) connect + success + mDut.attach(mockCallback, mMockLooperHandler); + inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(), + clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false)); + clientProxyCallback.getValue().onConnectSuccess(clientId); + mMockLooper.dispatchAll(); + inOrder.verify(mockCallback).onAttached(any(WifiAwareSession.class)); + + // (2) connect + success + mDut.attach(mockCallback, mMockLooperHandler); + inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(), + clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false)); + clientProxyCallback.getValue().onConnectSuccess(clientId + 1); + mMockLooper.dispatchAll(); + inOrder.verify(mockCallback).onAttached(any(WifiAwareSession.class)); + + verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService); + } + + /* + * WifiAwareDiscoverySessionCallbackProxy Tests + */ + + /** + * Validate the publish flow: (0) connect + success, (1) publish, (2) + * success creates session, (3) pass through everything, (4) update publish + * through session, (5) terminate locally, (6) try another command - + * ignored. + */ + @Test + public void testPublishFlow() throws Exception { + final int clientId = 4565; + final int sessionId = 123; + final ConfigRequest configRequest = new ConfigRequest.Builder().build(); + final PublishConfig publishConfig = new PublishConfig.Builder().build(); + final WifiAwareManager.PeerHandle peerHandle = new WifiAwareManager.PeerHandle(873); + final String string1 = "hey from here..."; + final String string2 = "some other arbitrary string..."; + final int messageId = 2123; + final int reason = AWARE_STATUS_ERROR; + + InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService, + mockPublishSession); + ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass( + WifiAwareSession.class); + ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor + .forClass(IWifiAwareEventCallback.class); + ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor + .forClass(IWifiAwareDiscoverySessionCallback.class); + ArgumentCaptor<WifiAwarePublishDiscoverySession> publishSession = ArgumentCaptor + .forClass(WifiAwarePublishDiscoverySession.class); + ArgumentCaptor<WifiAwareManager.PeerHandle> peerIdCaptor = ArgumentCaptor.forClass( + WifiAwareManager.PeerHandle.class); + + // (0) connect + success + mDut.attach(mMockLooperHandler, configRequest, mockCallback, null); + inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(), + clientProxyCallback.capture(), eq(configRequest), eq(false)); + clientProxyCallback.getValue().onConnectSuccess(clientId); + mMockLooper.dispatchAll(); + inOrder.verify(mockCallback).onAttached(sessionCaptor.capture()); + WifiAwareSession session = sessionCaptor.getValue(); + + // (1) publish + session.publish(publishConfig, mockSessionCallback, mMockLooperHandler); + inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig), + sessionProxyCallback.capture()); + + // (2) publish session created + sessionProxyCallback.getValue().onSessionStarted(sessionId); + mMockLooper.dispatchAll(); + inOrder.verify(mockSessionCallback).onPublishStarted(publishSession.capture()); + + // (3) ... + publishSession.getValue().sendMessage(peerHandle, messageId, string1.getBytes()); + sessionProxyCallback.getValue().onMatch(peerHandle.peerId, string1.getBytes(), + string2.getBytes()); + sessionProxyCallback.getValue().onMessageReceived(peerHandle.peerId, string1.getBytes()); + sessionProxyCallback.getValue().onMessageSendFail(messageId, reason); + sessionProxyCallback.getValue().onMessageSendSuccess(messageId); + mMockLooper.dispatchAll(); + + inOrder.verify(mockAwareService).sendMessage(eq(clientId), eq(sessionId), + eq(peerHandle.peerId), eq(string1.getBytes()), eq(messageId), eq(0)); + inOrder.verify(mockSessionCallback).onServiceDiscovered(peerIdCaptor.capture(), + eq(string1.getBytes()), eq(string2.getBytes())); + assertEquals(((WifiAwareManager.PeerHandle) peerIdCaptor.getValue()).peerId, + peerHandle.peerId); + inOrder.verify(mockSessionCallback).onMessageReceived(peerIdCaptor.capture(), + eq(string1.getBytes())); + assertEquals(((WifiAwareManager.PeerHandle) peerIdCaptor.getValue()).peerId, + peerHandle.peerId); + inOrder.verify(mockSessionCallback).onMessageSendFailed(eq(messageId)); + inOrder.verify(mockSessionCallback).onMessageSendSucceeded(eq(messageId)); + + // (4) update publish + publishSession.getValue().updatePublish(publishConfig); + sessionProxyCallback.getValue().onSessionConfigFail(reason); + mMockLooper.dispatchAll(); + inOrder.verify(mockAwareService).updatePublish(eq(clientId), eq(sessionId), + eq(publishConfig)); + inOrder.verify(mockSessionCallback).onSessionConfigFailed(); + + // (5) terminate + publishSession.getValue().destroy(); + mMockLooper.dispatchAll(); + inOrder.verify(mockAwareService).terminateSession(clientId, sessionId); + + // (6) try an update (nothing) + publishSession.getValue().updatePublish(publishConfig); + mMockLooper.dispatchAll(); + + verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService, + mockPublishSession); + } + + /** + * Validate race condition of session terminate and session action: (1) + * connect, (2) publish success + terminate, (3) update. + */ + @Test + public void testPublishRemoteTerminate() throws Exception { + final int clientId = 4565; + final int sessionId = 123; + final ConfigRequest configRequest = new ConfigRequest.Builder().build(); + final PublishConfig publishConfig = new PublishConfig.Builder().build(); + final int reason = WifiAwareDiscoverySessionCallback.TERMINATE_REASON_DONE; + + InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService, + mockPublishSession); + ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass( + WifiAwareSession.class); + ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor + .forClass(IWifiAwareEventCallback.class); + ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor + .forClass(IWifiAwareDiscoverySessionCallback.class); + ArgumentCaptor<WifiAwarePublishDiscoverySession> publishSession = ArgumentCaptor + .forClass(WifiAwarePublishDiscoverySession.class); + + // (1) connect successfully + mDut.attach(mMockLooperHandler, configRequest, mockCallback, null); + inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(), + clientProxyCallback.capture(), eq(configRequest), eq(false)); + clientProxyCallback.getValue().onConnectSuccess(clientId); + mMockLooper.dispatchAll(); + inOrder.verify(mockCallback).onAttached(sessionCaptor.capture()); + WifiAwareSession session = sessionCaptor.getValue(); + + // (2) publish: successfully - then terminated + session.publish(publishConfig, mockSessionCallback, mMockLooperHandler); + inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig), + sessionProxyCallback.capture()); + sessionProxyCallback.getValue().onSessionStarted(sessionId); + sessionProxyCallback.getValue().onSessionTerminated(reason); + mMockLooper.dispatchAll(); + inOrder.verify(mockSessionCallback).onPublishStarted(publishSession.capture()); + inOrder.verify(mockSessionCallback).onSessionTerminated(reason); + + // (3) failure when trying to update: NOP + publishSession.getValue().updatePublish(publishConfig); + + verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService, + mockPublishSession); + } + + /** + * Validate the subscribe flow: (0) connect + success, (1) subscribe, (2) + * success creates session, (3) pass through everything, (4) update + * subscribe through session, (5) terminate locally, (6) try another command + * - ignored. + */ + @Test + public void testSubscribeFlow() throws Exception { + final int clientId = 4565; + final int sessionId = 123; + final ConfigRequest configRequest = new ConfigRequest.Builder().build(); + final SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); + final WifiAwareManager.PeerHandle peerHandle = new WifiAwareManager.PeerHandle(873); + final String string1 = "hey from here..."; + final String string2 = "some other arbitrary string..."; + final int messageId = 2123; + final int reason = AWARE_STATUS_ERROR; + + InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService, + mockSubscribeSession); + ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass( + WifiAwareSession.class); + ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor + .forClass(IWifiAwareEventCallback.class); + ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor + .forClass(IWifiAwareDiscoverySessionCallback.class); + ArgumentCaptor<WifiAwareSubscribeDiscoverySession> subscribeSession = ArgumentCaptor + .forClass(WifiAwareSubscribeDiscoverySession.class); + ArgumentCaptor<WifiAwareManager.PeerHandle> peerIdCaptor = ArgumentCaptor.forClass( + WifiAwareManager.PeerHandle.class); + + // (0) connect + success + mDut.attach(mMockLooperHandler, configRequest, mockCallback, null); + inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(), + clientProxyCallback.capture(), eq(configRequest), eq(false)); + clientProxyCallback.getValue().onConnectSuccess(clientId); + mMockLooper.dispatchAll(); + inOrder.verify(mockCallback).onAttached(sessionCaptor.capture()); + WifiAwareSession session = sessionCaptor.getValue(); + + // (1) subscribe + session.subscribe(subscribeConfig, mockSessionCallback, mMockLooperHandler); + inOrder.verify(mockAwareService).subscribe(eq(clientId), eq(subscribeConfig), + sessionProxyCallback.capture()); + + // (2) subscribe session created + sessionProxyCallback.getValue().onSessionStarted(sessionId); + mMockLooper.dispatchAll(); + inOrder.verify(mockSessionCallback).onSubscribeStarted(subscribeSession.capture()); + + // (3) ... + subscribeSession.getValue().sendMessage(peerHandle, messageId, string1.getBytes()); + sessionProxyCallback.getValue().onMatch(peerHandle.peerId, string1.getBytes(), + string2.getBytes()); + sessionProxyCallback.getValue().onMessageReceived(peerHandle.peerId, string1.getBytes()); + sessionProxyCallback.getValue().onMessageSendFail(messageId, reason); + sessionProxyCallback.getValue().onMessageSendSuccess(messageId); + mMockLooper.dispatchAll(); + + inOrder.verify(mockAwareService).sendMessage(eq(clientId), eq(sessionId), + eq(peerHandle.peerId), eq(string1.getBytes()), eq(messageId), eq(0)); + inOrder.verify(mockSessionCallback).onServiceDiscovered(peerIdCaptor.capture(), + eq(string1.getBytes()), eq(string2.getBytes())); + assertEquals(((WifiAwareManager.PeerHandle) peerIdCaptor.getValue()).peerId, + peerHandle.peerId); + inOrder.verify(mockSessionCallback).onMessageReceived(peerIdCaptor.capture(), + eq(string1.getBytes())); + assertEquals(((WifiAwareManager.PeerHandle) peerIdCaptor.getValue()).peerId, + peerHandle.peerId); + inOrder.verify(mockSessionCallback).onMessageSendFailed(eq(messageId)); + inOrder.verify(mockSessionCallback).onMessageSendSucceeded(eq(messageId)); + + // (4) update subscribe + subscribeSession.getValue().updateSubscribe(subscribeConfig); + sessionProxyCallback.getValue().onSessionConfigFail(reason); + mMockLooper.dispatchAll(); + inOrder.verify(mockAwareService).updateSubscribe(eq(clientId), eq(sessionId), + eq(subscribeConfig)); + inOrder.verify(mockSessionCallback).onSessionConfigFailed(); + + // (5) terminate + subscribeSession.getValue().destroy(); + mMockLooper.dispatchAll(); + inOrder.verify(mockAwareService).terminateSession(clientId, sessionId); + + // (6) try an update (nothing) + subscribeSession.getValue().updateSubscribe(subscribeConfig); + mMockLooper.dispatchAll(); + + verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService, + mockSubscribeSession); + } + + /** + * Validate race condition of session terminate and session action: (1) + * connect, (2) subscribe success + terminate, (3) update. + */ + @Test + public void testSubscribeRemoteTerminate() throws Exception { + final int clientId = 4565; + final int sessionId = 123; + final ConfigRequest configRequest = new ConfigRequest.Builder().build(); + final SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); + final int reason = WifiAwareDiscoverySessionCallback.TERMINATE_REASON_DONE; + + InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService, + mockSubscribeSession); + ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass( + WifiAwareSession.class); + ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor + .forClass(IWifiAwareEventCallback.class); + ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor + .forClass(IWifiAwareDiscoverySessionCallback.class); + ArgumentCaptor<WifiAwareSubscribeDiscoverySession> subscribeSession = ArgumentCaptor + .forClass(WifiAwareSubscribeDiscoverySession.class); + + // (1) connect successfully + mDut.attach(mMockLooperHandler, configRequest, mockCallback, null); + inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(), + clientProxyCallback.capture(), eq(configRequest), eq(false)); + clientProxyCallback.getValue().onConnectSuccess(clientId); + mMockLooper.dispatchAll(); + inOrder.verify(mockCallback).onAttached(sessionCaptor.capture()); + WifiAwareSession session = sessionCaptor.getValue(); + + // (2) subscribe: successfully - then terminated + session.subscribe(subscribeConfig, mockSessionCallback, mMockLooperHandler); + inOrder.verify(mockAwareService).subscribe(eq(clientId), eq(subscribeConfig), + sessionProxyCallback.capture()); + sessionProxyCallback.getValue().onSessionStarted(sessionId); + sessionProxyCallback.getValue().onSessionTerminated(reason); + mMockLooper.dispatchAll(); + inOrder.verify(mockSessionCallback).onSubscribeStarted(subscribeSession.capture()); + inOrder.verify(mockSessionCallback).onSessionTerminated(reason); + + // (3) failure when trying to update: NOP + subscribeSession.getValue().updateSubscribe(subscribeConfig); + + verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService, + mockSubscribeSession); + } + + /* + * ConfigRequest Tests + */ + + @Test + public void testConfigRequestBuilderDefaults() { + ConfigRequest configRequest = new ConfigRequest.Builder().build(); + + collector.checkThat("mClusterHigh", ConfigRequest.CLUSTER_ID_MAX, + equalTo(configRequest.mClusterHigh)); + collector.checkThat("mClusterLow", ConfigRequest.CLUSTER_ID_MIN, + equalTo(configRequest.mClusterLow)); + collector.checkThat("mMasterPreference", 0, + equalTo(configRequest.mMasterPreference)); + collector.checkThat("mSupport5gBand", false, equalTo(configRequest.mSupport5gBand)); + } + + @Test + public void testConfigRequestBuilder() { + final int clusterHigh = 100; + final int clusterLow = 5; + final int masterPreference = 55; + final boolean supportBand5g = true; + + ConfigRequest configRequest = new ConfigRequest.Builder().setClusterHigh(clusterHigh) + .setClusterLow(clusterLow).setMasterPreference(masterPreference) + .setSupport5gBand(supportBand5g) + .build(); + + collector.checkThat("mClusterHigh", clusterHigh, equalTo(configRequest.mClusterHigh)); + collector.checkThat("mClusterLow", clusterLow, equalTo(configRequest.mClusterLow)); + collector.checkThat("mMasterPreference", masterPreference, + equalTo(configRequest.mMasterPreference)); + collector.checkThat("mSupport5gBand", supportBand5g, equalTo(configRequest.mSupport5gBand)); + } + + @Test(expected = IllegalArgumentException.class) + public void testConfigRequestBuilderMasterPrefNegative() { + ConfigRequest.Builder builder = new ConfigRequest.Builder(); + builder.setMasterPreference(-1); + } + + @Test(expected = IllegalArgumentException.class) + public void testConfigRequestBuilderMasterPrefReserved1() { + new ConfigRequest.Builder().setMasterPreference(1); + } + + @Test(expected = IllegalArgumentException.class) + public void testConfigRequestBuilderMasterPrefReserved255() { + new ConfigRequest.Builder().setMasterPreference(255); + } + + @Test(expected = IllegalArgumentException.class) + public void testConfigRequestBuilderMasterPrefTooLarge() { + new ConfigRequest.Builder().setMasterPreference(256); + } + + @Test(expected = IllegalArgumentException.class) + public void testConfigRequestBuilderClusterLowNegative() { + new ConfigRequest.Builder().setClusterLow(-1); + } + + @Test(expected = IllegalArgumentException.class) + public void testConfigRequestBuilderClusterHighNegative() { + new ConfigRequest.Builder().setClusterHigh(-1); + } + + @Test(expected = IllegalArgumentException.class) + public void testConfigRequestBuilderClusterLowAboveMax() { + new ConfigRequest.Builder().setClusterLow(ConfigRequest.CLUSTER_ID_MAX + 1); + } + + @Test(expected = IllegalArgumentException.class) + public void testConfigRequestBuilderClusterHighAboveMax() { + new ConfigRequest.Builder().setClusterHigh(ConfigRequest.CLUSTER_ID_MAX + 1); + } + + @Test(expected = IllegalArgumentException.class) + public void testConfigRequestBuilderClusterLowLargerThanHigh() { + new ConfigRequest.Builder().setClusterLow(100).setClusterHigh(5).build(); + } + + @Test + public void testConfigRequestParcel() { + final int clusterHigh = 189; + final int clusterLow = 25; + final int masterPreference = 177; + final boolean supportBand5g = true; + + ConfigRequest configRequest = new ConfigRequest.Builder().setClusterHigh(clusterHigh) + .setClusterLow(clusterLow).setMasterPreference(masterPreference) + .setSupport5gBand(supportBand5g) + .build(); + + Parcel parcelW = Parcel.obtain(); + configRequest.writeToParcel(parcelW, 0); + byte[] bytes = parcelW.marshall(); + parcelW.recycle(); + + Parcel parcelR = Parcel.obtain(); + parcelR.unmarshall(bytes, 0, bytes.length); + parcelR.setDataPosition(0); + ConfigRequest rereadConfigRequest = ConfigRequest.CREATOR.createFromParcel(parcelR); + + assertEquals(configRequest, rereadConfigRequest); + } + + /* + * SubscribeConfig Tests + */ + + @Test + public void testSubscribeConfigBuilderDefaults() { + SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); + + collector.checkThat("mServiceName", subscribeConfig.mServiceName, equalTo(null)); + collector.checkThat("mSubscribeType", subscribeConfig.mSubscribeType, + equalTo(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)); + collector.checkThat("mSubscribeCount", subscribeConfig.mSubscribeCount, equalTo(0)); + collector.checkThat("mTtlSec", subscribeConfig.mTtlSec, equalTo(0)); + collector.checkThat("mMatchStyle", subscribeConfig.mMatchStyle, + equalTo(SubscribeConfig.MATCH_STYLE_ALL)); + collector.checkThat("mEnableTerminateNotification", + subscribeConfig.mEnableTerminateNotification, equalTo(true)); + } + + @Test + public void testSubscribeConfigBuilder() { + final String serviceName = "some_service_or_other"; + final String serviceSpecificInfo = "long arbitrary string with some info"; + final byte[] matchFilter = { + 0, 1, 16, 1, 22 }; + final int subscribeType = SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE; + final int subscribeCount = 10; + final int subscribeTtl = 15; + final int matchStyle = SubscribeConfig.MATCH_STYLE_FIRST_ONLY; + final boolean enableTerminateNotification = false; + + SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName) + .setServiceSpecificInfo(serviceSpecificInfo.getBytes()).setMatchFilter(matchFilter) + .setSubscribeType(subscribeType) + .setSubscribeCount(subscribeCount).setTtlSec(subscribeTtl).setMatchStyle(matchStyle) + .setTerminateNotificationEnabled(enableTerminateNotification).build(); + + collector.checkThat("mServiceName", serviceName.getBytes(), + equalTo(subscribeConfig.mServiceName)); + collector.checkThat("mServiceSpecificInfo", + serviceSpecificInfo.getBytes(), equalTo(subscribeConfig.mServiceSpecificInfo)); + collector.checkThat("mMatchFilter", matchFilter, equalTo(subscribeConfig.mMatchFilter)); + collector.checkThat("mSubscribeType", subscribeType, + equalTo(subscribeConfig.mSubscribeType)); + collector.checkThat("mSubscribeCount", subscribeCount, + equalTo(subscribeConfig.mSubscribeCount)); + collector.checkThat("mTtlSec", subscribeTtl, equalTo(subscribeConfig.mTtlSec)); + collector.checkThat("mMatchStyle", matchStyle, equalTo(subscribeConfig.mMatchStyle)); + collector.checkThat("mEnableTerminateNotification", enableTerminateNotification, + equalTo(subscribeConfig.mEnableTerminateNotification)); + } + + @Test + public void testSubscribeConfigParcel() { + final String serviceName = "some_service_or_other"; + final String serviceSpecificInfo = "long arbitrary string with some info"; + final byte[] matchFilter = { + 0, 1, 16, 1, 22 }; + final int subscribeType = SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE; + final int subscribeCount = 10; + final int subscribeTtl = 15; + final int matchStyle = SubscribeConfig.MATCH_STYLE_FIRST_ONLY; + final boolean enableTerminateNotification = true; + + SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName) + .setServiceSpecificInfo(serviceSpecificInfo.getBytes()).setMatchFilter(matchFilter) + .setSubscribeType(subscribeType) + .setSubscribeCount(subscribeCount).setTtlSec(subscribeTtl).setMatchStyle(matchStyle) + .setTerminateNotificationEnabled(enableTerminateNotification).build(); + + Parcel parcelW = Parcel.obtain(); + subscribeConfig.writeToParcel(parcelW, 0); + byte[] bytes = parcelW.marshall(); + parcelW.recycle(); + + Parcel parcelR = Parcel.obtain(); + parcelR.unmarshall(bytes, 0, bytes.length); + parcelR.setDataPosition(0); + SubscribeConfig rereadSubscribeConfig = SubscribeConfig.CREATOR.createFromParcel(parcelR); + + assertEquals(subscribeConfig, rereadSubscribeConfig); + } + + @Test(expected = IllegalArgumentException.class) + public void testSubscribeConfigBuilderBadSubscribeType() { + new SubscribeConfig.Builder().setSubscribeType(10); + } + + @Test(expected = IllegalArgumentException.class) + public void testSubscribeConfigBuilderNegativeCount() { + new SubscribeConfig.Builder().setSubscribeCount(-1); + } + + @Test(expected = IllegalArgumentException.class) + public void testSubscribeConfigBuilderNegativeTtl() { + new SubscribeConfig.Builder().setTtlSec(-100); + } + + /** + * Validate that a bad match style configuration throws an exception. + */ + @Test(expected = IllegalArgumentException.class) + public void testSubscribeConfigBuilderBadMatchStyle() { + new SubscribeConfig.Builder().setMatchStyle(10); + } + + /* + * PublishConfig Tests + */ + + @Test + public void testPublishConfigBuilderDefaults() { + PublishConfig publishConfig = new PublishConfig.Builder().build(); + + collector.checkThat("mServiceName", publishConfig.mServiceName, equalTo(null)); + collector.checkThat("mPublishType", publishConfig.mPublishType, + equalTo(PublishConfig.PUBLISH_TYPE_UNSOLICITED)); + collector.checkThat("mPublishCount", publishConfig.mPublishCount, equalTo(0)); + collector.checkThat("mTtlSec", publishConfig.mTtlSec, equalTo(0)); + collector.checkThat("mEnableTerminateNotification", + publishConfig.mEnableTerminateNotification, equalTo(true)); + } + + @Test + public void testPublishConfigBuilder() { + final String serviceName = "some_service_or_other"; + final String serviceSpecificInfo = "long arbitrary string with some info"; + final byte[] matchFilter = { + 0, 1, 16, 1, 22 }; + final int publishType = PublishConfig.PUBLISH_TYPE_SOLICITED; + final int publishCount = 10; + final int publishTtl = 15; + final boolean enableTerminateNotification = false; + + PublishConfig publishConfig = new PublishConfig.Builder().setServiceName(serviceName) + .setServiceSpecificInfo(serviceSpecificInfo.getBytes()).setMatchFilter(matchFilter) + .setPublishType(publishType) + .setPublishCount(publishCount).setTtlSec(publishTtl) + .setTerminateNotificationEnabled(enableTerminateNotification).build(); + + collector.checkThat("mServiceName", serviceName.getBytes(), + equalTo(publishConfig.mServiceName)); + collector.checkThat("mServiceSpecificInfo", + serviceSpecificInfo.getBytes(), equalTo(publishConfig.mServiceSpecificInfo)); + collector.checkThat("mMatchFilter", matchFilter, equalTo(publishConfig.mMatchFilter)); + collector.checkThat("mPublishType", publishType, equalTo(publishConfig.mPublishType)); + collector.checkThat("mPublishCount", publishCount, equalTo(publishConfig.mPublishCount)); + collector.checkThat("mTtlSec", publishTtl, equalTo(publishConfig.mTtlSec)); + collector.checkThat("mEnableTerminateNotification", enableTerminateNotification, + equalTo(publishConfig.mEnableTerminateNotification)); + } + + @Test + public void testPublishConfigParcel() { + final String serviceName = "some_service_or_other"; + final String serviceSpecificInfo = "long arbitrary string with some info"; + final byte[] matchFilter = { + 0, 1, 16, 1, 22 }; + final int publishType = PublishConfig.PUBLISH_TYPE_SOLICITED; + final int publishCount = 10; + final int publishTtl = 15; + final boolean enableTerminateNotification = false; + + PublishConfig publishConfig = new PublishConfig.Builder().setServiceName(serviceName) + .setServiceSpecificInfo(serviceSpecificInfo.getBytes()).setMatchFilter(matchFilter) + .setPublishType(publishType) + .setPublishCount(publishCount).setTtlSec(publishTtl) + .setTerminateNotificationEnabled(enableTerminateNotification).build(); + + Parcel parcelW = Parcel.obtain(); + publishConfig.writeToParcel(parcelW, 0); + byte[] bytes = parcelW.marshall(); + parcelW.recycle(); + + Parcel parcelR = Parcel.obtain(); + parcelR.unmarshall(bytes, 0, bytes.length); + parcelR.setDataPosition(0); + PublishConfig rereadPublishConfig = PublishConfig.CREATOR.createFromParcel(parcelR); + + assertEquals(publishConfig, rereadPublishConfig); + } + + @Test(expected = IllegalArgumentException.class) + public void testPublishConfigBuilderBadPublishType() { + new PublishConfig.Builder().setPublishType(5); + } + + @Test(expected = IllegalArgumentException.class) + public void testPublishConfigBuilderNegativeCount() { + new PublishConfig.Builder().setPublishCount(-4); + } + + @Test(expected = IllegalArgumentException.class) + public void testPublishConfigBuilderNegativeTtl() { + new PublishConfig.Builder().setTtlSec(-10); + } + + /* + * Ranging tests + */ + + /** + * Validate ranging + success flow: (1) connect, (2) create a (publish) session, (3) start + * ranging, (4) ranging success callback, (5) ranging aborted callback ignored (since + * listener removed). + */ + @Test + public void testRangingCallbacks() throws Exception { + final int clientId = 4565; + final int sessionId = 123; + final int rangingId = 3482; + final ConfigRequest configRequest = new ConfigRequest.Builder().build(); + final PublishConfig publishConfig = new PublishConfig.Builder().build(); + final RttManager.RttParams rttParams = new RttManager.RttParams(); + rttParams.deviceType = RttManager.RTT_PEER_NAN; + rttParams.bssid = Integer.toString(1234); + final RttManager.RttResult rttResults = new RttManager.RttResult(); + rttResults.distance = 10; + + when(mockAwareService.startRanging(anyInt(), anyInt(), + any(RttManager.ParcelableRttParams.class))).thenReturn(rangingId); + + InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService, + mockPublishSession, mockRttListener); + ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass( + WifiAwareSession.class); + ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor + .forClass(IWifiAwareEventCallback.class); + ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor + .forClass(IWifiAwareDiscoverySessionCallback.class); + ArgumentCaptor<WifiAwarePublishDiscoverySession> publishSession = ArgumentCaptor + .forClass(WifiAwarePublishDiscoverySession.class); + ArgumentCaptor<RttManager.ParcelableRttParams> rttParamCaptor = ArgumentCaptor + .forClass(RttManager.ParcelableRttParams.class); + ArgumentCaptor<RttManager.RttResult[]> rttResultsCaptor = ArgumentCaptor + .forClass(RttManager.RttResult[].class); + + // (1) connect successfully + mDut.attach(mMockLooperHandler, configRequest, mockCallback, null); + inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(), + clientProxyCallback.capture(), eq(configRequest), eq(false)); + clientProxyCallback.getValue().onConnectSuccess(clientId); + mMockLooper.dispatchAll(); + inOrder.verify(mockCallback).onAttached(sessionCaptor.capture()); + WifiAwareSession session = sessionCaptor.getValue(); + + // (2) publish successfully + session.publish(publishConfig, mockSessionCallback, mMockLooperHandler); + inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig), + sessionProxyCallback.capture()); + sessionProxyCallback.getValue().onSessionStarted(sessionId); + mMockLooper.dispatchAll(); + inOrder.verify(mockSessionCallback).onPublishStarted(publishSession.capture()); + + // (3) start ranging + publishSession.getValue().startRanging(new RttManager.RttParams[]{rttParams}, + mockRttListener); + inOrder.verify(mockAwareService).startRanging(eq(clientId), eq(sessionId), + rttParamCaptor.capture()); + collector.checkThat("RttParams.deviceType", rttParams.deviceType, + equalTo(rttParamCaptor.getValue().mParams[0].deviceType)); + collector.checkThat("RttParams.bssid", rttParams.bssid, + equalTo(rttParamCaptor.getValue().mParams[0].bssid)); + + // (4) ranging success callback + clientProxyCallback.getValue().onRangingSuccess(rangingId, + new RttManager.ParcelableRttResults(new RttManager.RttResult[] { rttResults })); + mMockLooper.dispatchAll(); + inOrder.verify(mockRttListener).onSuccess(rttResultsCaptor.capture()); + collector.checkThat("RttResult.distance", rttResults.distance, + equalTo(rttResultsCaptor.getValue()[0].distance)); + + // (5) ranging aborted callback (should be ignored since listener cleared on first callback) + clientProxyCallback.getValue().onRangingAborted(rangingId); + mMockLooper.dispatchAll(); + + verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService, + mockPublishSession, mockRttListener); + } + + /* + * Data-path tests + */ + + /** + * Validate that correct network specifier is generated for client-based data-path. + */ + @Test + public void testNetworkSpecifierWithClient() throws Exception { + final int clientId = 4565; + final int sessionId = 123; + final WifiAwareManager.PeerHandle peerHandle = new WifiAwareManager.PeerHandle(123412); + final int role = WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR; + final String token = "Some arbitrary token string - can really be anything"; + final ConfigRequest configRequest = new ConfigRequest.Builder().build(); + final PublishConfig publishConfig = new PublishConfig.Builder().build(); + + String tokenB64 = Base64.encodeToString(token.getBytes(), Base64.DEFAULT); + + ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass( + WifiAwareSession.class); + ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor + .forClass(IWifiAwareEventCallback.class); + ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor + .forClass(IWifiAwareDiscoverySessionCallback.class); + ArgumentCaptor<WifiAwarePublishDiscoverySession> publishSession = ArgumentCaptor + .forClass(WifiAwarePublishDiscoverySession.class); + + InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService, + mockPublishSession, mockRttListener); + + // (1) connect successfully + mDut.attach(mMockLooperHandler, configRequest, mockCallback, null); + inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(), + clientProxyCallback.capture(), eq(configRequest), eq(false)); + clientProxyCallback.getValue().onConnectSuccess(clientId); + mMockLooper.dispatchAll(); + inOrder.verify(mockCallback).onAttached(sessionCaptor.capture()); + WifiAwareSession session = sessionCaptor.getValue(); + + // (2) publish successfully + session.publish(publishConfig, mockSessionCallback, mMockLooperHandler); + inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig), + sessionProxyCallback.capture()); + sessionProxyCallback.getValue().onSessionStarted(sessionId); + mMockLooper.dispatchAll(); + inOrder.verify(mockSessionCallback).onPublishStarted(publishSession.capture()); + + // (3) request a network specifier from the session + String networkSpecifier = publishSession.getValue().createNetworkSpecifier(role, peerHandle, + token.getBytes()); + + // validate format + JSONObject jsonObject = new JSONObject(networkSpecifier); + collector.checkThat("role", role, + equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE))); + collector.checkThat("client_id", clientId, + equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID))); + collector.checkThat("session_id", sessionId, + equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_SESSION_ID))); + collector.checkThat("peer_id", peerHandle.peerId, + equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_ID))); + collector.checkThat("token", tokenB64, + equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_TOKEN))); + + verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService, + mockPublishSession, mockRttListener); + } + + /** + * Validate that correct network specifier is generated for a direct data-path (i.e. + * specifying MAC address as opposed to a client-based oqaque specification). + */ + @Test + public void testNetworkSpecifierDirect() throws Exception { + final int clientId = 134; + final ConfigRequest configRequest = new ConfigRequest.Builder().build(); + final byte[] someMac = HexEncoding.decode("000102030405".toCharArray(), false); + final int role = WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR; + final String token = "Some arbitrary token string - can really be anything"; + + String tokenB64 = Base64.encodeToString(token.getBytes(), Base64.DEFAULT); + + ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass( + WifiAwareSession.class); + ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor + .forClass(IWifiAwareEventCallback.class); + + InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService, + mockPublishSession, mockRttListener); + + // (1) connect successfully + mDut.attach(mMockLooperHandler, configRequest, mockCallback, null); + inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(), + clientProxyCallback.capture(), eq(configRequest), eq(false)); + clientProxyCallback.getValue().onConnectSuccess(clientId); + mMockLooper.dispatchAll(); + inOrder.verify(mockCallback).onAttached(sessionCaptor.capture()); + WifiAwareSession session = sessionCaptor.getValue(); + + /* (2) request a direct network specifier*/ + String networkSpecifier = session.createNetworkSpecifier(role, someMac, token.getBytes()); + + /* validate format*/ + JSONObject jsonObject = new JSONObject(networkSpecifier); + collector.checkThat("role", role, + equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE))); + collector.checkThat("client_id", clientId, + equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID))); + collector.checkThat("peer_mac", someMac, equalTo(HexEncoding.decode( + jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_MAC).toCharArray(), + false))); + collector.checkThat("token", tokenB64, + equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_TOKEN))); + + verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService, + mockPublishSession, mockRttListener); + } +} |