You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@usergrid.apache.org by sf...@apache.org on 2014/08/20 19:32:50 UTC

[1/4] move tests

Repository: incubator-usergrid
Updated Branches:
  refs/heads/two-dot-o-push-notifications 51e093178 -> dd4e7650b


http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/3c761ff4/stack/services/src/test/java/org/apache/usergrid/services/notifications/AbstractServiceNotificationTest.java
----------------------------------------------------------------------
diff --git a/stack/services/src/test/java/org/apache/usergrid/services/notifications/AbstractServiceNotificationTest.java b/stack/services/src/test/java/org/apache/usergrid/services/notifications/AbstractServiceNotificationTest.java
new file mode 100644
index 0000000..87bed27
--- /dev/null
+++ b/stack/services/src/test/java/org/apache/usergrid/services/notifications/AbstractServiceNotificationTest.java
@@ -0,0 +1,107 @@
+package org.apache.usergrid.services.notifications;
+
+import org.apache.usergrid.persistence.*;
+import org.apache.usergrid.persistence.entities.Notification;
+import org.apache.usergrid.persistence.entities.Receipt;
+import org.apache.usergrid.persistence.index.query.Query;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.rules.TestName;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.usergrid.services.AbstractServiceIT;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+public class AbstractServiceNotificationTest extends AbstractServiceIT {
+    private NotificationsService ns;
+
+    @Rule
+    public TestName name = new TestName();
+
+    @BeforeClass
+    public static void beforeClass() {
+    }
+
+    @Before
+    public void before() throws Exception {
+
+    }
+
+    protected NotificationsService getNotificationService(){
+        ns = (NotificationsService) app.getSm().getService("notifications");
+        return ns;
+    }
+
+    protected Notification scheduleNotificationAndWait(Notification notification)
+            throws Exception {
+        getNotificationService().getQueueManager().processBatchAndReschedule(notification,null);
+        long timeout = System.currentTimeMillis() + 60000;
+        while (System.currentTimeMillis() < timeout) {
+            Thread.sleep(200);
+            notification = app.getEm().get(notification.getUuid(),
+                    Notification.class);
+            if (notification.getFinished() != null) {
+                return notification;
+            }
+        }
+        fail("Notification failed to complete");
+        return null;
+    }
+
+    protected List<EntityRef> getNotificationReceipts(EntityRef notification)
+            throws Exception {
+        Results r = app.getEm().getCollection(notification,
+                Notification.RECEIPTS_COLLECTION, null, 1000000,
+                Query.Level.REFS, false);
+        List<EntityRef> list =new ArrayList<EntityRef>();//get all
+        PagingResultsIterator it = new PagingResultsIterator(r);
+        while(it.hasNext()){
+           list.add((EntityRef)it.next());
+        }
+        return list;
+    }
+
+    protected void checkReceipts(Notification notification, int expected)
+            throws Exception {
+        List<EntityRef> receipts = getNotificationReceipts(notification);
+        long timeout = System.currentTimeMillis() + 60000;
+        while (System.currentTimeMillis() < timeout) {
+            Thread.sleep(200);
+            receipts =getNotificationReceipts(notification);
+            if (receipts.size()==expected) {
+                 break;
+            }
+        }
+        assertEquals(expected, receipts.size());
+        for (EntityRef receipt : receipts) {
+            Receipt r = app.getEm().get(receipt, Receipt.class);
+            assertNotNull(r.getSent());
+            assertNotNull(r.getPayload());
+            assertNotNull(r.getNotifierId());
+            EntityRef source = getNotificationService().getSourceNotification(r);
+            assertEquals(source.getUuid(), notification.getUuid());
+        }
+    }
+
+    protected void checkStatistics(Notification notification, long sent,  long errors) throws Exception{
+        Map<String, Long> statistics = null;
+        long timeout = System.currentTimeMillis() + 60000;
+        while (System.currentTimeMillis() < timeout) {
+            Thread.sleep(200);
+            statistics = app.getEm().get(notification.getUuid(), Notification.class).getStatistics();
+            if (statistics.get("sent")==sent && statistics.get("errors")==errors) {
+                break;
+            }
+        }
+        assertEquals(sent, statistics.get("sent").longValue());
+        assertEquals(errors, statistics.get("errors").longValue());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/3c761ff4/stack/services/src/test/java/org/apache/usergrid/services/notifications/apns/MockSuccessfulProviderAdapter.java
----------------------------------------------------------------------
diff --git a/stack/services/src/test/java/org/apache/usergrid/services/notifications/apns/MockSuccessfulProviderAdapter.java b/stack/services/src/test/java/org/apache/usergrid/services/notifications/apns/MockSuccessfulProviderAdapter.java
new file mode 100644
index 0000000..84b0125
--- /dev/null
+++ b/stack/services/src/test/java/org/apache/usergrid/services/notifications/apns/MockSuccessfulProviderAdapter.java
@@ -0,0 +1,99 @@
+package org.apache.usergrid.services.notifications.apns;
+
+import org.apache.usergrid.persistence.entities.Notification;
+import org.apache.usergrid.persistence.entities.Notifier;
+import org.apache.usergrid.services.notifications.ConnectionException;
+import org.apache.usergrid.services.notifications.NotificationsService;
+import org.apache.usergrid.services.notifications.ProviderAdapter;
+import org.apache.usergrid.services.notifications.TaskTracker;
+
+import java.util.Date;
+import java.util.Map;
+import java.util.Random;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import org.apache.usergrid.persistence.EntityManager;
+import org.apache.usergrid.services.ServicePayload;
+
+public class MockSuccessfulProviderAdapter implements ProviderAdapter {
+
+    private static ProviderAdapter realProviderAdapter;
+
+    public static void install(NotificationsService ns) {
+        install(ns, false);
+    }
+
+    public static void install(NotificationsService ns, boolean doAsync) {
+        if (realProviderAdapter != null)
+            realProviderAdapter = ns.providerAdapters.get("apple");
+        ns.providerAdapters.put("apple", new MockSuccessfulProviderAdapter(
+                doAsync));
+    }
+
+    public static void uninstall(NotificationsService ns) {
+        if (realProviderAdapter != null) {
+            ns.providerAdapters.put("apple", realProviderAdapter);
+        }
+    }
+
+    private ExecutorService pool;
+
+    public MockSuccessfulProviderAdapter() {
+    }
+
+    public MockSuccessfulProviderAdapter(boolean async) {
+        if (async) {
+            pool = Executors
+                    .newFixedThreadPool(APNsAdapter.MAX_CONNECTION_POOL_SIZE);
+        }
+    }
+
+    @Override
+    public void testConnection(Notifier notifier) throws ConnectionException {
+    }
+
+    @Override
+    public String translatePayload(Object payload) throws Exception {
+        return payload.toString();
+    }
+
+    @Override
+    public Map<String, Date> getInactiveDevices(Notifier notifier,
+            EntityManager em) throws Exception {
+        return null;
+    }
+
+    @Override
+    public void validateCreateNotifier(ServicePayload payload) throws Exception {
+    }
+
+    @Override
+    public void doneSendingNotifications() throws Exception {
+    }
+
+    @Override
+    public void sendNotification(final String providerId,
+            final Notifier notifier, final Object payload,
+            final Notification notification, final TaskTracker tracker)
+            throws Exception {
+
+        final APNsNotification apnsNotification = APNsNotification.create(
+                providerId, payload.toString(), notification, tracker);
+
+        if (pool == null) {
+            apnsNotification.messageSent();
+        } else {
+            pool.submit(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        Thread.sleep(new Random().nextInt(100));
+                        apnsNotification.messageSent();
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                }
+            });
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/3c761ff4/stack/services/src/test/java/org/apache/usergrid/services/notifications/apns/NotificationsServiceTest.java
----------------------------------------------------------------------
diff --git a/stack/services/src/test/java/org/apache/usergrid/services/notifications/apns/NotificationsServiceTest.java b/stack/services/src/test/java/org/apache/usergrid/services/notifications/apns/NotificationsServiceTest.java
new file mode 100644
index 0000000..c30edb7
--- /dev/null
+++ b/stack/services/src/test/java/org/apache/usergrid/services/notifications/apns/NotificationsServiceTest.java
@@ -0,0 +1,868 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * 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 org.apache.usergrid.services.notifications.apns;
+
+import com.relayrides.pushy.apns.*;
+import com.relayrides.pushy.apns.util.*;
+import org.apache.commons.io.IOUtils;
+import org.apache.usergrid.persistence.model.util.UUIDGenerator;
+import org.apache.usergrid.services.notifications.AbstractServiceNotificationTest;
+import org.apache.usergrid.persistence.*;
+import org.apache.usergrid.persistence.entities.*;
+import org.apache.usergrid.persistence.index.query.Query;
+import org.apache.usergrid.services.notifications.*;
+import org.junit.After;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.InputStream;
+import java.net.SocketException;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.apache.usergrid.services.ServiceAction;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.apache.usergrid.services.notifications.NotificationsService.NOTIFIER_ID_POSTFIX;
+
+// todo: test reschedule on delivery time change
+// todo: test restart of queuing
+public class NotificationsServiceTest extends AbstractServiceNotificationTest {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NotificationsServiceTest.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 Group group1;
+    private User user1;
+    private NotificationsService ns;
+
+    @Override
+    @Before
+    public void before() throws Exception {
+        super.before();
+        // create apns notifier //
+        NotificationsQueueManager.IS_TEST = true;
+
+        app.clear();
+        app.put("name", "apns");
+        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.getEm().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.getEm().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.getEm().get(e.getUuid(), Device.class);
+
+        // create User
+        app.put( "username", "edanuff" );
+        app.put( "email", "ed@anuff.com" );
+//        user1 = (User)app.testRequest( ServiceAction.POST, 1, "users" ).getEntity();
+//        app.getEm().createConnection(user1, "devices", device1);
+//        app.getEm().createConnection(user1, "devices", device2);
+
+        // create Group
+        app.put( "path", "path" );
+        app.put( "title", "group" );
+        group1 = (Group) app.testRequest( ServiceAction.POST, 1, "groups" ).getEntity();
+
+//        app.getEm().createConnection(group1, "users", user1);
+
+        ns = getNotificationService();
+    }
+
+    @After
+    public void after() throws Exception {
+    }
+
+    @Test
+    public void singlePushNotification() 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("queued", System.currentTimeMillis());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device1);
+
+//        // verify Query for CREATED state
+        Query query = new Query();
+        query.addFilter("state='"+Notification.State.STARTED.toString()+"'");
+        Results results = app.getEm().searchCollection(
+                app.getEm().getApplicationRef(), "notifications", query);
+        Entity entity = results.getEntitiesMap().get(notification.getUuid());
+        assertNotNull(entity);
+
+        // perform push //
+
+        notification = scheduleNotificationAndWait(notification);
+
+        // verify Query for FINISHED state
+        query = new Query();
+        query.addEqualityFilter("state", Notification.State.FINISHED.toString());
+        results = app.getEm().searchCollection(app.getEm().getApplicationRef(),
+                "notifications", query);
+        entity = results.getEntitiesMap().get(notification.getUuid());
+        assertNotNull(entity);
+
+        checkReceipts(notification, 1);
+        checkStatistics(notification, 1, 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.getEm().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());
+
+        e = app.testRequest(ServiceAction.POST, 1, "notifications").getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device);
+
+        // verify Query for CREATED state
+        Query query = new Query();
+        query.addEqualityFilter("state", Notification.State.STARTED.toString());
+        Results results = app.getEm().searchCollection(
+                app.getEm().getApplicationRef(), "notifications", query);
+        Entity entity = results.getEntitiesMap().get(notification.getUuid());
+        assertNotNull(entity);
+
+        // perform push //
+
+        ns.getQueueManager().processBatchAndReschedule(notification, null);
+
+        // verify Query for FINISHED state
+        query = new Query();
+        query.addEqualityFilter("state", Notification.State.FINISHED.toString());
+        results = app.getEm().searchCollection(app.getEm().getApplicationRef(),
+                "notifications", query);
+        entity = results.getEntitiesMap().get(notification.getUuid());
+        assertNotNull(entity);
+
+        notification = (Notification) entity.toTypedEntity();
+        checkReceipts(notification, 0);
+        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("queued", System.currentTimeMillis());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device1);
+
+        // delay until the scheduler has time to run
+        Thread.sleep(500);
+
+        // verify Query for SCHEDULED state
+        Query query = new Query();
+        query.addEqualityFilter("state",
+                Notification.State.SCHEDULED.toString());
+        Results results = app.getEm().searchCollection(
+                app.getEm().getApplicationRef(), "notifications", query);
+        Entity entity = results.getEntitiesMap().get(notification.getUuid());
+        assertNotNull(entity);
+
+        try {
+            e = app.testRequest(ServiceAction.DELETE, 1, "notifications",
+                    e.getUuid()).getEntity();
+        }catch (Exception deleteException){
+            LOG.error("Couldn't delete",deleteException);
+        }
+        app.getEm().get(e.getUuid(), Notification.class);
+    }
+
+    @Test
+    public void badPayloads() throws Exception {
+
+        MockSuccessfulProviderAdapter.uninstall(ns);
+
+        // bad payloads format
+
+        app.clear();
+        app.put("payloads", "{asdf}");
+
+        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, "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.getEm().get(e.getUuid(), Notifier.class);
+
+        payloads.clear();
+        StringBuilder sb = new StringBuilder();
+        sb.append("{\"x\":\"");
+        while (sb.length() < 255) {
+            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 256 characters or less");
+            // ok
+        }
+    }
+
+    @Ignore
+    // todo: how can I mock this?
+    @Test
+    public void badToken() throws Exception {
+
+        // mock action (based on verified actual behavior) //
+
+        if (!USE_REAL_CONNECTIONS) {
+            ns.providerAdapters.put("apple",
+                    new MockSuccessfulProviderAdapter() {
+                        @Override
+                        public void sendNotification(String providerId,
+                                Notifier notifier, Object payload,
+                                Notification notification, TaskTracker tracker)
+                                throws Exception {
+                            APNsNotification apnsNotification = APNsNotification
+                                    .create(providerId, payload.toString(),
+                                            notification, tracker);
+                            apnsNotification.messageSent();
+                            apnsNotification
+                                    .messageSendFailed( RejectedNotificationReason.INVALID_TOKEN);
+                        }
+                    });
+        }
+
+        // create push notification //
+
+        HashMap<String, Object> properties = new LinkedHashMap<String, Object>();
+        String payload = getPayload();
+        Map<String, String> payloads = new HashMap<String, String>(1);
+        payloads.put(notifier.getUuid().toString(), payload);
+        properties.put("payloads", payloads);
+        properties.put("queued", System.currentTimeMillis());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device1);
+
+        // perform push //
+        notification = scheduleNotificationAndWait(notification);
+        checkStatistics(notification, 0, 1);
+
+        notification = (Notification) app.getEm().get(notification)
+                .toTypedEntity();
+        checkReceipts(notification, 1);
+        List<EntityRef> receipts = getNotificationReceipts(notification);
+        Receipt receipt = app.getEm().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(notifier.getUuid().toString(), payload);
+        app.put("payloads", payloads);
+        app.put("queued", System.currentTimeMillis());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device1);
+        ns.addDevice(notification, device2);
+
+        // perform push //
+        notification = scheduleNotificationAndWait(notification);
+
+        checkReceipts(notification, 2);
+    }
+
+    @Test
+    public void twoDevicesTwoNotifiers() throws Exception {
+
+        // create a 2nd notifier //
+        app.clear();
+        app.put("name", "apns2");
+        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();
+        app.testRequest(ServiceAction.GET, 1, "notifiers", "apns2");
+
+        Notifier notifier2 = app.getEm().get(e.getUuid(), Notifier.class);
+        assertEquals(notifier2.getName(), "apns2");
+        assertEquals(notifier2.getProvider(), PROVIDER);
+        assertEquals(notifier2.getEnvironment(), "development");
+
+        String key = notifier.getName() + NOTIFIER_ID_POSTFIX;
+        String key2 = notifier2.getName() + NOTIFIER_ID_POSTFIX;
+        device2.setProperty(key, null);
+        device2.setProperty(key2, null);
+        app.getEm().update(device2);
+
+        // create push notification //
+
+        app.clear();
+        String payload = getPayload();
+        Map<String, String> payloads = new HashMap<String, String>(1);
+        payloads.put(notifier.getUuid().toString(), payload);
+        payloads.put(notifier2.getUuid().toString(), payload);
+        app.put("payloads", payloads);
+        app.put("queued", System.currentTimeMillis());
+
+        e = app.testRequest(ServiceAction.POST, 1, "notifications").getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device1);
+        ns.addDevice(notification, device2);
+
+        // perform push //
+        notification = scheduleNotificationAndWait(notification);
+
+        checkReceipts(notification, 2); //the second notifier isn't associated correctly so its 3 instead of 4
+    }
+
+    @Test
+    public void oneDeviceTwoNotifiers() throws Exception {
+
+        // create a 2nd notifier //
+        Object nameValue = "apns2";
+        Object environValue = "development";
+
+        app.clear();
+        app.put("name", nameValue);
+        app.put("provider", PROVIDER);
+        app.put("environment", environValue);
+        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", nameValue);
+
+        Notifier notifier2 = app.getEm().get(e.getUuid(), Notifier.class);
+        assertEquals(notifier2.getName(), nameValue);
+        assertEquals(notifier2.getProvider(), PROVIDER);
+        assertEquals(notifier2.getEnvironment(), environValue);
+
+        String key2 = notifier2.getName() + NOTIFIER_ID_POSTFIX;
+        device1.setProperty(key2, PUSH_TOKEN);
+        app.getEm().update(device1);
+
+        // create push notification //
+
+        app.clear();
+        String payload = getPayload();
+        Map<String, String> payloads = new HashMap<String, String>(1);
+        payloads.put(notifier.getUuid().toString(), payload);
+        payloads.put(notifier2.getUuid().toString(), payload);
+        app.put("payloads", payloads);
+        app.put("queued", System.currentTimeMillis());
+
+        e = app.testRequest(ServiceAction.POST, 1, "notifications").getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device1);
+
+        // perform push //
+        notification = scheduleNotificationAndWait(notification);
+
+        checkReceipts(notification, 2);
+    }
+
+    @Ignore
+    // todo: how can I mock this?
+    @Test
+    public void badCertificate() throws Exception {
+
+        // 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(
+                "empty.p12");
+        byte[] certBytes = IOUtils.toByteArray(fis);
+        app.put("p12Certificate", certBytes);
+        fis.close();
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifiers")
+                .getEntity();
+        notifier = app.getEm().get(e.getUuid(), Notifier.class);
+
+        // mock error (based on verified actual behavior) //
+        if (!USE_REAL_CONNECTIONS) {
+            ns.providerAdapters.put("apple",
+                    new MockSuccessfulProviderAdapter() {
+                        @Override
+                        public void testConnection(Notifier notifier)
+                                throws ConnectionException {
+                            Exception e = new SocketException(
+                                    "Connection closed by remote host");
+                            throw new ConnectionException(e.getMessage(), e);
+                        }
+                    });
+        }
+
+        // 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());
+
+        e = app.testRequest(ServiceAction.POST, 1, "notifications").getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device1);
+
+        // perform push //
+
+        try {
+            ns.getQueueManager().processBatchAndReschedule(notification,null);
+            fail("testConnection() should have failed");
+        } catch (Exception ex) {
+            // good, there should be an error
+        }
+
+        // verify Query for FAILED state
+        Query query = new Query();
+        query.addEqualityFilter("state", Notification.State.FAILED.toString());
+        Results results = app.getEm().searchCollection(
+                app.getEm().getApplicationRef(), "notifications", query);
+        Entity entity = results.getEntitiesMap().get(notification.getUuid());
+        assertNotNull(entity);
+    }
+
+    @Ignore
+    // todo: how can I mock this?
+    @Test
+    public void inactiveDeviceUpdate() throws Exception {
+
+        // mock action (based on verified actual behavior) //
+        if (!USE_REAL_CONNECTIONS) {
+            ns.providerAdapters.put("apple",
+                    new MockSuccessfulProviderAdapter() {
+                        @Override
+                        public Map<String, Date> getInactiveDevices(
+                                Notifier notifier, EntityManager em)
+                                throws Exception {
+                            return Collections.singletonMap(PUSH_TOKEN,
+                                    new Date());
+                        }
+                    });
+        }
+
+        // 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());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device1);
+        ns.addDevice(notification, device2);
+
+        assertNotNull(device1.getProperty(notifier.getName()
+                + NOTIFIER_ID_POSTFIX));
+        assertNotNull(device2.getProperty(notifier.getName()
+                + NOTIFIER_ID_POSTFIX));
+
+        // perform push //
+        notification = scheduleNotificationAndWait(notification);
+
+        // check provider IDs //
+
+        device1 = app.getEm().get(device1, Device.class);
+        assertNull(device1
+                .getProperty(notifier.getName() + NOTIFIER_ID_POSTFIX));
+        device2 = app.getEm().get(device2, Device.class);
+        assertNull(device2
+                .getProperty(notifier.getName() + NOTIFIER_ID_POSTFIX));
+    }
+
+    @Test
+    public void batchTest() throws Exception {
+
+        final int NUM_DEVICES = 50;
+
+        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());
+
+        // create a notification
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+        final Notification notification = (Notification) e.toTypedEntity();
+
+        // create a bunch of devices and add them to the notification
+        app.clear();
+        app.put(notifier.getName() + NOTIFIER_ID_POSTFIX, PUSH_TOKEN);
+        for (int i = 0; i < NUM_DEVICES; i++) {
+            Entity entity = app.getEm().create("device", app.getProperties());
+            ns.addDevice(notification, entity);
+        }
+
+        // perform push //
+        int oldBatchSize = NotificationsQueueManager.BATCH_SIZE;
+        NotificationsQueueManager.BATCH_SIZE = 10;
+        try {
+            ExecutorService pool = Executors
+                    .newFixedThreadPool(APNsAdapter.MAX_CONNECTION_POOL_SIZE);
+            pool.submit(new Runnable() {
+                @Override
+                public void run() {
+                        try {
+                             scheduleNotificationAndWait(notification);
+                        }catch (Exception e){}
+                }});
+        } finally {
+            NotificationsQueueManager.BATCH_SIZE = oldBatchSize;
+        }
+
+        // check receipts //
+        checkReceipts(notification, NUM_DEVICES);
+        checkStatistics(notification, NUM_DEVICES, 0);
+    }
+
+    @Ignore("Run only if you need to.")
+    @Test
+    public void loadTest() throws Exception {
+
+        MockSuccessfulProviderAdapter.install(ns, true);
+
+        final int NUM_DEVICES = 10000;
+
+        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());
+
+        // create a notification
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+        Notification notification = (Notification) e.toTypedEntity();
+
+        // create a bunch of devices and add them to the notification
+        app.clear();
+        app.put(notifier.getName() + NOTIFIER_ID_POSTFIX, PUSH_TOKEN);
+        for (int i = 0; i < NUM_DEVICES; i++) {
+            Entity entity = app.getEm().create("device", app.getProperties());
+            ns.addDevice(notification, entity);
+        }
+
+        long time = System.currentTimeMillis();
+        LOG.error("START DELIVERY OF {} NOTIFICATIONS", NUM_DEVICES);
+
+        // perform push //
+        notification = scheduleNotificationAndWait(notification);
+        LOG.error("END DELIVERY OF {} NOTIFICATIONS ({})", NUM_DEVICES,
+                System.currentTimeMillis() - time);
+
+        // check receipts //
+        checkReceipts(notification, NUM_DEVICES);
+        checkStatistics(notification, NUM_DEVICES, 0);
+    }
+
+    private String getPayload(){
+        ApnsPayloadBuilder builder = new ApnsPayloadBuilder();
+        builder.setAlertBody("Hello, World!");
+        builder.setSoundFileName("chime");
+        String payload = builder.buildWithDefaultMaximumLength();
+        return payload;
+    }
+    // todo: can't do the following tests here. do it in the REST tier...
+    // private Notification postNotification(String path) throws Exception {
+    // HashMap<String, Object> properties = new LinkedHashMap<String, Object>();
+    // String payload =
+    // APNS.newPayload().alertBody("Hello, World!").sound("chime").build();
+    // Map<String, String> payloads = new HashMap<String, String>(1);
+    // payloads.put(notifier.getUuid().toString(), payload);
+    // properties.put("payloads", payloads);
+    //
+    // Entity e = testRequest(sm, ServiceAction.POST, 1, properties,
+    // path).getEntity();
+    // Thread.sleep(1000); // this sucks
+    // Notification notification = app.getEm().get(e, Notification.class);
+    // return notification;
+    // }
+    //
+    // @Test
+    // public void matrixPushDevice() throws Exception {
+    //
+    // Notification notification = postNotification("devices/" +
+    // device1.getName() + "/notifications");
+    // checkReceipts(notification, 1);
+    // checkStatistics(notification, 1, 0);
+    // }
+    //
+    // @Test
+    // public void matrixPushViaUser() throws Exception {
+    //
+    // Notification notification = postNotification("users/" + user1.getName() +
+    // "/notifications");
+    // checkReceipts(notification, 2);
+    // checkStatistics(notification, 2, 0);
+    // }
+    //
+    // @Test
+    // public void matrixPushViaGroup() throws Exception {
+    //
+    // Notification notification = postNotification("devices/" +
+    // device1.getName() + "/notifications");
+    // checkReceipts(notification, 2);
+    // checkStatistics(notification, 2, 0);
+    // }
+    //
+    // @Test
+    // public void matrixPushDeviceQuery() throws Exception {
+    //
+    // Notification notification = postNotification("devices;ql=name=" +
+    // device1.getName() + "/notifications");
+    // checkReceipts(notification, 1);
+    // checkStatistics(notification, 1, 0);
+    // }
+    //
+    // @Test
+    // public void matrixPushUserQuery() throws Exception {
+    //
+    // Notification notification = postNotification("users;ql=/notifications");
+    // checkReceipts(notification, 2);
+    // checkStatistics(notification, 2, 0);
+    // }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/3c761ff4/stack/services/src/test/java/org/apache/usergrid/services/notifications/gcm/MockSuccessfulProviderAdapter.java
----------------------------------------------------------------------
diff --git a/stack/services/src/test/java/org/apache/usergrid/services/notifications/gcm/MockSuccessfulProviderAdapter.java b/stack/services/src/test/java/org/apache/usergrid/services/notifications/gcm/MockSuccessfulProviderAdapter.java
new file mode 100644
index 0000000..656beae
--- /dev/null
+++ b/stack/services/src/test/java/org/apache/usergrid/services/notifications/gcm/MockSuccessfulProviderAdapter.java
@@ -0,0 +1,72 @@
+package org.apache.usergrid.services.notifications.gcm;
+
+import org.apache.usergrid.persistence.entities.Notification;
+import org.apache.usergrid.persistence.entities.Notifier;
+import org.apache.usergrid.services.notifications.ConnectionException;
+import org.apache.usergrid.services.notifications.NotificationsService;
+import org.apache.usergrid.services.notifications.ProviderAdapter;
+import org.apache.usergrid.services.notifications.TaskTracker;
+
+import java.util.Date;
+import java.util.Map;
+import org.apache.usergrid.persistence.EntityManager;
+import org.apache.usergrid.services.ServicePayload;
+
+public class MockSuccessfulProviderAdapter implements ProviderAdapter {
+
+    private static ProviderAdapter realProviderAdapter;
+
+    public static void install(NotificationsService ns) {
+        if (realProviderAdapter != null)
+            realProviderAdapter = ns.providerAdapters.get("google");
+        ns.providerAdapters.put("google", new MockSuccessfulProviderAdapter());
+    }
+
+    public static void uninstall(NotificationsService ns) {
+        if (realProviderAdapter != null) {
+            ns.providerAdapters.put("google", realProviderAdapter);
+        }
+    }
+
+    public MockSuccessfulProviderAdapter() {
+    }
+
+    @Override
+    public void testConnection(Notifier notifier) throws ConnectionException {
+    }
+
+    @Override
+    public String translatePayload(Object payload) throws Exception {
+        return payload.toString();
+    }
+
+    @Override
+    public Map<String, Date> getInactiveDevices(Notifier notifier,
+            EntityManager em) throws Exception {
+        return null;
+    }
+
+    @Override
+    public void validateCreateNotifier(ServicePayload payload) throws Exception {
+    }
+
+    @Override
+    public void doneSendingNotifications() throws Exception {
+    }
+
+    @Override
+    public void sendNotification(String providerId, Notifier notifier,
+            Object payload, Notification notification, final TaskTracker tracker)
+            throws Exception {
+        new Thread() {
+            @Override
+            public void run() {
+                try {
+                    tracker.completed();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }.start();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/3c761ff4/stack/services/src/test/java/org/apache/usergrid/services/notifications/gcm/NotificationsServiceTest.java
----------------------------------------------------------------------
diff --git a/stack/services/src/test/java/org/apache/usergrid/services/notifications/gcm/NotificationsServiceTest.java b/stack/services/src/test/java/org/apache/usergrid/services/notifications/gcm/NotificationsServiceTest.java
new file mode 100644
index 0000000..7be8e88
--- /dev/null
+++ b/stack/services/src/test/java/org/apache/usergrid/services/notifications/gcm/NotificationsServiceTest.java
@@ -0,0 +1,546 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * 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 org.apache.usergrid.services.notifications.gcm;
+
+import org.apache.usergrid.services.notifications.AbstractServiceNotificationTest;
+import org.apache.usergrid.persistence.entities.Notification;
+import org.apache.usergrid.persistence.entities.Notifier;
+import org.apache.usergrid.persistence.entities.Receipt;
+import org.apache.usergrid.services.notifications.NotificationsService;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.usergrid.services.notifications.ConnectionException;
+import org.apache.usergrid.services.notifications.TaskTracker;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.*;
+import org.apache.usergrid.persistence.Entity;
+import org.apache.usergrid.persistence.EntityRef;
+import org.apache.usergrid.persistence.entities.Device;
+import org.apache.usergrid.services.ServiceAction;
+
+import static org.junit.Assert.*;
+import static org.apache.usergrid.services.notifications.NotificationsService.NOTIFIER_ID_POSTFIX;
+
+public class NotificationsServiceTest extends AbstractServiceNotificationTest {
+
+    private static final Logger LOG = LoggerFactory
+            .getLogger(NotificationsServiceTest.class);
+
+    /**
+     * set to true to run tests against actual GCM servers - but they may not
+     * all run correctly
+     */
+    private static final boolean USE_REAL_CONNECTIONS = false;
+    private static final String PROVIDER = USE_REAL_CONNECTIONS ? "google"
+            : "noop";
+
+    private static final String API_KEY = "AIzaSyCIH_7WC0mOqBGMOXyQnFgrBpOePgHvQJM";
+    private static final String PUSH_TOKEN = "APA91bGxRGnMK8tKgVPzSlxtCFvwSVqx0xEPjA06sBmiK0kQsiwUt6ipSYF0iPRHyUgpXle0P8OlRWJADkQrcN7yxG4pLMg1CVmrqDu8tfSe63mZ-MRU2IW0cOhmosqzC9trl33moS3OvT7qjDjkP4Qq8LYdwwYC5A";
+
+    private Notifier notifier;
+    private Device device1, device2;
+    private NotificationsService ns;
+
+    @Override
+    @Before
+    public void before() throws Exception {
+        super.before();
+
+        // create gcm notifier //
+
+        app.clear();
+        app.put("name", "gcm");
+        app.put("provider", PROVIDER);
+        app.put("environment", "development");
+        app.put("apiKey", API_KEY);
+
+        notifier = (Notifier) app
+                .testRequest(ServiceAction.POST, 1, "notifiers").getEntity()
+                .toTypedEntity();
+        String key = notifier.getName() + NOTIFIER_ID_POSTFIX;
+
+        // create devices //
+
+        app.clear();
+        app.put(key, PUSH_TOKEN);
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "devices")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "devices", e.getUuid());
+
+        device1 = app.getEm().get(e.getUuid(), Device.class);
+        assertEquals(device1.getProperty(key), PUSH_TOKEN);
+
+        app.put(key, PUSH_TOKEN);
+        e = app.testRequest(ServiceAction.POST, 1, "devices").getEntity();
+        device2 = app.getEm().get(e.getUuid(), Device.class);
+        ns = getNotificationService();
+    }
+
+    @Test
+    public void emptyPushNotification() throws Exception {
+
+        app.clear();
+        app.put("name", "foo");
+        app.put("provider", PROVIDER);
+        app.put("environment", "development");
+        app.put("apiKey", API_KEY);
+        Notifier n = (Notifier) app
+                .testRequest(ServiceAction.POST, 1, "notifiers").getEntity()
+                .toTypedEntity();
+
+        app.clear();
+        String payload = "Hello, World!";
+        Map<String, String> payloads = new HashMap<String, String>(1);
+        payloads.put("foo", payload);
+        app.put("payloads", payloads);
+        app.put("queued", System.currentTimeMillis());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        ns.addDevice(notification, device1);
+
+        // perform push //
+        notification = scheduleNotificationAndWait(notification);
+        checkReceipts(notification, 0);
+    }
+
+    @Test
+    public void singlePushNotification() 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());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device1);
+
+        // perform push //
+        notification = scheduleNotificationAndWait(notification);
+        checkReceipts(notification, 1);
+    }
+
+    @Test
+    public void singlePushNotificationViaUser() throws Exception {
+
+        app.clear();
+
+        app.put("username", "asdf");
+        app.put("email", "asdf@adsf.com");
+        Entity user = app.testRequest(ServiceAction.POST, 1, "users")
+                .getEntity();
+        assertNotNull(user);
+        Entity device = app.testRequest(ServiceAction.POST, 1, "users",
+                user.getUuid(), "devices", device1.getUuid()).getEntity();
+        assertEquals(device.getUuid(), device1.getUuid());
+
+        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());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        ns.addDevice(notification, device1);
+
+        // perform push //
+        notification = scheduleNotificationAndWait(notification);
+        checkReceipts(notification, 1);
+    }
+
+    @Test
+    public void twoBatchNotification() 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());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device2);
+        ns.addDevice(notification, device1);
+
+        // reduce Batch size to 1
+        Field field = GCMAdapter.class.getDeclaredField("BATCH_SIZE");
+        field.setAccessible(true);
+        int multicastSize = field.getInt(GCMAdapter.class);
+        try {
+            field.setInt(GCMAdapter.class, 1);
+
+            // perform push //
+            notification = scheduleNotificationAndWait(notification);
+
+            checkReceipts(notification, 2);
+        } finally {
+            field.setInt(GCMAdapter.class, multicastSize);
+        }
+    }
+
+    @Ignore
+    // todo: how can I mock this?
+    @Test
+    public void providerIdUpdate() throws Exception {
+
+        // mock action (based on verified actual behavior) //
+        final String newProviderId = "newProviderId";
+        ns.providerAdapters.put("google", new MockSuccessfulProviderAdapter() {
+            @Override
+            public void sendNotification(String providerId, Notifier notifier,
+                    Object payload, Notification notification,
+                    TaskTracker tracker) throws Exception {
+                tracker.completed(newProviderId);
+            }
+        });
+
+        // create push notification //
+
+        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());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device1);
+
+        // perform push //
+        notification = scheduleNotificationAndWait(notification);
+        checkReceipts(notification, 1);
+
+        Device device = (Device) app.getEm().get(device1).toTypedEntity();
+        assertEquals(newProviderId,
+                device.getProperty(notifier.getName() + NOTIFIER_ID_POSTFIX));
+    }
+
+    @Test
+    public void badPayloads() throws Exception {
+
+        // bad payloads format
+
+        app.clear();
+        app.put("payloads", "{asdf}");
+
+        try {
+            app.testRequest(ServiceAction.POST, 1, "notifications");
+            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 {
+            app.testRequest(ServiceAction.POST, 1, "notifications");
+            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", "gcm2");
+        app.put("provider", "google");
+        app.put("environment", "development");
+        app.put("apiKey", API_KEY);
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifiers")
+                .getEntity();
+        Notifier notifier2 = app.getEm().get(e.getUuid(), Notifier.class);
+
+        payloads.clear();
+        StringBuilder sb = new StringBuilder();
+        sb.append("{\"x\":\"");
+        while (sb.length() < 4080) {
+            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");
+            fail("invalid payload should have been rejected");
+        } catch (Exception ex) {
+            assertEquals("java.lang.IllegalArgumentException: GCM payloads must be 4096 characters or less",
+                    ex.getMessage());
+            // ok
+        }
+    }
+
+    @Ignore
+    // todo: how can I mock this?
+    @Test
+    public void badToken() throws Exception {
+
+        // mock action (based on verified actual behavior) //
+        if (!USE_REAL_CONNECTIONS) {
+            ns.providerAdapters.put("google",
+                    new MockSuccessfulProviderAdapter() {
+                        @Override
+                        public void sendNotification(String providerId,
+                                Notifier notifier, Object payload,
+                                Notification notification, TaskTracker tracker)
+                                throws Exception {
+                            tracker.failed("InvalidRegistration",
+                                    "InvalidRegistration");
+                        }
+                    });
+        }
+
+        // create push notification //
+
+        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());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        // device w/ bad token
+        app.clear();
+        app.put(notifier.getName() + NOTIFIER_ID_POSTFIX, PUSH_TOKEN + "x");
+
+        e = app.testRequest(ServiceAction.POST, 1, "devices").getEntity();
+        device1 = app.getEm().get(e.getUuid(), Device.class);
+
+        ns.addDevice(notification, device1);
+
+        // perform push //
+        notification = scheduleNotificationAndWait(notification);
+
+        List<EntityRef> receipts = getNotificationReceipts(notification);
+        assertEquals(1, receipts.size());
+        Receipt receipt = app.getEm().get(receipts.get(0), Receipt.class);
+        assertEquals("InvalidRegistration", receipt.getErrorCode());
+    }
+
+    @Ignore
+    // todo: how can I mock this?
+    @Test
+    public void badAPIKey() throws Exception {
+
+        if (!USE_REAL_CONNECTIONS) {
+            // mock action (based on verified actual behavior) //
+            ns.providerAdapters.put("google",
+                    new MockSuccessfulProviderAdapter() {
+                        @Override
+                        public void sendNotification(String providerId,
+                                Notifier notifier, Object payload,
+                                Notification notification, TaskTracker tracker)
+                                throws Exception {
+                            Exception e = new IOException();
+                            throw new ConnectionException(e.getMessage(), e);
+                        }
+                    });
+        }
+
+        // create push notification //
+
+        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());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device1);
+
+        // save bad API key
+        app.getEm().setProperty(notifier, "apiKey", API_KEY + "x");
+
+        // perform push //
+
+        try {
+            ns.getQueueManager().processBatchAndReschedule(notification, null);
+            fail("Should have received a ConnectionException");
+        } catch (ConnectionException ex) {
+            // good
+        }
+    }
+
+    @Ignore("Run only if you need to.")
+    @Test
+    public void loadTest() throws Exception {
+
+        final int NUM_DEVICES = 10000;
+
+        // create notification //
+
+        HashMap<String, Object> properties = new LinkedHashMap<String, Object>();
+        String payload = "Hello, World!";
+        Map<String, String> payloads = new HashMap<String, String>(1);
+        payloads.put(notifier.getUuid().toString(), payload);
+        properties.put("payloads", payloads);
+        properties.put("queued", System.currentTimeMillis());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        // create a bunch of devices and add them to the notification
+        properties = new LinkedHashMap<String, Object>();
+        properties.put(notifier.getName() + NOTIFIER_ID_POSTFIX, PUSH_TOKEN);
+        for (int i = 0; i < NUM_DEVICES; i++) {
+            Entity entity = app.getEm().create("device", properties);
+            ns.addDevice(notification, entity);
+        }
+
+        long time = System.currentTimeMillis();
+        LOG.error("START DELIVERY OF {} NOTIFICATIONS", NUM_DEVICES);
+
+        // perform push //
+        notification = scheduleNotificationAndWait(notification);
+        LOG.error("END DELIVERY OF {} NOTIFICATIONS ({})", NUM_DEVICES,
+                System.currentTimeMillis() - time);
+
+        // check receipts //
+        checkReceipts(notification, NUM_DEVICES);
+        checkStatistics(notification, NUM_DEVICES, 0);
+    }
+
+    // @Test
+    // public void inactiveDeviceUpdate() throws Exception {
+    //
+    // if (!USE_REAL_CONNECTIONS) {
+    // // mock action (based on verified actual behavior) //
+    // NotificationsService.providerAdapters.put("apple", new
+    // MockSuccessfulProviderAdapter() {
+    // public Map<String,Date> getInactiveDevices(Notifier notifier,
+    // EntityManager em) throws Exception {
+    // return Collections.singletonMap(PUSH_TOKEN, new Date());
+    // }
+    // });
+    // }
+    //
+    // // create push notification //
+    //
+    // HashMap<String, Object> properties = new LinkedHashMap<String, Object>();
+    // String payload =
+    // APNS.newPayload().alertBody("Hello, World!").sound("chime").build();
+    // Map<String, String> payloads = new HashMap<String, String>(1);
+    // payloads.put(notifier.getUuid().toString(), payload);
+    // properties.put("payloads", payloads);
+    // properties.put("queued", System.currentTimeMillis());
+    //
+    // Entity e = testRequest(sm, ServiceAction.POST, 1, properties,
+    // "notifications").getEntity();
+    // testRequest(sm, ServiceAction.GET, 1, null, "notifications",
+    // e.getUuid());
+    //
+    // Notification notification = em.get(e.getUuid(), Notification.class);
+    // assertEquals(notification.getPayloads().get(notifier.getUuid().toString()),
+    // payload);
+    //
+    // ns.addDevice(notification, device1);
+    // ns.addDevice(notification, device2);
+    //
+    // assertNotNull(device1.getProperty(notifier.getName() +
+    // NOTIFIER_ID_POSTFIX));
+    // assertNotNull(device2.getProperty(notifier.getName() +
+    // NOTIFIER_ID_POSTFIX));
+    //
+    // // perform push //
+    // notification = scheduleNotificationAndWait(notification);
+    //
+    // // check provider IDs //
+    //
+    // device1 = em.get(device1, Device.class);
+    // assertNull(device1.getProperty(notifier.getName() +
+    // NOTIFIER_ID_POSTFIX));
+    // device2 = em.get(device2, Device.class);
+    // assertNull(device2.getProperty(notifier.getName() +
+    // NOTIFIER_ID_POSTFIX));
+    // }
+}


