/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.usergrid.services.notifications.apns;
import com.google.common.util.concurrent.Service;
import com.relayrides.pushy.apns.util.*;
import net.jcip.annotations.NotThreadSafe;
import org.apache.commons.io.IOUtils;
import org.apache.usergrid.persistence.*;
import org.apache.usergrid.persistence.entities.*;
import org.apache.usergrid.persistence.Query;
import org.apache.usergrid.services.exceptions.ForbiddenServiceOperationException;
import org.apache.usergrid.services.notifications.*;
import org.junit.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.InputStream;
import java.util.*;
import org.apache.usergrid.services.ServiceAction;
import static org.apache.usergrid.services.notifications.impl.ApplicationQueueManagerImpl.NOTIFIER_ID_POSTFIX;
import static org.junit.Assert.*;
@NotThreadSafe
public class NotificationsServiceIT extends AbstractServiceNotificationIT {
private static final Logger logger = LoggerFactory.getLogger(NotificationsServiceIT.class);
/**
* set to true to run tests against actual Apple servers - but they may not
* all run correctly
*/
private static final boolean USE_REAL_CONNECTIONS = false;
private static final String PROVIDER = USE_REAL_CONNECTIONS ? "apple" : "noop";
private static final String PUSH_TOKEN = "29026b5a4d2761ef13843e8bcab9fc83b47f1dfbd1d977d225ab296153ce06d6";
private Notifier notifier;
private Device device1, device2;
private User user1, user2;
private NotificationsService ns;
private QueueListener listener;
private String notifierName = "apNs";
@BeforeClass
public static void setup(){
}
@Before
public void before() throws Exception {
// create apns notifier //
app.clear();
app.put("name", notifierName);
app.put("provider",PROVIDER);
app.put("environment", USE_REAL_CONNECTIONS ? "development" : "mock");
InputStream fis = getClass().getClassLoader().getResourceAsStream( "pushtest_dev_recent.p12");
byte[] certBytes = IOUtils.toByteArray(fis);
app.put("p12Certificate", certBytes);
fis.close();
Entity e = app.testRequest(ServiceAction.POST, 1, "notifiers").getEntity();
notifier = app.getEntityManager().get(e.getUuid(), Notifier.class);
final String notifierKey = notifier.getName() + NOTIFIER_ID_POSTFIX;
// create devices //
app.clear();
app.put(notifierKey, PUSH_TOKEN);
app.put("name", "device1");
e = app.testRequest(ServiceAction.POST, 1, "devices").getEntity();
app.testRequest(ServiceAction.GET, 1, "devices", e.getUuid());
device1 = app.getEntityManager().get(e.getUuid(), Device.class);
assertEquals(device1.getProperty(notifierKey), PUSH_TOKEN);
app.clear();
app.put(notifierKey, PUSH_TOKEN);
app.put("name", "device2");
e = app.testRequest(ServiceAction.POST, 1, "devices").getEntity();
device2 = app.getEntityManager().get(e.getUuid(), Device.class);
Map<String, Object> props = app.getEntityManager().getProperties(e);
assertEquals(device2.getProperty(notifierKey), PUSH_TOKEN);
setup.getEntityIndex().refresh(app.getId());
// create User
user1 = new User();
user1.setUsername("user1");
user1.setEmail("user1@usergrid.org");
user1 = app.getEntityManager().create(user1);
// create User
user2 = new User();
user2.setUsername("user2");
user2.setEmail("user2@usergrid.org");
user2 = app.getEntityManager().create(user2);
ns = getNotificationService();
setup.getEntityIndex().refresh(app.getId());
listener = new QueueListener(ns.getServiceManagerFactory(),ns.getEntityManagerFactory(), new Properties());
listener.start();
if ( !setup.getJobSchedulerService().isRunning()) {
setup.getJobSchedulerService().startAsync();
setup.getJobSchedulerService().awaitRunning();
}
}
@After
public void after() throws Exception {
if(listener != null) {
listener.stop();
}
}
@Test
public void singlePushNotification() throws Exception {
app.clear();
String payload = getPayload();
Map<String, String> payloads = new HashMap<String, String>(1);
payloads.put(notifier.getName(), payload);
app.put("payloads", payloads);
app.put("queued", System.currentTimeMillis());
app.put("debug",true);
app.put("expire", System.currentTimeMillis() + 300000); // add 5 minutes to current time
// post notification to service manager
Entity e = app.testRequest(ServiceAction.POST, 1,"devices",device1.getUuid(), "notifications").getEntity();
app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
// ensure notification has expected name
Notification notification = app.getEntityManager().get(e.getUuid(), Notification.class);
assertEquals(
notification.getPayloads().get(notifier.getName().toString()),
payload);
// perform push //
notification = notificationWaitForComplete(notification);
checkReceipts(notification, 1);
}
@Test
public void singlePushNotificationNoReceipts() throws Exception {
app.clear();
String payload = "Hello, World!";
Map<String, String> payloads = new HashMap<String, String>(1);
payloads.put(notifier.getUuid().toString(), payload);
app.put("payloads", payloads);
app.put("queued", System.currentTimeMillis());
app.put("debug", true);
app.put("saveReceipts",false );
app.put("expire", System.currentTimeMillis() + 300000); // add 5 minutes to current time
Entity e = app.testRequest(ServiceAction.POST, 1, "devices", device1.getUuid(), "notifications").getEntity();
app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
Notification notification = app.getEntityManager().get(e.getUuid(), Notification.class);
assertEquals(
notification.getPayloads().get(notifier.getUuid().toString()),
payload);
// perform push //
notification = notificationWaitForComplete(notification);
checkReceipts(notification, 0);
}
@Test
public void pushWithNoValidDevicesShouldComplete() throws Exception {
// create unrelated notifier
app.clear();
app.put("name", "gcm");
app.put("provider", PROVIDER);
app.put("environment", "development");
app.put("apiKey", "xxx");
InputStream fis = getClass().getClassLoader().getResourceAsStream( "pushtest_dev_recent.p12");
byte[] certBytes = IOUtils.toByteArray(fis);
app.put("p12Certificate", certBytes);
app.testRequest(ServiceAction.POST, 1, "notifiers").getEntity().toTypedEntity();
String key = "gcm" + NOTIFIER_ID_POSTFIX;
// create unrelated device
app.clear();
app.put(key, PUSH_TOKEN);
Entity e = app.testRequest(ServiceAction.POST, 1, "devices").getEntity();
app.testRequest(ServiceAction.GET, 1, "devices", e.getUuid());
Device device = app.getEntityManager().get(e.getUuid(), Device.class);
assertEquals(device.getProperty(key), PUSH_TOKEN);
// create push notification //
app.clear();
String payload = getPayload();
Map<String, String> payloads = new HashMap<String, String>(1);
payloads.put(notifier.getUuid().toString(), payload);
app.put("payloads", payloads);
app.put("started", System.currentTimeMillis());
app.put("queued", System.currentTimeMillis());
app.put("debug",true);
e = app.testRequest(ServiceAction.POST, 1, "notifications").getEntity();
app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
Notification notification = app.getEntityManager().get(e.getUuid(), Notification.class);
assertEquals(
notification.getPayloads().get(notifier.getUuid().toString()),
payload
);
notificationWaitForComplete(notification);
app.waitForQueueDrainAndRefreshIndex(250);
// verify Query for FINISHED state and that the devices processed is 0
Query query = Query.fromEquals( "state", Notification.State.FINISHED.toString() );
Results results = app.getEntityManager().searchCollection(app.getEntityManager().getApplicationRef(), "notifications", query);
notification = (Notification)results.getEntitiesMap().get(notification.getUuid()).toTypedEntity();
assertEquals(0, notification.getDeviceProcessedCount());
// perform push //
notification = app.getEntityManager().get(e.getUuid(), Notification.class);
// verify Query for FINISHED state
query = Query.fromEquals("state", Notification.State.FINISHED.toString());
results = app.getEntityManager().searchCollection(app.getEntityManager().getApplicationRef(),
"notifications", query);
Entity entity = results.getEntitiesMap().get(notification.getUuid());
assertNotNull(entity);
notification = (Notification) entity.toTypedEntity();
checkReceipts(notification, 0);
// Statistics are not accurate -- see https://issues.apache.org/jira/browse/USERGRID-1207
//checkStatistics(notification, 0, 0);
}
@Test
public void scheduledNotification() throws Exception {
// create push notification //
app.clear();
String payload = getPayload();
Map<String, String> payloads = new HashMap<String, String>(1);
payloads.put(notifier.getUuid().toString(), payload);
app.put("payloads", payloads);
app.put("deliver", System.currentTimeMillis() + 240000);
app.put("debug",true);
Entity e = app.testRequest(ServiceAction.POST, 1,"devices",device1.getUuid(), "notifications")
.getEntity();
app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
Notification notification = app.getEntityManager().get(e.getUuid(),
Notification.class);
assertEquals(
notification.getPayloads().get(notifier.getUuid().toString()),
payload);
// delay until the scheduler has time to run
Thread.sleep(500);
notification = app.getEntityManager().get(e.getUuid(), Notification.class);
assertEquals(Notification.State.SCHEDULED, notification.getState());
}
@Test
public void scheduledNotificationAndEnsureSend() throws Exception {
// create push notification //
app.clear();
String payload = getPayload();
Map<String, String> payloads = new HashMap<String, String>(1);
payloads.put(notifier.getUuid().toString(), payload);
app.put("payloads", payloads);
app.put("deliver", System.currentTimeMillis() + 2000);
app.put("debug",true);
Entity e = app.testRequest(ServiceAction.POST, 1,"devices",device1.getUuid(), "notifications")
.getEntity();
app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
Notification notification = app.getEntityManager().get(e.getUuid(),
Notification.class);
assertEquals(
notification.getPayloads().get(notifier.getUuid().toString()),
payload);
// delay until the scheduler has time to run
logger.info("Sleeping while the scheduler does its work");
Thread.sleep(5000);
notification = app.getEntityManager().get(e.getUuid(), Notification.class);
assertEquals(Notification.State.FINISHED, notification.getState());
}
@Test
public void badPayloads() throws Exception {
// bad payloads format
app.clear();
app.put("payloads", "{asdf}");
app.put("debug",true);
try {
Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
.getEntity();
fail("invalid payload should have been rejected");
} catch (IllegalArgumentException ex) {
// ok
}
// bad notifier
Map<String, String> payloads = new HashMap<String, String>(2);
app.put("payloads", payloads);
payloads.put("xxx", "");
try {
Entity e = app.testRequest(ServiceAction.POST, 1,"devices",device1.getUuid(), "notifications")
.getEntity();
fail("invalid payload should have been rejected");
} catch (IllegalArgumentException ex) {
// ok
}
// payload too long
// need the real provider for this one...
app.clear();
app.put("name", "apNS2");
app.put("provider", "apple");
app.put("environment", "development");
InputStream fis = getClass().getClassLoader().getResourceAsStream(
"pushtest_dev_recent.p12");
byte[] certBytes = IOUtils.toByteArray(fis);
app.put("p12Certificate", certBytes);
fis.close();
Entity e = app.testRequest(ServiceAction.POST, 1, "notifiers")
.getEntity();
Notifier notifier2 = app.getEntityManager().get(e.getUuid(), Notifier.class);
payloads.clear();
StringBuilder sb = new StringBuilder();
sb.append("{\"x\":\"");
while (sb.length() < 2048) {
sb.append("x");
}
sb.append("\"}");
payloads.put(notifier2.getUuid().toString(), sb.toString());
app.clear();
app.put("payloads", payloads);
try {
app.testRequest(ServiceAction.POST, 1, "notifications").getEntity();
fail("invalid payload should have been rejected");
} catch (Exception ex) {
assertEquals(ex.getMessage(),
"java.lang.IllegalArgumentException: Apple APNs payloads must be 2048 characters or less");
// ok
}
}
@Test
public void badToken() throws Exception {
// test adapter doesn't currently support this behavior
if(!USE_REAL_CONNECTIONS){
return;
}
// create push notification //
app.clear();
String payload = getPayload();
Map<String, String> payloads = new HashMap<String, String>(1);
payloads.put(notifier.getUuid().toString(), payload);
app.put("payloads", payloads);
app.put("queued", System.currentTimeMillis());
app.put("debug",true);
Entity e = app.testRequest(ServiceAction.POST, 1,"devices",device1.getUuid(), "notifications")
.getEntity();
app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
Notification notification = app.getEntityManager().get(e.getUuid(),
Notification.class);
assertEquals(
notification.getPayloads().get(notifier.getUuid().toString()),
payload);
ns.addDevice(notification, device1);
// perform push //
notification = notificationWaitForComplete(notification);
// Statistics are not accurate -- see https://issues.apache.org/jira/browse/USERGRID-1207
//checkStatistics(notification, 0, 1);
notification = (Notification) app.getEntityManager().get(notification)
.toTypedEntity();
checkReceipts(notification, 1);
List<EntityRef> receipts = getNotificationReceipts(notification);
Receipt receipt = app.getEntityManager().get(receipts.get(0), Receipt.class);
assertEquals(8, ((Long) receipt.getErrorCode()).longValue());
}
@Test
public void twoDevicesOneNotifier() throws Exception {
// create push notification //
app.clear();
String payload = getPayload();
Map<String, String> payloads = new HashMap<String, String>(1);
payloads.put(notifierName, payload);
app.put("payloads", payloads);
app.put("queued", System.currentTimeMillis());
app.put("debug",true);
Entity e = app.testRequest(ServiceAction.POST, 1, "devices","notifications").getEntity();
app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
Notification notification = app.getEntityManager().get(e.getUuid(),Notification.class);
//assertEquals(notification.getPayloads().get(notifier.getUuid().toString()),payload);
// perform push //
notification = notificationWaitForComplete(notification);
checkReceipts(notification, 2);
}
@Test
public void twoDevicesTwoNotifiers() throws Exception {
String notifier2Name = "apNs2";
// create a 2nd notifier //
app.clear();
app.put("name", notifier2Name);
app.put("provider", PROVIDER);
app.put("environment", "development");
InputStream fis = getClass().getClassLoader().getResourceAsStream(
"pushtest_dev_recent.p12");
byte[] certBytes = IOUtils.toByteArray(fis);
app.put("p12Certificate", certBytes);
fis.close();
Entity e = app.testRequest(ServiceAction.POST, 1, "notifiers")
.getEntity();
setup.getEntityIndex().refresh(app.getId());
app.testRequest(ServiceAction.GET, 1, "notifiers", "apNs2");
Notifier notifier2 = app.getEntityManager().get(e.getUuid(), Notifier.class);
assertEquals(notifier2.getName(), "apNs2");
assertEquals(notifier2.getProvider(), PROVIDER);
assertEquals(notifier2.getEnvironment(), "development");
String key = notifierName + NOTIFIER_ID_POSTFIX;
String key2 = notifier2Name + NOTIFIER_ID_POSTFIX;
device2.setProperty(key, null);
device2.setProperty(key2, PUSH_TOKEN);
app.getEntityManager().update(device2);
setup.getEntityIndex().refresh(app.getId());
// create push notification //
app.clear();
String payload = getPayload();
Map<String, String> payloads = new HashMap<String, String>(1);
payloads.put(notifierName, payload);
payloads.put(notifier2Name, payload);
app.put("payloads", payloads);
app.put("queued", System.currentTimeMillis());
app.put("debug",true);
e = app.testRequest(ServiceAction.POST, 1, "devices","notifications").getEntity();
app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
setup.getEntityIndex().refresh(app.getId());
Notification notification = app.getEntityManager().get(e.getUuid(), Notification.class);
assertEquals(notification.getPayloads().get(notifierName), payload);
// perform push //
notification = notificationWaitForComplete(notification);
setup.getEntityIndex().refresh(app.getId());
checkReceipts(notification, 2); //the second notifier isn't associated correctly so its 3 instead of 4
}
@Test
public void oneDeviceTwoNotifiers() throws Exception {
// This test should configure 2 notifiers on device1 and ensure that we can send to one of them
// create a 2nd notifier //
Object notifierName1 = "apNs2";
Object environment1 = "development";
app.clear();
app.put("name", notifierName1);
app.put("provider", PROVIDER);
app.put("environment", environment1);
InputStream fis = getClass().getClassLoader().getResourceAsStream(
"pushtest_dev_recent.p12");
byte[] certBytes = IOUtils.toByteArray(fis);
app.put("p12Certificate", certBytes);
fis.close();
Entity e = app.testRequest(ServiceAction.POST, 1, "notifiers").getEntity();
app.testRequest(ServiceAction.GET, 1, "notifiers", notifierName1);
Notifier notifier2 = app.getEntityManager().get(e.getUuid(), Notifier.class);
assertEquals(notifier2.getName(), notifierName1);
assertEquals(notifier2.getProvider(), PROVIDER);
assertEquals(notifier2.getEnvironment(), environment1);
// Add a device token for the 2nd notifier
app.clear();
String key2 = notifier2.getName() + NOTIFIER_ID_POSTFIX;
app.put(key2, PUSH_TOKEN);
app.testRequest(ServiceAction.PUT, 1, "devices", device1).getEntity();
// create push notification //
app.clear();
String payload = getPayload();
Map<String, String> payloads = new HashMap<String, String>(1);
payloads.put(notifierName, payload);
app.put("payloads", payloads);
app.put("debug",true);
Entity notificationEntity = app.testRequest(ServiceAction.POST, 1,"devices",device1.getUuid(),
"notifications").getEntity();
app.testRequest(ServiceAction.GET, 1, "notifications", notificationEntity.getUuid());
Notification notification = app.getEntityManager().get(notificationEntity.getUuid(), Notification.class);
assertEquals(payload, notification.getPayloads().get(notifierName));
// perform push //
notification = notificationWaitForComplete(notification);
app.waitForQueueDrainAndRefreshIndex(2500);
checkReceipts(notification, 1);
}
@Test
public void badCertificate() throws Exception {
// if we're not using real connections, then adding a notifier with bad cert is noop as certs don't exist
// for the test adapter
if(!USE_REAL_CONNECTIONS){
return;
}
// create an apns notifier with the wrong certificate //
app.clear();
app.put("name", "prod_apns");
app.put("provider", PROVIDER);
app.put("environment", "development");
InputStream fis = getClass().getClassLoader().getResourceAsStream("pushtest_dev_recent.p12");
byte[] certBytes = IOUtils.toByteArray(fis);
app.put("p12Certificate", certBytes);
fis.close();
Entity e = app.testRequest(ServiceAction.POST, 1, "notifiers")
.getEntity();
notifier = app.getEntityManager().get(e.getUuid(), Notifier.class);
// create push notification //
app.clear();
String payload = getPayload();
Map<String, String> payloads = new HashMap<String, String>(1);
payloads.put(notifier.getUuid().toString(), payload);
app.put("payloads", payloads);
app.put("queued", System.currentTimeMillis());
app.put("debug",true);
e = app.testRequest(ServiceAction.POST, 1,"devices",device1.getUuid(), "notifications").getEntity();
app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
Notification notification = app.getEntityManager().get(e.getUuid(),
Notification.class);
assertEquals(
notification.getPayloads().get(notifier.getUuid().toString()),
payload);
// perform push //
try {
notificationWaitForComplete(notification);
fail("testConnection() should have failed");
} catch (Exception ex) {
// good, there should be an error
}
// verify Query for FAILED state
Query query = Query.fromEquals("state", Notification.State.FAILED.toString());
Results results = app.getEntityManager().searchCollection(
app.getEntityManager().getApplicationRef(), "notifications", query);
Entity entity = results.getEntitiesMap().get(notification.getUuid());
assertNotNull(entity);
}
@Test
public void inactiveDeviceUpdate() throws Exception {
// test adapter doesn't currently support this
if (!USE_REAL_CONNECTIONS) {
return;
}
// create push notification //
app.clear();
String payload = getPayload();
Map<String, String> payloads = new HashMap<String, String>(1);
payloads.put(notifier.getUuid().toString(), payload);
app.put("payloads", payloads);
app.put("queued", System.currentTimeMillis());
app.put("debug",true);
Entity e = app.testRequest(ServiceAction.POST, 1,"devices",device1.getUuid(), "notifications")
.getEntity();
app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
Notification notification = app.getEntityManager().get(e.getUuid(),
Notification.class);
assertEquals(
notification.getPayloads().get(notifier.getUuid().toString()),
payload);
assertNotNull(device1.getProperty(notifier.getName()
+ NOTIFIER_ID_POSTFIX));
assertNotNull(device2.getProperty(notifier.getName()
+ NOTIFIER_ID_POSTFIX));
// perform push //
notificationWaitForComplete(notification);
// check provider IDs //
device1 = app.getEntityManager().get(device1, Device.class);
assertNull(device1 .getProperty(notifier.getName() + NOTIFIER_ID_POSTFIX));
device2 = app.getEntityManager().get(device2, Device.class);
assertNull(device2 .getProperty(notifier.getName() + NOTIFIER_ID_POSTFIX));
}
@Test
public void singleUserMultipleDevices() throws Exception{
app.testRequest(ServiceAction.POST, 1, "users",user1.getUuid(),"devices",device1.getUuid()).getEntity();
app.testRequest(ServiceAction.POST, 1, "users",user1.getUuid(),"devices",device2.getUuid()).getEntity();
List device1Users = app.getEntityManager().getCollection(device1,"users",null,100, Query.Level.REFS,false).getEntities();
assertEquals(device1Users.size(),1);
List user1Devices = app.getEntityManager().getCollection(user1,"devices",null,100, Query.Level.REFS,false).getEntities();
assertEquals(user1Devices.size(),2);
app.clear();
// create a "hello world" notification
String payload = getPayload();
Map<String, String> payloads = new HashMap<String, String>(1);
payloads.put(notifier.getName(), payload);
app.put("payloads", payloads);
app.put("debug",true);
// post notification to service manager
Entity e = app.testRequest(ServiceAction.POST, 1,"users",user1.getUuid(), "notifications").getEntity();
// ensure notification it was created
app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
// ensure notification has expected name
Notification notification = app.getEntityManager().get(e.getUuid(), Notification.class);
assertEquals(
notification.getPayloads().get(notifier.getName()),
payload);
// perform push //
notification = notificationWaitForComplete(notification);
app.waitForQueueDrainAndRefreshIndex(250);
checkReceipts(notification, 2);
// Statistics are not accurate. See - https://issues.apache.org/jira/browse/USERGRID-1207
//checkStatistics(notification, 2, 0);
}
@Test
@Ignore("This is creating 51 instead of 50 currently with new queue implementation")
public void batchTest() throws Exception {
final int NUM_DEVICES = 50;
// perform push //
int oldBatchSize = QueueListener.MAX_TAKE;
app.clear();
app.put("name", UUID.randomUUID().toString());
app.put("provider","noop");
app.put("environment", "mock");
Entity entity = app.testRequest(ServiceAction.POST, 1, "notifiers").getEntity();
Notifier notifier = app.getEntityManager().get(entity.getUuid(), Notifier.class);
final String notifierKey = notifier.getName() + NOTIFIER_ID_POSTFIX;
setup.getEntityIndex().refresh(app.getId());
// create a bunch of devices and add them to the notification
for (int i = 0; i < NUM_DEVICES; i++) {
app.clear();
app.put(notifierKey, PUSH_TOKEN);
app.put("name", "device"+i*10);
app.testRequest(ServiceAction.POST, 1, "devices").getEntity();
setup.getEntityIndex().refresh(app.getId());
}
app.clear();
String payload = getPayload();
Map<String, String> payloads = new HashMap<String, String>(1);
payloads.put(notifier.getUuid().toString(), payload);
app.put("payloads", payloads);
app.put("queued", System.currentTimeMillis());
app.put("debug",true);
// create a notification
entity = app.testRequest(ServiceAction.POST, 1, "devices","notifications").getEntity();
app.testRequest(ServiceAction.GET, 1, "notifications", entity.getUuid());
setup.getEntityIndex().refresh(app.getId());
final Notification notification = (Notification) entity.toTypedEntity();
try {
notificationWaitForComplete(notification);
} finally {
//noop
}
// check receipts //
checkReceipts(notification, NUM_DEVICES);
// Statistics are not accurate. See - https://issues.apache.org/jira/browse/USERGRID-1207
// checkStatistics(notification, NUM_DEVICES, 0);
}
@Test
public void testDeleteNotification() throws Exception {
// create push notification //
app.clear();
String payload = getPayload();
Map<String, String> payloads = new HashMap<String, String>(1);
payloads.put(notifier.getName(), payload);
app.put("payloads", payloads);
app.put("debug", true);
// stop the queue listener to it can't process the notification
listener.stop();
Entity sentNotification = app.testRequest(ServiceAction.POST, 1, "devices",device1.getUuid(), "notifications")
.getEntity();
// can't delete before it's finished
try {
app.testRequest(ServiceAction.DELETE, 1, "notifications", sentNotification.getUuid());
} catch (Exception e) {
assertEquals(e.getClass(), ForbiddenServiceOperationException.class);
}
// start the queue listener and send another notification that should complete properly
listener.start();
app.clear();
app.put("payloads", payloads);
app.put("debug", true);
Entity sentNotification1 = app.testRequest(ServiceAction.POST, 1, "devices",device1.getUuid(), "notifications")
.getEntity();
Entity fetchedNotification = app.testRequest(ServiceAction.GET, 1, "notifications",
sentNotification1.getUuid()).getEntity();
Notification notification = app.getEntityManager().get(fetchedNotification.getUuid(),
Notification.class);
// perform push //
notification = notificationWaitForComplete(notification);
try {
notification = app.getEntityManager().get(notification.getUuid(), Notification.class);
assertEquals(Notification.State.FINISHED, notification.getState());
//try to delete again after it is in the FINISHED STATE
app.testRequest(ServiceAction.DELETE, 1, "notifications", notification.getUuid());
} catch (Exception e) {
fail("Delete should be successful after notification has finished.");
}
}
@Test
public void pushNotificationBadDeliverProperty() throws Exception {
// try with timestamp in the past
app.clear();
String payload = getPayload();
Map<String, String> payloads = new HashMap<String, String>(1);
payloads.put(notifier.getName(), payload);
app.put("payloads", payloads);
app.put("deliver", System.currentTimeMillis() - 1000); // some time in the past
app.put("debug",true);
// post notification to
try {
app.testRequest(ServiceAction.POST, 1,"devices",device1.getUuid(), "notifications").getEntity();
} catch (Exception e) {
// should be bad request due to time in the past
assertEquals(e.getClass(), IllegalArgumentException.class);
assertTrue(e.getMessage().contains("Property 'deliver' cannot have a value in the past"));
}
// try with invalid type of a string for deliver, should be a number
app.clear();
payload = getPayload();
payloads = new HashMap<String, String>(1);
payloads.put(notifier.getName(), payload);
app.put("payloads", payloads);
app.put("deliver", "notatime"); // some time in the past
app.put("debug",true);
// post notification
try {
app.testRequest(ServiceAction.POST, 1,"devices",device1.getUuid(), "notifications").getEntity();
} catch (Exception e) {
// should be bad request due invalid deliver value
assertEquals(e.getClass(), IllegalArgumentException.class);
assertTrue(e.getMessage().contains("Property 'deliver' must be a number"));
}
}
private String getPayload(){
ApnsPayloadBuilder builder = new ApnsPayloadBuilder();
builder.setAlertBody("Hello, World!");
builder.setSoundFileName("chime");
return builder.buildWithDefaultMaximumLength();
}
}