Delay processing FCM uninstalled feedback
Check to make sure client is not still active before unregistering, since FCM feedback seems to be often erroneous
This commit is contained in:
parent
92ca8862e1
commit
4d9c9206cf
|
@ -210,7 +210,8 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
|||
ActiveUserCounter activeUserCounter = new ActiveUserCounter(config.getMetricsFactory(), cacheClient);
|
||||
DirectoryReconciler directoryReconciler = new DirectoryReconciler(directoryReconciliationClient, directory);
|
||||
AccountCleaner accountCleaner = new AccountCleaner(accountsManager, directoryQueue);
|
||||
List<AccountDatabaseCrawlerListener> accountDatabaseCrawlerListeners = Arrays.asList(activeUserCounter, directoryReconciler, accountCleaner);
|
||||
PushFeedbackProcessor pushFeedbackProcessor = new PushFeedbackProcessor(accountsManager, directoryQueue);
|
||||
List<AccountDatabaseCrawlerListener> accountDatabaseCrawlerListeners = List.of(pushFeedbackProcessor, activeUserCounter, directoryReconciler, accountCleaner);
|
||||
|
||||
AccountDatabaseCrawlerCache accountDatabaseCrawlerCache = new AccountDatabaseCrawlerCache(cacheClient);
|
||||
AccountDatabaseCrawler accountDatabaseCrawler = new AccountDatabaseCrawler(accounts, accountDatabaseCrawlerCache, accountDatabaseCrawlerListeners, config.getAccountDatabaseCrawlerConfiguration().getChunkSize(), config.getAccountDatabaseCrawlerConfiguration().getChunkIntervalMs());
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.whispersystems.textsecuregcm.storage.Account;
|
|||
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
||||
import org.whispersystems.textsecuregcm.storage.Device;
|
||||
import org.whispersystems.textsecuregcm.util.Constants;
|
||||
import org.whispersystems.textsecuregcm.util.Util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
@ -111,19 +112,20 @@ public class GCMSender implements Managed {
|
|||
GcmMessage message = (GcmMessage)result.getContext();
|
||||
logger.warn("Got GCM unregistered notice! " + message.getGcmId());
|
||||
|
||||
// Optional<Account> account = getAccountForEvent(message);
|
||||
//
|
||||
// if (account.isPresent()) {
|
||||
// Device device = account.get().getDevice(message.getDeviceId()).get();
|
||||
Optional<Account> account = getAccountForEvent(message);
|
||||
|
||||
if (account.isPresent()) {
|
||||
Device device = account.get().getDevice(message.getDeviceId()).get();
|
||||
device.setUninstalledFeedbackTimestamp(Util.todayInMillis());
|
||||
// device.setGcmId(null);
|
||||
// device.setFetchesMessages(false);
|
||||
//
|
||||
// accountsManager.update(account.get());
|
||||
//
|
||||
|
||||
accountsManager.update(account.get());
|
||||
|
||||
// if (!account.get().isActive()) {
|
||||
// directoryQueue.deleteRegisteredUser(account.get().getNumber());
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
unregistered.mark();
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ public class Account implements Principal {
|
|||
}
|
||||
|
||||
public void removeDevice(long deviceId) {
|
||||
this.devices.remove(new Device(deviceId, null, null, null, null, null, null, null, false, 0, null, 0, 0, "NA", false));
|
||||
this.devices.remove(new Device(deviceId, null, null, null, null, null, null, null, false, 0, null, 0, 0, "NA", false, 0));
|
||||
}
|
||||
|
||||
public Set<Device> getDevices() {
|
||||
|
|
|
@ -55,6 +55,9 @@ public class Device {
|
|||
@JsonProperty
|
||||
private long pushTimestamp;
|
||||
|
||||
@JsonProperty
|
||||
private long uninstalledFeedback;
|
||||
|
||||
@JsonProperty
|
||||
private boolean fetchesMessages;
|
||||
|
||||
|
@ -83,7 +86,7 @@ public class Device {
|
|||
String voipApnId, boolean fetchesMessages,
|
||||
int registrationId, SignedPreKey signedPreKey,
|
||||
long lastSeen, long created, String userAgent,
|
||||
boolean unauthenticatedDelivery)
|
||||
boolean unauthenticatedDelivery, long uninstalledFeedback)
|
||||
{
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
|
@ -100,6 +103,7 @@ public class Device {
|
|||
this.created = created;
|
||||
this.userAgent = userAgent;
|
||||
this.unauthenticatedDelivery = unauthenticatedDelivery;
|
||||
this.uninstalledFeedback = uninstalledFeedback;
|
||||
}
|
||||
|
||||
public String getApnId() {
|
||||
|
@ -122,6 +126,14 @@ public class Device {
|
|||
this.voipApnId = voipApnId;
|
||||
}
|
||||
|
||||
public void setUninstalledFeedbackTimestamp(long uninstalledFeedback) {
|
||||
this.uninstalledFeedback = uninstalledFeedback;
|
||||
}
|
||||
|
||||
public long getUninstalledFeedbackTimestamp() {
|
||||
return uninstalledFeedback;
|
||||
}
|
||||
|
||||
public void setLastSeen(long lastSeen) {
|
||||
this.lastSeen = lastSeen;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
package org.whispersystems.textsecuregcm.storage;
|
||||
|
||||
import com.codahale.metrics.Meter;
|
||||
import com.codahale.metrics.MetricRegistry;
|
||||
import com.codahale.metrics.SharedMetricRegistries;
|
||||
import org.whispersystems.textsecuregcm.sqs.DirectoryQueue;
|
||||
import org.whispersystems.textsecuregcm.util.Constants;
|
||||
import org.whispersystems.textsecuregcm.util.Util;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.codahale.metrics.MetricRegistry.name;
|
||||
|
||||
public class PushFeedbackProcessor implements AccountDatabaseCrawlerListener {
|
||||
|
||||
private final MetricRegistry metricRegistry = SharedMetricRegistries.getOrCreate(Constants.METRICS_NAME);
|
||||
private final Meter expired = metricRegistry.meter(name(getClass(), "unregistered", "expired"));
|
||||
private final Meter recovered = metricRegistry.meter(name(getClass(), "unregistered", "recovered"));
|
||||
|
||||
private final AccountsManager accountsManager;
|
||||
private final DirectoryQueue directoryQueue;
|
||||
|
||||
public PushFeedbackProcessor(AccountsManager accountsManager, DirectoryQueue directoryQueue) {
|
||||
this.accountsManager = accountsManager;
|
||||
this.directoryQueue = directoryQueue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCrawlStart() {}
|
||||
|
||||
@Override
|
||||
public void onCrawlChunk(Optional<String> fromNumber, List<Account> chunkAccounts) {
|
||||
for (Account account : chunkAccounts) {
|
||||
boolean update = false;
|
||||
|
||||
for (Device device : account.getDevices()) {
|
||||
if (device.getUninstalledFeedbackTimestamp() != 0 &&
|
||||
device.getUninstalledFeedbackTimestamp() + TimeUnit.DAYS.toMillis(2) <= Util.todayInMillis())
|
||||
{
|
||||
if (device.getLastSeen() + TimeUnit.DAYS.toMillis(2) <= Util.todayInMillis()) {
|
||||
device.setGcmId(null);
|
||||
device.setApnId(null);
|
||||
device.setVoipApnId(null);
|
||||
device.setFetchesMessages(false);
|
||||
expired.mark();
|
||||
} else {
|
||||
device.setUninstalledFeedbackTimestamp(0);
|
||||
recovered.mark();
|
||||
}
|
||||
|
||||
update = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (update) {
|
||||
accountsManager.update(account);
|
||||
|
||||
if (!account.isEnabled()) {
|
||||
directoryQueue.deleteRegisteredUser(account.getNumber());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCrawlEnd(Optional<String> fromNumber) {}
|
||||
}
|
|
@ -80,13 +80,13 @@ public class MessageControllerTest {
|
|||
@Before
|
||||
public void setup() throws Exception {
|
||||
Set<Device> singleDeviceList = new HashSet<Device>() {{
|
||||
add(new Device(1, null, "foo", "bar", "baz", "isgcm", null, null, false, 111, new SignedPreKey(333, "baz", "boop"), System.currentTimeMillis(), System.currentTimeMillis(), "Test", true));
|
||||
add(new Device(1, null, "foo", "bar", "baz", "isgcm", null, null, false, 111, new SignedPreKey(333, "baz", "boop"), System.currentTimeMillis(), System.currentTimeMillis(), "Test", true, 0));
|
||||
}};
|
||||
|
||||
Set<Device> multiDeviceList = new HashSet<Device>() {{
|
||||
add(new Device(1, null, "foo", "bar", "baz", "isgcm", null, null, false, 222, new SignedPreKey(111, "foo", "bar"), System.currentTimeMillis(), System.currentTimeMillis(), "Test", true));
|
||||
add(new Device(2, null, "foo", "bar", "baz", "isgcm", null, null, false, 333, new SignedPreKey(222, "oof", "rab"), System.currentTimeMillis(), System.currentTimeMillis(), "Test", true));
|
||||
add(new Device(3, null, "foo", "bar", "baz", "isgcm", null, null, false, 444, null, System.currentTimeMillis() - TimeUnit.DAYS.toMillis(31), System.currentTimeMillis(), "Test", true));
|
||||
add(new Device(1, null, "foo", "bar", "baz", "isgcm", null, null, false, 222, new SignedPreKey(111, "foo", "bar"), System.currentTimeMillis(), System.currentTimeMillis(), "Test", true, 0));
|
||||
add(new Device(2, null, "foo", "bar", "baz", "isgcm", null, null, false, 333, new SignedPreKey(222, "oof", "rab"), System.currentTimeMillis(), System.currentTimeMillis(), "Test", true, 0));
|
||||
add(new Device(3, null, "foo", "bar", "baz", "isgcm", null, null, false, 444, null, System.currentTimeMillis() - TimeUnit.DAYS.toMillis(31), System.currentTimeMillis(), "Test", true, 0));
|
||||
}};
|
||||
|
||||
Account singleDeviceAccount = new Account(SINGLE_DEVICE_RECIPIENT, singleDeviceList, "1234".getBytes());
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
package org.whispersystems.textsecuregcm.tests.controllers;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
|
||||
import org.hamcrest.MatcherAssert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
@ -25,7 +23,6 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import io.dropwizard.auth.AuthValueFactoryProvider;
|
||||
import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider;
|
||||
import io.dropwizard.testing.junit.ResourceTestRule;
|
||||
import static junit.framework.TestCase.*;
|
||||
|
@ -55,8 +52,8 @@ public class TransparentDataControllerTest {
|
|||
|
||||
@Before
|
||||
public void setup() {
|
||||
Account accountOne = new Account("+14151231111", Collections.singleton(new Device(1, "foo", "bar", "salt", "keykey", "gcm-id", "apn-id", "voipapn-id", true, 1234, new SignedPreKey(5, "public-signed", "signtture-signed"), 31337, 31336, "CoolClient", true)), new byte[16]);
|
||||
Account accountTwo = new Account("+14151232222", Collections.singleton(new Device(1, "2foo", "2bar", "2salt", "2keykey", "2gcm-id", "2apn-id", "2voipapn-id", true, 1234, new SignedPreKey(5, "public-signed", "signtture-signed"), 31337, 31336, "CoolClient", true)), new byte[16]);
|
||||
Account accountOne = new Account("+14151231111", Collections.singleton(new Device(1, "foo", "bar", "salt", "keykey", "gcm-id", "apn-id", "voipapn-id", true, 1234, new SignedPreKey(5, "public-signed", "signtture-signed"), 31337, 31336, "CoolClient", true, 0)), new byte[16]);
|
||||
Account accountTwo = new Account("+14151232222", Collections.singleton(new Device(1, "2foo", "2bar", "2salt", "2keykey", "2gcm-id", "2apn-id", "2voipapn-id", true, 1234, new SignedPreKey(5, "public-signed", "signtture-signed"), 31337, 31336, "CoolClient", true, 0)), new byte[16]);
|
||||
|
||||
accountOne.setProfileName("OneProfileName");
|
||||
accountOne.setIdentityKey("identity_key_value");
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.whispersystems.textsecuregcm.storage.Account;
|
|||
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
||||
import org.whispersystems.textsecuregcm.storage.Device;
|
||||
import org.whispersystems.textsecuregcm.tests.util.SynchronousExecutorService;
|
||||
import org.whispersystems.textsecuregcm.util.Util;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
|
@ -48,45 +49,45 @@ public class GCMSenderTest {
|
|||
verify(sender, times(1)).send(any(Message.class), eq(message));
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void testSendError() {
|
||||
// String destinationNumber = "+12223334444";
|
||||
// String gcmId = "foo";
|
||||
//
|
||||
// AccountsManager accountsManager = mock(AccountsManager.class);
|
||||
// Sender sender = mock(Sender.class );
|
||||
// Result invalidResult = mock(Result.class );
|
||||
// DirectoryQueue directoryQueue = mock(DirectoryQueue.class );
|
||||
// SynchronousExecutorService executorService = new SynchronousExecutorService();
|
||||
//
|
||||
// Account destinationAccount = mock(Account.class);
|
||||
// Device destinationDevice = mock(Device.class );
|
||||
//
|
||||
// when(destinationAccount.getDevice(1)).thenReturn(Optional.of(destinationDevice));
|
||||
// when(accountsManager.get(destinationNumber)).thenReturn(Optional.of(destinationAccount));
|
||||
// when(destinationDevice.getGcmId()).thenReturn(gcmId);
|
||||
//
|
||||
// when(invalidResult.isInvalidRegistrationId()).thenReturn(true);
|
||||
// when(invalidResult.isUnregistered()).thenReturn(false);
|
||||
// when(invalidResult.hasCanonicalRegistrationId()).thenReturn(false);
|
||||
// when(invalidResult.isSuccess()).thenReturn(true);
|
||||
//
|
||||
// GcmMessage message = new GcmMessage(gcmId, destinationNumber, 1, false);
|
||||
// GCMSender gcmSender = new GCMSender(accountsManager, sender, directoryQueue, executorService);
|
||||
//
|
||||
// SettableFuture<Result> invalidFuture = SettableFuture.create();
|
||||
// invalidFuture.set(invalidResult);
|
||||
//
|
||||
// when(sender.send(any(Message.class), Matchers.anyObject())).thenReturn(invalidFuture);
|
||||
// when(invalidResult.getContext()).thenReturn(message);
|
||||
//
|
||||
// gcmSender.sendMessage(message);
|
||||
//
|
||||
// verify(sender, times(1)).send(any(Message.class), eq(message));
|
||||
// verify(accountsManager, times(1)).get(eq(destinationNumber));
|
||||
// verify(accountsManager, times(1)).update(eq(destinationAccount));
|
||||
// verify(destinationDevice, times(1)).setGcmId(eq((String)null));
|
||||
// }
|
||||
@Test
|
||||
public void testSendUninstalled() {
|
||||
String destinationNumber = "+12223334444";
|
||||
String gcmId = "foo";
|
||||
|
||||
AccountsManager accountsManager = mock(AccountsManager.class);
|
||||
Sender sender = mock(Sender.class );
|
||||
Result invalidResult = mock(Result.class );
|
||||
DirectoryQueue directoryQueue = mock(DirectoryQueue.class );
|
||||
SynchronousExecutorService executorService = new SynchronousExecutorService();
|
||||
|
||||
Account destinationAccount = mock(Account.class);
|
||||
Device destinationDevice = mock(Device.class );
|
||||
|
||||
when(destinationAccount.getDevice(1)).thenReturn(Optional.of(destinationDevice));
|
||||
when(accountsManager.get(destinationNumber)).thenReturn(Optional.of(destinationAccount));
|
||||
when(destinationDevice.getGcmId()).thenReturn(gcmId);
|
||||
|
||||
when(invalidResult.isInvalidRegistrationId()).thenReturn(true);
|
||||
when(invalidResult.isUnregistered()).thenReturn(false);
|
||||
when(invalidResult.hasCanonicalRegistrationId()).thenReturn(false);
|
||||
when(invalidResult.isSuccess()).thenReturn(true);
|
||||
|
||||
GcmMessage message = new GcmMessage(gcmId, destinationNumber, 1, false);
|
||||
GCMSender gcmSender = new GCMSender(accountsManager, sender, directoryQueue, executorService);
|
||||
|
||||
SettableFuture<Result> invalidFuture = SettableFuture.create();
|
||||
invalidFuture.set(invalidResult);
|
||||
|
||||
when(sender.send(any(Message.class), Matchers.anyObject())).thenReturn(invalidFuture);
|
||||
when(invalidResult.getContext()).thenReturn(message);
|
||||
|
||||
gcmSender.sendMessage(message);
|
||||
|
||||
verify(sender, times(1)).send(any(Message.class), eq(message));
|
||||
verify(accountsManager, times(1)).get(eq(destinationNumber));
|
||||
verify(accountsManager, times(1)).update(eq(destinationAccount));
|
||||
verify(destinationDevice, times(1)).setUninstalledFeedbackTimestamp(eq(Util.todayInMillis()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanonicalId() {
|
||||
|
|
|
@ -241,7 +241,7 @@ public class AccountsTest {
|
|||
private Device generateDevice(long id) {
|
||||
Random random = new Random(System.currentTimeMillis());
|
||||
SignedPreKey signedPreKey = new SignedPreKey(random.nextInt(), "testPublicKey-" + random.nextInt(), "testSignature-" + random.nextInt());
|
||||
return new Device(id, "testName-" + random.nextInt(), "testAuthToken-" + random.nextInt(), "testSalt-" + random.nextInt(), null, "testGcmId-" + random.nextInt(), "testApnId-" + random.nextInt(), "testVoipApnId-" + random.nextInt(), random.nextBoolean(), random.nextInt(), signedPreKey, random.nextInt(), random.nextInt(), "testUserAgent-" + random.nextInt(), random.nextBoolean());
|
||||
return new Device(id, "testName-" + random.nextInt(), "testAuthToken-" + random.nextInt(), "testSalt-" + random.nextInt(), null, "testGcmId-" + random.nextInt(), "testApnId-" + random.nextInt(), "testVoipApnId-" + random.nextInt(), random.nextBoolean(), random.nextInt(), signedPreKey, random.nextInt(), random.nextInt(), "testUserAgent-" + random.nextInt(), random.nextBoolean(), 0);
|
||||
}
|
||||
|
||||
private Account generateAccount(String number) {
|
||||
|
|
|
@ -21,7 +21,7 @@ public class PublicAccountTest {
|
|||
|
||||
@Test
|
||||
public void testPinSanitation() throws IOException {
|
||||
Set<Device> devices = Collections.singleton(new Device(1, "foo", "bar", "12345", null, "gcm-1234", null, null, true, 1234, new SignedPreKey(1, "public-foo", "signature-foo"), 31337, 31336, "Android4Life", true));
|
||||
Set<Device> devices = Collections.singleton(new Device(1, "foo", "bar", "12345", null, "gcm-1234", null, null, true, 1234, new SignedPreKey(1, "public-foo", "signature-foo"), 31337, 31336, "Android4Life", true, 0));
|
||||
Account account = new Account("+14151231234", devices, new byte[16]);
|
||||
account.setPin("123456");
|
||||
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
package org.whispersystems.textsecuregcm.tests.storage;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.whispersystems.textsecuregcm.sqs.DirectoryQueue;
|
||||
import org.whispersystems.textsecuregcm.storage.Account;
|
||||
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
||||
import org.whispersystems.textsecuregcm.storage.Device;
|
||||
import org.whispersystems.textsecuregcm.storage.PushFeedbackProcessor;
|
||||
import org.whispersystems.textsecuregcm.util.Util;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
public class PushFeedbackProcessorTest {
|
||||
|
||||
private AccountsManager accountsManager = mock(AccountsManager.class);
|
||||
private DirectoryQueue directoryQueue = mock(DirectoryQueue.class);
|
||||
|
||||
private Account uninstalledAccount = mock(Account.class);
|
||||
private Account mixedAccount = mock(Account.class);
|
||||
private Account freshAccount = mock(Account.class);
|
||||
private Account cleanAccount = mock(Account.class);
|
||||
private Account stillActiveAccount = mock(Account.class);
|
||||
|
||||
private Device uninstalledDevice = mock(Device.class);
|
||||
private Device uninstalledDeviceTwo = mock(Device.class);
|
||||
private Device installedDevice = mock(Device.class);
|
||||
private Device installedDeviceTwo = mock(Device.class);
|
||||
private Device recentUninstalledDevice = mock(Device.class);
|
||||
private Device stillActiveDevice = mock(Device.class);
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
when(uninstalledDevice.getUninstalledFeedbackTimestamp()).thenReturn(Util.todayInMillis() - TimeUnit.DAYS.toMillis(2));
|
||||
when(uninstalledDevice.getLastSeen()).thenReturn(Util.todayInMillis() - TimeUnit.DAYS.toMillis(2));
|
||||
when(uninstalledDeviceTwo.getUninstalledFeedbackTimestamp()).thenReturn(Util.todayInMillis() - TimeUnit.DAYS.toMillis(3));
|
||||
when(uninstalledDeviceTwo.getLastSeen()).thenReturn(Util.todayInMillis() - TimeUnit.DAYS.toMillis(3));
|
||||
|
||||
when(installedDevice.getUninstalledFeedbackTimestamp()).thenReturn(0L);
|
||||
when(installedDeviceTwo.getUninstalledFeedbackTimestamp()).thenReturn(0L);
|
||||
|
||||
when(recentUninstalledDevice.getUninstalledFeedbackTimestamp()).thenReturn(Util.todayInMillis() - TimeUnit.DAYS.toMillis(1));
|
||||
when(recentUninstalledDevice.getLastSeen()).thenReturn(Util.todayInMillis());
|
||||
|
||||
when(stillActiveDevice.getUninstalledFeedbackTimestamp()).thenReturn(Util.todayInMillis() - TimeUnit.DAYS.toMillis(2));
|
||||
when(stillActiveDevice.getLastSeen()).thenReturn(Util.todayInMillis());
|
||||
|
||||
when(uninstalledAccount.getDevices()).thenReturn(Set.of(uninstalledDevice));
|
||||
when(mixedAccount.getDevices()).thenReturn(Set.of(installedDevice, uninstalledDeviceTwo));
|
||||
when(freshAccount.getDevices()).thenReturn(Set.of(recentUninstalledDevice));
|
||||
when(cleanAccount.getDevices()).thenReturn(Set.of(installedDeviceTwo));
|
||||
when(stillActiveAccount.getDevices()).thenReturn(Set.of(stillActiveDevice));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testEmpty() {
|
||||
PushFeedbackProcessor processor = new PushFeedbackProcessor(accountsManager, directoryQueue);
|
||||
processor.onCrawlChunk(Optional.of("+14152222222"), Collections.emptyList());
|
||||
|
||||
verifyZeroInteractions(accountsManager);
|
||||
verifyZeroInteractions(directoryQueue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdate() {
|
||||
PushFeedbackProcessor processor = new PushFeedbackProcessor(accountsManager, directoryQueue);
|
||||
processor.onCrawlChunk(Optional.of("+14153333333"), List.of(uninstalledAccount, mixedAccount, stillActiveAccount, freshAccount, cleanAccount));
|
||||
|
||||
verify(uninstalledDevice).setApnId(isNull());
|
||||
verify(uninstalledDevice).setGcmId(isNull());
|
||||
verify(uninstalledDevice).setFetchesMessages(eq(false));
|
||||
|
||||
verify(accountsManager).update(eq(uninstalledAccount));
|
||||
|
||||
verify(uninstalledDeviceTwo).setApnId(isNull());
|
||||
verify(uninstalledDeviceTwo).setGcmId(isNull());
|
||||
verify(uninstalledDeviceTwo).setFetchesMessages(eq(false));
|
||||
|
||||
verify(installedDevice, never()).setApnId(any());
|
||||
verify(installedDevice, never()).setGcmId(any());
|
||||
verify(installedDevice, never()).setFetchesMessages(anyBoolean());
|
||||
|
||||
verify(accountsManager).update(eq(mixedAccount));
|
||||
|
||||
verify(recentUninstalledDevice, never()).setApnId(any());
|
||||
verify(recentUninstalledDevice, never()).setGcmId(any());
|
||||
verify(recentUninstalledDevice, never()).setFetchesMessages(anyBoolean());
|
||||
|
||||
verify(accountsManager, never()).update(eq(freshAccount));
|
||||
|
||||
verify(installedDeviceTwo, never()).setApnId(any());
|
||||
verify(installedDeviceTwo, never()).setGcmId(any());
|
||||
verify(installedDeviceTwo, never()).setFetchesMessages(anyBoolean());
|
||||
|
||||
verify(accountsManager, never()).update(eq(cleanAccount));
|
||||
|
||||
verify(stillActiveDevice).setUninstalledFeedbackTimestamp(eq(0L));
|
||||
verify(stillActiveDevice, never()).setApnId(any());
|
||||
verify(stillActiveDevice, never()).setGcmId(any());
|
||||
verify(stillActiveDevice, never()).setFetchesMessages(anyBoolean());
|
||||
|
||||
verify(accountsManager).update(eq(stillActiveAccount));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1 +1 @@
|
|||
{"devices":[{"id":1,"name":"foo","authToken":"bar","salt":"salt","signalingKey":"keykey","gcmId":"gcm-id","apnId":"apn-id","voipApnId":"voipapn-id","pushTimestamp":0,"fetchesMessages":true,"registrationId":1234,"signedPreKey":{"keyId":5,"publicKey":"public-signed","signature":"signtture-signed"},"lastSeen":31337,"created":31336,"userAgent":"CoolClient","unauthenticatedDelivery":true}],"identityKey":"identity_key_value","name":"OneProfileName","avatar":null,"avatarDigest":null,"pin":"******","uak":"AAAAAAAAAAAAAAAAAAAAAA==","uua":false}
|
||||
{"devices":[{"id":1,"name":"foo","authToken":"bar","salt":"salt","signalingKey":"keykey","gcmId":"gcm-id","apnId":"apn-id","voipApnId":"voipapn-id","pushTimestamp":0,"uninstalledFeedback":0,"fetchesMessages":true,"registrationId":1234,"signedPreKey":{"keyId":5,"publicKey":"public-signed","signature":"signtture-signed"},"lastSeen":31337,"created":31336,"userAgent":"CoolClient","unauthenticatedDelivery":true}],"identityKey":"identity_key_value","name":"OneProfileName","avatar":null,"avatarDigest":null,"pin":"******","uak":"AAAAAAAAAAAAAAAAAAAAAA==","uua":false}
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"devices":[{"id":1,"name":"2foo","authToken":"2bar","salt":"2salt","signalingKey":"2keykey","gcmId":"2gcm-id","apnId":"2apn-id","voipApnId":"2voipapn-id","pushTimestamp":0,"fetchesMessages":true,"registrationId":1234,"signedPreKey":{"keyId":5,"publicKey":"public-signed","signature":"signtture-signed"},"lastSeen":31337,"created":31336,"userAgent":"CoolClient","unauthenticatedDelivery":true}],"identityKey":"different_identity_key_value","name":"TwoProfileName","avatar":null,"avatarDigest":null,"pin":"******","uak":"AAAAAAAAAAAAAAAAAAAAAA==","uua":false}
|
||||
{"devices":[{"id":1,"name":"2foo","authToken":"2bar","salt":"2salt","signalingKey":"2keykey","gcmId":"2gcm-id","apnId":"2apn-id","voipApnId":"2voipapn-id","pushTimestamp":0,"uninstalledFeedback":0,"fetchesMessages":true,"registrationId":1234,"signedPreKey":{"keyId":5,"publicKey":"public-signed","signature":"signtture-signed"},"lastSeen":31337,"created":31336,"userAgent":"CoolClient","unauthenticatedDelivery":true}],"identityKey":"different_identity_key_value","name":"TwoProfileName","avatar":null,"avatarDigest":null,"pin":"******","uak":"AAAAAAAAAAAAAAAAAAAAAA==","uua":false}
|
||||
|
|
Loading…
Reference in New Issue