[3/4] move tests

Posted by sf...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/dd4e7650/stack/services/src/test/java/org/apache/usergrid/services/notifications/apns/NotificationsServiceTest.java
----------------------------------------------------------------------
diff --git a/stack/services/src/test/java/org/apache/usergrid/services/notifications/apns/NotificationsServiceTest.java b/stack/services/src/test/java/org/apache/usergrid/services/notifications/apns/NotificationsServiceTest.java
deleted file mode 100644
index c30edb7..0000000
--- a/stack/services/src/test/java/org/apache/usergrid/services/notifications/apns/NotificationsServiceTest.java
+++ /dev/null
@@ -1,868 +0,0 @@
-/*******************************************************************************
- * Copyright 2012 Apigee Corporation
- *
- * 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 org.apache.usergrid.services.notifications.apns;
-
-import com.relayrides.pushy.apns.*;
-import com.relayrides.pushy.apns.util.*;
-import org.apache.commons.io.IOUtils;
-import org.apache.usergrid.persistence.model.util.UUIDGenerator;
-import org.apache.usergrid.services.notifications.AbstractServiceNotificationTest;
-import org.apache.usergrid.persistence.*;
-import org.apache.usergrid.persistence.entities.*;
-import org.apache.usergrid.persistence.index.query.Query;
-import org.apache.usergrid.services.notifications.*;
-import org.junit.After;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.InputStream;
-import java.net.SocketException;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-import org.apache.usergrid.services.ServiceAction;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import static org.apache.usergrid.services.notifications.NotificationsService.NOTIFIER_ID_POSTFIX;
-
-// todo: test reschedule on delivery time change
-// todo: test restart of queuing
-public class NotificationsServiceTest extends AbstractServiceNotificationTest {
-
-    private static final Logger LOG = LoggerFactory.getLogger(NotificationsServiceTest.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 Group group1;
-    private User user1;
-    private NotificationsService ns;
-
-    @Override
-    @Before
-    public void before() throws Exception {
-        super.before();
-        // create apns notifier //
-        NotificationsQueueManager.IS_TEST = true;
-
-        app.clear();
-        app.put("name", "apns");
-        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.getEm().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.getEm().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.getEm().get(e.getUuid(), Device.class);
-
-        // create User
-        app.put( "username", "edanuff" );
-        app.put( "email", "ed@anuff.com" );
-//        user1 = (User)app.testRequest( ServiceAction.POST, 1, "users" ).getEntity();
-//        app.getEm().createConnection(user1, "devices", device1);
-//        app.getEm().createConnection(user1, "devices", device2);
-
-        // create Group
-        app.put( "path", "path" );
-        app.put( "title", "group" );
-        group1 = (Group) app.testRequest( ServiceAction.POST, 1, "groups" ).getEntity();
-
-//        app.getEm().createConnection(group1, "users", user1);
-
-        ns = getNotificationService();
-    }
-
-    @After
-    public void after() throws Exception {
-    }
-
-    @Test
-    public void singlePushNotification() 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("queued", System.currentTimeMillis());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device1);
-
-//        // verify Query for CREATED state
-        Query query = new Query();
-        query.addFilter("state='"+Notification.State.STARTED.toString()+"'");
-        Results results = app.getEm().searchCollection(
-                app.getEm().getApplicationRef(), "notifications", query);
-        Entity entity = results.getEntitiesMap().get(notification.getUuid());
-        assertNotNull(entity);
-
-        // perform push //
-
-        notification = scheduleNotificationAndWait(notification);
-
-        // verify Query for FINISHED state
-        query = new Query();
-        query.addEqualityFilter("state", Notification.State.FINISHED.toString());
-        results = app.getEm().searchCollection(app.getEm().getApplicationRef(),
-                "notifications", query);
-        entity = results.getEntitiesMap().get(notification.getUuid());
-        assertNotNull(entity);
-
-        checkReceipts(notification, 1);
-        checkStatistics(notification, 1, 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.getEm().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());
-
-        e = app.testRequest(ServiceAction.POST, 1, "notifications").getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device);
-
-        // verify Query for CREATED state
-        Query query = new Query();
-        query.addEqualityFilter("state", Notification.State.STARTED.toString());
-        Results results = app.getEm().searchCollection(
-                app.getEm().getApplicationRef(), "notifications", query);
-        Entity entity = results.getEntitiesMap().get(notification.getUuid());
-        assertNotNull(entity);
-
-        // perform push //
-
-        ns.getQueueManager().processBatchAndReschedule(notification, null);
-
-        // verify Query for FINISHED state
-        query = new Query();
-        query.addEqualityFilter("state", Notification.State.FINISHED.toString());
-        results = app.getEm().searchCollection(app.getEm().getApplicationRef(),
-                "notifications", query);
-        entity = results.getEntitiesMap().get(notification.getUuid());
-        assertNotNull(entity);
-
-        notification = (Notification) entity.toTypedEntity();
-        checkReceipts(notification, 0);
-        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("queued", System.currentTimeMillis());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device1);
-
-        // delay until the scheduler has time to run
-        Thread.sleep(500);
-
-        // verify Query for SCHEDULED state
-        Query query = new Query();
-        query.addEqualityFilter("state",
-                Notification.State.SCHEDULED.toString());
-        Results results = app.getEm().searchCollection(
-                app.getEm().getApplicationRef(), "notifications", query);
-        Entity entity = results.getEntitiesMap().get(notification.getUuid());
-        assertNotNull(entity);
-
-        try {
-            e = app.testRequest(ServiceAction.DELETE, 1, "notifications",
-                    e.getUuid()).getEntity();
-        }catch (Exception deleteException){
-            LOG.error("Couldn't delete",deleteException);
-        }
-        app.getEm().get(e.getUuid(), Notification.class);
-    }
-
-    @Test
-    public void badPayloads() throws Exception {
-
-        MockSuccessfulProviderAdapter.uninstall(ns);
-
-        // bad payloads format
-
-        app.clear();
-        app.put("payloads", "{asdf}");
-
-        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, "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.getEm().get(e.getUuid(), Notifier.class);
-
-        payloads.clear();
-        StringBuilder sb = new StringBuilder();
-        sb.append("{\"x\":\"");
-        while (sb.length() < 255) {
-            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 256 characters or less");
-            // ok
-        }
-    }
-
-    @Ignore
-    // todo: how can I mock this?
-    @Test
-    public void badToken() throws Exception {
-
-        // mock action (based on verified actual behavior) //
-
-        if (!USE_REAL_CONNECTIONS) {
-            ns.providerAdapters.put("apple",
-                    new MockSuccessfulProviderAdapter() {
-                        @Override
-                        public void sendNotification(String providerId,
-                                Notifier notifier, Object payload,
-                                Notification notification, TaskTracker tracker)
-                                throws Exception {
-                            APNsNotification apnsNotification = APNsNotification
-                                    .create(providerId, payload.toString(),
-                                            notification, tracker);
-                            apnsNotification.messageSent();
-                            apnsNotification
-                                    .messageSendFailed( RejectedNotificationReason.INVALID_TOKEN);
-                        }
-                    });
-        }
-
-        // create push notification //
-
-        HashMap<String, Object> properties = new LinkedHashMap<String, Object>();
-        String payload = getPayload();
-        Map<String, String> payloads = new HashMap<String, String>(1);
-        payloads.put(notifier.getUuid().toString(), payload);
-        properties.put("payloads", payloads);
-        properties.put("queued", System.currentTimeMillis());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device1);
-
-        // perform push //
-        notification = scheduleNotificationAndWait(notification);
-        checkStatistics(notification, 0, 1);
-
-        notification = (Notification) app.getEm().get(notification)
-                .toTypedEntity();
-        checkReceipts(notification, 1);
-        List<EntityRef> receipts = getNotificationReceipts(notification);
-        Receipt receipt = app.getEm().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(notifier.getUuid().toString(), payload);
-        app.put("payloads", payloads);
-        app.put("queued", System.currentTimeMillis());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device1);
-        ns.addDevice(notification, device2);
-
-        // perform push //
-        notification = scheduleNotificationAndWait(notification);
-
-        checkReceipts(notification, 2);
-    }
-
-    @Test
-    public void twoDevicesTwoNotifiers() throws Exception {
-
-        // create a 2nd notifier //
-        app.clear();
-        app.put("name", "apns2");
-        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();
-        app.testRequest(ServiceAction.GET, 1, "notifiers", "apns2");
-
-        Notifier notifier2 = app.getEm().get(e.getUuid(), Notifier.class);
-        assertEquals(notifier2.getName(), "apns2");
-        assertEquals(notifier2.getProvider(), PROVIDER);
-        assertEquals(notifier2.getEnvironment(), "development");
-
-        String key = notifier.getName() + NOTIFIER_ID_POSTFIX;
-        String key2 = notifier2.getName() + NOTIFIER_ID_POSTFIX;
-        device2.setProperty(key, null);
-        device2.setProperty(key2, null);
-        app.getEm().update(device2);
-
-        // create push notification //
-
-        app.clear();
-        String payload = getPayload();
-        Map<String, String> payloads = new HashMap<String, String>(1);
-        payloads.put(notifier.getUuid().toString(), payload);
-        payloads.put(notifier2.getUuid().toString(), payload);
-        app.put("payloads", payloads);
-        app.put("queued", System.currentTimeMillis());
-
-        e = app.testRequest(ServiceAction.POST, 1, "notifications").getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device1);
-        ns.addDevice(notification, device2);
-
-        // perform push //
-        notification = scheduleNotificationAndWait(notification);
-
-        checkReceipts(notification, 2); //the second notifier isn't associated correctly so its 3 instead of 4
-    }
-
-    @Test
-    public void oneDeviceTwoNotifiers() throws Exception {
-
-        // create a 2nd notifier //
-        Object nameValue = "apns2";
-        Object environValue = "development";
-
-        app.clear();
-        app.put("name", nameValue);
-        app.put("provider", PROVIDER);
-        app.put("environment", environValue);
-        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", nameValue);
-
-        Notifier notifier2 = app.getEm().get(e.getUuid(), Notifier.class);
-        assertEquals(notifier2.getName(), nameValue);
-        assertEquals(notifier2.getProvider(), PROVIDER);
-        assertEquals(notifier2.getEnvironment(), environValue);
-
-        String key2 = notifier2.getName() + NOTIFIER_ID_POSTFIX;
-        device1.setProperty(key2, PUSH_TOKEN);
-        app.getEm().update(device1);
-
-        // create push notification //
-
-        app.clear();
-        String payload = getPayload();
-        Map<String, String> payloads = new HashMap<String, String>(1);
-        payloads.put(notifier.getUuid().toString(), payload);
-        payloads.put(notifier2.getUuid().toString(), payload);
-        app.put("payloads", payloads);
-        app.put("queued", System.currentTimeMillis());
-
-        e = app.testRequest(ServiceAction.POST, 1, "notifications").getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device1);
-
-        // perform push //
-        notification = scheduleNotificationAndWait(notification);
-
-        checkReceipts(notification, 2);
-    }
-
-    @Ignore
-    // todo: how can I mock this?
-    @Test
-    public void badCertificate() throws Exception {
-
-        // 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(
-                "empty.p12");
-        byte[] certBytes = IOUtils.toByteArray(fis);
-        app.put("p12Certificate", certBytes);
-        fis.close();
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifiers")
-                .getEntity();
-        notifier = app.getEm().get(e.getUuid(), Notifier.class);
-
-        // mock error (based on verified actual behavior) //
-        if (!USE_REAL_CONNECTIONS) {
-            ns.providerAdapters.put("apple",
-                    new MockSuccessfulProviderAdapter() {
-                        @Override
-                        public void testConnection(Notifier notifier)
-                                throws ConnectionException {
-                            Exception e = new SocketException(
-                                    "Connection closed by remote host");
-                            throw new ConnectionException(e.getMessage(), e);
-                        }
-                    });
-        }
-
-        // 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());
-
-        e = app.testRequest(ServiceAction.POST, 1, "notifications").getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device1);
-
-        // perform push //
-
-        try {
-            ns.getQueueManager().processBatchAndReschedule(notification,null);
-            fail("testConnection() should have failed");
-        } catch (Exception ex) {
-            // good, there should be an error
-        }
-
-        // verify Query for FAILED state
-        Query query = new Query();
-        query.addEqualityFilter("state", Notification.State.FAILED.toString());
-        Results results = app.getEm().searchCollection(
-                app.getEm().getApplicationRef(), "notifications", query);
-        Entity entity = results.getEntitiesMap().get(notification.getUuid());
-        assertNotNull(entity);
-    }
-
-    @Ignore
-    // todo: how can I mock this?
-    @Test
-    public void inactiveDeviceUpdate() throws Exception {
-
-        // mock action (based on verified actual behavior) //
-        if (!USE_REAL_CONNECTIONS) {
-            ns.providerAdapters.put("apple",
-                    new MockSuccessfulProviderAdapter() {
-                        @Override
-                        public Map<String, Date> getInactiveDevices(
-                                Notifier notifier, EntityManager em)
-                                throws Exception {
-                            return Collections.singletonMap(PUSH_TOKEN,
-                                    new Date());
-                        }
-                    });
-        }
-
-        // 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());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device1);
-        ns.addDevice(notification, device2);
-
-        assertNotNull(device1.getProperty(notifier.getName()
-                + NOTIFIER_ID_POSTFIX));
-        assertNotNull(device2.getProperty(notifier.getName()
-                + NOTIFIER_ID_POSTFIX));
-
-        // perform push //
-        notification = scheduleNotificationAndWait(notification);
-
-        // check provider IDs //
-
-        device1 = app.getEm().get(device1, Device.class);
-        assertNull(device1
-                .getProperty(notifier.getName() + NOTIFIER_ID_POSTFIX));
-        device2 = app.getEm().get(device2, Device.class);
-        assertNull(device2
-                .getProperty(notifier.getName() + NOTIFIER_ID_POSTFIX));
-    }
-
-    @Test
-    public void batchTest() throws Exception {
-
-        final int NUM_DEVICES = 50;
-
-        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());
-
-        // create a notification
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-        final Notification notification = (Notification) e.toTypedEntity();
-
-        // create a bunch of devices and add them to the notification
-        app.clear();
-        app.put(notifier.getName() + NOTIFIER_ID_POSTFIX, PUSH_TOKEN);
-        for (int i = 0; i < NUM_DEVICES; i++) {
-            Entity entity = app.getEm().create("device", app.getProperties());
-            ns.addDevice(notification, entity);
-        }
-
-        // perform push //
-        int oldBatchSize = NotificationsQueueManager.BATCH_SIZE;
-        NotificationsQueueManager.BATCH_SIZE = 10;
-        try {
-            ExecutorService pool = Executors
-                    .newFixedThreadPool(APNsAdapter.MAX_CONNECTION_POOL_SIZE);
-            pool.submit(new Runnable() {
-                @Override
-                public void run() {
-                        try {
-                             scheduleNotificationAndWait(notification);
-                        }catch (Exception e){}
-                }});
-        } finally {
-            NotificationsQueueManager.BATCH_SIZE = oldBatchSize;
-        }
-
-        // check receipts //
-        checkReceipts(notification, NUM_DEVICES);
-        checkStatistics(notification, NUM_DEVICES, 0);
-    }
-
-    @Ignore("Run only if you need to.")
-    @Test
-    public void loadTest() throws Exception {
-
-        MockSuccessfulProviderAdapter.install(ns, true);
-
-        final int NUM_DEVICES = 10000;
-
-        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());
-
-        // create a notification
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-        Notification notification = (Notification) e.toTypedEntity();
-
-        // create a bunch of devices and add them to the notification
-        app.clear();
-        app.put(notifier.getName() + NOTIFIER_ID_POSTFIX, PUSH_TOKEN);
-        for (int i = 0; i < NUM_DEVICES; i++) {
-            Entity entity = app.getEm().create("device", app.getProperties());
-            ns.addDevice(notification, entity);
-        }
-
-        long time = System.currentTimeMillis();
-        LOG.error("START DELIVERY OF {} NOTIFICATIONS", NUM_DEVICES);
-
-        // perform push //
-        notification = scheduleNotificationAndWait(notification);
-        LOG.error("END DELIVERY OF {} NOTIFICATIONS ({})", NUM_DEVICES,
-                System.currentTimeMillis() - time);
-
-        // check receipts //
-        checkReceipts(notification, NUM_DEVICES);
-        checkStatistics(notification, NUM_DEVICES, 0);
-    }
-
-    private String getPayload(){
-        ApnsPayloadBuilder builder = new ApnsPayloadBuilder();
-        builder.setAlertBody("Hello, World!");
-        builder.setSoundFileName("chime");
-        String payload = builder.buildWithDefaultMaximumLength();
-        return payload;
-    }
-    // todo: can't do the following tests here. do it in the REST tier...
-    // private Notification postNotification(String path) throws Exception {
-    // HashMap<String, Object> properties = new LinkedHashMap<String, Object>();
-    // String payload =
-    // APNS.newPayload().alertBody("Hello, World!").sound("chime").build();
-    // Map<String, String> payloads = new HashMap<String, String>(1);
-    // payloads.put(notifier.getUuid().toString(), payload);
-    // properties.put("payloads", payloads);
-    //
-    // Entity e = testRequest(sm, ServiceAction.POST, 1, properties,
-    // path).getEntity();
-    // Thread.sleep(1000); // this sucks
-    // Notification notification = app.getEm().get(e, Notification.class);
-    // return notification;
-    // }
-    //
-    // @Test
-    // public void matrixPushDevice() throws Exception {
-    //
-    // Notification notification = postNotification("devices/" +
-    // device1.getName() + "/notifications");
-    // checkReceipts(notification, 1);
-    // checkStatistics(notification, 1, 0);
-    // }
-    //
-    // @Test
-    // public void matrixPushViaUser() throws Exception {
-    //
-    // Notification notification = postNotification("users/" + user1.getName() +
-    // "/notifications");
-    // checkReceipts(notification, 2);
-    // checkStatistics(notification, 2, 0);
-    // }
-    //
-    // @Test
-    // public void matrixPushViaGroup() throws Exception {
-    //
-    // Notification notification = postNotification("devices/" +
-    // device1.getName() + "/notifications");
-    // checkReceipts(notification, 2);
-    // checkStatistics(notification, 2, 0);
-    // }
-    //
-    // @Test
-    // public void matrixPushDeviceQuery() throws Exception {
-    //
-    // Notification notification = postNotification("devices;ql=name=" +
-    // device1.getName() + "/notifications");
-    // checkReceipts(notification, 1);
-    // checkStatistics(notification, 1, 0);
-    // }
-    //
-    // @Test
-    // public void matrixPushUserQuery() throws Exception {
-    //
-    // Notification notification = postNotification("users;ql=/notifications");
-    // checkReceipts(notification, 2);
-    // checkStatistics(notification, 2, 0);
-    // }
-}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/dd4e7650/stack/services/src/test/java/org/apache/usergrid/services/notifications/gcm/NotificationsServiceIT.java
----------------------------------------------------------------------
diff --git a/stack/services/src/test/java/org/apache/usergrid/services/notifications/gcm/NotificationsServiceIT.java b/stack/services/src/test/java/org/apache/usergrid/services/notifications/gcm/NotificationsServiceIT.java
new file mode 100644
index 0000000..989c2ce
--- /dev/null
+++ b/stack/services/src/test/java/org/apache/usergrid/services/notifications/gcm/NotificationsServiceIT.java
@@ -0,0 +1,546 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * 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 org.apache.usergrid.services.notifications.gcm;
+
+import org.apache.usergrid.services.notifications.AbstractServiceNotificationIT;
+import org.apache.usergrid.persistence.entities.Notification;
+import org.apache.usergrid.persistence.entities.Notifier;
+import org.apache.usergrid.persistence.entities.Receipt;
+import org.apache.usergrid.services.notifications.NotificationsService;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.usergrid.services.notifications.ConnectionException;
+import org.apache.usergrid.services.notifications.TaskTracker;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.*;
+import org.apache.usergrid.persistence.Entity;
+import org.apache.usergrid.persistence.EntityRef;
+import org.apache.usergrid.persistence.entities.Device;
+import org.apache.usergrid.services.ServiceAction;
+
+import static org.junit.Assert.*;
+import static org.apache.usergrid.services.notifications.NotificationsService.NOTIFIER_ID_POSTFIX;
+
+public class NotificationsServiceIT extends AbstractServiceNotificationIT {
+
+    private static final Logger LOG = LoggerFactory
+            .getLogger(NotificationsServiceIT.class);
+
+    /**
+     * set to true to run tests against actual GCM servers - but they may not
+     * all run correctly
+     */
+    private static final boolean USE_REAL_CONNECTIONS = false;
+    private static final String PROVIDER = USE_REAL_CONNECTIONS ? "google"
+            : "noop";
+
+    private static final String API_KEY = "AIzaSyCIH_7WC0mOqBGMOXyQnFgrBpOePgHvQJM";
+    private static final String PUSH_TOKEN = "APA91bGxRGnMK8tKgVPzSlxtCFvwSVqx0xEPjA06sBmiK0kQsiwUt6ipSYF0iPRHyUgpXle0P8OlRWJADkQrcN7yxG4pLMg1CVmrqDu8tfSe63mZ-MRU2IW0cOhmosqzC9trl33moS3OvT7qjDjkP4Qq8LYdwwYC5A";
+
+    private Notifier notifier;
+    private Device device1, device2;
+    private NotificationsService ns;
+
+    @Override
+    @Before
+    public void before() throws Exception {
+        super.before();
+
+        // create gcm notifier //
+
+        app.clear();
+        app.put("name", "gcm");
+        app.put("provider", PROVIDER);
+        app.put("environment", "development");
+        app.put("apiKey", API_KEY);
+
+        notifier = (Notifier) app
+                .testRequest(ServiceAction.POST, 1, "notifiers").getEntity()
+                .toTypedEntity();
+        String key = notifier.getName() + NOTIFIER_ID_POSTFIX;
+
+        // create devices //
+
+        app.clear();
+        app.put(key, PUSH_TOKEN);
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "devices")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "devices", e.getUuid());
+
+        device1 = app.getEm().get(e.getUuid(), Device.class);
+        assertEquals(device1.getProperty(key), PUSH_TOKEN);
+
+        app.put(key, PUSH_TOKEN);
+        e = app.testRequest(ServiceAction.POST, 1, "devices").getEntity();
+        device2 = app.getEm().get(e.getUuid(), Device.class);
+        ns = getNotificationService();
+    }
+
+    @Test
+    public void emptyPushNotification() throws Exception {
+
+        app.clear();
+        app.put("name", "foo");
+        app.put("provider", PROVIDER);
+        app.put("environment", "development");
+        app.put("apiKey", API_KEY);
+        Notifier n = (Notifier) app
+                .testRequest(ServiceAction.POST, 1, "notifiers").getEntity()
+                .toTypedEntity();
+
+        app.clear();
+        String payload = "Hello, World!";
+        Map<String, String> payloads = new HashMap<String, String>(1);
+        payloads.put("foo", payload);
+        app.put("payloads", payloads);
+        app.put("queued", System.currentTimeMillis());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        ns.addDevice(notification, device1);
+
+        // perform push //
+        notification = scheduleNotificationAndWait(notification);
+        checkReceipts(notification, 0);
+    }
+
+    @Test
+    public void singlePushNotification() 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());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device1);
+
+        // perform push //
+        notification = scheduleNotificationAndWait(notification);
+        checkReceipts(notification, 1);
+    }
+
+    @Test
+    public void singlePushNotificationViaUser() throws Exception {
+
+        app.clear();
+
+        app.put("username", "asdf");
+        app.put("email", "asdf@adsf.com");
+        Entity user = app.testRequest(ServiceAction.POST, 1, "users")
+                .getEntity();
+        assertNotNull(user);
+        Entity device = app.testRequest(ServiceAction.POST, 1, "users",
+                user.getUuid(), "devices", device1.getUuid()).getEntity();
+        assertEquals(device.getUuid(), device1.getUuid());
+
+        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());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        ns.addDevice(notification, device1);
+
+        // perform push //
+        notification = scheduleNotificationAndWait(notification);
+        checkReceipts(notification, 1);
+    }
+
+    @Test
+    public void twoBatchNotification() 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());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device2);
+        ns.addDevice(notification, device1);
+
+        // reduce Batch size to 1
+        Field field = GCMAdapter.class.getDeclaredField("BATCH_SIZE");
+        field.setAccessible(true);
+        int multicastSize = field.getInt(GCMAdapter.class);
+        try {
+            field.setInt(GCMAdapter.class, 1);
+
+            // perform push //
+            notification = scheduleNotificationAndWait(notification);
+
+            checkReceipts(notification, 2);
+        } finally {
+            field.setInt(GCMAdapter.class, multicastSize);
+        }
+    }
+
+    @Ignore
+    // todo: how can I mock this?
+    @Test
+    public void providerIdUpdate() throws Exception {
+
+        // mock action (based on verified actual behavior) //
+        final String newProviderId = "newProviderId";
+        ns.providerAdapters.put("google", new MockSuccessfulProviderAdapter() {
+            @Override
+            public void sendNotification(String providerId, Notifier notifier,
+                    Object payload, Notification notification,
+                    TaskTracker tracker) throws Exception {
+                tracker.completed(newProviderId);
+            }
+        });
+
+        // create push notification //
+
+        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());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device1);
+
+        // perform push //
+        notification = scheduleNotificationAndWait(notification);
+        checkReceipts(notification, 1);
+
+        Device device = (Device) app.getEm().get(device1).toTypedEntity();
+        assertEquals(newProviderId,
+                device.getProperty(notifier.getName() + NOTIFIER_ID_POSTFIX));
+    }
+
+    @Test
+    public void badPayloads() throws Exception {
+
+        // bad payloads format
+
+        app.clear();
+        app.put("payloads", "{asdf}");
+
+        try {
+            app.testRequest(ServiceAction.POST, 1, "notifications");
+            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 {
+            app.testRequest(ServiceAction.POST, 1, "notifications");
+            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", "gcm2");
+        app.put("provider", "google");
+        app.put("environment", "development");
+        app.put("apiKey", API_KEY);
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifiers")
+                .getEntity();
+        Notifier notifier2 = app.getEm().get(e.getUuid(), Notifier.class);
+
+        payloads.clear();
+        StringBuilder sb = new StringBuilder();
+        sb.append("{\"x\":\"");
+        while (sb.length() < 4080) {
+            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");
+            fail("invalid payload should have been rejected");
+        } catch (Exception ex) {
+            assertEquals("java.lang.IllegalArgumentException: GCM payloads must be 4096 characters or less",
+                    ex.getMessage());
+            // ok
+        }
+    }
+
+    @Ignore
+    // todo: how can I mock this?
+    @Test
+    public void badToken() throws Exception {
+
+        // mock action (based on verified actual behavior) //
+        if (!USE_REAL_CONNECTIONS) {
+            ns.providerAdapters.put("google",
+                    new MockSuccessfulProviderAdapter() {
+                        @Override
+                        public void sendNotification(String providerId,
+                                Notifier notifier, Object payload,
+                                Notification notification, TaskTracker tracker)
+                                throws Exception {
+                            tracker.failed("InvalidRegistration",
+                                    "InvalidRegistration");
+                        }
+                    });
+        }
+
+        // create push notification //
+
+        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());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        // device w/ bad token
+        app.clear();
+        app.put(notifier.getName() + NOTIFIER_ID_POSTFIX, PUSH_TOKEN + "x");
+
+        e = app.testRequest(ServiceAction.POST, 1, "devices").getEntity();
+        device1 = app.getEm().get(e.getUuid(), Device.class);
+
+        ns.addDevice(notification, device1);
+
+        // perform push //
+        notification = scheduleNotificationAndWait(notification);
+
+        List<EntityRef> receipts = getNotificationReceipts(notification);
+        assertEquals(1, receipts.size());
+        Receipt receipt = app.getEm().get(receipts.get(0), Receipt.class);
+        assertEquals("InvalidRegistration", receipt.getErrorCode());
+    }
+
+    @Ignore
+    // todo: how can I mock this?
+    @Test
+    public void badAPIKey() throws Exception {
+
+        if (!USE_REAL_CONNECTIONS) {
+            // mock action (based on verified actual behavior) //
+            ns.providerAdapters.put("google",
+                    new MockSuccessfulProviderAdapter() {
+                        @Override
+                        public void sendNotification(String providerId,
+                                Notifier notifier, Object payload,
+                                Notification notification, TaskTracker tracker)
+                                throws Exception {
+                            Exception e = new IOException();
+                            throw new ConnectionException(e.getMessage(), e);
+                        }
+                    });
+        }
+
+        // create push notification //
+
+        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());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device1);
+
+        // save bad API key
+        app.getEm().setProperty(notifier, "apiKey", API_KEY + "x");
+
+        // perform push //
+
+        try {
+            ns.getQueueManager().processBatchAndReschedule(notification, null);
+            fail("Should have received a ConnectionException");
+        } catch (ConnectionException ex) {
+            // good
+        }
+    }
+
+    @Ignore("Run only if you need to.")
+    @Test
+    public void loadTest() throws Exception {
+
+        final int NUM_DEVICES = 10000;
+
+        // create notification //
+
+        HashMap<String, Object> properties = new LinkedHashMap<String, Object>();
+        String payload = "Hello, World!";
+        Map<String, String> payloads = new HashMap<String, String>(1);
+        payloads.put(notifier.getUuid().toString(), payload);
+        properties.put("payloads", payloads);
+        properties.put("queued", System.currentTimeMillis());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        // create a bunch of devices and add them to the notification
+        properties = new LinkedHashMap<String, Object>();
+        properties.put(notifier.getName() + NOTIFIER_ID_POSTFIX, PUSH_TOKEN);
+        for (int i = 0; i < NUM_DEVICES; i++) {
+            Entity entity = app.getEm().create("device", properties);
+            ns.addDevice(notification, entity);
+        }
+
+        long time = System.currentTimeMillis();
+        LOG.error("START DELIVERY OF {} NOTIFICATIONS", NUM_DEVICES);
+
+        // perform push //
+        notification = scheduleNotificationAndWait(notification);
+        LOG.error("END DELIVERY OF {} NOTIFICATIONS ({})", NUM_DEVICES,
+                System.currentTimeMillis() - time);
+
+        // check receipts //
+        checkReceipts(notification, NUM_DEVICES);
+        checkStatistics(notification, NUM_DEVICES, 0);
+    }
+
+    // @Test
+    // public void inactiveDeviceUpdate() throws Exception {
+    //
+    // if (!USE_REAL_CONNECTIONS) {
+    // // mock action (based on verified actual behavior) //
+    // NotificationsService.providerAdapters.put("apple", new
+    // MockSuccessfulProviderAdapter() {
+    // public Map<String,Date> getInactiveDevices(Notifier notifier,
+    // EntityManager em) throws Exception {
+    // return Collections.singletonMap(PUSH_TOKEN, new Date());
+    // }
+    // });
+    // }
+    //
+    // // create push notification //
+    //
+    // HashMap<String, Object> properties = new LinkedHashMap<String, Object>();
+    // String payload =
+    // APNS.newPayload().alertBody("Hello, World!").sound("chime").build();
+    // Map<String, String> payloads = new HashMap<String, String>(1);
+    // payloads.put(notifier.getUuid().toString(), payload);
+    // properties.put("payloads", payloads);
+    // properties.put("queued", System.currentTimeMillis());
+    //
+    // Entity e = testRequest(sm, ServiceAction.POST, 1, properties,
+    // "notifications").getEntity();
+    // testRequest(sm, ServiceAction.GET, 1, null, "notifications",
+    // e.getUuid());
+    //
+    // Notification notification = em.get(e.getUuid(), Notification.class);
+    // assertEquals(notification.getPayloads().get(notifier.getUuid().toString()),
+    // payload);
+    //
+    // ns.addDevice(notification, device1);
+    // ns.addDevice(notification, device2);
+    //
+    // assertNotNull(device1.getProperty(notifier.getName() +
+    // NOTIFIER_ID_POSTFIX));
+    // assertNotNull(device2.getProperty(notifier.getName() +
+    // NOTIFIER_ID_POSTFIX));
+    //
+    // // perform push //
+    // notification = scheduleNotificationAndWait(notification);
+    //
+    // // check provider IDs //
+    //
+    // device1 = em.get(device1, Device.class);
+    // assertNull(device1.getProperty(notifier.getName() +
+    // NOTIFIER_ID_POSTFIX));
+    // device2 = em.get(device2, Device.class);
+    // assertNull(device2.getProperty(notifier.getName() +
+    // NOTIFIER_ID_POSTFIX));
+    // }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/dd4e7650/stack/services/src/test/java/org/apache/usergrid/services/notifications/gcm/NotificationsServiceTest.java
----------------------------------------------------------------------
diff --git a/stack/services/src/test/java/org/apache/usergrid/services/notifications/gcm/NotificationsServiceTest.java b/stack/services/src/test/java/org/apache/usergrid/services/notifications/gcm/NotificationsServiceTest.java
deleted file mode 100644
index 7be8e88..0000000
--- a/stack/services/src/test/java/org/apache/usergrid/services/notifications/gcm/NotificationsServiceTest.java
+++ /dev/null
@@ -1,546 +0,0 @@
-/*******************************************************************************
- * Copyright 2012 Apigee Corporation
- *
- * 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 org.apache.usergrid.services.notifications.gcm;
-
-import org.apache.usergrid.services.notifications.AbstractServiceNotificationTest;
-import org.apache.usergrid.persistence.entities.Notification;
-import org.apache.usergrid.persistence.entities.Notifier;
-import org.apache.usergrid.persistence.entities.Receipt;
-import org.apache.usergrid.services.notifications.NotificationsService;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.usergrid.services.notifications.ConnectionException;
-import org.apache.usergrid.services.notifications.TaskTracker;
-
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.util.*;
-import org.apache.usergrid.persistence.Entity;
-import org.apache.usergrid.persistence.EntityRef;
-import org.apache.usergrid.persistence.entities.Device;
-import org.apache.usergrid.services.ServiceAction;
-
-import static org.junit.Assert.*;
-import static org.apache.usergrid.services.notifications.NotificationsService.NOTIFIER_ID_POSTFIX;
-
-public class NotificationsServiceTest extends AbstractServiceNotificationTest {
-
-    private static final Logger LOG = LoggerFactory
-            .getLogger(NotificationsServiceTest.class);
-
-    /**
-     * set to true to run tests against actual GCM servers - but they may not
-     * all run correctly
-     */
-    private static final boolean USE_REAL_CONNECTIONS = false;
-    private static final String PROVIDER = USE_REAL_CONNECTIONS ? "google"
-            : "noop";
-
-    private static final String API_KEY = "AIzaSyCIH_7WC0mOqBGMOXyQnFgrBpOePgHvQJM";
-    private static final String PUSH_TOKEN = "APA91bGxRGnMK8tKgVPzSlxtCFvwSVqx0xEPjA06sBmiK0kQsiwUt6ipSYF0iPRHyUgpXle0P8OlRWJADkQrcN7yxG4pLMg1CVmrqDu8tfSe63mZ-MRU2IW0cOhmosqzC9trl33moS3OvT7qjDjkP4Qq8LYdwwYC5A";
-
-    private Notifier notifier;
-    private Device device1, device2;
-    private NotificationsService ns;
-
-    @Override
-    @Before
-    public void before() throws Exception {
-        super.before();
-
-        // create gcm notifier //
-
-        app.clear();
-        app.put("name", "gcm");
-        app.put("provider", PROVIDER);
-        app.put("environment", "development");
-        app.put("apiKey", API_KEY);
-
-        notifier = (Notifier) app
-                .testRequest(ServiceAction.POST, 1, "notifiers").getEntity()
-                .toTypedEntity();
-        String key = notifier.getName() + NOTIFIER_ID_POSTFIX;
-
-        // create devices //
-
-        app.clear();
-        app.put(key, PUSH_TOKEN);
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "devices")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "devices", e.getUuid());
-
-        device1 = app.getEm().get(e.getUuid(), Device.class);
-        assertEquals(device1.getProperty(key), PUSH_TOKEN);
-
-        app.put(key, PUSH_TOKEN);
-        e = app.testRequest(ServiceAction.POST, 1, "devices").getEntity();
-        device2 = app.getEm().get(e.getUuid(), Device.class);
-        ns = getNotificationService();
-    }
-
-    @Test
-    public void emptyPushNotification() throws Exception {
-
-        app.clear();
-        app.put("name", "foo");
-        app.put("provider", PROVIDER);
-        app.put("environment", "development");
-        app.put("apiKey", API_KEY);
-        Notifier n = (Notifier) app
-                .testRequest(ServiceAction.POST, 1, "notifiers").getEntity()
-                .toTypedEntity();
-
-        app.clear();
-        String payload = "Hello, World!";
-        Map<String, String> payloads = new HashMap<String, String>(1);
-        payloads.put("foo", payload);
-        app.put("payloads", payloads);
-        app.put("queued", System.currentTimeMillis());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        ns.addDevice(notification, device1);
-
-        // perform push //
-        notification = scheduleNotificationAndWait(notification);
-        checkReceipts(notification, 0);
-    }
-
-    @Test
-    public void singlePushNotification() 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());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device1);
-
-        // perform push //
-        notification = scheduleNotificationAndWait(notification);
-        checkReceipts(notification, 1);
-    }
-
-    @Test
-    public void singlePushNotificationViaUser() throws Exception {
-
-        app.clear();
-
-        app.put("username", "asdf");
-        app.put("email", "asdf@adsf.com");
-        Entity user = app.testRequest(ServiceAction.POST, 1, "users")
-                .getEntity();
-        assertNotNull(user);
-        Entity device = app.testRequest(ServiceAction.POST, 1, "users",
-                user.getUuid(), "devices", device1.getUuid()).getEntity();
-        assertEquals(device.getUuid(), device1.getUuid());
-
-        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());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        ns.addDevice(notification, device1);
-
-        // perform push //
-        notification = scheduleNotificationAndWait(notification);
-        checkReceipts(notification, 1);
-    }
-
-    @Test
-    public void twoBatchNotification() 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());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device2);
-        ns.addDevice(notification, device1);
-
-        // reduce Batch size to 1
-        Field field = GCMAdapter.class.getDeclaredField("BATCH_SIZE");
-        field.setAccessible(true);
-        int multicastSize = field.getInt(GCMAdapter.class);
-        try {
-            field.setInt(GCMAdapter.class, 1);
-
-            // perform push //
-            notification = scheduleNotificationAndWait(notification);
-
-            checkReceipts(notification, 2);
-        } finally {
-            field.setInt(GCMAdapter.class, multicastSize);
-        }
-    }
-
-    @Ignore
-    // todo: how can I mock this?
-    @Test
-    public void providerIdUpdate() throws Exception {
-
-        // mock action (based on verified actual behavior) //
-        final String newProviderId = "newProviderId";
-        ns.providerAdapters.put("google", new MockSuccessfulProviderAdapter() {
-            @Override
-            public void sendNotification(String providerId, Notifier notifier,
-                    Object payload, Notification notification,
-                    TaskTracker tracker) throws Exception {
-                tracker.completed(newProviderId);
-            }
-        });
-
-        // create push notification //
-
-        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());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device1);
-
-        // perform push //
-        notification = scheduleNotificationAndWait(notification);
-        checkReceipts(notification, 1);
-
-        Device device = (Device) app.getEm().get(device1).toTypedEntity();
-        assertEquals(newProviderId,
-                device.getProperty(notifier.getName() + NOTIFIER_ID_POSTFIX));
-    }
-
-    @Test
-    public void badPayloads() throws Exception {
-
-        // bad payloads format
-
-        app.clear();
-        app.put("payloads", "{asdf}");
-
-        try {
-            app.testRequest(ServiceAction.POST, 1, "notifications");
-            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 {
-            app.testRequest(ServiceAction.POST, 1, "notifications");
-            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", "gcm2");
-        app.put("provider", "google");
-        app.put("environment", "development");
-        app.put("apiKey", API_KEY);
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifiers")
-                .getEntity();
-        Notifier notifier2 = app.getEm().get(e.getUuid(), Notifier.class);
-
-        payloads.clear();
-        StringBuilder sb = new StringBuilder();
-        sb.append("{\"x\":\"");
-        while (sb.length() < 4080) {
-            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");
-            fail("invalid payload should have been rejected");
-        } catch (Exception ex) {
-            assertEquals("java.lang.IllegalArgumentException: GCM payloads must be 4096 characters or less",
-                    ex.getMessage());
-            // ok
-        }
-    }
-
-    @Ignore
-    // todo: how can I mock this?
-    @Test
-    public void badToken() throws Exception {
-
-        // mock action (based on verified actual behavior) //
-        if (!USE_REAL_CONNECTIONS) {
-            ns.providerAdapters.put("google",
-                    new MockSuccessfulProviderAdapter() {
-                        @Override
-                        public void sendNotification(String providerId,
-                                Notifier notifier, Object payload,
-                                Notification notification, TaskTracker tracker)
-                                throws Exception {
-                            tracker.failed("InvalidRegistration",
-                                    "InvalidRegistration");
-                        }
-                    });
-        }
-
-        // create push notification //
-
-        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());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        // device w/ bad token
-        app.clear();
-        app.put(notifier.getName() + NOTIFIER_ID_POSTFIX, PUSH_TOKEN + "x");
-
-        e = app.testRequest(ServiceAction.POST, 1, "devices").getEntity();
-        device1 = app.getEm().get(e.getUuid(), Device.class);
-
-        ns.addDevice(notification, device1);
-
-        // perform push //
-        notification = scheduleNotificationAndWait(notification);
-
-        List<EntityRef> receipts = getNotificationReceipts(notification);
-        assertEquals(1, receipts.size());
-        Receipt receipt = app.getEm().get(receipts.get(0), Receipt.class);
-        assertEquals("InvalidRegistration", receipt.getErrorCode());
-    }
-
-    @Ignore
-    // todo: how can I mock this?
-    @Test
-    public void badAPIKey() throws Exception {
-
-        if (!USE_REAL_CONNECTIONS) {
-            // mock action (based on verified actual behavior) //
-            ns.providerAdapters.put("google",
-                    new MockSuccessfulProviderAdapter() {
-                        @Override
-                        public void sendNotification(String providerId,
-                                Notifier notifier, Object payload,
-                                Notification notification, TaskTracker tracker)
-                                throws Exception {
-                            Exception e = new IOException();
-                            throw new ConnectionException(e.getMessage(), e);
-                        }
-                    });
-        }
-
-        // create push notification //
-
-        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());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device1);
-
-        // save bad API key
-        app.getEm().setProperty(notifier, "apiKey", API_KEY + "x");
-
-        // perform push //
-
-        try {
-            ns.getQueueManager().processBatchAndReschedule(notification, null);
-            fail("Should have received a ConnectionException");
-        } catch (ConnectionException ex) {
-            // good
-        }
-    }
-
-    @Ignore("Run only if you need to.")
-    @Test
-    public void loadTest() throws Exception {
-
-        final int NUM_DEVICES = 10000;
-
-        // create notification //
-
-        HashMap<String, Object> properties = new LinkedHashMap<String, Object>();
-        String payload = "Hello, World!";
-        Map<String, String> payloads = new HashMap<String, String>(1);
-        payloads.put(notifier.getUuid().toString(), payload);
-        properties.put("payloads", payloads);
-        properties.put("queued", System.currentTimeMillis());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        // create a bunch of devices and add them to the notification
-        properties = new LinkedHashMap<String, Object>();
-        properties.put(notifier.getName() + NOTIFIER_ID_POSTFIX, PUSH_TOKEN);
-        for (int i = 0; i < NUM_DEVICES; i++) {
-            Entity entity = app.getEm().create("device", properties);
-            ns.addDevice(notification, entity);
-        }
-
-        long time = System.currentTimeMillis();
-        LOG.error("START DELIVERY OF {} NOTIFICATIONS", NUM_DEVICES);
-
-        // perform push //
-        notification = scheduleNotificationAndWait(notification);
-        LOG.error("END DELIVERY OF {} NOTIFICATIONS ({})", NUM_DEVICES,
-                System.currentTimeMillis() - time);
-
-        // check receipts //
-        checkReceipts(notification, NUM_DEVICES);
-        checkStatistics(notification, NUM_DEVICES, 0);
-    }
-
-    // @Test
-    // public void inactiveDeviceUpdate() throws Exception {
-    //
-    // if (!USE_REAL_CONNECTIONS) {
-    // // mock action (based on verified actual behavior) //
-    // NotificationsService.providerAdapters.put("apple", new
-    // MockSuccessfulProviderAdapter() {
-    // public Map<String,Date> getInactiveDevices(Notifier notifier,
-    // EntityManager em) throws Exception {
-    // return Collections.singletonMap(PUSH_TOKEN, new Date());
-    // }
-    // });
-    // }
-    //
-    // // create push notification //
-    //
-    // HashMap<String, Object> properties = new LinkedHashMap<String, Object>();
-    // String payload =
-    // APNS.newPayload().alertBody("Hello, World!").sound("chime").build();
-    // Map<String, String> payloads = new HashMap<String, String>(1);
-    // payloads.put(notifier.getUuid().toString(), payload);
-    // properties.put("payloads", payloads);
-    // properties.put("queued", System.currentTimeMillis());
-    //
-    // Entity e = testRequest(sm, ServiceAction.POST, 1, properties,
-    // "notifications").getEntity();
-    // testRequest(sm, ServiceAction.GET, 1, null, "notifications",
-    // e.getUuid());
-    //
-    // Notification notification = em.get(e.getUuid(), Notification.class);
-    // assertEquals(notification.getPayloads().get(notifier.getUuid().toString()),
-    // payload);
-    //
-    // ns.addDevice(notification, device1);
-    // ns.addDevice(notification, device2);
-    //
-    // assertNotNull(device1.getProperty(notifier.getName() +
-    // NOTIFIER_ID_POSTFIX));
-    // assertNotNull(device2.getProperty(notifier.getName() +
-    // NOTIFIER_ID_POSTFIX));
-    //
-    // // perform push //
-    // notification = scheduleNotificationAndWait(notification);
-    //
-    // // check provider IDs //
-    //
-    // device1 = em.get(device1, Device.class);
-    // assertNull(device1.getProperty(notifier.getName() +
-    // NOTIFIER_ID_POSTFIX));
-    // device2 = em.get(device2, Device.class);
-    // assertNull(device2.getProperty(notifier.getName() +
-    // NOTIFIER_ID_POSTFIX));
-    // }
-}


