Support for APN fallback retries.

// FREEBIE
This commit is contained in:
Moxie Marlinspike
2015-05-15 16:04:27 -07:00
parent 6363be81e0
commit bbb09b558c
9 changed files with 394 additions and 21 deletions

View File

@@ -0,0 +1,83 @@
package org.whispersystems.textsecuregcm.tests.push;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.whispersystems.textsecuregcm.entities.ApnMessage;
import org.whispersystems.textsecuregcm.push.ApnFallbackManager;
import org.whispersystems.textsecuregcm.push.ApnFallbackManager.ApnFallbackTask;
import org.whispersystems.textsecuregcm.push.PushServiceClient;
import org.whispersystems.textsecuregcm.util.Util;
import org.whispersystems.textsecuregcm.websocket.WebsocketAddress;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;
public class ApnFallbackManagerTest {
@Test
public void testFullFallback() throws Exception {
PushServiceClient pushServiceClient = mock(PushServiceClient.class);
WebsocketAddress address = mock(WebsocketAddress.class );
ApnMessage message = new ApnMessage("bar", "123", 1, "hmm", true);
ApnFallbackTask task = new ApnFallbackTask("foo", message, 0, 500);
ApnFallbackManager apnFallbackManager = new ApnFallbackManager(pushServiceClient);
apnFallbackManager.start();
apnFallbackManager.schedule(address, task);
Util.sleep(1100);
ArgumentCaptor<ApnMessage> captor = ArgumentCaptor.forClass(ApnMessage.class);
verify(pushServiceClient, times(2)).send(captor.capture());
List<ApnMessage> messages = captor.getAllValues();
assertEquals(messages.get(0), message);
assertEquals(messages.get(1).getApnId(), task.getApnId());
assertFalse(messages.get(1).isVoip());
}
@Test
public void testPartialFallback() throws Exception {
PushServiceClient pushServiceClient = mock(PushServiceClient.class);
WebsocketAddress address = mock(WebsocketAddress.class );
ApnMessage message = new ApnMessage("bar", "123", 1, "hmm", true);
ApnFallbackTask task = new ApnFallbackTask ("foo", message, 0, 500);
ApnFallbackManager apnFallbackManager = new ApnFallbackManager(pushServiceClient);
apnFallbackManager.start();
apnFallbackManager.schedule(address, task);
Util.sleep(600);
apnFallbackManager.cancel(address);
Util.sleep(600);
verify(pushServiceClient, times(1)).send(eq(message));
}
@Test
public void testNoFallback() throws Exception {
PushServiceClient pushServiceClient = mock(PushServiceClient.class);
WebsocketAddress address = mock(WebsocketAddress.class );
ApnMessage message = new ApnMessage("bar", "123", 1, "hmm", true);
ApnFallbackTask task = new ApnFallbackTask ("foo", message, 0, 500);
ApnFallbackManager apnFallbackManager = new ApnFallbackManager(pushServiceClient);
apnFallbackManager.start();
apnFallbackManager.schedule(address, task);
apnFallbackManager.cancel(address);
Util.sleep(1100);
verifyNoMoreInteractions(pushServiceClient);
}
}

View File

