summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorEtan Cohen <etancohen@google.com>2017-02-09 15:13:40 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2017-02-09 15:13:40 +0000
commit9f729996277994d6320b046a74f75237f0f4e64c (patch)
tree03b78fbde6657550fd7e4ef503bd10efc09a62a8 /tests
parentee13bbb487f6484b8a7d92104c0f3d2997439db3 (diff)
parent26f57d4921a2390f90d4bf474cb76ec3761d6c69 (diff)
Merge "[AWARE] Send message: error code handling"
Diffstat (limited to 'tests')
-rw-r--r--tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java520
1 files changed, 339 insertions, 181 deletions
diff --git a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java
index b5806b7de..4dd268f9d 100644
--- a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java
@@ -19,6 +19,7 @@ package com.android.server.wifi.aware;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.hamcrest.core.IsNull.nullValue;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
@@ -56,7 +57,6 @@ import android.os.test.TestLooper;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
import android.util.SparseArray;
-import android.util.SparseIntArray;
import libcore.util.HexEncoding;
@@ -70,9 +70,12 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.lang.reflect.Field;
-import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
import java.util.Map;
import java.util.Random;
+import java.util.Set;
/**
* Unit test harness for WifiAwareStateManager.
@@ -1377,11 +1380,12 @@ public class WifiAwareStateManagerTest {
}
/**
- * Validate that on send message timeout correct callback is dispatched and that a later
- * firmware notification is ignored.
+ * Validate that on send message errors are handled correctly: immediate send error, queue fail
+ * error (not queue full), and timeout. Behavior: correct callback is dispatched and a later
+ * firmware notification is ignored. Intersperse with one successfull transmission.
*/
@Test
- public void testSendMessageTimeout() throws Exception {
+ public void testSendMessageErrorsImmediateQueueTimeout() throws Exception {
final int clientId = 1005;
final int uid = 1000;
final int pid = 2000;
@@ -1450,16 +1454,47 @@ public class WifiAwareStateManagerTest {
mDut.onMessageSendQueuedSuccessResponse(transactionId2);
mMockLooper.dispatchAll();
- // (4) message send timeout
+ // (4) send a message and get a queueing failure (not queue full)
+ mDut.sendMessage(clientId, sessionId.getValue(), requestorId, ssi.getBytes(), messageId + 2,
+ 0);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId),
+ eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId + 2));
+ short transactionId3 = transactionId.getValue();
+ mDut.onMessageSendQueuedFailResponse(transactionId3, NanStatusType.INTERNAL_FAILURE);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockSessionCallback).onMessageSendFail(messageId + 2,
+ NanStatusType.INTERNAL_FAILURE);
+ validateInternalSendMessageQueuesCleanedUp(messageId + 2);
+
+ // (5) send a message and get an immediate failure (configure first)
+ when(mMockNative.sendMessage(anyShort(), anyInt(), anyInt(), any(byte[].class),
+ any(byte[].class), anyInt())).thenReturn(false);
+
+ mDut.sendMessage(clientId, sessionId.getValue(), requestorId, ssi.getBytes(), messageId + 3,
+ 0);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId),
+ eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId + 3));
+ short transactionId4 = transactionId.getValue();
+ inOrder.verify(mockSessionCallback).onMessageSendFail(messageId + 3,
+ NanStatusType.INTERNAL_FAILURE);
+ validateInternalSendMessageQueuesCleanedUp(messageId + 3);
+
+ // (6) message send timeout
assertTrue(mAlarmManager.dispatch(WifiAwareStateManager.HAL_SEND_MESSAGE_TIMEOUT_TAG));
mMockLooper.dispatchAll();
inOrder.verify(mockSessionCallback).onMessageSendFail(messageId,
NanStatusType.INTERNAL_FAILURE);
validateInternalSendMessageQueuesCleanedUp(messageId);
- // (5) firmware response (unlikely - but good to check)
+ // (7) firmware response (unlikely - but good to check)
mDut.onMessageSendSuccessNotification(transactionId1);
mDut.onMessageSendSuccessNotification(transactionId2);
+
+ // bogus: these didn't even go to firmware or weren't queued
+ mDut.onMessageSendSuccessNotification(transactionId3);
+ mDut.onMessageSendFailNotification(transactionId4, NanStatusType.INTERNAL_FAILURE);
mMockLooper.dispatchAll();
inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId + 1);
@@ -1639,36 +1674,33 @@ public class WifiAwareStateManagerTest {
}
/**
- * Validate that can send empty message successfully: null, byte[0], ""
+ * Validate that the host-side message queue functions. Tests the perfect case of queue always
+ * succeeds and all messages are received on first attempt.
*/
@Test
- public void testSendEmptyMessages() throws Exception {
+ public void testSendMessageQueueSequence() throws Exception {
final int clientId = 1005;
final int uid = 1000;
final int pid = 2000;
final String callingPackage = "com.google.somePackage";
final String serviceName = "some-service-name";
- final String ssi = "some much longer and more arbitrary data";
- final int subscribeCount = 7;
final int subscribeId = 15;
final int requestorId = 22;
final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false);
- final String peerSsi = "some peer ssi data";
- final String peerMatchFilter = "filter binary array represented as string";
- final int messageId = 6948;
+ final int messageIdBase = 6948;
+ final int numberOfMessages = 30;
+ final int queueDepth = 6;
ConfigRequest configRequest = new ConfigRequest.Builder().build();
SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName)
- .setServiceSpecificInfo(ssi.getBytes())
- .setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)
- .setSubscribeCount(subscribeCount).build();
+ .build();
IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class);
IWifiAwareDiscoverySessionCallback mockSessionCallback = mock(
IWifiAwareDiscoverySessionCallback.class);
ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class);
ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class);
- ArgumentCaptor<byte[]> byteArrayCaptor = ArgumentCaptor.forClass(byte[].class);
+ ArgumentCaptor<Integer> messageIdCaptor = ArgumentCaptor.forClass(Integer.class);
InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative);
mDut.enableUsage();
@@ -1695,255 +1727,381 @@ public class WifiAwareStateManagerTest {
inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture());
// (2) match
- mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(),
- peerMatchFilter.getBytes());
+ mDut.onMatchNotification(subscribeId, requestorId, peerMac, null, null);
mMockLooper.dispatchAll();
- inOrder.verify(mockSessionCallback).onMatch(requestorId, peerSsi.getBytes(),
- peerMatchFilter.getBytes());
+ inOrder.verify(mockSessionCallback).onMatch(requestorId, null, null);
- // (3) message null Tx successful queuing
- mDut.sendMessage(clientId, sessionId.getValue(), requestorId, null, messageId, 0);
- mMockLooper.dispatchAll();
- inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId),
- eq(requestorId), eq(peerMac), isNull(byte[].class), eq(messageId));
- short tid = transactionId.getValue();
- mDut.onMessageSendQueuedSuccessResponse(tid);
- mMockLooper.dispatchAll();
+ // (3) transmit messages
+ SendMessageQueueModelAnswer answerObj = new SendMessageQueueModelAnswer(queueDepth,
+ null, null, null);
+ when(mMockNative.sendMessage(anyShort(), anyInt(), anyInt(), any(byte[].class),
+ any(byte[].class), anyInt())).thenAnswer(answerObj);
- // (4) final Tx results (on-air results)
- mDut.onMessageSendSuccessNotification(tid);
- mMockLooper.dispatchAll();
- inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId);
- validateInternalSendMessageQueuesCleanedUp(messageId);
+ int remainingMessages = numberOfMessages;
+ for (int i = 0; i < numberOfMessages; ++i) {
+ mDut.sendMessage(clientId, sessionId.getValue(), requestorId, null, messageIdBase + i,
+ 0);
+ mMockLooper.dispatchAll();
+ // at 1/2 interval have the system simulate transmitting a queued message over-the-air
+ if (i % 2 == 1) {
+ assertTrue(answerObj.process());
+ remainingMessages--;
+ mMockLooper.dispatchAll();
+ }
+ }
+ for (int i = 0; i < remainingMessages; ++i) {
+ assertTrue(answerObj.process());
+ mMockLooper.dispatchAll();
+ }
+ assertEquals("queue empty", 0, answerObj.queueSize());
- // (5) message byte[0] Tx successful queuing
- mDut.sendMessage(clientId, sessionId.getValue(), requestorId, new byte[0], messageId, 0);
+ inOrder.verify(mockSessionCallback, times(numberOfMessages)).onMessageSendSuccess(
+ messageIdCaptor.capture());
+ for (int i = 0; i < numberOfMessages; ++i) {
+ assertEquals("message ID: " + i, (long) messageIdBase + i,
+ (long) messageIdCaptor.getAllValues().get(i));
+ }
+
+ verifyNoMoreInteractions(mockCallback, mockSessionCallback);
+ }
+
+ /**
+ * Validate that the host-side message queue functions. A combination of imperfect conditions:
+ * - Failure to queue: synchronous firmware error
+ * - Failure to queue: asyncronous firmware error
+ * - Failure to transmit: OTA (which will be retried)
+ * - Failure to transmit: other
+ */
+ @Test
+ public void testSendMessageQueueSequenceImperfect() throws Exception {
+ final int clientId = 1005;
+ final int uid = 1000;
+ final int pid = 2000;
+ final String callingPackage = "com.google.somePackage";
+ final String serviceName = "some-service-name";
+ final int subscribeId = 15;
+ final int requestorId = 22;
+ final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false);
+ final int messageIdBase = 6948;
+ final int numberOfMessages = 300;
+ final int queueDepth = 6;
+ final int retransmitCount = 3; // not the maximum
+
+ ConfigRequest configRequest = new ConfigRequest.Builder().build();
+ SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName)
+ .build();
+
+ IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class);
+ IWifiAwareDiscoverySessionCallback mockSessionCallback = mock(
+ IWifiAwareDiscoverySessionCallback.class);
+ ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class);
+ ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class);
+ ArgumentCaptor<Integer> messageIdCaptor = ArgumentCaptor.forClass(Integer.class);
+ InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative);
+
+ mDut.enableUsage();
mMockLooper.dispatchAll();
- inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId),
- eq(requestorId), eq(peerMac), eq(new byte[0]), eq(messageId));
- tid = transactionId.getValue();
- mDut.onMessageSendQueuedSuccessResponse(tid);
+ inOrder.verify(mMockNative).getCapabilities(transactionId.capture());
+ mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities());
mMockLooper.dispatchAll();
- // (6) final Tx results (on-air results)
- mDut.onMessageSendSuccessNotification(tid);
+ // (0) connect
+ mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false);
mMockLooper.dispatchAll();
- inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId);
- validateInternalSendMessageQueuesCleanedUp(messageId);
+ inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
+ eq(configRequest), eq(false), eq(true));
+ mDut.onConfigSuccessResponse(transactionId.getValue());
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockCallback).onConnectSuccess(clientId);
- // (7) message "" Tx successful queuing
- mDut.sendMessage(clientId, sessionId.getValue(), requestorId, "".getBytes(), messageId, 0);
+ // (1) subscribe
+ mDut.subscribe(clientId, subscribeConfig, mockSessionCallback);
mMockLooper.dispatchAll();
- inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId),
- eq(requestorId), eq(peerMac), byteArrayCaptor.capture(), eq(messageId));
- collector.checkThat("Empty message contents", "",
- equalTo(new String(byteArrayCaptor.getValue())));
- tid = transactionId.getValue();
- mDut.onMessageSendQueuedSuccessResponse(tid);
+ inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig));
+ mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId);
mMockLooper.dispatchAll();
+ inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture());
- // (8) final Tx results (on-air results)
- mDut.onMessageSendSuccessNotification(tid);
- mMockLooper.dispatchAll();
- inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId);
- validateInternalSendMessageQueuesCleanedUp(messageId);
+ // (2) match
+ mDut.onMatchNotification(subscribeId, requestorId, peerMac, null, null);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockSessionCallback).onMatch(requestorId, null, null);
+
+ // (3) transmit messages: configure a mix of failures/success
+ Set<Integer> failQueueCommandImmediately = new HashSet<>();
+ Set<Integer> failQueueCommandLater = new HashSet<>();
+ Map<Integer, Integer> numberOfRetries = new HashMap<>();
+
+ int numOfSuccesses = 0;
+ int numOfFailuresInternalFailure = 0;
+ int numOfFailuresNoOta = 0;
+ for (int i = 0; i < numberOfMessages; ++i) {
+ // random results:
+ // - 0-50: success
+ // - 51-60: retransmit value (which will fail for >5)
+ // - 61-70: fail queue later
+ // - 71-80: fail queue immediately
+ // - 81-90: fail retransmit with non-OTA failure
+ int random = mRandomNg.nextInt(90);
+ if (random <= 50) {
+ numberOfRetries.put(messageIdBase + i, 0);
+ numOfSuccesses++;
+ } else if (random <= 60) {
+ numberOfRetries.put(messageIdBase + i, random - 51);
+ if (random - 51 > retransmitCount) {
+ numOfFailuresNoOta++;
+ } else {
+ numOfSuccesses++;
+ }
+ } else if (random <= 70) {
+ failQueueCommandLater.add(messageIdBase + i);
+ numOfFailuresInternalFailure++;
+ } else if (random <= 80) {
+ failQueueCommandImmediately.add(messageIdBase + i);
+ numOfFailuresInternalFailure++;
+ } else {
+ numberOfRetries.put(messageIdBase + i, -1);
+ numOfFailuresInternalFailure++;
+ }
+ }
- verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative);
- }
+ Log.v("WifiAwareStateManagerTest",
+ "failQueueCommandImmediately=" + failQueueCommandImmediately
+ + ", failQueueCommandLater=" + failQueueCommandLater + ", numberOfRetries="
+ + numberOfRetries + ", numOfSuccesses=" + numOfSuccesses
+ + ", numOfFailuresInternalFailure=" + numOfFailuresInternalFailure
+ + ", numOfFailuresNoOta=" + numOfFailuresNoOta);
- @Test
- public void testSendMessageQueueAllQueueFail() throws Exception {
- Capabilities cap = getCapabilities();
- testSendMessageQueue(SendMessageAnswer.OP_QUEUE_FAIL, cap,
- cap.maxQueuedTransmitMessages + 5);
- }
+ SendMessageQueueModelAnswer answerObj = new SendMessageQueueModelAnswer(queueDepth,
+ failQueueCommandImmediately, failQueueCommandLater, numberOfRetries);
+ when(mMockNative.sendMessage(anyShort(), anyInt(), anyInt(), any(byte[].class),
+ any(byte[].class), anyInt())).thenAnswer(answerObj);
- @Test
- public void testSendMessageQueueAllTxSuccess() throws Exception {
- Capabilities cap = getCapabilities();
- testSendMessageQueue(SendMessageAnswer.OP_QUEUE_OK_SEND_OK, cap,
- cap.maxQueuedTransmitMessages + 5);
- }
+ for (int i = 0; i < numberOfMessages; ++i) {
+ mDut.sendMessage(clientId, sessionId.getValue(), requestorId, null, messageIdBase + i,
+ retransmitCount);
+ mMockLooper.dispatchAll();
+ }
- @Test
- public void testSendMessageQueueAllTxFailRetxOk() throws Exception {
- Capabilities cap = getCapabilities();
- testSendMessageQueue(SendMessageAnswer.OP_QUEUE_OK_SEND_RETX_OK, cap,
- cap.maxQueuedTransmitMessages + 5);
- }
+ while (answerObj.queueSize() != 0) {
+ assertTrue(answerObj.process());
+ mMockLooper.dispatchAll();
+ }
- @Test
- public void testSendMessageQueueAllTxFail() throws Exception {
- Capabilities cap = getCapabilities();
- testSendMessageQueue(SendMessageAnswer.OP_QUEUE_OK_SEND_RETX_FAIL, cap,
- cap.maxQueuedTransmitMessages + 5);
- }
+ verify(mockSessionCallback, times(numOfSuccesses)).onMessageSendSuccess(anyInt());
+ verify(mockSessionCallback, times(numOfFailuresInternalFailure)).onMessageSendFail(anyInt(),
+ eq(NanStatusType.INTERNAL_FAILURE));
+ verify(mockSessionCallback, times(numOfFailuresNoOta)).onMessageSendFail(anyInt(),
+ eq(NanStatusType.NO_OTA_ACK));
- @Test
- public void testSendMessageQueueRandomize() throws Exception {
- Capabilities cap = getCapabilities();
- testSendMessageQueue(SendMessageAnswer.OP_QUEUE_RANDOMIZE, cap,
- cap.maxQueuedTransmitMessages * 10);
+ verifyNoMoreInteractions(mockCallback, mockSessionCallback);
}
/**
- * Validate that when sending more messages than can be queued by the firmware (based on
- * capability information) they are queued. Support all possible test success/failure codes.
- * @param behavior: SendMessageAnswer.OP_*.
+ * Validate that can send empty message successfully: null, byte[0], ""
*/
- private void testSendMessageQueue(int behavior, Capabilities cap,
- int numMessages) throws Exception {
+ @Test
+ public void testSendEmptyMessages() throws Exception {
final int clientId = 1005;
final int uid = 1000;
final int pid = 2000;
final String callingPackage = "com.google.somePackage";
+ final String serviceName = "some-service-name";
final String ssi = "some much longer and more arbitrary data";
+ final int subscribeCount = 7;
final int subscribeId = 15;
final int requestorId = 22;
final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false);
final String peerSsi = "some peer ssi data";
final String peerMatchFilter = "filter binary array represented as string";
final int messageId = 6948;
- final int retryCount = 3;
- final int reason = NanStatusType.INTERNAL_FAILURE;
ConfigRequest configRequest = new ConfigRequest.Builder().build();
- SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build();
+ SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName)
+ .setServiceSpecificInfo(ssi.getBytes())
+ .setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)
+ .setSubscribeCount(subscribeCount).build();
IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class);
IWifiAwareDiscoverySessionCallback mockSessionCallback = mock(
IWifiAwareDiscoverySessionCallback.class);
ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class);
ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class);
- ArgumentCaptor<Integer> msgId = ArgumentCaptor.forClass(Integer.class);
+ ArgumentCaptor<byte[]> byteArrayCaptor = ArgumentCaptor.forClass(byte[].class);
+ InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative);
- // (0) initial conditions
mDut.enableUsage();
mMockLooper.dispatchAll();
- verify(mMockNative).getCapabilities(transactionId.capture());
- mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), cap);
+ inOrder.verify(mMockNative).getCapabilities(transactionId.capture());
+ mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities());
mMockLooper.dispatchAll();
- // (1) connect
+ // (0) connect
mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false);
mMockLooper.dispatchAll();
- verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
- eq(false), eq(true));
+ inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
+ eq(configRequest), eq(false), eq(true));
mDut.onConfigSuccessResponse(transactionId.getValue());
mMockLooper.dispatchAll();
- verify(mockCallback).onConnectSuccess(clientId);
+ inOrder.verify(mockCallback).onConnectSuccess(clientId);
- // (2) subscribe & match
+ // (1) subscribe
mDut.subscribe(clientId, subscribeConfig, mockSessionCallback);
mMockLooper.dispatchAll();
- verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig));
+ inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig));
mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture());
+
+ // (2) match
mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(),
peerMatchFilter.getBytes());
mMockLooper.dispatchAll();
- verify(mockSessionCallback).onSessionStarted(sessionId.capture());
- verify(mockSessionCallback).onMatch(requestorId, peerSsi.getBytes(),
+ inOrder.verify(mockSessionCallback).onMatch(requestorId, peerSsi.getBytes(),
peerMatchFilter.getBytes());
- // (3) send large number of messages
- SendMessageAnswer answerObj = new SendMessageAnswer(behavior);
- when(mMockNative.sendMessage(anyShort(), anyInt(), anyInt(), any(byte[].class),
- any(byte[].class), anyInt())).thenAnswer(answerObj);
- for (int i = 0; i < numMessages; ++i) {
- mDut.sendMessage(clientId, sessionId.getValue(), requestorId, ssi.getBytes(),
- messageId + i, retryCount);
- }
+ // (3) message null Tx successful queuing
+ mDut.sendMessage(clientId, sessionId.getValue(), requestorId, null, messageId, 0);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId),
+ eq(requestorId), eq(peerMac), isNull(byte[].class), eq(messageId));
+ short tid = transactionId.getValue();
+ mDut.onMessageSendQueuedSuccessResponse(tid);
mMockLooper.dispatchAll();
- int numSends = answerObj.ops[SendMessageAnswer.OP_QUEUE_FAIL]
- + answerObj.ops[SendMessageAnswer.OP_QUEUE_OK_SEND_OK]
- + answerObj.ops[SendMessageAnswer.OP_QUEUE_OK_SEND_RETX_OK] * 2
- + answerObj.ops[SendMessageAnswer.OP_QUEUE_OK_SEND_RETX_FAIL] * (retryCount + 1);
- int numOnSendSuccess = answerObj.ops[SendMessageAnswer.OP_QUEUE_OK_SEND_OK]
- + answerObj.ops[SendMessageAnswer.OP_QUEUE_OK_SEND_RETX_OK];
- int numOnSendFail = answerObj.ops[SendMessageAnswer.OP_QUEUE_OK_SEND_RETX_FAIL];
+ // (4) final Tx results (on-air results)
+ mDut.onMessageSendSuccessNotification(tid);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId);
+ validateInternalSendMessageQueuesCleanedUp(messageId);
- Log.v("WifiAwareStateMgrTest",
- "testSendMessageQueue: ops=" + Arrays.toString(answerObj.ops) + ", numSends="
- + numSends + ", numOnSendSuccess=" + numOnSendSuccess + ", numOnSendFail="
- + numOnSendFail);
+ // (5) message byte[0] Tx successful queuing
+ mDut.sendMessage(clientId, sessionId.getValue(), requestorId, new byte[0], messageId, 0);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId),
+ eq(requestorId), eq(peerMac), eq(new byte[0]), eq(messageId));
+ tid = transactionId.getValue();
+ mDut.onMessageSendQueuedSuccessResponse(tid);
+ mMockLooper.dispatchAll();
- verify(mMockNative, times(numSends)).sendMessage(anyShort(), eq(subscribeId),
- eq(requestorId), eq(peerMac), eq(ssi.getBytes()), anyInt());
- verify(mockSessionCallback, times(numOnSendSuccess)).onMessageSendSuccess(anyInt());
- verify(mockSessionCallback, times(numOnSendFail)).onMessageSendFail(anyInt(), anyInt());
+ // (6) final Tx results (on-air results)
+ mDut.onMessageSendSuccessNotification(tid);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId);
+ validateInternalSendMessageQueuesCleanedUp(messageId);
+
+ // (7) message "" Tx successful queuing
+ mDut.sendMessage(clientId, sessionId.getValue(), requestorId, "".getBytes(), messageId, 0);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId),
+ eq(requestorId), eq(peerMac), byteArrayCaptor.capture(), eq(messageId));
+ collector.checkThat("Empty message contents", "",
+ equalTo(new String(byteArrayCaptor.getValue())));
+ tid = transactionId.getValue();
+ mDut.onMessageSendQueuedSuccessResponse(tid);
+ mMockLooper.dispatchAll();
+
+ // (8) final Tx results (on-air results)
+ mDut.onMessageSendSuccessNotification(tid);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId);
+ validateInternalSendMessageQueuesCleanedUp(messageId);
verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative);
}
- private class SendMessageAnswer extends MockAnswerUtil.AnswerWithArguments {
- public static final int OP_QUEUE_FAIL = 0;
- public static final int OP_QUEUE_OK_SEND_OK = 1;
- public static final int OP_QUEUE_OK_SEND_RETX_OK = 2;
- public static final int OP_QUEUE_OK_SEND_RETX_FAIL = 3;
+ private class SendMessageQueueModelAnswer extends MockAnswerUtil.AnswerWithArguments {
+ private final int mMaxQueueDepth;
- /* psuedo operation: randomly pick from the above 4 operations */
- public static final int OP_QUEUE_RANDOMIZE = -1;
+ // keyed by message ID
+ private final Set<Integer> mFailQueueCommandImmediately; // return a false
+ private final Set<Integer> mFailQueueCommandLater; // return an error != TX_QUEUE_FULL
- /* the number of operations which can be executed. Doesn't cound RANDOMIZE since it is
- * resolved to one of the 4 types */
- private static final int NUM_OPS = 4;
+ // # of times to return NO_OTA_ACK before returning SUCCESS. So a 0 means success on first
+ // try, a very large number means - never succeed (since max retry is 5).
+ // a -1 impiles a non-OTA failure: on first attempt
+ private final Map<Integer, Integer> mRetryLimit;
- public int[] ops = new int[NUM_OPS];
+ private final LinkedList<Short> mQueue = new LinkedList<>(); // transaction ID (tid)
+ private final Map<Short, Integer> mMessageIdsByTid = new HashMap<>(); // tid -> message ID
+ private final Map<Integer, Integer> mTriesUsedByMid = new HashMap<>(); // mid -> # of retx
- private int mBehavior = 0;
- private SparseIntArray mPacketBehavior = new SparseIntArray();
+ SendMessageQueueModelAnswer(int maxQueueDepth, Set<Integer> failQueueCommandImmediately,
+ Set<Integer> failQueueCommandLater, Map<Integer, Integer> numberOfRetries) {
+ mMaxQueueDepth = maxQueueDepth;
+ mFailQueueCommandImmediately = failQueueCommandImmediately;
+ mFailQueueCommandLater = failQueueCommandLater;
+ mRetryLimit = numberOfRetries;
- SendMessageAnswer(int behavior) {
- mBehavior = behavior;
+ if (mRetryLimit != null) {
+ for (int mid : mRetryLimit.keySet()) {
+ mTriesUsedByMid.put(mid, 0);
+ }
+ }
}
public boolean answer(short transactionId, int pubSubId, int requestorInstanceId,
byte[] dest, byte[] message, int messageId) throws Exception {
- Log.v("WifiAwareStateMgrTest",
- "SendMessageAnswer.answer: mBehavior=" + mBehavior + ", transactionId="
- + transactionId + ", messageId=" + messageId
- + ", mPacketBehavior[messageId]" + mPacketBehavior.get(messageId, -1));
-
- int behavior = mBehavior;
- if (behavior == OP_QUEUE_RANDOMIZE) {
- behavior = mRandomNg.nextInt(NUM_OPS);
+ if (mFailQueueCommandImmediately != null && mFailQueueCommandImmediately.contains(
+ messageId)) {
+ return false;
}
- boolean packetRetx = mPacketBehavior.get(messageId, -1) != -1;
- if (packetRetx) {
- behavior = mPacketBehavior.get(messageId);
+ if (mFailQueueCommandLater != null && mFailQueueCommandLater.contains(messageId)) {
+ mDut.onMessageSendQueuedFailResponse(transactionId, NanStatusType.INTERNAL_FAILURE);
} else {
- mPacketBehavior.put(messageId, behavior);
+ if (mQueue.size() <= mMaxQueueDepth) {
+ mQueue.addLast(transactionId);
+ mMessageIdsByTid.put(transactionId, messageId);
+ mDut.onMessageSendQueuedSuccessResponse(transactionId);
+ } else {
+ mDut.onMessageSendQueuedFailResponse(transactionId,
+ NanStatusType.FOLLOWUP_TX_QUEUE_FULL);
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Processes the first message in the queue: i.e. responds as if sent over-the-air
+ * (successfully or failed)
+ */
+ boolean process() {
+ if (mQueue.size() == 0) {
+ return false;
}
+ short tid = mQueue.poll();
+ int mid = mMessageIdsByTid.get(tid);
- if (behavior == OP_QUEUE_FAIL) {
- ops[OP_QUEUE_FAIL]++;
- mDut.onMessageSendQueuedFailResponse(transactionId,
- NanStatusType.INTERNAL_FAILURE);
- } else if (behavior == OP_QUEUE_OK_SEND_OK) {
- ops[OP_QUEUE_OK_SEND_OK]++;
- mDut.onMessageSendQueuedSuccessResponse(transactionId);
- mDut.onMessageSendSuccessNotification(transactionId);
- } else if (behavior == OP_QUEUE_OK_SEND_RETX_OK) {
- mDut.onMessageSendQueuedSuccessResponse(transactionId);
- if (!packetRetx) {
- mDut.onMessageSendFailNotification(transactionId,
- NanStatusType.NO_OTA_ACK);
+ if (mRetryLimit != null && mRetryLimit.containsKey(mid)) {
+ int numRetries = mRetryLimit.get(mid);
+ if (numRetries == -1) {
+ mDut.onMessageSendFailNotification(tid, NanStatusType.INTERNAL_FAILURE);
} else {
- ops[OP_QUEUE_OK_SEND_RETX_OK]++;
- mDut.onMessageSendSuccessNotification(transactionId);
+ int currentRetries = mTriesUsedByMid.get(mid);
+ if (currentRetries > numRetries) {
+ return false; // shouldn't be retrying!?
+ } else if (currentRetries == numRetries) {
+ mDut.onMessageSendSuccessNotification(tid);
+ } else {
+ mDut.onMessageSendFailNotification(tid, NanStatusType.NO_OTA_ACK);
+ }
+ mTriesUsedByMid.put(mid, currentRetries + 1);
}
- } else if (behavior == OP_QUEUE_OK_SEND_RETX_FAIL) {
- mDut.onMessageSendQueuedSuccessResponse(transactionId);
- if (!packetRetx) {
- ops[OP_QUEUE_OK_SEND_RETX_FAIL]++;
- }
- mDut.onMessageSendFailNotification(transactionId,
- NanStatusType.NO_OTA_ACK);
+ } else {
+ mDut.onMessageSendSuccessNotification(tid);
}
+
return true;
}
+
+ /**
+ * Returns the number of elements in the queue.
+ */
+ int queueSize() {
+ return mQueue.size();
+ }
}
/**