[2/4] git commit: move tests

Posted by sf...@apache.org.
move tests


Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/3c761ff4
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/3c761ff4
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/3c761ff4

Branch: refs/heads/two-dot-o-push-notifications
Commit: 3c761ff4b2b51be594efe02ed660a8790858444b
Parents: 51e0931
Author: Shawn Feldman <sf...@apache.org>
Authored: Tue Aug 19 17:02:28 2014 -0600
Committer: Shawn Feldman <sf...@apache.org>
Committed: Tue Aug 19 17:02:28 2014 -0600

----------------------------------------------------------------------
 .../AbstractServiceNotificationTest.java        | 108 ---
 .../apns/MockSuccessfulProviderAdapter.java     | 101 ---
 .../apns/NotificationsServiceTest.java          | 870 -------------------
 .../gcm/MockSuccessfulProviderAdapter.java      |  72 --
 .../gcm/NotificationsServiceTest.java           | 547 ------------
 .../notifiers/NotifiersServiceTest.java         | 224 -----
 .../usergrid/services/NotifiersServiceTest.java | 224 +++++
 .../AbstractServiceNotificationTest.java        | 107 +++
 .../apns/MockSuccessfulProviderAdapter.java     |  99 +++
 .../apns/NotificationsServiceTest.java          | 868 ++++++++++++++++++
 .../gcm/MockSuccessfulProviderAdapter.java      |  72 ++
 .../gcm/NotificationsServiceTest.java           | 546 ++++++++++++
 12 files changed, 1916 insertions(+), 1922 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/3c761ff4/stack/services/src/test/java/org/apache/usergrid/notifications/AbstractServiceNotificationTest.java