@@ -0,0 +1,93 @@
package org.whispersystems.textsecuregcm.tests.push;
import org.junit.Test;
import org.whispersystems.textsecuregcm.push.ApnFallbackManager;
import org.whispersystems.textsecuregcm.push.ApnFallbackManager.ApnFallbackTask;
import org.whispersystems.textsecuregcm.push.ApnFallbackManager.ApnFallbackTaskQueue;
import org.whispersystems.textsecuregcm.util.Util;
import org.whispersystems.textsecuregcm.websocket.WebsocketAddress;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class ApnFallbackTaskQueueTest {
@Test
public void testBlocking() {
final ApnFallbackTaskQueue taskQueue = new ApnFallbackTaskQueue();
final WebsocketAddress address = mock(WebsocketAddress.class);
final ApnFallbackTask task = mock(ApnFallbackTask.class );
when(task.getExecutionTime()).thenReturn(System.currentTimeMillis() - 1000);
new Thread() {
@Override
public void run() {
Util.sleep(500);
taskQueue.put(address, task);
}
}.start();
Map.Entry<WebsocketAddress, ApnFallbackTask> result = taskQueue.get();
assertEquals(result.getKey(), address);
assertEquals(result.getValue(), task);
}
@Test
public void testElapsedTime() {
final ApnFallbackTaskQueue taskQueue = new ApnFallbackTaskQueue();
final WebsocketAddress address = mock(WebsocketAddress.class);
final ApnFallbackTask task = mock(ApnFallbackTask.class );
long currentTime = System.currentTimeMillis();
when(task.getExecutionTime()).thenReturn(currentTime + 1000);
taskQueue.put(address, task);
Map.Entry<WebsocketAddress, ApnFallbackTask> result = taskQueue.get();
assertTrue(System.currentTimeMillis() >= currentTime + 1000);
assertEquals(result.getKey(), address);
assertEquals(result.getValue(), task);
}
@Test
public void testCanceled() {
final ApnFallbackTaskQueue taskQueue = new ApnFallbackTaskQueue();
final WebsocketAddress addressOne = mock(WebsocketAddress.class);
final ApnFallbackTask taskOne = mock(ApnFallbackTask.class );
final WebsocketAddress addressTwo = mock(WebsocketAddress.class);
final ApnFallbackTask taskTwo = mock(ApnFallbackTask.class );
long currentTime = System.currentTimeMillis();
when(taskOne.getExecutionTime()).thenReturn(currentTime + 1000);
when(taskTwo.getExecutionTime()).thenReturn(currentTime + 2000);
taskQueue.put(addressOne, taskOne);
taskQueue.put(addressTwo, taskTwo);
new Thread() {
@Override
public void run() {
Util.sleep(300);
taskQueue.remove(addressOne);
}
}.start();
Map.Entry<WebsocketAddress, ApnFallbackTask> result = taskQueue.get();
assertTrue(System.currentTimeMillis() >= currentTime + 2000);
assertEquals(result.getKey(), addressTwo);
assertEquals(result.getValue(), taskTwo);
}
}

View File

@@ -10,6 +10,7 @@ import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.whispersystems.textsecuregcm.auth.AccountAuthenticator;
import org.whispersystems.textsecuregcm.entities.OutgoingMessageEntity;
import org.whispersystems.textsecuregcm.push.ApnFallbackManager;
import org.whispersystems.textsecuregcm.push.PushSender;
import org.whispersystems.textsecuregcm.push.ReceiptSender;
import org.whispersystems.textsecuregcm.storage.Account;
@@ -60,12 +61,13 @@ public class WebSocketConnectionTest {
private static final UpgradeRequest upgradeRequest = mock(UpgradeRequest.class );
private static final PushSender pushSender = mock(PushSender.class);
private static final ReceiptSender receiptSender = mock(ReceiptSender.class);
private static final ApnFallbackManager apnFallbackManager = mock(ApnFallbackManager.class);
@Test
public void testCredentials() throws Exception {
MessagesManager storedMessages = mock(MessagesManager.class);
WebSocketAccountAuthenticator webSocketAuthenticator = new WebSocketAccountAuthenticator(accountAuthenticator);
AuthenticatedConnectListener connectListener = new AuthenticatedConnectListener(accountsManager, pushSender, receiptSender, storedMessages, pubSubManager);
AuthenticatedConnectListener connectListener = new AuthenticatedConnectListener(accountsManager, pushSender, receiptSender, storedMessages, pubSubManager, apnFallbackManager);
WebSocketSessionContext sessionContext = mock(WebSocketSessionContext.class);
when(accountAuthenticator.authenticate(eq(new BasicCredentials(VALID_USER, VALID_PASSWORD))))