001/**
002 * Copyright 2005-2014 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.ken.services.impl;
017
018import org.apache.commons.io.IOUtils;
019import org.junit.Test;
020import org.kuali.rice.core.api.criteria.QueryByCriteria;
021import org.kuali.rice.core.api.util.xml.XmlException;
022import org.kuali.rice.ken.bo.NotificationBo;
023import org.kuali.rice.ken.bo.NotificationMessageDelivery;
024import org.kuali.rice.ken.bo.NotificationResponseBo;
025import org.kuali.rice.ken.service.NotificationMessageDeliveryService;
026import org.kuali.rice.ken.service.NotificationService;
027import org.kuali.rice.ken.service.ProcessingResult;
028import org.kuali.rice.ken.test.KENTestCase;
029import org.kuali.rice.ken.test.TestConstants;
030import org.kuali.rice.ken.util.NotificationConstants;
031import org.kuali.rice.kew.actionrequest.ActionRequestValue;
032import org.kuali.rice.kew.doctype.bo.DocumentType;
033import org.kuali.rice.kew.service.KEWServiceLocator;
034import org.kuali.rice.krad.service.KRADServiceLocator;
035import org.kuali.rice.test.BaselineTestCase;
036import org.quartz.SchedulerException;
037
038import java.io.IOException;
039import java.util.Collection;
040import java.util.List;
041
042import static org.junit.Assert.*;
043
044import static org.kuali.rice.core.api.criteria.PredicateFactory.equal;
045
046
047/**
048 * This class tests the notification service impl.
049 * @author Kuali Rice Team (rice.collab@kuali.org)
050 */
051// this whole test case is suspect
052@BaselineTestCase.BaselineMode(BaselineTestCase.Mode.CLEAR_DB)
053public class NotificationServiceImplTest extends KENTestCase {
054
055    public NotificationServiceImplTest() {
056    }
057
058    @Test
059    public void testGetNotification_validNotification() {
060        NotificationService nSvc = services.getNotificationService();
061
062        NotificationBo notification = nSvc.getNotification(TestConstants.NOTIFICATION_1);
063
064        assertNotNull(notification.getContent());
065        assertTrue(notification.getDeliveryType().equals(TestConstants.NOTIFICATION_1_DELIVERY_TYPE));
066    }
067
068    @Test
069    public void testGetNotification_nonExistentNotification() {
070        NotificationService nSvc = services.getNotificationService();
071
072        NotificationBo notification = nSvc.getNotification(TestConstants.NON_EXISTENT_ID);
073
074        assertNull(notification);
075    }
076
077    @Test
078    public void testGetNotificationsForRecipientByType_validInput() {
079        NotificationService nSvc = services.getNotificationService();
080
081        assertTrue(nSvc.getNotificationsForRecipientByType(TestConstants.NOTIFICATION_RECIPIENT_CONTENT_TYPE, TestConstants.NOTIFICATION_RECIPIENT_ID).size() > 0);
082    }
083
084    @Test
085    public void testGetNotificationsForRecipientByType_invalidInput() {
086        NotificationService nSvc = services.getNotificationService();
087
088        assertTrue(nSvc.getNotificationsForRecipientByType(TestConstants.INVALID_CONTENT_TYPE, TestConstants.NOTIFICATION_RECIPIENT_ID).size() == 0);
089    }
090
091    @Test
092    // deadlocks
093    public void testSendNotificationAsXml_validInput() throws InterruptedException, SchedulerException, IOException, XmlException  {
094        services.getNotificationMessageDeliveryResolverService().resolveNotificationMessageDeliveries();
095        
096        Thread.sleep(10000);
097        services.getNotificationMessageDeliveryAutoRemovalService().processAutoRemovalOfDeliveredNotificationMessageDeliveries();
098
099        // get the count of pending action requests
100        DocumentType docType = KEWServiceLocator.getDocumentTypeService().findByName("KualiNotification");
101        List<ActionRequestValue> list = KEWServiceLocator.getActionRequestService().findPendingRootRequestsByDocumentType(docType.getDocumentTypeId());
102        int count_before = list.size();
103        LOG.info("ActionRequests: " + count_before);
104        for (ActionRequestValue v: list) {
105            LOG.info("Root request: " + v.getActionRequested() + " " + v.getPrincipalId() + " " + v.getStatus() + " " + v.getRoleName());
106        }
107
108        // now send ours
109        final NotificationService nSvc = services.getNotificationService();
110
111        final String notificationMessageAsXml = IOUtils.toString(getClass().getResourceAsStream("valid_input.xml"));
112
113        QueryByCriteria.Builder criteria = QueryByCriteria.Builder.create();
114        criteria.setPredicates(equal(NotificationConstants.BO_PROPERTY_NAMES.PROCESSING_FLAG,
115                NotificationConstants.PROCESSING_FLAGS.UNRESOLVED));
116
117        Collection<NotificationBo> notifications = KRADServiceLocator.getDataObjectService().findMatching(
118                NotificationBo.class, criteria.build()).getResults();
119        assertEquals(0, notifications.size());
120        final String[] result = new String[1];
121
122        NotificationResponseBo response = nSvc.sendNotification(notificationMessageAsXml);
123
124        LOG.info("response XML: " + response);
125        assertEquals(NotificationConstants.RESPONSE_STATUSES.SUCCESS, response.getStatus());
126        notifications = KRADServiceLocator.getDataObjectService().findMatching(NotificationBo.class, criteria.build())
127                .getResults();
128        assertEquals(1, notifications.size());
129        LOG.info("Notification: " + notifications.iterator().next());
130
131        services.getNotificationMessageDeliveryResolverService().resolveNotificationMessageDeliveries();
132        services.getNotificationMessageDeliveryAutoRemovalService().processAutoRemovalOfDeliveredNotificationMessageDeliveries();
133
134        list = KEWServiceLocator.getActionRequestService().findPendingRootRequestsByDocumentType(docType.getDocumentTypeId());
135        int count_after = list.size();
136        LOG.info("ActionRequests before: " + count_before);
137        LOG.info("ActionRequests after: " + count_after);
138        for (ActionRequestValue v: list) {
139            LOG.info("Root request: " + v.getActionRequested() + " " + v.getPrincipalId() + " " + v.getStatus() + " " + v.getRoleName());
140        }
141
142        // should have 6 requests, 1 to each user in in Rice Team group
143        assertEquals(6, count_after - count_before);
144    }
145
146    @Test
147    public void testSendNotificationAsXml_invalidInput() throws IOException {
148        NotificationService nSvc = services.getNotificationService();
149
150        final String notificationMessageAsXml = IOUtils.toString(getClass().getResourceAsStream("invalid_input.xml"));
151
152        try {
153            nSvc.sendNotification(notificationMessageAsXml);
154            fail("XmlException not thrown");
155        } catch (IOException ioe) {
156            fail("Wrong exception thrown, expected XmlException: " + ioe);
157        } catch (XmlException ixe) {
158            // expected
159        } catch (Exception e) {
160            fail("Wrong exception thrown, expected XmlException: " + e);
161        }
162
163    }
164
165    @Test
166    public void testSendNotificationAsXml_producerNotAuthorized() throws IOException, XmlException {
167        NotificationService nSvc = services.getNotificationService();
168
169        final String notificationMessageAsXml = IOUtils.toString(getClass().getResourceAsStream("producer_not_authorized.xml"));
170
171        NotificationResponseBo response = nSvc.sendNotification(notificationMessageAsXml);
172        assertEquals(NotificationConstants.RESPONSE_STATUSES.FAILURE, response.getStatus());
173        assertEquals(NotificationConstants.RESPONSE_MESSAGES.PRODUCER_NOT_AUTHORIZED_FOR_CHANNEL, response.getMessage());
174    }
175
176    /**
177     * Tests that dismissing a single message delivery for a given user, also removes all other message deliveries for that
178     * user that were generated for the same notification 
179     * @throws InterruptedException
180     */
181    @Test
182    public void testDismiss() throws InterruptedException {
183        // first check that the right amount of deliveries are present in the test data
184        NotificationBo n = services.getNotificationService().getNotification(TestConstants.NOTIFICATION_1);
185        NotificationMessageDeliveryService nmds = services.getNotificationMessageDeliveryService();
186        Collection<NotificationMessageDelivery> deliveries = nmds.getNotificationMessageDeliveries(n, TestConstants.TEST_USER_FIVE);
187        assertNotNull(deliveries);
188        assertEquals(TestConstants.NUM_OF_MSG_DELIVS_FOR_NOTIF_1_TEST_USER_5, deliveries.size());
189        // make sure they are not yet delivered
190        for (NotificationMessageDelivery delivery: deliveries) {
191            assertEquals(NotificationConstants.MESSAGE_DELIVERY_STATUS.UNDELIVERED, delivery.getMessageDeliveryStatus());
192        }
193
194        NotificationService nSvc = services.getNotificationService();
195
196        // go ahead and dispatch the message deliveries...
197        ProcessingResult result = services.getNotificationMessageDeliveryResolverService().resolveNotificationMessageDeliveries();
198
199        deliveries = nmds.getNotificationMessageDeliveries(n, TestConstants.TEST_USER_FIVE);
200        assertNotNull(deliveries);
201        assertEquals(TestConstants.NUM_OF_MSG_DELIVS_FOR_NOTIF_1_TEST_USER_5, deliveries.size());
202        // they should be delivered now
203        for (NotificationMessageDelivery delivery: deliveries) {
204            if (delivery.getId().equals(TestConstants.BAD_MESSAGE_DELIVERY_ID)) {
205                assertEquals("Message Delivery #" + delivery.getId() + "was not delivered", NotificationConstants.MESSAGE_DELIVERY_STATUS.DELIVERED, delivery.getMessageDeliveryStatus());
206            }
207        }
208
209        String action;
210        if (NotificationConstants.DELIVERY_TYPES.FYI.equals(TestConstants.NOTIFICATION_1_DELIVERY_TYPE)) {
211            action = "fyi";
212        } else if (NotificationConstants.DELIVERY_TYPES.ACK.equals(TestConstants.NOTIFICATION_1_DELIVERY_TYPE)) {
213            action = "ack";
214        } else {
215            throw new RuntimeException("A new delivery type was defined...this test needs to be updated");
216        }
217        nSvc.dismissNotificationMessageDelivery(TestConstants.NOT_MSG_DELIV_NOTIF_1_TEST_USER_5, TestConstants.TEST_USER_FIVE, action);
218
219        // after dismissing ONE message delivery, they should ALL be dismissed/removed
220        deliveries = nmds.getNotificationMessageDeliveries(n, TestConstants.TEST_USER_FIVE);
221        assertNotNull(deliveries);
222        assertEquals(TestConstants.NUM_OF_MSG_DELIVS_FOR_NOTIF_1_TEST_USER_5, deliveries.size());
223        for (NotificationMessageDelivery delivery: deliveries) {
224            if (delivery.getId() != TestConstants.BAD_MESSAGE_DELIVERY_ID) {
225                assertEquals("Message Delivery #" + delivery.getId() + "was not removed", NotificationConstants.MESSAGE_DELIVERY_STATUS.REMOVED, delivery.getMessageDeliveryStatus());
226            }
227        }
228
229    }
230
231}