----------------------------------------------------------------------
diff --git a/stack/services/src/test/java/org/apache/usergrid/notifications/AbstractServiceNotificationTest.java b/stack/services/src/test/java/org/apache/usergrid/notifications/AbstractServiceNotificationTest.java
deleted file mode 100644
index d3d0727..0000000
--- a/stack/services/src/test/java/org/apache/usergrid/notifications/AbstractServiceNotificationTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package org.apache.usergrid.notifications;
-
-import org.apache.usergrid.persistence.*;
-import org.apache.usergrid.persistence.entities.Notification;
-import org.apache.usergrid.persistence.entities.Receipt;
-import org.apache.usergrid.persistence.index.query.Query;
-import org.apache.usergrid.services.notifications.NotificationsService;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Rule;
-import org.junit.rules.TestName;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.usergrid.services.AbstractServiceIT;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-
-public class AbstractServiceNotificationTest extends AbstractServiceIT {
-    private NotificationsService ns;
-
-    @Rule
-    public TestName name = new TestName();
-
-    @BeforeClass
-    public static void beforeClass() {
-    }
-
-    @Before
-    public void before() throws Exception {
-
-    }
-
-    protected NotificationsService getNotificationService(){
-        ns = (NotificationsService) app.getSm().getService("notifications");
-        return ns;
-    }
-
-    protected Notification scheduleNotificationAndWait(Notification notification)
-            throws Exception {
-        getNotificationService().getQueueManager().processBatchAndReschedule(notification,null);
-        long timeout = System.currentTimeMillis() + 60000;
-        while (System.currentTimeMillis() < timeout) {
-            Thread.sleep(200);
-            notification = app.getEm().get(notification.getUuid(),
-                    Notification.class);
-            if (notification.getFinished() != null) {
-                return notification;
-            }
-        }
-        fail("Notification failed to complete");
-        return null;
-    }
-
-    protected List<EntityRef> getNotificationReceipts(EntityRef notification)
-            throws Exception {
-        Results r = app.getEm().getCollection(notification,
-                Notification.RECEIPTS_COLLECTION, null, 1000000,
-                Query.Level.REFS, false);
-        List<EntityRef> list =new ArrayList<EntityRef>();//get all
-        PagingResultsIterator it = new PagingResultsIterator(r);
-        while(it.hasNext()){
-           list.add((EntityRef)it.next());
-        }
-        return list;
-    }
-
-    protected void checkReceipts(Notification notification, int expected)
-            throws Exception {
-        List<EntityRef> receipts = getNotificationReceipts(notification);
-        long timeout = System.currentTimeMillis() + 60000;
-        while (System.currentTimeMillis() < timeout) {
-            Thread.sleep(200);
-            receipts =getNotificationReceipts(notification);
-            if (receipts.size()==expected) {
-                 break;
-            }
-        }
-        assertEquals(expected, receipts.size());
-        for (EntityRef receipt : receipts) {
-            Receipt r = app.getEm().get(receipt, Receipt.class);
-            assertNotNull(r.getSent());
-            assertNotNull(r.getPayload());
-            assertNotNull(r.getNotifierId());
-            EntityRef source = getNotificationService().getSourceNotification(r);
-            assertEquals(source.getUuid(), notification.getUuid());
-        }
-    }
-
-    protected void checkStatistics(Notification notification, long sent,  long errors) throws Exception{
-        Map<String, Long> statistics = null;
-        long timeout = System.currentTimeMillis() + 60000;
-        while (System.currentTimeMillis() < timeout) {
-            Thread.sleep(200);
-            statistics = app.getEm().get(notification.getUuid(), Notification.class).getStatistics();
-            if (statistics.get("sent")==sent && statistics.get("errors")==errors) {
-                break;
-            }
-        }
-        assertEquals(sent, statistics.get("sent").longValue());
-        assertEquals(errors, statistics.get("errors").longValue());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/3c761ff4/stack/services/src/test/java/org/apache/usergrid/notifications/apns/MockSuccessfulProviderAdapter.java
----------------------------------------------------------------------
diff --git a/stack/services/src/test/java/org/apache/usergrid/notifications/apns/MockSuccessfulProviderAdapter.java b/stack/services/src/test/java/org/apache/usergrid/notifications/apns/MockSuccessfulProviderAdapter.java
deleted file mode 100644
index d780150..0000000
--- a/stack/services/src/test/java/org/apache/usergrid/notifications/apns/MockSuccessfulProviderAdapter.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package org.apache.usergrid.notifications.apns;
-
-import org.apache.usergrid.persistence.entities.Notification;
-import org.apache.usergrid.persistence.entities.Notifier;
-import org.apache.usergrid.services.notifications.apns.APNsNotification;
-import org.apache.usergrid.services.notifications.apns.APNsAdapter;
-import org.apache.usergrid.services.notifications.ConnectionException;
-import org.apache.usergrid.services.notifications.NotificationsService;
-import org.apache.usergrid.services.notifications.ProviderAdapter;
-import org.apache.usergrid.services.notifications.TaskTracker;
-
-import java.util.Date;
-import java.util.Map;
-import java.util.Random;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import org.apache.usergrid.persistence.EntityManager;
-import org.apache.usergrid.services.ServicePayload;
-
-public class MockSuccessfulProviderAdapter implements ProviderAdapter {
-
-    private static ProviderAdapter realProviderAdapter;
-
-    public static void install(NotificationsService ns) {
-        install(ns, false);
-    }
-
-    public static void install(NotificationsService ns, boolean doAsync) {
-        if (realProviderAdapter != null)
-            realProviderAdapter = ns.providerAdapters.get("apple");
-        ns.providerAdapters.put("apple", new MockSuccessfulProviderAdapter(
-                doAsync));
-    }
-
-    public static void uninstall(NotificationsService ns) {
-        if (realProviderAdapter != null) {
-            ns.providerAdapters.put("apple", realProviderAdapter);
-        }
-    }
-
-    private ExecutorService pool;
-
-    public MockSuccessfulProviderAdapter() {
-    }
-
-    public MockSuccessfulProviderAdapter(boolean async) {
-        if (async) {
-            pool = Executors
-                    .newFixedThreadPool(APNsAdapter.MAX_CONNECTION_POOL_SIZE);
-        }
-    }
-
-    @Override
-    public void testConnection(Notifier notifier) throws ConnectionException {
-    }
-
-    @Override
-    public String translatePayload(Object payload) throws Exception {
-        return payload.toString();
-    }
-
-    @Override
-    public Map<String, Date> getInactiveDevices(Notifier notifier,
-            EntityManager em) throws Exception {
-        return null;
-    }
-
-    @Override
-    public void validateCreateNotifier(ServicePayload payload) throws Exception {
-    }
-
-    @Override
-    public void doneSendingNotifications() throws Exception {
-    }
-
-    @Override
-    public void sendNotification(final String providerId,
-            final Notifier notifier, final Object payload,
-            final Notification notification, final TaskTracker tracker)
-            throws Exception {
-
-        final APNsNotification apnsNotification = APNsNotification.create(
-                providerId, payload.toString(), notification, tracker);
-
-        if (pool == null) {
-            apnsNotification.messageSent();
-        } else {
-            pool.submit(new Runnable() {
-                @Override
-                public void run() {
-                    try {
-                        Thread.sleep(new Random().nextInt(100));
-                        apnsNotification.messageSent();
-                    } catch (Exception e) {
-                        e.printStackTrace();
-                    }
-                }
-            });
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/3c761ff4/stack/services/src/test/java/org/apache/usergrid/notifications/apns/NotificationsServiceTest.java
----------------------------------------------------------------------
diff --git a/stack/services/src/test/java/org/apache/usergrid/notifications/apns/NotificationsServiceTest.java b/stack/services/src/test/java/org/apache/usergrid/notifications/apns/NotificationsServiceTest.java
deleted file mode 100644
index a50d942..0000000
--- a/stack/services/src/test/java/org/apache/usergrid/notifications/apns/NotificationsServiceTest.java
+++ /dev/null
@@ -1,870 +0,0 @@
-/*******************************************************************************
- * Copyright 2012 Apigee Corporation
- *
- * 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 org.apache.usergrid.notifications.apns;
-
-import com.relayrides.pushy.apns.*;
-import com.relayrides.pushy.apns.util.*;
-import org.apache.commons.io.IOUtils;
-import org.apache.usergrid.notifications.AbstractServiceNotificationTest;
-import org.apache.usergrid.persistence.*;
-import org.apache.usergrid.persistence.entities.*;
-import org.apache.usergrid.persistence.index.query.Query;
-import org.apache.usergrid.persistence.model.util.UUIDGenerator;
-import org.apache.usergrid.services.notifications.*;
-import org.apache.usergrid.services.notifications.apns.APNsAdapter;
-import org.apache.usergrid.services.notifications.apns.APNsNotification;
-import org.junit.After;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.InputStream;
-import java.net.SocketException;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-import org.apache.usergrid.services.ServiceAction;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import static org.apache.usergrid.services.notifications.NotificationsService.NOTIFIER_ID_POSTFIX;
-
-// todo: test reschedule on delivery time change
-// todo: test restart of queuing
-public class NotificationsServiceTest extends AbstractServiceNotificationTest {
-
-    private static final Logger LOG = LoggerFactory.getLogger(NotificationsServiceTest.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 Group group1;
-    private User user1;
-    private NotificationsService ns;
-
-    @Override
-    @Before
-    public void before() throws Exception {
-        super.before();
-        // create apns notifier //
-        NotificationsQueueManager.IS_TEST = true;
-
-        app.clear();
-        app.put("name", "apns");
-        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.getEm().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.getEm().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.getEm().get(e.getUuid(), Device.class);
-
-//        // create User
-//        user1 = new User();
-//        user1.setUsername("user1");
-//        user1.setEmail("user1@usergrid.org");
-//        user1 = app.getEm().create(user1);
-//        app.getEm().createConnection(user1, "devices", device1);
-//        app.getEm().createConnection(user1, "devices", device2);
-//
-//        // create Group
-//        group1 = new Group();
-//        group1.setPath("path");
-//        group1 = app.getEm().create(group1);
-//        app.getEm().createConnection(group1, "users", user1);
-
-        ns = getNotificationService();
-    }
-
-    @After
-    public void after() throws Exception {
-    }
-
-    @Test
-    public void singlePushNotification() 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("queued", System.currentTimeMillis());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device1);
-
-//        // verify Query for CREATED state
-        Query query = new Query();
-//        query.addEqualityFilter("state", Notification.State.STARTED.toString());
-        Results results = app.getEm().searchCollection(
-                app.getEm().getApplicationRef(), "notifications", query);
-        Entity entity = results.getEntitiesMap().get(notification.getUuid());
-//        assertNotNull(entity);
-
-        // perform push //
-
-        notification = scheduleNotificationAndWait(notification);
-
-        // verify Query for FINISHED state
-        query = new Query();
-        query.addEqualityFilter("state", Notification.State.FINISHED.toString());
-        results = app.getEm().searchCollection(app.getEm().getApplicationRef(),
-                "notifications", query);
-        entity = results.getEntitiesMap().get(notification.getUuid());
-        assertNotNull(entity);
-
-        checkReceipts(notification, 1);
-        checkStatistics(notification, 1, 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.getEm().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());
-
-        e = app.testRequest(ServiceAction.POST, 1, "notifications").getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device);
-
-        // verify Query for CREATED state
-        Query query = new Query();
-        query.addEqualityFilter("state", Notification.State.STARTED.toString());
-        Results results = app.getEm().searchCollection(
-                app.getEm().getApplicationRef(), "notifications", query);
-        Entity entity = results.getEntitiesMap().get(notification.getUuid());
-        assertNotNull(entity);
-
-        // perform push //
-
-        ns.getQueueManager().processBatchAndReschedule(notification, null);
-
-        // verify Query for FINISHED state
-        query = new Query();
-        query.addEqualityFilter("state", Notification.State.FINISHED.toString());
-        results = app.getEm().searchCollection(app.getEm().getApplicationRef(),
-                "notifications", query);
-        entity = results.getEntitiesMap().get(notification.getUuid());
-        assertNotNull(entity);
-
-        notification = (Notification) entity.toTypedEntity();
-        checkReceipts(notification, 0);
-        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("queued", System.currentTimeMillis());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device1);
-
-        // delay until the scheduler has time to run
-        Thread.sleep(500);
-
-        // verify Query for SCHEDULED state
-        Query query = new Query();
-        query.addEqualityFilter("state",
-                Notification.State.SCHEDULED.toString());
-        Results results = app.getEm().searchCollection(
-                app.getEm().getApplicationRef(), "notifications", query);
-        Entity entity = results.getEntitiesMap().get(notification.getUuid());
-        assertNotNull(entity);
-
-        try {
-            e = app.testRequest(ServiceAction.DELETE, 1, "notifications",
-                    e.getUuid()).getEntity();
-        }catch (Exception deleteException){
-            LOG.error("Couldn't delete",deleteException);
-        }
-        app.getEm().get(e.getUuid(), Notification.class);
-    }
-
-    @Test
-    public void badPayloads() throws Exception {
-
-        MockSuccessfulProviderAdapter.uninstall(ns);
-
-        // bad payloads format
-
-        app.clear();
-        app.put("payloads", "{asdf}");
-
-        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, "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.getEm().get(e.getUuid(), Notifier.class);
-
-        payloads.clear();
-        StringBuilder sb = new StringBuilder();
-        sb.append("{\"x\":\"");
-        while (sb.length() < 255) {
-            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 256 characters or less");
-            // ok
-        }
-    }
-
-    @Ignore
-    // todo: how can I mock this?
-    @Test
-    public void badToken() throws Exception {
-
-        // mock action (based on verified actual behavior) //
-
-        if (!USE_REAL_CONNECTIONS) {
-            ns.providerAdapters.put("apple",
-                    new MockSuccessfulProviderAdapter() {
-                        @Override
-                        public void sendNotification(String providerId,
-                                Notifier notifier, Object payload,
-                                Notification notification, TaskTracker tracker)
-                                throws Exception {
-                            APNsNotification apnsNotification = APNsNotification
-                                    .create(providerId, payload.toString(),
-                                            notification, tracker);
-                            apnsNotification.messageSent();
-                            apnsNotification
-                                    .messageSendFailed( RejectedNotificationReason.INVALID_TOKEN);
-                        }
-                    });
-        }
-
-        // create push notification //
-
-        HashMap<String, Object> properties = new LinkedHashMap<String, Object>();
-        String payload = getPayload();
-        Map<String, String> payloads = new HashMap<String, String>(1);
-        payloads.put(notifier.getUuid().toString(), payload);
-        properties.put("payloads", payloads);
-        properties.put("queued", System.currentTimeMillis());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device1);
-
-        // perform push //
-        notification = scheduleNotificationAndWait(notification);
-        checkStatistics(notification, 0, 1);
-
-        notification = (Notification) app.getEm().get(notification)
-                .toTypedEntity();
-        checkReceipts(notification, 1);
-        List<EntityRef> receipts = getNotificationReceipts(notification);
-        Receipt receipt = app.getEm().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(notifier.getUuid().toString(), payload);
-        app.put("payloads", payloads);
-        app.put("queued", System.currentTimeMillis());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device1);
-        ns.addDevice(notification, device2);
-
-        // perform push //
-        notification = scheduleNotificationAndWait(notification);
-
-        checkReceipts(notification, 2);
-    }
-
-    @Test
-    public void twoDevicesTwoNotifiers() throws Exception {
-
-        // create a 2nd notifier //
-        app.clear();
-        app.put("name", "apns2");
-        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();
-        app.testRequest(ServiceAction.GET, 1, "notifiers", "apns2");
-
-        Notifier notifier2 = app.getEm().get(e.getUuid(), Notifier.class);
-        assertEquals(notifier2.getName(), "apns2");
-        assertEquals(notifier2.getProvider(), PROVIDER);
-        assertEquals(notifier2.getEnvironment(), "development");
-
-        String key = notifier.getName() + NOTIFIER_ID_POSTFIX;
-        String key2 = notifier2.getName() + NOTIFIER_ID_POSTFIX;
-        device2.setProperty(key, null);
-        device2.setProperty(key2, null);
-        app.getEm().update(device2);
-
-        // create push notification //
-
-        app.clear();
-        String payload = getPayload();
-        Map<String, String> payloads = new HashMap<String, String>(1);
-        payloads.put(notifier.getUuid().toString(), payload);
-        payloads.put(notifier2.getUuid().toString(), payload);
-        app.put("payloads", payloads);
-        app.put("queued", System.currentTimeMillis());
-
-        e = app.testRequest(ServiceAction.POST, 1, "notifications").getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device1);
-        ns.addDevice(notification, device2);
-
-        // perform push //
-        notification = scheduleNotificationAndWait(notification);
-
-        checkReceipts(notification, 2); //the second notifier isn't associated correctly so its 3 instead of 4
-    }
-
-    @Test
-    public void oneDeviceTwoNotifiers() throws Exception {
-
-        // create a 2nd notifier //
-        Object nameValue = "apns2";
-        Object environValue = "development";
-
-        app.clear();
-        app.put("name", nameValue);
-        app.put("provider", PROVIDER);
-        app.put("environment", environValue);
-        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", nameValue);
-
-        Notifier notifier2 = app.getEm().get(e.getUuid(), Notifier.class);
-        assertEquals(notifier2.getName(), nameValue);
-        assertEquals(notifier2.getProvider(), PROVIDER);
-        assertEquals(notifier2.getEnvironment(), environValue);
-
-        String key2 = notifier2.getName() + NOTIFIER_ID_POSTFIX;
-        device1.setProperty(key2, PUSH_TOKEN);
-        app.getEm().update(device1);
-
-        // create push notification //
-
-        app.clear();
-        String payload = getPayload();
-        Map<String, String> payloads = new HashMap<String, String>(1);
-        payloads.put(notifier.getUuid().toString(), payload);
-        payloads.put(notifier2.getUuid().toString(), payload);
-        app.put("payloads", payloads);
-        app.put("queued", System.currentTimeMillis());
-
-        e = app.testRequest(ServiceAction.POST, 1, "notifications").getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device1);
-
-        // perform push //
-        notification = scheduleNotificationAndWait(notification);
-
-        checkReceipts(notification, 2);
-    }
-
-    @Ignore
-    // todo: how can I mock this?
-    @Test
-    public void badCertificate() throws Exception {
-
-        // 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(
-                "empty.p12");
-        byte[] certBytes = IOUtils.toByteArray(fis);
-        app.put("p12Certificate", certBytes);
-        fis.close();
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifiers")
-                .getEntity();
-        notifier = app.getEm().get(e.getUuid(), Notifier.class);
-
-        // mock error (based on verified actual behavior) //
-        if (!USE_REAL_CONNECTIONS) {
-            ns.providerAdapters.put("apple",
-                    new MockSuccessfulProviderAdapter() {
-                        @Override
-                        public void testConnection(Notifier notifier)
-                                throws ConnectionException {
-                            Exception e = new SocketException(
-                                    "Connection closed by remote host");
-                            throw new ConnectionException(e.getMessage(), e);
-                        }
-                    });
-        }
-
-        // 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());
-
-        e = app.testRequest(ServiceAction.POST, 1, "notifications").getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device1);
-
-        // perform push //
-
-        try {
-            ns.getQueueManager().processBatchAndReschedule(notification,null);
-            fail("testConnection() should have failed");
-        } catch (Exception ex) {
-            // good, there should be an error
-        }
-
-        // verify Query for FAILED state
-        Query query = new Query();
-        query.addEqualityFilter("state", Notification.State.FAILED.toString());
-        Results results = app.getEm().searchCollection(
-                app.getEm().getApplicationRef(), "notifications", query);
-        Entity entity = results.getEntitiesMap().get(notification.getUuid());
-        assertNotNull(entity);
-    }
-
-    @Ignore
-    // todo: how can I mock this?
-    @Test
-    public void inactiveDeviceUpdate() throws Exception {
-
-        // mock action (based on verified actual behavior) //
-        if (!USE_REAL_CONNECTIONS) {
-            ns.providerAdapters.put("apple",
-                    new MockSuccessfulProviderAdapter() {
-                        @Override
-                        public Map<String, Date> getInactiveDevices(
-                                Notifier notifier, EntityManager em)
-                                throws Exception {
-                            return Collections.singletonMap(PUSH_TOKEN,
-                                    new Date());
-                        }
-                    });
-        }
-
-        // 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());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device1);
-        ns.addDevice(notification, device2);
-
-        assertNotNull(device1.getProperty(notifier.getName()
-                + NOTIFIER_ID_POSTFIX));
-        assertNotNull(device2.getProperty(notifier.getName()
-                + NOTIFIER_ID_POSTFIX));
-
-        // perform push //
-        notification = scheduleNotificationAndWait(notification);
-
-        // check provider IDs //
-
-        device1 = app.getEm().get(device1, Device.class);
-        assertNull(device1
-                .getProperty(notifier.getName() + NOTIFIER_ID_POSTFIX));
-        device2 = app.getEm().get(device2, Device.class);
-        assertNull(device2
-                .getProperty(notifier.getName() + NOTIFIER_ID_POSTFIX));
-    }
-
-    @Test
-    public void batchTest() throws Exception {
-
-        final int NUM_DEVICES = 50;
-
-        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());
-
-        // create a notification
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-        final Notification notification = (Notification) e.toTypedEntity();
-
-        // create a bunch of devices and add them to the notification
-        app.clear();
-        app.put(notifier.getName() + NOTIFIER_ID_POSTFIX, PUSH_TOKEN);
-        for (int i = 0; i < NUM_DEVICES; i++) {
-            Entity entity = app.getEm().create("device", app.getProperties());
-            ns.addDevice(notification, entity);
-        }
-
-        // perform push //
-        int oldBatchSize = NotificationsQueueManager.BATCH_SIZE;
-        NotificationsQueueManager.BATCH_SIZE = 10;
-        try {
-            ExecutorService pool = Executors
-                    .newFixedThreadPool(APNsAdapter.MAX_CONNECTION_POOL_SIZE);
-            pool.submit(new Runnable() {
-                @Override
-                public void run() {
-                        try {
-                             scheduleNotificationAndWait(notification);
-                        }catch (Exception e){}
-                }});
-        } finally {
-            NotificationsQueueManager.BATCH_SIZE = oldBatchSize;
-        }
-
-        // check receipts //
-        checkReceipts(notification, NUM_DEVICES);
-        checkStatistics(notification, NUM_DEVICES, 0);
-    }
-
-    @Ignore("Run only if you need to.")
-    @Test
-    public void loadTest() throws Exception {
-
-        MockSuccessfulProviderAdapter.install(ns, true);
-
-        final int NUM_DEVICES = 10000;
-
-        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());
-
-        // create a notification
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-        Notification notification = (Notification) e.toTypedEntity();
-
-        // create a bunch of devices and add them to the notification
-        app.clear();
-        app.put(notifier.getName() + NOTIFIER_ID_POSTFIX, PUSH_TOKEN);
-        for (int i = 0; i < NUM_DEVICES; i++) {
-            Entity entity = app.getEm().create("device", app.getProperties());
-            ns.addDevice(notification, entity);
-        }
-
-        long time = System.currentTimeMillis();
-        LOG.error("START DELIVERY OF {} NOTIFICATIONS", NUM_DEVICES);
-
-        // perform push //
-        notification = scheduleNotificationAndWait(notification);
-        LOG.error("END DELIVERY OF {} NOTIFICATIONS ({})", NUM_DEVICES,
-                System.currentTimeMillis() - time);
-
-        // check receipts //
-        checkReceipts(notification, NUM_DEVICES);
-        checkStatistics(notification, NUM_DEVICES, 0);
-    }
-
-    private String getPayload(){
-        ApnsPayloadBuilder builder = new ApnsPayloadBuilder();
-        builder.setAlertBody("Hello, World!");
-        builder.setSoundFileName("chime");
-        String payload = builder.buildWithDefaultMaximumLength();
-        return payload;
-    }
-    // todo: can't do the following tests here. do it in the REST tier...
-    // private Notification postNotification(String path) throws Exception {
-    // HashMap<String, Object> properties = new LinkedHashMap<String, Object>();
-    // String payload =
-    // APNS.newPayload().alertBody("Hello, World!").sound("chime").build();
-    // Map<String, String> payloads = new HashMap<String, String>(1);
-    // payloads.put(notifier.getUuid().toString(), payload);
-    // properties.put("payloads", payloads);
-    //
-    // Entity e = testRequest(sm, ServiceAction.POST, 1, properties,
-    // path).getEntity();
-    // Thread.sleep(1000); // this sucks
-    // Notification notification = app.getEm().get(e, Notification.class);
-    // return notification;
-    // }
-    //
-    // @Test
-    // public void matrixPushDevice() throws Exception {
-    //
-    // Notification notification = postNotification("devices/" +
-    // device1.getName() + "/notifications");
-    // checkReceipts(notification, 1);
-    // checkStatistics(notification, 1, 0);
-    // }
-    //
-    // @Test
-    // public void matrixPushViaUser() throws Exception {
-    //
-    // Notification notification = postNotification("users/" + user1.getName() +
-    // "/notifications");
-    // checkReceipts(notification, 2);
-    // checkStatistics(notification, 2, 0);
-    // }
-    //
-    // @Test
-    // public void matrixPushViaGroup() throws Exception {
-    //
-    // Notification notification = postNotification("devices/" +
-    // device1.getName() + "/notifications");
-    // checkReceipts(notification, 2);
-    // checkStatistics(notification, 2, 0);
-    // }
-    //
-    // @Test
-    // public void matrixPushDeviceQuery() throws Exception {
-    //
-    // Notification notification = postNotification("devices;ql=name=" +
-    // device1.getName() + "/notifications");
-    // checkReceipts(notification, 1);
-    // checkStatistics(notification, 1, 0);
-    // }
-    //
-    // @Test
-    // public void matrixPushUserQuery() throws Exception {
-    //
-    // Notification notification = postNotification("users;ql=/notifications");
-    // checkReceipts(notification, 2);
-    // checkStatistics(notification, 2, 0);
-    // }
-}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/3c761ff4/stack/services/src/test/java/org/apache/usergrid/notifications/gcm/MockSuccessfulProviderAdapter.java
----------------------------------------------------------------------
diff --git a/stack/services/src/test/java/org/apache/usergrid/notifications/gcm/MockSuccessfulProviderAdapter.java b/stack/services/src/test/java/org/apache/usergrid/notifications/gcm/MockSuccessfulProviderAdapter.java
deleted file mode 100644
index 12dbe08..0000000
--- a/stack/services/src/test/java/org/apache/usergrid/notifications/gcm/MockSuccessfulProviderAdapter.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.apache.usergrid.notifications.gcm;
-
-import org.apache.usergrid.persistence.entities.Notification;
-import org.apache.usergrid.persistence.entities.Notifier;
-import org.apache.usergrid.services.notifications.ConnectionException;
-import org.apache.usergrid.services.notifications.NotificationsService;
-import org.apache.usergrid.services.notifications.ProviderAdapter;
-import org.apache.usergrid.services.notifications.TaskTracker;
-
-import java.util.Date;
-import java.util.Map;
-import org.apache.usergrid.persistence.EntityManager;
-import org.apache.usergrid.services.ServicePayload;
-
-public class MockSuccessfulProviderAdapter implements ProviderAdapter {
-
-    private static ProviderAdapter realProviderAdapter;
-
-    public static void install(NotificationsService ns) {
-        if (realProviderAdapter != null)
-            realProviderAdapter = ns.providerAdapters.get("google");
-        ns.providerAdapters.put("google", new MockSuccessfulProviderAdapter());
-    }
-
-    public static void uninstall(NotificationsService ns) {
-        if (realProviderAdapter != null) {
-            ns.providerAdapters.put("google", realProviderAdapter);
-        }
-    }
-
-    public MockSuccessfulProviderAdapter() {
-    }
-
-    @Override
-    public void testConnection(Notifier notifier) throws ConnectionException {
-    }
-
-    @Override
-    public String translatePayload(Object payload) throws Exception {
-        return payload.toString();
-    }
-
-    @Override
-    public Map<String, Date> getInactiveDevices(Notifier notifier,
-            EntityManager em) throws Exception {
-        return null;
-    }
-
-    @Override
-    public void validateCreateNotifier(ServicePayload payload) throws Exception {
-    }
-
-    @Override
-    public void doneSendingNotifications() throws Exception {
-    }
-
-    @Override
-    public void sendNotification(String providerId, Notifier notifier,
-            Object payload, Notification notification, final TaskTracker tracker)
-            throws Exception {
-        new Thread() {
-            @Override
-            public void run() {
-                try {
-                    tracker.completed();
-                } catch (Exception e) {
-                    e.printStackTrace();
-                }
-            }
-        }.start();
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/3c761ff4/stack/services/src/test/java/org/apache/usergrid/notifications/gcm/NotificationsServiceTest.java
----------------------------------------------------------------------
diff --git a/stack/services/src/test/java/org/apache/usergrid/notifications/gcm/NotificationsServiceTest.java b/stack/services/src/test/java/org/apache/usergrid/notifications/gcm/NotificationsServiceTest.java
deleted file mode 100644
index ad64fd5..0000000
--- a/stack/services/src/test/java/org/apache/usergrid/notifications/gcm/NotificationsServiceTest.java
+++ /dev/null
@@ -1,547 +0,0 @@
-/*******************************************************************************
- * Copyright 2012 Apigee Corporation
- *
- * 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 org.apache.usergrid.notifications.gcm;
-
-import org.apache.usergrid.notifications.AbstractServiceNotificationTest;
-import org.apache.usergrid.persistence.entities.Notification;
-import org.apache.usergrid.persistence.entities.Notifier;
-import org.apache.usergrid.persistence.entities.Receipt;
-import org.apache.usergrid.services.notifications.NotificationsService;
-import org.apache.usergrid.services.notifications.gcm.GCMAdapter;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.usergrid.services.notifications.ConnectionException;
-import org.apache.usergrid.services.notifications.TaskTracker;
-
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.util.*;
-import org.apache.usergrid.persistence.Entity;
-import org.apache.usergrid.persistence.EntityRef;
-import org.apache.usergrid.persistence.entities.Device;
-import org.apache.usergrid.services.ServiceAction;
-
-import static org.junit.Assert.*;
-import static org.apache.usergrid.services.notifications.NotificationsService.NOTIFIER_ID_POSTFIX;
-
-public class NotificationsServiceTest extends AbstractServiceNotificationTest {
-
-    private static final Logger LOG = LoggerFactory
-            .getLogger(NotificationsServiceTest.class);
-
-    /**
-     * set to true to run tests against actual GCM servers - but they may not
-     * all run correctly
-     */
-    private static final boolean USE_REAL_CONNECTIONS = false;
-    private static final String PROVIDER = USE_REAL_CONNECTIONS ? "google"
-            : "noop";
-
-    private static final String API_KEY = "AIzaSyCIH_7WC0mOqBGMOXyQnFgrBpOePgHvQJM";
-    private static final String PUSH_TOKEN = "APA91bGxRGnMK8tKgVPzSlxtCFvwSVqx0xEPjA06sBmiK0kQsiwUt6ipSYF0iPRHyUgpXle0P8OlRWJADkQrcN7yxG4pLMg1CVmrqDu8tfSe63mZ-MRU2IW0cOhmosqzC9trl33moS3OvT7qjDjkP4Qq8LYdwwYC5A";
-
-    private Notifier notifier;
-    private Device device1, device2;
-    private NotificationsService ns;
-
-    @Override
-    @Before
-    public void before() throws Exception {
-        super.before();
-
-        // create gcm notifier //
-
-        app.clear();
-        app.put("name", "gcm");
-        app.put("provider", PROVIDER);
-        app.put("environment", "development");
-        app.put("apiKey", API_KEY);
-
-        notifier = (Notifier) app
-                .testRequest(ServiceAction.POST, 1, "notifiers").getEntity()
-                .toTypedEntity();
-        String key = notifier.getName() + NOTIFIER_ID_POSTFIX;
-
-        // create devices //
-
-        app.clear();
-        app.put(key, PUSH_TOKEN);
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "devices")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "devices", e.getUuid());
-
-        device1 = app.getEm().get(e.getUuid(), Device.class);
-        assertEquals(device1.getProperty(key), PUSH_TOKEN);
-
-        app.put(key, PUSH_TOKEN);
-        e = app.testRequest(ServiceAction.POST, 1, "devices").getEntity();
-        device2 = app.getEm().get(e.getUuid(), Device.class);
-        ns = getNotificationService();
-    }
-
-    @Test
-    public void emptyPushNotification() throws Exception {
-
-        app.clear();
-        app.put("name", "foo");
-        app.put("provider", PROVIDER);
-        app.put("environment", "development");
-        app.put("apiKey", API_KEY);
-        Notifier n = (Notifier) app
-                .testRequest(ServiceAction.POST, 1, "notifiers").getEntity()
-                .toTypedEntity();
-
-        app.clear();
-        String payload = "Hello, World!";
-        Map<String, String> payloads = new HashMap<String, String>(1);
-        payloads.put("foo", payload);
-        app.put("payloads", payloads);
-        app.put("queued", System.currentTimeMillis());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        ns.addDevice(notification, device1);
-
-        // perform push //
-        notification = scheduleNotificationAndWait(notification);
-        checkReceipts(notification, 0);
-    }
-
-    @Test
-    public void singlePushNotification() 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());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device1);
-
-        // perform push //
-        notification = scheduleNotificationAndWait(notification);
-        checkReceipts(notification, 1);
-    }
-
-    @Test
-    public void singlePushNotificationViaUser() throws Exception {
-
-        app.clear();
-
-        app.put("username", "asdf");
-        app.put("email", "asdf@adsf.com");
-        Entity user = app.testRequest(ServiceAction.POST, 1, "users")
-                .getEntity();
-        assertNotNull(user);
-        Entity device = app.testRequest(ServiceAction.POST, 1, "users",
-                user.getUuid(), "devices", device1.getUuid()).getEntity();
-        assertEquals(device.getUuid(), device1.getUuid());
-
-        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());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        ns.addDevice(notification, device1);
-
-        // perform push //
-        notification = scheduleNotificationAndWait(notification);
-        checkReceipts(notification, 1);
-    }
-
-    @Test
-    public void twoBatchNotification() 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());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device2);
-        ns.addDevice(notification, device1);
-
-        // reduce Batch size to 1
-        Field field = GCMAdapter.class.getDeclaredField("BATCH_SIZE");
-        field.setAccessible(true);
-        int multicastSize = field.getInt(GCMAdapter.class);
-        try {
-            field.setInt(GCMAdapter.class, 1);
-
-            // perform push //
-            notification = scheduleNotificationAndWait(notification);
-
-            checkReceipts(notification, 2);
-        } finally {
-            field.setInt(GCMAdapter.class, multicastSize);
-        }
-    }
-
-    @Ignore
-    // todo: how can I mock this?
-    @Test
-    public void providerIdUpdate() throws Exception {
-
-        // mock action (based on verified actual behavior) //
-        final String newProviderId = "newProviderId";
-        ns.providerAdapters.put("google", new MockSuccessfulProviderAdapter() {
-            @Override
-            public void sendNotification(String providerId, Notifier notifier,
-                    Object payload, Notification notification,
-                    TaskTracker tracker) throws Exception {
-                tracker.completed(newProviderId);
-            }
-        });
-
-        // create push notification //
-
-        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());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device1);
-
-        // perform push //
-        notification = scheduleNotificationAndWait(notification);
-        checkReceipts(notification, 1);
-
-        Device device = (Device) app.getEm().get(device1).toTypedEntity();
-        assertEquals(newProviderId,
-                device.getProperty(notifier.getName() + NOTIFIER_ID_POSTFIX));
-    }
-
-    @Test
-    public void badPayloads() throws Exception {
-
-        // bad payloads format
-
-        app.clear();
-        app.put("payloads", "{asdf}");
-
-        try {
-            app.testRequest(ServiceAction.POST, 1, "notifications");
-            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 {
-            app.testRequest(ServiceAction.POST, 1, "notifications");
-            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", "gcm2");
-        app.put("provider", "google");
-        app.put("environment", "development");
-        app.put("apiKey", API_KEY);
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifiers")
-                .getEntity();
-        Notifier notifier2 = app.getEm().get(e.getUuid(), Notifier.class);
-
-        payloads.clear();
-        StringBuilder sb = new StringBuilder();
-        sb.append("{\"x\":\"");
-        while (sb.length() < 4080) {
-            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");
-            fail("invalid payload should have been rejected");
-        } catch (Exception ex) {
-            assertEquals("java.lang.IllegalArgumentException: GCM payloads must be 4096 characters or less",
-                    ex.getMessage());
-            // ok
-        }
-    }
-
-    @Ignore
-    // todo: how can I mock this?
-    @Test
-    public void badToken() throws Exception {
-
-        // mock action (based on verified actual behavior) //
-        if (!USE_REAL_CONNECTIONS) {
-            ns.providerAdapters.put("google",
-                    new MockSuccessfulProviderAdapter() {
-                        @Override
-                        public void sendNotification(String providerId,
-                                Notifier notifier, Object payload,
-                                Notification notification, TaskTracker tracker)
-                                throws Exception {
-                            tracker.failed("InvalidRegistration",
-                                    "InvalidRegistration");
-                        }
-                    });
-        }
-
-        // create push notification //
-
-        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());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        // device w/ bad token
-        app.clear();
-        app.put(notifier.getName() + NOTIFIER_ID_POSTFIX, PUSH_TOKEN + "x");
-
-        e = app.testRequest(ServiceAction.POST, 1, "devices").getEntity();
-        device1 = app.getEm().get(e.getUuid(), Device.class);
-
-        ns.addDevice(notification, device1);
-
-        // perform push //
-        notification = scheduleNotificationAndWait(notification);
-
-        List<EntityRef> receipts = getNotificationReceipts(notification);
-        assertEquals(1, receipts.size());
-        Receipt receipt = app.getEm().get(receipts.get(0), Receipt.class);
-        assertEquals("InvalidRegistration", receipt.getErrorCode());
-    }
-
-    @Ignore
-    // todo: how can I mock this?
-    @Test
-    public void badAPIKey() throws Exception {
-
-        if (!USE_REAL_CONNECTIONS) {
-            // mock action (based on verified actual behavior) //
-            ns.providerAdapters.put("google",
-                    new MockSuccessfulProviderAdapter() {
-                        @Override
-                        public void sendNotification(String providerId,
-                                Notifier notifier, Object payload,
-                                Notification notification, TaskTracker tracker)
-                                throws Exception {
-                            Exception e = new IOException();
-                            throw new ConnectionException(e.getMessage(), e);
-                        }
-                    });
-        }
-
-        // create push notification //
-
-        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());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        ns.addDevice(notification, device1);
-
-        // save bad API key
-        app.getEm().setProperty(notifier, "apiKey", API_KEY + "x");
-
-        // perform push //
-
-        try {
-            ns.getQueueManager().processBatchAndReschedule(notification, null);
-            fail("Should have received a ConnectionException");
-        } catch (ConnectionException ex) {
-            // good
-        }
-    }
-
-    @Ignore("Run only if you need to.")
-    @Test
-    public void loadTest() throws Exception {
-
-        final int NUM_DEVICES = 10000;
-
-        // create notification //
-
-        HashMap<String, Object> properties = new LinkedHashMap<String, Object>();
-        String payload = "Hello, World!";
-        Map<String, String> payloads = new HashMap<String, String>(1);
-        payloads.put(notifier.getUuid().toString(), payload);
-        properties.put("payloads", payloads);
-        properties.put("queued", System.currentTimeMillis());
-
-        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
-                .getEntity();
-        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
-
-        Notification notification = app.getEm().get(e.getUuid(),
-                Notification.class);
-        assertEquals(
-                notification.getPayloads().get(notifier.getUuid().toString()),
-                payload);
-
-        // create a bunch of devices and add them to the notification
-        properties = new LinkedHashMap<String, Object>();
-        properties.put(notifier.getName() + NOTIFIER_ID_POSTFIX, PUSH_TOKEN);
-        for (int i = 0; i < NUM_DEVICES; i++) {
-            Entity entity = app.getEm().create("device", properties);
-            ns.addDevice(notification, entity);
-        }
-
-        long time = System.currentTimeMillis();
-        LOG.error("START DELIVERY OF {} NOTIFICATIONS", NUM_DEVICES);
-
-        // perform push //
-        notification = scheduleNotificationAndWait(notification);
-        LOG.error("END DELIVERY OF {} NOTIFICATIONS ({})", NUM_DEVICES,
-                System.currentTimeMillis() - time);
-
-        // check receipts //
-        checkReceipts(notification, NUM_DEVICES);
-        checkStatistics(notification, NUM_DEVICES, 0);
-    }
-
-    // @Test
-    // public void inactiveDeviceUpdate() throws Exception {
-    //
-    // if (!USE_REAL_CONNECTIONS) {
-    // // mock action (based on verified actual behavior) //
-    // NotificationsService.providerAdapters.put("apple", new
-    // MockSuccessfulProviderAdapter() {
-    // public Map<String,Date> getInactiveDevices(Notifier notifier,
-    // EntityManager em) throws Exception {
-    // return Collections.singletonMap(PUSH_TOKEN, new Date());
-    // }
-    // });
-    // }
-    //
-    // // create push notification //
-    //
-    // HashMap<String, Object> properties = new LinkedHashMap<String, Object>();
-    // String payload =
-    // APNS.newPayload().alertBody("Hello, World!").sound("chime").build();
-    // Map<String, String> payloads = new HashMap<String, String>(1);
-    // payloads.put(notifier.getUuid().toString(), payload);
-    // properties.put("payloads", payloads);
-    // properties.put("queued", System.currentTimeMillis());
-    //
-    // Entity e = testRequest(sm, ServiceAction.POST, 1, properties,
-    // "notifications").getEntity();
-    // testRequest(sm, ServiceAction.GET, 1, null, "notifications",
-    // e.getUuid());
-    //
-    // Notification notification = em.get(e.getUuid(), Notification.class);
-    // assertEquals(notification.getPayloads().get(notifier.getUuid().toString()),
-    // payload);
-    //
-    // ns.addDevice(notification, device1);
-    // ns.addDevice(notification, device2);
-    //
-    // assertNotNull(device1.getProperty(notifier.getName() +
-    // NOTIFIER_ID_POSTFIX));
-    // assertNotNull(device2.getProperty(notifier.getName() +
-    // NOTIFIER_ID_POSTFIX));
-    //
-    // // perform push //
-    // notification = scheduleNotificationAndWait(notification);
-    //
-    // // check provider IDs //
-    //
-    // device1 = em.get(device1, Device.class);
-    // assertNull(device1.getProperty(notifier.getName() +
-    // NOTIFIER_ID_POSTFIX));
-    // device2 = em.get(device2, Device.class);
-    // assertNull(device2.getProperty(notifier.getName() +
-    // NOTIFIER_ID_POSTFIX));
-    // }
-}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/3c761ff4/stack/services/src/test/java/org/apache/usergrid/notifiers/NotifiersServiceTest.java
----------------------------------------------------------------------
diff --git a/stack/services/src/test/java/org/apache/usergrid/notifiers/NotifiersServiceTest.java b/stack/services/src/test/java/org/apache/usergrid/notifiers/NotifiersServiceTest.java
deleted file mode 100644
index ff97578..0000000
--- a/stack/services/src/test/java/org/apache/usergrid/notifiers/NotifiersServiceTest.java
+++ /dev/null
@@ -1,224 +0,0 @@
-package org.apache.usergrid.notifiers;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.usergrid.notifications.apns.MockSuccessfulProviderAdapter;
-import org.apache.usergrid.persistence.entities.Notifier;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.apache.usergrid.services.notifications.ConnectionException;
-import org.apache.usergrid.services.notifications.NotificationsService;
-
-import java.io.InputStream;
-import java.lang.reflect.Field;
-import java.net.SocketException;
-import org.apache.usergrid.persistence.Schema;
-import org.apache.usergrid.persistence.exceptions.RequiredPropertyNotFoundException;
-import org.apache.usergrid.services.AbstractServiceIT;
-import org.apache.usergrid.services.ServiceAction;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertArrayEquals;
-
-import static org.junit.Assert.fail;
-
-public class NotifiersServiceTest extends AbstractServiceIT {
-    private NotificationsService ns;
-
-    @Before
-    public void before() throws Exception {
-        ns = (NotificationsService) app.getSm().getService("notifications");
-        MockSuccessfulProviderAdapter.install(ns);
-    }
-
-    @Test
-    public void badProvider() throws Exception {
-
-        app.clear();
-        app.put("provider", "xxx");
-        app.put("environment", "production");
-
-        try {
-            app.testRequest(ServiceAction.POST, 1, "notifiers");
-            fail("notifier creation should have failed with a bad provider");
-        } catch (IllegalArgumentException e) {
-            // ok
-        }
-    }
-
-    @Ignore("Mock doesn't work")
-    @Test
-    public void badGcmToken() throws Exception {
-        app.clear();
-        app.put("provider", "google");
-        app.put("environment", "xxx");
-
-        try {
-            app.testRequest(ServiceAction.POST, 1, "notifiers");
-            fail("notifier creation should have failed with missing apiKey");
-        } catch (RequiredPropertyNotFoundException e) {
-            // ok
-        }
-
-        // mock action (based on verified actual behavior) //
-        ns.providerAdapters
-                .put("google",
-                        new org.apache.usergrid.notifications.gcm.MockSuccessfulProviderAdapter() {
-                            @Override
-                            public void testConnection(Notifier notifier)
-                                    throws ConnectionException {
-                                throw new ConnectionException("", null);
-                            }
-                        });
-
-        app.put("apiKey", "xxx");
-
-        try {
-            app.testRequest(ServiceAction.POST, 1, "notifiers");
-            fail("notifier creation should have failed with bad connection");
-        } catch (ConnectionException e) {
-            // ok
-        }
-    }
-
-    @Test
-    public void badAPNsEnvironment() throws Exception {
-
-        MockSuccessfulProviderAdapter.uninstall(ns);
-
-        app.clear();
-        app.put("provider", "apple");
-        app.put("environment", "xxx");
-
-        try {
-            app.testRequest(ServiceAction.POST, 1, "notifiers");
-            fail("notifier creation should have failed with a bad environment");
-        } catch (IllegalArgumentException e) {
-            // ok
-        }
-    }
-
-    @Test
-    public void goodAPNsCreation() throws Exception {
-
-        app.clear();
-        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();
-
-        Notifier notifier = (Notifier) app
-                .testRequest(ServiceAction.POST, 1, false,
-                        new Object[] { "notifiers" }).getEntity()
-                .toTypedEntity();
-
-        assertEquals(app.get("provider"), notifier.getProvider());
-        assertEquals(app.get("environment"), notifier.getEnvironment());
-        assertArrayEquals(notifier.getP12Certificate(), certBytes);
-    }
-
-    @Ignore("Mock doesn't work")
-    @Test
-    public void badAPNsCertificate() throws Exception {
-
-        // mock error (based on verified actual behavior) //
-        ns.providerAdapters.put("apple", new MockSuccessfulProviderAdapter() {
-            @Override
-            public void testConnection(Notifier notifier)
-                    throws ConnectionException {
-                Exception e = new SocketException(
-                        "Connection closed by remote host");
-                throw new ConnectionException(e.getMessage(), e);
-            }
-        });
-
-        app.clear();
-        app.put("provider", "apple");
-        app.put("environment", "development");
-
-        InputStream fis = getClass().getClassLoader().getResourceAsStream(
-                "pushtest_prod.p12");
-        byte[] certBytes = IOUtils.toByteArray(fis);
-        app.put("p12Certificate", certBytes);
-        fis.close();
-
-        try {
-            app.testRequest(ServiceAction.POST, 1, "notifiers");
-            fail("notifier creation should have failed with a bad connection test");
-        } catch (ConnectionException e) {
-            // ok
-        }
-    }
-
-    @Ignore("Mock doesn't work")
-    @Test
-    public void badAPNsPassword() throws Exception {
-
-        // mock error (based on verified actual behavior) //
-        ns.providerAdapters.put("apple", new MockSuccessfulProviderAdapter() {
-            @Override
-            public void testConnection(Notifier notifier)
-                    throws ConnectionException {
-                Exception e = new Exception("invalid ssl config");
-                throw new ConnectionException(e.getMessage(), e);
-            }
-        });
-
-        app.clear();
-        app.put("provider", "apple");
-        app.put("environment", "development");
-        app.put("certificatePassword", "wrong");
-
-        InputStream fis = getClass().getClassLoader().getResourceAsStream(
-                "pushtest_dev_recent.p12");
-        byte[] certBytes = IOUtils.toByteArray(fis);
-        app.put("p12Certificate", certBytes);
-        fis.close();
-
-        try {
-            app.testRequest(ServiceAction.POST, 1, "notifiers");
-            fail("notifier creation should have failed with a bad connection test");
-        } catch (ConnectionException e) {
-            // ok
-        }
-    }
-
-    @Test
-    public void encryption() throws Exception {
-
-        app.clear();
-        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();
-
-        Field f = Schema.class.getDeclaredField("encryptionSeed");
-        f.setAccessible(true);
-        byte[] originalSeed = (byte[]) f.get(Schema.class);
-        byte[] encryptionSeed = "This is a new seed.".getBytes();
-        f.set(Schema.class, encryptionSeed);
-
-        Notifier notifier = (Notifier) app
-                .testRequest(ServiceAction.POST, 1, "notifiers").getEntity()
-                .toTypedEntity();
-
-        assertArrayEquals(notifier.getP12Certificate(), certBytes);
-
-        f.set(Schema.class, originalSeed);
-
-        try {
-            app.getEm().get(notifier.getUuid());
-            fail("Should have failed to retrieve the encrypted entity.");
-        } catch (IllegalStateException e) {
-            // ok! This should happen.
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/3c761ff4/stack/services/src/test/java/org/apache/usergrid/services/NotifiersServiceTest.java
----------------------------------------------------------------------
diff --git a/stack/services/src/test/java/org/apache/usergrid/services/NotifiersServiceTest.java b/stack/services/src/test/java/org/apache/usergrid/services/NotifiersServiceTest.java
new file mode 100644
index 0000000..06dc1a3
--- /dev/null
+++ b/stack/services/src/test/java/org/apache/usergrid/services/NotifiersServiceTest.java
@@ -0,0 +1,224 @@
+package org.apache.usergrid.services;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.usergrid.services.notifications.apns.MockSuccessfulProviderAdapter;
+import org.apache.usergrid.persistence.entities.Notifier;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.apache.usergrid.services.notifications.ConnectionException;
+import org.apache.usergrid.services.notifications.NotificationsService;
+
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.net.SocketException;
+import org.apache.usergrid.persistence.Schema;
+import org.apache.usergrid.persistence.exceptions.RequiredPropertyNotFoundException;
+import org.apache.usergrid.services.AbstractServiceIT;
+import org.apache.usergrid.services.ServiceAction;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertArrayEquals;
+
+import static org.junit.Assert.fail;
+
+public class NotifiersServiceTest extends AbstractServiceIT {
+    private NotificationsService ns;
+
+    @Before
+    public void before() throws Exception {
+        ns = (NotificationsService) app.getSm().getService("notifications");
+        MockSuccessfulProviderAdapter.install(ns);
+    }
+
+    @Test
+    public void badProvider() throws Exception {
+
+        app.clear();
+        app.put("provider", "xxx");
+        app.put("environment", "production");
+
+        try {
+            app.testRequest(ServiceAction.POST, 1, "notifiers");
+            fail("notifier creation should have failed with a bad provider");
+        } catch (IllegalArgumentException e) {
+            // ok
+        }
+    }
+
+    @Ignore("Mock doesn't work")
+    @Test
+    public void badGcmToken() throws Exception {
+        app.clear();
+        app.put("provider", "google");
+        app.put("environment", "xxx");
+
+        try {
+            app.testRequest(ServiceAction.POST, 1, "notifiers");
+            fail("notifier creation should have failed with missing apiKey");
+        } catch (RequiredPropertyNotFoundException e) {
+            // ok
+        }
+
+        // mock action (based on verified actual behavior) //
+        ns.providerAdapters
+                .put("google",
+                        new org.apache.usergrid.services.notifications.gcm.MockSuccessfulProviderAdapter() {
+                            @Override
+                            public void testConnection(Notifier notifier)
+                                    throws ConnectionException {
+                                throw new ConnectionException("", null);
+                            }
+                        });
+
+        app.put("apiKey", "xxx");
+
+        try {
+            app.testRequest(ServiceAction.POST, 1, "notifiers");
+            fail("notifier creation should have failed with bad connection");
+        } catch (ConnectionException e) {
+            // ok
+        }
+    }
+
+    @Test
+    public void badAPNsEnvironment() throws Exception {
+
+        MockSuccessfulProviderAdapter.uninstall(ns);
+
+        app.clear();
+        app.put("provider", "apple");
+        app.put("environment", "xxx");
+
+        try {
+            app.testRequest(ServiceAction.POST, 1, "notifiers");
+            fail("notifier creation should have failed with a bad environment");
+        } catch (IllegalArgumentException e) {
+            // ok
+        }
+    }
+
+    @Test
+    public void goodAPNsCreation() throws Exception {
+
+        app.clear();
+        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();
+
+        Notifier notifier = (Notifier) app
+                .testRequest(ServiceAction.POST, 1, false,
+                        new Object[] { "notifiers" }).getEntity()
+                .toTypedEntity();
+
+        assertEquals(app.get("provider"), notifier.getProvider());
+        assertEquals(app.get("environment"), notifier.getEnvironment());
+        assertArrayEquals(notifier.getP12Certificate(), certBytes);
+    }
+
+    @Ignore("Mock doesn't work")
+    @Test
+    public void badAPNsCertificate() throws Exception {
+
+        // mock error (based on verified actual behavior) //
+        ns.providerAdapters.put("apple", new MockSuccessfulProviderAdapter() {
+            @Override
+            public void testConnection(Notifier notifier)
+                    throws ConnectionException {
+                Exception e = new SocketException(
+                        "Connection closed by remote host");
+                throw new ConnectionException(e.getMessage(), e);
+            }
+        });
+
+        app.clear();
+        app.put("provider", "apple");
+        app.put("environment", "development");
+
+        InputStream fis = getClass().getClassLoader().getResourceAsStream(
+                "pushtest_prod.p12");
+        byte[] certBytes = IOUtils.toByteArray(fis);
+        app.put("p12Certificate", certBytes);
+        fis.close();
+
+        try {
+            app.testRequest(ServiceAction.POST, 1, "notifiers");
+            fail("notifier creation should have failed with a bad connection test");
+        } catch (ConnectionException e) {
+            // ok
+        }
+    }
+
+    @Ignore("Mock doesn't work")
+    @Test
+    public void badAPNsPassword() throws Exception {
+
+        // mock error (based on verified actual behavior) //
+        ns.providerAdapters.put("apple", new MockSuccessfulProviderAdapter() {
+            @Override
+            public void testConnection(Notifier notifier)
+                    throws ConnectionException {
+                Exception e = new Exception("invalid ssl config");
+                throw new ConnectionException(e.getMessage(), e);
+            }
+        });
+
+        app.clear();
+        app.put("provider", "apple");
+        app.put("environment", "development");
+        app.put("certificatePassword", "wrong");
+
+        InputStream fis = getClass().getClassLoader().getResourceAsStream(
+                "pushtest_dev_recent.p12");
+        byte[] certBytes = IOUtils.toByteArray(fis);
+        app.put("p12Certificate", certBytes);
+        fis.close();
+
+        try {
+            app.testRequest(ServiceAction.POST, 1, "notifiers");
+            fail("notifier creation should have failed with a bad connection test");
+        } catch (ConnectionException e) {
+            // ok
+        }
+    }
+
+    @Test
+    public void encryption() throws Exception {
+
+        app.clear();
+        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();
+
+        Field f = Schema.class.getDeclaredField("encryptionSeed");
+        f.setAccessible(true);
+        byte[] originalSeed = (byte[]) f.get(Schema.class);
+        byte[] encryptionSeed = "This is a new seed.".getBytes();
+        f.set(Schema.class, encryptionSeed);
+
+        Notifier notifier = (Notifier) app
+                .testRequest(ServiceAction.POST, 1, "notifiers").getEntity()
+                .toTypedEntity();
+
+        assertArrayEquals(notifier.getP12Certificate(), certBytes);
+
+        f.set(Schema.class, originalSeed);
+
+        try {
+            app.getEm().get(notifier.getUuid());
+            fail("Should have failed to retrieve the encrypted entity.");
+        } catch (IllegalStateException e) {
+            // ok! This should happen.
+        }
+    }
+}


[4/4] git commit: move tests

Posted by sf...@apache.org.
move tests


Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/dd4e7650
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/dd4e7650
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/dd4e7650

Branch: refs/heads/two-dot-o-push-notifications
Commit: dd4e7650bcf84488c05343a6bd768f2871f532df
Parents: 3c761ff
Author: Shawn Feldman <sf...@apache.org>
Authored: Tue Aug 19 20:02:31 2014 -0600
Committer: Shawn Feldman <sf...@apache.org>
Committed: Tue Aug 19 20:02:31 2014 -0600

----------------------------------------------------------------------
 .../persistence/entities/Notification.java      |   2 +-
 .../usergrid/services/NotifiersServiceTest.java | 224 -----
 .../AbstractServiceNotificationIT.java          | 107 +++
 .../AbstractServiceNotificationTest.java        | 107 ---
 .../notifications/NotifiersServiceIT.java       | 224 +++++
 .../apns/NotificationsServiceIT.java            | 857 ++++++++++++++++++
 .../apns/NotificationsServiceTest.java          | 868 -------------------
 .../gcm/NotificationsServiceIT.java             | 546 ++++++++++++
 .../gcm/NotificationsServiceTest.java           | 546 ------------
 9 files changed, 1735 insertions(+), 1746 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/dd4e7650/stack/core/src/main/java/org/apache/usergrid/persistence/entities/Notification.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/persistence/entities/Notification.java b/stack/core/src/main/java/org/apache/usergrid/persistence/entities/Notification.java
index c723302..7a643ac 100644
--- a/stack/core/src/main/java/org/apache/usergrid/persistence/entities/Notification.java
+++ b/stack/core/src/main/java/org/apache/usergrid/persistence/entities/Notification.java
@@ -195,7 +195,7 @@ public class Notification extends TypedEntity {
         // does nothing - state is derived
     }
 
-    @EntityProperty
+    @EntityProperty(mutable = true, indexed = true)
     public State getState() {
         if (getErrorMessage() != null) {
             return State.FAILED;

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/dd4e7650/stack/services/src/test/java/org/apache/usergrid/services/NotifiersServiceTest.java
----------------------------------------------------------------------
diff --git a/stack/services/src/test/java/org/apache/usergrid/services/NotifiersServiceTest.java b/stack/services/src/test/java/org/apache/usergrid/services/NotifiersServiceTest.java
deleted file mode 100644
index 06dc1a3..0000000
--- a/stack/services/src/test/java/org/apache/usergrid/services/NotifiersServiceTest.java
+++ /dev/null
@@ -1,224 +0,0 @@
-package org.apache.usergrid.services;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.usergrid.services.notifications.apns.MockSuccessfulProviderAdapter;
-import org.apache.usergrid.persistence.entities.Notifier;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.apache.usergrid.services.notifications.ConnectionException;
-import org.apache.usergrid.services.notifications.NotificationsService;
-
-import java.io.InputStream;
-import java.lang.reflect.Field;
-import java.net.SocketException;
-import org.apache.usergrid.persistence.Schema;
-import org.apache.usergrid.persistence.exceptions.RequiredPropertyNotFoundException;
-import org.apache.usergrid.services.AbstractServiceIT;
-import org.apache.usergrid.services.ServiceAction;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertArrayEquals;
-
-import static org.junit.Assert.fail;
-
-public class NotifiersServiceTest extends AbstractServiceIT {
-    private NotificationsService ns;
-
-    @Before
-    public void before() throws Exception {
-        ns = (NotificationsService) app.getSm().getService("notifications");
-        MockSuccessfulProviderAdapter.install(ns);
-    }
-
-    @Test
-    public void badProvider() throws Exception {
-
-        app.clear();
-        app.put("provider", "xxx");
-        app.put("environment", "production");
-
-        try {
-            app.testRequest(ServiceAction.POST, 1, "notifiers");
-            fail("notifier creation should have failed with a bad provider");
-        } catch (IllegalArgumentException e) {
-            // ok
-        }
-    }
-
-    @Ignore("Mock doesn't work")
-    @Test
-    public void badGcmToken() throws Exception {
-        app.clear();
-        app.put("provider", "google");
-        app.put("environment", "xxx");
-
-        try {
-            app.testRequest(ServiceAction.POST, 1, "notifiers");
-            fail("notifier creation should have failed with missing apiKey");
-        } catch (RequiredPropertyNotFoundException e) {
-            // ok
-        }
-
-        // mock action (based on verified actual behavior) //
-        ns.providerAdapters
-                .put("google",
-                        new org.apache.usergrid.services.notifications.gcm.MockSuccessfulProviderAdapter() {
-                            @Override
-                            public void testConnection(Notifier notifier)
-                                    throws ConnectionException {
-                                throw new ConnectionException("", null);
-                            }
-                        });
-
-        app.put("apiKey", "xxx");
-
-        try {
-            app.testRequest(ServiceAction.POST, 1, "notifiers");
-            fail("notifier creation should have failed with bad connection");
-        } catch (ConnectionException e) {
-            // ok
-        }
-    }
-
-    @Test
-    public void badAPNsEnvironment() throws Exception {
-
-        MockSuccessfulProviderAdapter.uninstall(ns);
-
-        app.clear();
-        app.put("provider", "apple");
-        app.put("environment", "xxx");
-
-        try {
-            app.testRequest(ServiceAction.POST, 1, "notifiers");
-            fail("notifier creation should have failed with a bad environment");
-        } catch (IllegalArgumentException e) {
-            // ok
-        }
-    }
-
-    @Test
-    public void goodAPNsCreation() throws Exception {
-
-        app.clear();
-        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();
-
-        Notifier notifier = (Notifier) app
-                .testRequest(ServiceAction.POST, 1, false,
-                        new Object[] { "notifiers" }).getEntity()
-                .toTypedEntity();
-
-        assertEquals(app.get("provider"), notifier.getProvider());
-        assertEquals(app.get("environment"), notifier.getEnvironment());
-        assertArrayEquals(notifier.getP12Certificate(), certBytes);
-    }
-
-    @Ignore("Mock doesn't work")
-    @Test
-    public void badAPNsCertificate() throws Exception {
-
-        // mock error (based on verified actual behavior) //
-        ns.providerAdapters.put("apple", new MockSuccessfulProviderAdapter() {
-            @Override
-            public void testConnection(Notifier notifier)
-                    throws ConnectionException {
-                Exception e = new SocketException(
-                        "Connection closed by remote host");
-                throw new ConnectionException(e.getMessage(), e);
-            }
-        });
-
-        app.clear();
-        app.put("provider", "apple");
-        app.put("environment", "development");
-
-        InputStream fis = getClass().getClassLoader().getResourceAsStream(
-                "pushtest_prod.p12");
-        byte[] certBytes = IOUtils.toByteArray(fis);
-        app.put("p12Certificate", certBytes);
-        fis.close();
-
-        try {
-            app.testRequest(ServiceAction.POST, 1, "notifiers");
-            fail("notifier creation should have failed with a bad connection test");
-        } catch (ConnectionException e) {
-            // ok
-        }
-    }
-
-    @Ignore("Mock doesn't work")
-    @Test
-    public void badAPNsPassword() throws Exception {
-
-        // mock error (based on verified actual behavior) //
-        ns.providerAdapters.put("apple", new MockSuccessfulProviderAdapter() {
-            @Override
-            public void testConnection(Notifier notifier)
-                    throws ConnectionException {
-                Exception e = new Exception("invalid ssl config");
-                throw new ConnectionException(e.getMessage(), e);
-            }
-        });
-
-        app.clear();
-        app.put("provider", "apple");
-        app.put("environment", "development");
-        app.put("certificatePassword", "wrong");
-
-        InputStream fis = getClass().getClassLoader().getResourceAsStream(
-                "pushtest_dev_recent.p12");
-        byte[] certBytes = IOUtils.toByteArray(fis);
-        app.put("p12Certificate", certBytes);
-        fis.close();
-
-        try {
-            app.testRequest(ServiceAction.POST, 1, "notifiers");
-            fail("notifier creation should have failed with a bad connection test");
-        } catch (ConnectionException e) {
-            // ok
-        }
-    }
-
-    @Test
-    public void encryption() throws Exception {
-
-        app.clear();
-        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();
-
-        Field f = Schema.class.getDeclaredField("encryptionSeed");
-        f.setAccessible(true);
-        byte[] originalSeed = (byte[]) f.get(Schema.class);
-        byte[] encryptionSeed = "This is a new seed.".getBytes();
-        f.set(Schema.class, encryptionSeed);
-
-        Notifier notifier = (Notifier) app
-                .testRequest(ServiceAction.POST, 1, "notifiers").getEntity()
-                .toTypedEntity();
-
-        assertArrayEquals(notifier.getP12Certificate(), certBytes);
-
-        f.set(Schema.class, originalSeed);
-
-        try {
-            app.getEm().get(notifier.getUuid());
-            fail("Should have failed to retrieve the encrypted entity.");
-        } catch (IllegalStateException e) {
-            // ok! This should happen.
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/dd4e7650/stack/services/src/test/java/org/apache/usergrid/services/notifications/AbstractServiceNotificationIT.java
----------------------------------------------------------------------
diff --git a/stack/services/src/test/java/org/apache/usergrid/services/notifications/AbstractServiceNotificationIT.java b/stack/services/src/test/java/org/apache/usergrid/services/notifications/AbstractServiceNotificationIT.java
new file mode 100644
index 0000000..5cef8a8
--- /dev/null
+++ b/stack/services/src/test/java/org/apache/usergrid/services/notifications/AbstractServiceNotificationIT.java
@@ -0,0 +1,107 @@
+package org.apache.usergrid.services.notifications;
+
+import org.apache.usergrid.persistence.*;
+import org.apache.usergrid.persistence.entities.Notification;
+import org.apache.usergrid.persistence.entities.Receipt;
+import org.apache.usergrid.persistence.index.query.Query;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.rules.TestName;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.usergrid.services.AbstractServiceIT;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+public class AbstractServiceNotificationIT extends AbstractServiceIT {
+    private NotificationsService ns;
+
+    @Rule
+    public TestName name = new TestName();
+
+    @BeforeClass
+    public static void beforeClass() {
+    }
+
+    @Before
+    public void before() throws Exception {
+
+    }
+
+    protected NotificationsService getNotificationService(){
+        ns = (NotificationsService) app.getSm().getService("notifications");
+        return ns;
+    }
+
+    protected Notification scheduleNotificationAndWait(Notification notification)
+            throws Exception {
+        getNotificationService().getQueueManager().processBatchAndReschedule(notification,null);
+        long timeout = System.currentTimeMillis() + 60000;
+        while (System.currentTimeMillis() < timeout) {
+            Thread.sleep(200);
+            notification = app.getEm().get(notification.getUuid(),
+                    Notification.class);
+            if (notification.getFinished() != null) {
+                return notification;
+            }
+        }
+        fail("Notification failed to complete");
+        return null;
+    }
+
+    protected List<EntityRef> getNotificationReceipts(EntityRef notification)
+            throws Exception {
+        Results r = app.getEm().getCollection(notification,
+                Notification.RECEIPTS_COLLECTION, null, 1000000,
+                Query.Level.REFS, false);
+        List<EntityRef> list =new ArrayList<EntityRef>();//get all
+        PagingResultsIterator it = new PagingResultsIterator(r);
+        while(it.hasNext()){
+           list.add((EntityRef)it.next());
+        }
+        return list;
+    }
+
+    protected void checkReceipts(Notification notification, int expected)
+            throws Exception {
+        List<EntityRef> receipts = getNotificationReceipts(notification);
+        long timeout = System.currentTimeMillis() + 60000;
+        while (System.currentTimeMillis() < timeout) {
+            Thread.sleep(200);
+            receipts =getNotificationReceipts(notification);
+            if (receipts.size()==expected) {
+                 break;
+            }
+        }
+        assertEquals(expected, receipts.size());
+        for (EntityRef receipt : receipts) {
+            Receipt r = app.getEm().get(receipt, Receipt.class);
+            assertNotNull(r.getSent());
+            assertNotNull(r.getPayload());
+            assertNotNull(r.getNotifierId());
+            EntityRef source = getNotificationService().getSourceNotification(r);
+            assertEquals(source.getUuid(), notification.getUuid());
+        }
+    }
+
+    protected void checkStatistics(Notification notification, long sent,  long errors) throws Exception{
+        Map<String, Long> statistics = null;
+        long timeout = System.currentTimeMillis() + 60000;
+        while (System.currentTimeMillis() < timeout) {
+            Thread.sleep(200);
+            statistics = app.getEm().get(notification.getUuid(), Notification.class).getStatistics();
+            if (statistics.get("sent")==sent && statistics.get("errors")==errors) {
+                break;
+            }
+        }
+        assertEquals(sent, statistics.get("sent").longValue());
+        assertEquals(errors, statistics.get("errors").longValue());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/dd4e7650/stack/services/src/test/java/org/apache/usergrid/services/notifications/AbstractServiceNotificationTest.java
----------------------------------------------------------------------
diff --git a/stack/services/src/test/java/org/apache/usergrid/services/notifications/AbstractServiceNotificationTest.java b/stack/services/src/test/java/org/apache/usergrid/services/notifications/AbstractServiceNotificationTest.java
deleted file mode 100644
index 87bed27..0000000
--- a/stack/services/src/test/java/org/apache/usergrid/services/notifications/AbstractServiceNotificationTest.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package org.apache.usergrid.services.notifications;
-
-import org.apache.usergrid.persistence.*;
-import org.apache.usergrid.persistence.entities.Notification;
-import org.apache.usergrid.persistence.entities.Receipt;
-import org.apache.usergrid.persistence.index.query.Query;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Rule;
-import org.junit.rules.TestName;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.usergrid.services.AbstractServiceIT;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-
-public class AbstractServiceNotificationTest extends AbstractServiceIT {
-    private NotificationsService ns;
-
-    @Rule
-    public TestName name = new TestName();
-
-    @BeforeClass
-    public static void beforeClass() {
-    }
-
-    @Before
-    public void before() throws Exception {
-
-    }
-
-    protected NotificationsService getNotificationService(){
-        ns = (NotificationsService) app.getSm().getService("notifications");
-        return ns;
-    }
-
-    protected Notification scheduleNotificationAndWait(Notification notification)
-            throws Exception {
-        getNotificationService().getQueueManager().processBatchAndReschedule(notification,null);
-        long timeout = System.currentTimeMillis() + 60000;
-        while (System.currentTimeMillis() < timeout) {
-            Thread.sleep(200);
-            notification = app.getEm().get(notification.getUuid(),
-                    Notification.class);
-            if (notification.getFinished() != null) {
-                return notification;
-            }
-        }
-        fail("Notification failed to complete");
-        return null;
-    }
-
-    protected List<EntityRef> getNotificationReceipts(EntityRef notification)
-            throws Exception {
-        Results r = app.getEm().getCollection(notification,
-                Notification.RECEIPTS_COLLECTION, null, 1000000,
-                Query.Level.REFS, false);
-        List<EntityRef> list =new ArrayList<EntityRef>();//get all
-        PagingResultsIterator it = new PagingResultsIterator(r);
-        while(it.hasNext()){
-           list.add((EntityRef)it.next());
-        }
-        return list;
-    }
-
-    protected void checkReceipts(Notification notification, int expected)
-            throws Exception {
-        List<EntityRef> receipts = getNotificationReceipts(notification);
-        long timeout = System.currentTimeMillis() + 60000;
-        while (System.currentTimeMillis() < timeout) {
-            Thread.sleep(200);
-            receipts =getNotificationReceipts(notification);
-            if (receipts.size()==expected) {
-                 break;
-            }
-        }
-        assertEquals(expected, receipts.size());
-        for (EntityRef receipt : receipts) {
-            Receipt r = app.getEm().get(receipt, Receipt.class);
-            assertNotNull(r.getSent());
-            assertNotNull(r.getPayload());
-            assertNotNull(r.getNotifierId());
-            EntityRef source = getNotificationService().getSourceNotification(r);
-            assertEquals(source.getUuid(), notification.getUuid());
-        }
-    }
-
-    protected void checkStatistics(Notification notification, long sent,  long errors) throws Exception{
-        Map<String, Long> statistics = null;
-        long timeout = System.currentTimeMillis() + 60000;
-        while (System.currentTimeMillis() < timeout) {
-            Thread.sleep(200);
-            statistics = app.getEm().get(notification.getUuid(), Notification.class).getStatistics();
-            if (statistics.get("sent")==sent && statistics.get("errors")==errors) {
-                break;
-            }
-        }
-        assertEquals(sent, statistics.get("sent").longValue());
-        assertEquals(errors, statistics.get("errors").longValue());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/dd4e7650/stack/services/src/test/java/org/apache/usergrid/services/notifications/NotifiersServiceIT.java
----------------------------------------------------------------------
diff --git a/stack/services/src/test/java/org/apache/usergrid/services/notifications/NotifiersServiceIT.java b/stack/services/src/test/java/org/apache/usergrid/services/notifications/NotifiersServiceIT.java
new file mode 100644
index 0000000..a0dc60c
--- /dev/null
+++ b/stack/services/src/test/java/org/apache/usergrid/services/notifications/NotifiersServiceIT.java
@@ -0,0 +1,224 @@
+package org.apache.usergrid.services.notifications;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.usergrid.services.notifications.apns.MockSuccessfulProviderAdapter;
+import org.apache.usergrid.persistence.entities.Notifier;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.apache.usergrid.services.notifications.ConnectionException;
+import org.apache.usergrid.services.notifications.NotificationsService;
+
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.net.SocketException;
+import org.apache.usergrid.persistence.Schema;
+import org.apache.usergrid.persistence.exceptions.RequiredPropertyNotFoundException;
+import org.apache.usergrid.services.AbstractServiceIT;
+import org.apache.usergrid.services.ServiceAction;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertArrayEquals;
+
+import static org.junit.Assert.fail;
+
+public class NotifiersServiceIT extends AbstractServiceIT {
+    private NotificationsService ns;
+
+    @Before
+    public void before() throws Exception {
+        ns = (NotificationsService) app.getSm().getService("notifications");
+        MockSuccessfulProviderAdapter.install(ns);
+    }
+
+    @Test
+    public void badProvider() throws Exception {
+
+        app.clear();
+        app.put("provider", "xxx");
+        app.put("environment", "production");
+
+        try {
+            app.testRequest(ServiceAction.POST, 1, "notifiers");
+            fail("notifier creation should have failed with a bad provider");
+        } catch (IllegalArgumentException e) {
+            // ok
+        }
+    }
+
+    @Ignore("Mock doesn't work")
+    @Test
+    public void badGcmToken() throws Exception {
+        app.clear();
+        app.put("provider", "google");
+        app.put("environment", "xxx");
+
+        try {
+            app.testRequest(ServiceAction.POST, 1, "notifiers");
+            fail("notifier creation should have failed with missing apiKey");
+        } catch (RequiredPropertyNotFoundException e) {
+            // ok
+        }
+
+        // mock action (based on verified actual behavior) //
+        ns.providerAdapters
+                .put("google",
+                        new org.apache.usergrid.services.notifications.gcm.MockSuccessfulProviderAdapter() {
+                            @Override
+                            public void testConnection(Notifier notifier)
+                                    throws ConnectionException {
+                                throw new ConnectionException("", null);
+                            }
+                        });
+
+        app.put("apiKey", "xxx");
+
+        try {
+            app.testRequest(ServiceAction.POST, 1, "notifiers");
+            fail("notifier creation should have failed with bad connection");
+        } catch (ConnectionException e) {
+            // ok
+        }
+    }
+
+    @Test
+    public void badAPNsEnvironment() throws Exception {
+
+        MockSuccessfulProviderAdapter.uninstall(ns);
+
+        app.clear();
+        app.put("provider", "apple");
+        app.put("environment", "xxx");
+
+        try {
+            app.testRequest(ServiceAction.POST, 1, "notifiers");
+            fail("notifier creation should have failed with a bad environment");
+        } catch (IllegalArgumentException e) {
+            // ok
+        }
+    }
+
+    @Test
+    public void goodAPNsCreation() throws Exception {
+
+        app.clear();
+        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();
+
+        Notifier notifier = (Notifier) app
+                .testRequest(ServiceAction.POST, 1, false,
+                        new Object[] { "notifiers" }).getEntity()
+                .toTypedEntity();
+
+        assertEquals(app.get("provider"), notifier.getProvider());
+        assertEquals(app.get("environment"), notifier.getEnvironment());
+        assertArrayEquals(notifier.getP12Certificate(), certBytes);
+    }
+
+    @Ignore("Mock doesn't work")
+    @Test
+    public void badAPNsCertificate() throws Exception {
+
+        // mock error (based on verified actual behavior) //
+        ns.providerAdapters.put("apple", new MockSuccessfulProviderAdapter() {
+            @Override
+            public void testConnection(Notifier notifier)
+                    throws ConnectionException {
+                Exception e = new SocketException(
+                        "Connection closed by remote host");
+                throw new ConnectionException(e.getMessage(), e);
+            }
+        });
+
+        app.clear();
+        app.put("provider", "apple");
+        app.put("environment", "development");
+
+        InputStream fis = getClass().getClassLoader().getResourceAsStream(
+                "pushtest_prod.p12");
+        byte[] certBytes = IOUtils.toByteArray(fis);
+        app.put("p12Certificate", certBytes);
+        fis.close();
+
+        try {
+            app.testRequest(ServiceAction.POST, 1, "notifiers");
+            fail("notifier creation should have failed with a bad connection test");
+        } catch (ConnectionException e) {
+            // ok
+        }
+    }
+
+    @Ignore("Mock doesn't work")
+    @Test
+    public void badAPNsPassword() throws Exception {
+
+        // mock error (based on verified actual behavior) //
+        ns.providerAdapters.put("apple", new MockSuccessfulProviderAdapter() {
+            @Override
+            public void testConnection(Notifier notifier)
+                    throws ConnectionException {
+                Exception e = new Exception("invalid ssl config");
+                throw new ConnectionException(e.getMessage(), e);
+            }
+        });
+
+        app.clear();
+        app.put("provider", "apple");
+        app.put("environment", "development");
+        app.put("certificatePassword", "wrong");
+
+        InputStream fis = getClass().getClassLoader().getResourceAsStream(
+                "pushtest_dev_recent.p12");
+        byte[] certBytes = IOUtils.toByteArray(fis);
+        app.put("p12Certificate", certBytes);
+        fis.close();
+
+        try {
+            app.testRequest(ServiceAction.POST, 1, "notifiers");
+            fail("notifier creation should have failed with a bad connection test");
+        } catch (ConnectionException e) {
+            // ok
+        }
+    }
+
+    @Test
+    public void encryption() throws Exception {
+
+        app.clear();
+        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();
+
+        Field f = Schema.class.getDeclaredField("encryptionSeed");
+        f.setAccessible(true);
+        byte[] originalSeed = (byte[]) f.get(Schema.class);
+        byte[] encryptionSeed = "This is a new seed.".getBytes();
+        f.set(Schema.class, encryptionSeed);
+
+        Notifier notifier = (Notifier) app
+                .testRequest(ServiceAction.POST, 1, "notifiers").getEntity()
+                .toTypedEntity();
+
+        assertArrayEquals(notifier.getP12Certificate(), certBytes);
+
+        f.set(Schema.class, originalSeed);
+
+        try {
+            app.getEm().get(notifier.getUuid());
+            fail("Should have failed to retrieve the encrypted entity.");
+        } catch (IllegalStateException e) {
+            // ok! This should happen.
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/dd4e7650/stack/services/src/test/java/org/apache/usergrid/services/notifications/apns/NotificationsServiceIT.java
----------------------------------------------------------------------
diff --git a/stack/services/src/test/java/org/apache/usergrid/services/notifications/apns/NotificationsServiceIT.java b/stack/services/src/test/java/org/apache/usergrid/services/notifications/apns/NotificationsServiceIT.java
new file mode 100644
index 0000000..fd00d39
--- /dev/null
+++ b/stack/services/src/test/java/org/apache/usergrid/services/notifications/apns/NotificationsServiceIT.java
@@ -0,0 +1,857 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * 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 org.apache.usergrid.services.notifications.apns;
+
+import com.relayrides.pushy.apns.*;
+import com.relayrides.pushy.apns.util.*;
+import org.apache.commons.io.IOUtils;
+import org.apache.usergrid.services.notifications.AbstractServiceNotificationIT;
+import org.apache.usergrid.persistence.*;
+import org.apache.usergrid.persistence.entities.*;
+import org.apache.usergrid.persistence.index.query.Query;
+import org.apache.usergrid.services.notifications.*;
+import org.junit.After;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.InputStream;
+import java.net.SocketException;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.apache.usergrid.services.ServiceAction;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.apache.usergrid.services.notifications.NotificationsService.NOTIFIER_ID_POSTFIX;
+
+// todo: test reschedule on delivery time change
+// todo: test restart of queuing
+public class NotificationsServiceIT extends AbstractServiceNotificationIT {
+
+    private static final Logger LOG = 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 Group group1;
+    private User user1;
+    private NotificationsService ns;
+
+    @Override
+    @Before
+    public void before() throws Exception {
+        super.before();
+        // create apns notifier //
+        NotificationsQueueManager.IS_TEST = true;
+
+        app.clear();
+        app.put("name", "apns");
+        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.getEm().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.getEm().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.getEm().get(e.getUuid(), Device.class);
+
+        // create User
+        app.put( "username", "edanuff" );
+        app.put( "email", "ed@anuff.com" );
+//        user1 = (User)app.testRequest( ServiceAction.POST, 1, "users" ).getEntity();
+//        app.getEm().createConnection(user1, "devices", device1);
+//        app.getEm().createConnection(user1, "devices", device2);
+
+        // create Group
+        app.put( "path", "path" );
+        app.put( "title", "group" );
+        group1 = (Group) app.testRequest( ServiceAction.POST, 1, "groups" ).getEntity();
+
+//        app.getEm().createConnection(group1, "users", user1);
+
+        ns = getNotificationService();
+    }
+
+    @After
+    public void after() throws Exception {
+    }
+
+    @Test
+    public void singlePushNotification() 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("queued", System.currentTimeMillis());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device1);
+
+//        // verify Query for CREATED state
+        assertEquals(notification.getState(), Notification.State.STARTED);
+
+        // perform push //
+
+        notification = scheduleNotificationAndWait(notification);
+
+        // verify Query for FINISHED state
+        assertEquals(notification.getState(), Notification.State.FINISHED);
+
+        checkReceipts(notification, 1);
+        checkStatistics(notification, 1, 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.getEm().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());
+
+        e = app.testRequest(ServiceAction.POST, 1, "notifications").getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device);
+
+        // verify Query for CREATED state
+        Query query = new Query();
+        query.addEqualityFilter("state", Notification.State.STARTED.toString());
+        Results results = app.getEm().searchCollection(
+                app.getEm().getApplicationRef(), "notifications", query);
+        Entity entity = results.getEntitiesMap().get(notification.getUuid());
+        assertNotNull(entity);
+
+        // perform push //
+
+        ns.getQueueManager().processBatchAndReschedule(notification, null);
+
+        // verify Query for FINISHED state
+        query = new Query();
+        query.addEqualityFilter("state", Notification.State.FINISHED.toString());
+        results = app.getEm().searchCollection(app.getEm().getApplicationRef(),
+                "notifications", query);
+        entity = results.getEntitiesMap().get(notification.getUuid());
+        assertNotNull(entity);
+
+        notification = (Notification) entity.toTypedEntity();
+        checkReceipts(notification, 0);
+        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("queued", System.currentTimeMillis());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device1);
+
+        // delay until the scheduler has time to run
+        Thread.sleep(500);
+
+        // verify Query for SCHEDULED state
+        Query query = new Query();
+        query.addEqualityFilter("state",
+                Notification.State.SCHEDULED.toString());
+        Results results = app.getEm().searchCollection(
+                app.getEm().getApplicationRef(), "notifications", query);
+        Entity entity = results.getEntitiesMap().get(notification.getUuid());
+        assertNotNull(entity);
+
+        try {
+            e = app.testRequest(ServiceAction.DELETE, 1, "notifications",
+                    e.getUuid()).getEntity();
+        }catch (Exception deleteException){
+            LOG.error("Couldn't delete",deleteException);
+        }
+        app.getEm().get(e.getUuid(), Notification.class);
+    }
+
+    @Test
+    public void badPayloads() throws Exception {
+
+        MockSuccessfulProviderAdapter.uninstall(ns);
+
+        // bad payloads format
+
+        app.clear();
+        app.put("payloads", "{asdf}");
+
+        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, "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.getEm().get(e.getUuid(), Notifier.class);
+
+        payloads.clear();
+        StringBuilder sb = new StringBuilder();
+        sb.append("{\"x\":\"");
+        while (sb.length() < 255) {
+            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 256 characters or less");
+            // ok
+        }
+    }
+
+    @Ignore
+    // todo: how can I mock this?
+    @Test
+    public void badToken() throws Exception {
+
+        // mock action (based on verified actual behavior) //
+
+        if (!USE_REAL_CONNECTIONS) {
+            ns.providerAdapters.put("apple",
+                    new MockSuccessfulProviderAdapter() {
+                        @Override
+                        public void sendNotification(String providerId,
+                                Notifier notifier, Object payload,
+                                Notification notification, TaskTracker tracker)
+                                throws Exception {
+                            APNsNotification apnsNotification = APNsNotification
+                                    .create(providerId, payload.toString(),
+                                            notification, tracker);
+                            apnsNotification.messageSent();
+                            apnsNotification
+                                    .messageSendFailed( RejectedNotificationReason.INVALID_TOKEN);
+                        }
+                    });
+        }
+
+        // create push notification //
+
+        HashMap<String, Object> properties = new LinkedHashMap<String, Object>();
+        String payload = getPayload();
+        Map<String, String> payloads = new HashMap<String, String>(1);
+        payloads.put(notifier.getUuid().toString(), payload);
+        properties.put("payloads", payloads);
+        properties.put("queued", System.currentTimeMillis());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device1);
+
+        // perform push //
+        notification = scheduleNotificationAndWait(notification);
+        checkStatistics(notification, 0, 1);
+
+        notification = (Notification) app.getEm().get(notification)
+                .toTypedEntity();
+        checkReceipts(notification, 1);
+        List<EntityRef> receipts = getNotificationReceipts(notification);
+        Receipt receipt = app.getEm().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(notifier.getUuid().toString(), payload);
+        app.put("payloads", payloads);
+        app.put("queued", System.currentTimeMillis());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device1);
+        ns.addDevice(notification, device2);
+
+        // perform push //
+        notification = scheduleNotificationAndWait(notification);
+
+        checkReceipts(notification, 2);
+    }
+
+    @Test
+    public void twoDevicesTwoNotifiers() throws Exception {
+
+        // create a 2nd notifier //
+        app.clear();
+        app.put("name", "apns2");
+        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();
+        app.testRequest(ServiceAction.GET, 1, "notifiers", "apns2");
+
+        Notifier notifier2 = app.getEm().get(e.getUuid(), Notifier.class);
+        assertEquals(notifier2.getName(), "apns2");
+        assertEquals(notifier2.getProvider(), PROVIDER);
+        assertEquals(notifier2.getEnvironment(), "development");
+
+        String key = notifier.getName() + NOTIFIER_ID_POSTFIX;
+        String key2 = notifier2.getName() + NOTIFIER_ID_POSTFIX;
+        device2.setProperty(key, null);
+        device2.setProperty(key2, null);
+        app.getEm().update(device2);
+
+        // create push notification //
+
+        app.clear();
+        String payload = getPayload();
+        Map<String, String> payloads = new HashMap<String, String>(1);
+        payloads.put(notifier.getUuid().toString(), payload);
+        payloads.put(notifier2.getUuid().toString(), payload);
+        app.put("payloads", payloads);
+        app.put("queued", System.currentTimeMillis());
+
+        e = app.testRequest(ServiceAction.POST, 1, "notifications").getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device1);
+        ns.addDevice(notification, device2);
+
+        // perform push //
+        notification = scheduleNotificationAndWait(notification);
+
+        checkReceipts(notification, 2); //the second notifier isn't associated correctly so its 3 instead of 4
+    }
+
+    @Test
+    public void oneDeviceTwoNotifiers() throws Exception {
+
+        // create a 2nd notifier //
+        Object nameValue = "apns2";
+        Object environValue = "development";
+
+        app.clear();
+        app.put("name", nameValue);
+        app.put("provider", PROVIDER);
+        app.put("environment", environValue);
+        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", nameValue);
+
+        Notifier notifier2 = app.getEm().get(e.getUuid(), Notifier.class);
+        assertEquals(notifier2.getName(), nameValue);
+        assertEquals(notifier2.getProvider(), PROVIDER);
+        assertEquals(notifier2.getEnvironment(), environValue);
+
+        String key2 = notifier2.getName() + NOTIFIER_ID_POSTFIX;
+        device1.setProperty(key2, PUSH_TOKEN);
+        app.getEm().update(device1);
+
+        // create push notification //
+
+        app.clear();
+        String payload = getPayload();
+        Map<String, String> payloads = new HashMap<String, String>(1);
+        payloads.put(notifier.getUuid().toString(), payload);
+        payloads.put(notifier2.getUuid().toString(), payload);
+        app.put("payloads", payloads);
+        app.put("queued", System.currentTimeMillis());
+
+        e = app.testRequest(ServiceAction.POST, 1, "notifications").getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device1);
+
+        // perform push //
+        notification = scheduleNotificationAndWait(notification);
+
+        checkReceipts(notification, 2);
+    }
+
+    @Ignore
+    // todo: how can I mock this?
+    @Test
+    public void badCertificate() throws Exception {
+
+        // 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(
+                "empty.p12");
+        byte[] certBytes = IOUtils.toByteArray(fis);
+        app.put("p12Certificate", certBytes);
+        fis.close();
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifiers")
+                .getEntity();
+        notifier = app.getEm().get(e.getUuid(), Notifier.class);
+
+        // mock error (based on verified actual behavior) //
+        if (!USE_REAL_CONNECTIONS) {
+            ns.providerAdapters.put("apple",
+                    new MockSuccessfulProviderAdapter() {
+                        @Override
+                        public void testConnection(Notifier notifier)
+                                throws ConnectionException {
+                            Exception e = new SocketException(
+                                    "Connection closed by remote host");
+                            throw new ConnectionException(e.getMessage(), e);
+                        }
+                    });
+        }
+
+        // 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());
+
+        e = app.testRequest(ServiceAction.POST, 1, "notifications").getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device1);
+
+        // perform push //
+
+        try {
+            ns.getQueueManager().processBatchAndReschedule(notification,null);
+            fail("testConnection() should have failed");
+        } catch (Exception ex) {
+            // good, there should be an error
+        }
+
+        // verify Query for FAILED state
+        Query query = new Query();
+        query.addEqualityFilter("state", Notification.State.FAILED.toString());
+        Results results = app.getEm().searchCollection(
+                app.getEm().getApplicationRef(), "notifications", query);
+        Entity entity = results.getEntitiesMap().get(notification.getUuid());
+        assertNotNull(entity);
+    }
+
+    @Ignore
+    // todo: how can I mock this?
+    @Test
+    public void inactiveDeviceUpdate() throws Exception {
+
+        // mock action (based on verified actual behavior) //
+        if (!USE_REAL_CONNECTIONS) {
+            ns.providerAdapters.put("apple",
+                    new MockSuccessfulProviderAdapter() {
+                        @Override
+                        public Map<String, Date> getInactiveDevices(
+                                Notifier notifier, EntityManager em)
+                                throws Exception {
+                            return Collections.singletonMap(PUSH_TOKEN,
+                                    new Date());
+                        }
+                    });
+        }
+
+        // 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());
+
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+
+        Notification notification = app.getEm().get(e.getUuid(),
+                Notification.class);
+        assertEquals(
+                notification.getPayloads().get(notifier.getUuid().toString()),
+                payload);
+
+        ns.addDevice(notification, device1);
+        ns.addDevice(notification, device2);
+
+        assertNotNull(device1.getProperty(notifier.getName()
+                + NOTIFIER_ID_POSTFIX));
+        assertNotNull(device2.getProperty(notifier.getName()
+                + NOTIFIER_ID_POSTFIX));
+
+        // perform push //
+        notification = scheduleNotificationAndWait(notification);
+
+        // check provider IDs //
+
+        device1 = app.getEm().get(device1, Device.class);
+        assertNull(device1
+                .getProperty(notifier.getName() + NOTIFIER_ID_POSTFIX));
+        device2 = app.getEm().get(device2, Device.class);
+        assertNull(device2
+                .getProperty(notifier.getName() + NOTIFIER_ID_POSTFIX));
+    }
+
+    @Test
+    public void batchTest() throws Exception {
+
+        final int NUM_DEVICES = 50;
+
+        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());
+
+        // create a notification
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+        final Notification notification = (Notification) e.toTypedEntity();
+
+        // create a bunch of devices and add them to the notification
+        app.clear();
+        app.put(notifier.getName() + NOTIFIER_ID_POSTFIX, PUSH_TOKEN);
+        for (int i = 0; i < NUM_DEVICES; i++) {
+            Entity entity = app.getEm().create("device", app.getProperties());
+            ns.addDevice(notification, entity);
+        }
+
+        // perform push //
+        int oldBatchSize = NotificationsQueueManager.BATCH_SIZE;
+        NotificationsQueueManager.BATCH_SIZE = 10;
+        try {
+            ExecutorService pool = Executors
+                    .newFixedThreadPool(APNsAdapter.MAX_CONNECTION_POOL_SIZE);
+            pool.submit(new Runnable() {
+                @Override
+                public void run() {
+                        try {
+                             scheduleNotificationAndWait(notification);
+                        }catch (Exception e){}
+                }});
+        } finally {
+            NotificationsQueueManager.BATCH_SIZE = oldBatchSize;
+        }
+
+        // check receipts //
+        checkReceipts(notification, NUM_DEVICES);
+        checkStatistics(notification, NUM_DEVICES, 0);
+    }
+
+    @Ignore("Run only if you need to.")
+    @Test
+    public void loadTest() throws Exception {
+
+        MockSuccessfulProviderAdapter.install(ns, true);
+
+        final int NUM_DEVICES = 10000;
+
+        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());
+
+        // create a notification
+        Entity e = app.testRequest(ServiceAction.POST, 1, "notifications")
+                .getEntity();
+        app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid());
+        Notification notification = (Notification) e.toTypedEntity();
+
+        // create a bunch of devices and add them to the notification
+        app.clear();
+        app.put(notifier.getName() + NOTIFIER_ID_POSTFIX, PUSH_TOKEN);
+        for (int i = 0; i < NUM_DEVICES; i++) {
+            Entity entity = app.getEm().create("device", app.getProperties());
+            ns.addDevice(notification, entity);
+        }
+
+        long time = System.currentTimeMillis();
+        LOG.error("START DELIVERY OF {} NOTIFICATIONS", NUM_DEVICES);
+
+        // perform push //
+        notification = scheduleNotificationAndWait(notification);
+        LOG.error("END DELIVERY OF {} NOTIFICATIONS ({})", NUM_DEVICES,
+                System.currentTimeMillis() - time);
+
+        // check receipts //
+        checkReceipts(notification, NUM_DEVICES);
+        checkStatistics(notification, NUM_DEVICES, 0);
+    }
+
+    private String getPayload(){
+        ApnsPayloadBuilder builder = new ApnsPayloadBuilder();
+        builder.setAlertBody("Hello, World!");
+        builder.setSoundFileName("chime");
+        String payload = builder.buildWithDefaultMaximumLength();
+        return payload;
+    }
+    // todo: can't do the following tests here. do it in the REST tier...
+    // private Notification postNotification(String path) throws Exception {
+    // HashMap<String, Object> properties = new LinkedHashMap<String, Object>();
+    // String payload =
+    // APNS.newPayload().alertBody("Hello, World!").sound("chime").build();
+    // Map<String, String> payloads = new HashMap<String, String>(1);
+    // payloads.put(notifier.getUuid().toString(), payload);
+    // properties.put("payloads", payloads);
+    //
+    // Entity e = testRequest(sm, ServiceAction.POST, 1, properties,
+    // path).getEntity();
+    // Thread.sleep(1000); // this sucks
+    // Notification notification = app.getEm().get(e, Notification.class);
+    // return notification;
+    // }
+    //
+    // @Test
+    // public void matrixPushDevice() throws Exception {
+    //
+    // Notification notification = postNotification("devices/" +
+    // device1.getName() + "/notifications");
+    // checkReceipts(notification, 1);
+    // checkStatistics(notification, 1, 0);
+    // }
+    //
+    // @Test
+    // public void matrixPushViaUser() throws Exception {
+    //
+    // Notification notification = postNotification("users/" + user1.getName() +
+    // "/notifications");
+    // checkReceipts(notification, 2);
+    // checkStatistics(notification, 2, 0);
+    // }
+    //
+    // @Test
+    // public void matrixPushViaGroup() throws Exception {
+    //
+    // Notification notification = postNotification("devices/" +
+    // device1.getName() + "/notifications");
+    // checkReceipts(notification, 2);
+    // checkStatistics(notification, 2, 0);
+    // }
+    //
+    // @Test
+    // public void matrixPushDeviceQuery() throws Exception {
+    //
+    // Notification notification = postNotification("devices;ql=name=" +
+    // device1.getName() + "/notifications");
+    // checkReceipts(notification, 1);
+    // checkStatistics(notification, 1, 0);
+    // }
+    //
+    // @Test
+    // public void matrixPushUserQuery() throws Exception {
+    //
+    // Notification notification = postNotification("users;ql=/notifications");
+    // checkReceipts(notification, 2);
+    // checkStatistics(notification, 2, 0);
+    // }
+}