/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <hr>
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* This file has been modified by the OpenOLAT community. Changes are licensed
* under the Apache 2.0 license as the original file.
* <p>
*/
package org.olat.core.commons.services.notifications.manager;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.junit.Assert;
import org.junit.Test;
import org.olat.core.commons.persistence.DB;
import org.olat.core.commons.services.notifications.NotificationsManager;
import org.olat.core.commons.services.notifications.Publisher;
import org.olat.core.commons.services.notifications.PublisherData;
import org.olat.core.commons.services.notifications.Subscriber;
import org.olat.core.commons.services.notifications.SubscriptionContext;
import org.olat.core.commons.services.notifications.SubscriptionInfo;
import org.olat.core.commons.services.notifications.manager.NotificationsManagerImpl;
import org.olat.core.id.Identity;
import org.olat.core.logging.DBRuntimeException;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.test.JunitTestHelper;
import org.olat.test.OlatTestCase;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Initial Date: Dec 9, 2004
*
* @author Felix Jost
*
* Comment:
*
*/
public class NotificationsManagerTest extends OlatTestCase {
private static OLog log = Tracing.createLoggerFor(NotificationsManagerTest.class);
@Autowired
private NotificationsManager notificationManager;
@Autowired
private DB dbInstance;
@Test
public void getUserIntervalOrDefault() {
String defInterval = notificationManager.getDefaultNotificationInterval();
Assert.assertNotNull(defInterval);
Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("subs-1");
dbInstance.commitAndCloseSession();
String checkId = notificationManager.getUserIntervalOrDefault(id);
Assert.assertNotNull(checkId);
String nullInterval = notificationManager.getUserIntervalOrDefault(null);
Assert.assertNotNull(nullInterval);
Assert.assertEquals(defInterval, nullInterval);
}
@Test
public void testCreatePublisher() {
String identifier = UUID.randomUUID().toString().replace("-", "");
SubscriptionContext context = new SubscriptionContext("PS", new Long(123), identifier);
PublisherData publisherData = new PublisherData("testPublisherSubscriber", "e.g. forumdata=keyofforum", null);
Publisher publisher = notificationManager.getOrCreatePublisher(context, publisherData);
dbInstance.commitAndCloseSession();
//check values
Assert.assertNotNull(publisher);
Assert.assertNotNull(publisher.getKey());
Assert.assertNotNull(publisher.getCreationDate());
Assert.assertNotNull(publisher.getLatestNewsDate());
Assert.assertEquals("PS", publisher.getResName());
Assert.assertEquals(new Long(123), publisher.getResId());
Assert.assertEquals(identifier, publisher.getSubidentifier());
//check if exists
Publisher reloadedPublisher = notificationManager.getPublisher(context);
Assert.assertNotNull(reloadedPublisher);
Assert.assertEquals(publisher, reloadedPublisher);
}
@Test
public void testCreateUpdatePublisher() {
String identifier = UUID.randomUUID().toString().replace("-", "");
SubscriptionContext context = new SubscriptionContext("PS2", new Long(124), identifier);
PublisherData publisherData = new PublisherData("testPublisherSubscriber", "e.g. forumdata=keyofforum", null);
Publisher publisher = notificationManager.getOrCreatePublisher(context, publisherData);
dbInstance.commitAndCloseSession();
//check values
Assert.assertNotNull(publisher);
Assert.assertNotNull(publisher.getKey());
Assert.assertNotNull(publisher.getCreationDate());
Assert.assertNotNull(publisher.getLatestNewsDate());
Assert.assertEquals("PS2", publisher.getResName());
Assert.assertEquals(new Long(124), publisher.getResId());
sleep(2000);
//update the publisher
notificationManager.markPublisherNews(context, null, false);
//check if exists and last news date is updated
Publisher reloadedPublisher = notificationManager.getPublisher(context);
Assert.assertNotNull(reloadedPublisher);
Assert.assertEquals(publisher, reloadedPublisher);
Assert.assertTrue(publisher.getLatestNewsDate().before(reloadedPublisher.getLatestNewsDate()));
}
@Test
public void testAllPublishers() {
String identifier = UUID.randomUUID().toString().replace("-", "");
SubscriptionContext context = new SubscriptionContext("All", new Long(123), identifier);
PublisherData publisherData = new PublisherData("testAllPublishers", "e.g. forumdata=keyofforum", null);
Publisher publisher = notificationManager.getOrCreatePublisher(context, publisherData);
dbInstance.commitAndCloseSession();
Assert.assertNotNull(publisher);
List<Publisher> publishers = notificationManager.getAllPublisher();
Assert.assertNotNull(publishers);
Assert.assertTrue(publishers.contains(publisher));
}
@Test
public void testSubscribe() {
Identity id = JunitTestHelper.createAndPersistIdentityAsUser("subs-" + UUID.randomUUID().toString());
//create a publisher
String identifier = UUID.randomUUID().toString().replace("-", "");
SubscriptionContext context = new SubscriptionContext("All", new Long(123), identifier);
PublisherData publisherData = new PublisherData("testAllPublishers", "e.g. forumdata=keyofforum", null);
Publisher publisher = notificationManager.getOrCreatePublisher(context, publisherData);
dbInstance.commitAndCloseSession();
Assert.assertNotNull(publisher);
//subscribe
notificationManager.subscribe(id, context, publisherData);
dbInstance.commitAndCloseSession();
//check
boolean subscribed = notificationManager.isSubscribed(id, context);
Assert.assertTrue(subscribed);
dbInstance.commitAndCloseSession();
//double check
Subscriber subscriber = notificationManager.getSubscriber(id, publisher);
Assert.assertNotNull(subscriber);
Assert.assertEquals(publisher, subscriber.getPublisher());
dbInstance.commitAndCloseSession();
//triple check
Subscriber reloadedSubscriber = notificationManager.getSubscriber(subscriber.getKey());
Assert.assertNotNull(reloadedSubscriber);
Assert.assertEquals(subscriber, reloadedSubscriber);
}
@Test
public void testMarkSubscriberRead() {
Identity id = JunitTestHelper.createAndPersistIdentityAsUser("subs-" + UUID.randomUUID().toString());
//create a publisher
String identifier = UUID.randomUUID().toString().replace("-", "");
SubscriptionContext context = new SubscriptionContext("All", new Long(123), identifier);
PublisherData publisherData = new PublisherData("testAllPublishers", "e.g. forumdata=keyofforum", null);
Publisher publisher = notificationManager.getOrCreatePublisher(context, publisherData);
dbInstance.commit();
Assert.assertNotNull(publisher);
//subscribe
notificationManager.subscribe(id, context, publisherData);
dbInstance.commit();
//load the subscriber
Subscriber subscriber = notificationManager.getSubscriber(id, publisher);
Assert.assertNotNull(subscriber);
dbInstance.commitAndCloseSession();
sleep(2000);
notificationManager.markSubscriberRead(id, context);
//check the last modification date
Subscriber reloadedSubscriber = notificationManager.getSubscriber(subscriber.getKey());
Assert.assertNotNull(reloadedSubscriber);
Assert.assertEquals(subscriber, reloadedSubscriber);
Assert.assertTrue(subscriber.getLastModified().before(reloadedSubscriber.getLastModified()));
}
@Test
public void testUnsubscribe_v1() {
Identity id = JunitTestHelper.createAndPersistIdentityAsUser("unsubs-" + UUID.randomUUID().toString());
//create a publisher
String identifier = UUID.randomUUID().toString().replace("-", "");
SubscriptionContext context = new SubscriptionContext("All", new Long(123), identifier);
PublisherData publisherData = new PublisherData("testUnsubscribe", "e.g. forumdata=keyofforum", null);
Publisher publisher = notificationManager.getOrCreatePublisher(context, publisherData);
dbInstance.commitAndCloseSession();
Assert.assertNotNull(publisher);
//subscribe
notificationManager.subscribe(id, context, publisherData);
dbInstance.commitAndCloseSession();
//check
Subscriber subscriber = notificationManager.getSubscriber(id, publisher);
Assert.assertNotNull(subscriber);
//unsubscribe
notificationManager.unsubscribe(subscriber);
dbInstance.commitAndCloseSession();
//check
boolean subscribed = notificationManager.isSubscribed(id, context);
Assert.assertFalse(subscribed);
}
@Test
public void testUnsubscribe_v2() {
Identity id = JunitTestHelper.createAndPersistIdentityAsUser("unsubs-" + UUID.randomUUID().toString());
//create a publisher
String identifier = UUID.randomUUID().toString().replace("-", "");
SubscriptionContext context = new SubscriptionContext("All", new Long(123), identifier);
PublisherData publisherData = new PublisherData("testUnsubscribe", "e.g. forumdata=keyofforum", null);
Publisher publisher = notificationManager.getOrCreatePublisher(context, publisherData);
dbInstance.commitAndCloseSession();
Assert.assertNotNull(publisher);
//subscribe
notificationManager.subscribe(id, context, publisherData);
dbInstance.commitAndCloseSession();
//check
Subscriber subscriber = notificationManager.getSubscriber(id, publisher);
Assert.assertNotNull(subscriber);
//unsubscribe
notificationManager.unsubscribe(id, context);
dbInstance.commitAndCloseSession();
//check
boolean subscribed = notificationManager.isSubscribed(id, context);
Assert.assertFalse(subscribed);
}
@Test
public void testValidSubscribers() {
Identity id1 = JunitTestHelper.createAndPersistIdentityAsUser("valid1-" + UUID.randomUUID().toString());
Identity id2 = JunitTestHelper.createAndPersistIdentityAsUser("valid1-" + UUID.randomUUID().toString());
//create a publisher
String identifier = UUID.randomUUID().toString().replace("-", "");
SubscriptionContext context = new SubscriptionContext("Valid", new Long(123), identifier);
PublisherData publisherData = new PublisherData("testValidSubscribers", "e.g. forumdata=keyofforum", null);
Publisher publisher = notificationManager.getOrCreatePublisher(context, publisherData);
dbInstance.commitAndCloseSession();
Assert.assertNotNull(publisher);
//add subscribers
notificationManager.subscribe(id1, context, publisherData);
notificationManager.subscribe(id2, context, publisherData);
dbInstance.commitAndCloseSession();
//get valid subscribers
List<Subscriber> subscribers = notificationManager.getValidSubscribers(id1);
Assert.assertNotNull(subscribers);
Assert.assertEquals(1, subscribers.size());
Assert.assertEquals(publisher, subscribers.get(0).getPublisher());
Assert.assertEquals(id1, subscribers.get(0).getIdentity());
}
@Test
public void testValidSubscribersOf() {
Identity id1 = JunitTestHelper.createAndPersistIdentityAsUser("valid1b-" + UUID.randomUUID().toString());
Identity id2 = JunitTestHelper.createAndPersistIdentityAsUser("valid1b-" + UUID.randomUUID().toString());
//create a publisher
String identifier = UUID.randomUUID().toString().replace("-", "");
SubscriptionContext context = new SubscriptionContext("Validb", new Long(123), identifier);
PublisherData publisherData = new PublisherData("testValidSubscribers", "e.g. forumdata=keyofforum", null);
Publisher publisher = notificationManager.getOrCreatePublisher(context, publisherData);
dbInstance.commitAndCloseSession();
Assert.assertNotNull(publisher);
//add subscribers
notificationManager.subscribe(id1, context, publisherData);
notificationManager.subscribe(id2, context, publisherData);
dbInstance.commitAndCloseSession();
//get all subscribers of the publisher
List<Subscriber> subscribers = notificationManager.getValidSubscribersOf(publisher);
Assert.assertNotNull(subscribers);
Assert.assertEquals(2, subscribers.size());
Assert.assertEquals(publisher, subscribers.get(0).getPublisher());
Assert.assertEquals(publisher, subscribers.get(1).getPublisher());
}
@Test
public void testGetSubscriberIdentities() {
Identity id1 = JunitTestHelper.createAndPersistIdentityAsUser("valid1b-" + UUID.randomUUID().toString());
Identity id2 = JunitTestHelper.createAndPersistIdentityAsUser("valid1b-" + UUID.randomUUID().toString());
//create a publisher
String identifier = UUID.randomUUID().toString().replace("-", "");
SubscriptionContext context = new SubscriptionContext("Subscribers", new Long(123), identifier);
PublisherData publisherData = new PublisherData("testGetSubscriberIdentities", "e.g. forumdata=keyofforum", null);
Publisher publisher = notificationManager.getOrCreatePublisher(context, publisherData);
dbInstance.commitAndCloseSession();
//add subscribers
notificationManager.subscribe(id1, context, publisherData);
notificationManager.subscribe(id2, context, publisherData);
dbInstance.commitAndCloseSession();
//get identities
List<Identity> identities = notificationManager.getSubscriberIdentities(publisher);
Assert.assertNotNull(identities);
Assert.assertEquals(2, identities.size());
Assert.assertTrue(identities.contains(id1));
Assert.assertTrue(identities.contains(id2));
}
@Test
public void testGetSubscribersByTypes() {
Identity id = JunitTestHelper.createAndPersistIdentityAsUser("type1-" + UUID.randomUUID().toString());
//create a first publisher
String identifier = UUID.randomUUID().toString().replace("-", "");
SubscriptionContext context1 = new SubscriptionContext("Subscribers", new Long(123), identifier);
PublisherData publisherData1 = new PublisherData("testGetSubscribersByType1", "e.g. forumdata=keyofforum", null);
Publisher publisher1 = notificationManager.getOrCreatePublisher(context1, publisherData1);
dbInstance.commitAndCloseSession();
String identifier2 = UUID.randomUUID().toString().replace("-", "");
SubscriptionContext context2 = new SubscriptionContext("Subscribers", new Long(123), identifier2);
PublisherData publisherData2 = new PublisherData("testGetSubscribersByType2", "e.g. forumdata=keyofforum", null);
Publisher publisher2 = notificationManager.getOrCreatePublisher(context2, publisherData2);
dbInstance.commitAndCloseSession();
//add subscribers
notificationManager.subscribe(id, context1, publisherData1);
notificationManager.subscribe(id, context2, publisherData2);
dbInstance.commitAndCloseSession();
//get subscribers without types
List<Subscriber> emptySubscribers = notificationManager.getSubscribers(id, null);
Assert.assertNotNull(emptySubscribers);
Assert.assertEquals(2, emptySubscribers.size());
//get subscribers with 1 type
List<String> types = Collections.singletonList(publisher1.getType());
List<Subscriber> typedSubscribers = notificationManager.getSubscribers(id, types);
Assert.assertNotNull(typedSubscribers);
Assert.assertEquals(1, typedSubscribers.size());
//get subscribers with 2 types
List<String> allTypes = new ArrayList<String>(2);
allTypes.add(publisher1.getType());
allTypes.add(publisher2.getType());
List<Subscriber> allSubscribers = notificationManager.getSubscribers(id, allTypes);
Assert.assertNotNull(allSubscribers);
Assert.assertEquals(2, allSubscribers.size());
}
//markPublisherNews
@Test
public void testGetSubscriptionInfos() {
Identity id = JunitTestHelper.createAndPersistIdentityAsUser("fi1-" + UUID.randomUUID().toString());
SubscriptionContext context = new SubscriptionContext("Course", new Long(789521), UUID.randomUUID().toString());
PublisherData publisherData = new PublisherData("Forum", "e.g. forumdata=keyofforum", null);
Publisher publisher = notificationManager.getOrCreatePublisher(context, publisherData);
dbInstance.commitAndCloseSession();
notificationManager.subscribe(id, context, publisherData);
dbInstance.commitAndCloseSession();
//get infos
List<SubscriptionInfo> infos = notificationManager.getSubscriptionInfos(id, publisher.getType());
Assert.assertNotNull(infos);
}
@Test
public void testSubscriptions() {
Identity id1 = JunitTestHelper.createAndPersistIdentityAsUser("fi1-" + UUID.randomUUID().toString());
Identity id2 = JunitTestHelper.createAndPersistIdentityAsUser("fi2-" + UUID.randomUUID().toString());
Identity id3 = JunitTestHelper.createAndPersistIdentityAsUser("fi3-" + UUID.randomUUID().toString());
SubscriptionContext sc = new SubscriptionContext("Course", new Long(123), UUID.randomUUID().toString());
PublisherData pd = new PublisherData("Forum", "e.g. forumdata=keyofforum", null);
SubscriptionContext sc2 = new SubscriptionContext("Course2", new Long(123), UUID.randomUUID().toString());
PublisherData pd2 = new PublisherData("Forum", "e.g. forumdata=keyofforum2", null);
dbInstance.closeSession();
notificationManager.subscribe(id1, sc, pd);
notificationManager.subscribe(id3, sc, pd);
notificationManager.subscribe(id2, sc2, pd2);
notificationManager.subscribe(id1, sc2, pd2);
dbInstance.closeSession();
Publisher p = notificationManager.getPublisher(sc);
assertNotNull(p);
assertEquals(p.getResName(), sc.getResName());
assertEquals(p.getResId(), sc.getResId());
assertEquals(p.getSubidentifier(), sc.getSubidentifier());
boolean isSub = notificationManager.isSubscribed(id1, sc);
assertTrue("subscribed::", isSub);
notificationManager.notifyAllSubscribersByEmail();
dbInstance.closeSession();
notificationManager.unsubscribe(id1, sc);
dbInstance.closeSession();
boolean isStillSub = notificationManager.isSubscribed(id1, sc);
assertFalse("subscribed::", isStillSub);
notificationManager.delete(sc);
dbInstance.commitAndCloseSession();
Publisher p2 = notificationManager.getPublisher(sc);
assertNull("publisher marked deleted should not be found", p2);
}
@Test(expected=DBRuntimeException.class)
public void testDuplicateSubscribers() throws Exception {
try {
PublisherData pd = new PublisherData("CreateSubscriber@2x", "e.g. forumdata=keyofforum", null);
SubscriptionContext sc = new SubscriptionContext("Course", new Long(1238778567), UUID.randomUUID().toString().replace("-", ""));
Identity id = JunitTestHelper.createAndPersistIdentityAsUser("fci@2x-" + UUID.randomUUID().toString());
Publisher publisher = notificationManager.getOrCreatePublisher(sc, pd);
dbInstance.commit();
((NotificationsManagerImpl)notificationManager).doCreateAndPersistSubscriber(publisher, id);
dbInstance.commit();
((NotificationsManagerImpl)notificationManager).doCreateAndPersistSubscriber(publisher, id);
dbInstance.commit();
} catch (Exception e) {
dbInstance.rollback();
throw e;
}
}
/**
* Test creation of concurrent subscriber
*/
@Test
public void testConcurrentCreateSubscriberWithOneIdentity() {
final int NUM_OF_THREADS = 100;
PublisherData pd = new PublisherData("CreateSubscriber", "e.g. forumdata=keyofforum", null);
SubscriptionContext sc = new SubscriptionContext("Course", new Long(1238778566), UUID.randomUUID().toString().replace("-", ""));
Identity id = JunitTestHelper.createAndPersistIdentityAsUser("fci-" + UUID.randomUUID().toString());
final CountDownLatch finishCount = new CountDownLatch(NUM_OF_THREADS);
List<Exception> exceptionHolder = Collections.synchronizedList(new ArrayList<Exception>(1));
List<Boolean> statusList = Collections.synchronizedList(new ArrayList<Boolean>(1));
List<SubscribeThread> threads = new ArrayList<SubscribeThread>();
for(int i=0; i<NUM_OF_THREADS; i++) {
SubscribeThread thread = new SubscribeThread(sc, pd, id, exceptionHolder, statusList, finishCount);
threads.add(thread);
}
for(SubscribeThread thread:threads) {
thread.start();
}
// sleep until threads should have terminated/excepted
try {
finishCount.await(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
log.error("", e);
}
for(Exception e:exceptionHolder) {
log.error("Excpetion during concurrent subscription: ", e);
}
assertTrue("It throws an exception in test", exceptionHolder.isEmpty());
assertEquals("Thread(s) did not finish", NUM_OF_THREADS, statusList.size());
assertTrue("Subscriber does not exists", NotificationsManager.getInstance().isSubscribed(id, sc));
}
/**
* Test creation of concurrent subscriber
*/
@Test
public void testConcurrentSubscriberOperationsWithOneIdentity() {
final int NUM_OF_THREADS = 100;
PublisherData pd = new PublisherData("MPSubscriber", "e.g. forumdata=keyofforum", null);
SubscriptionContext sc = new SubscriptionContext("MPSubscriber", new Long(1238778566), UUID.randomUUID().toString().replace("-", ""));
Identity id = JunitTestHelper.createAndPersistIdentityAsUser("fci-" + UUID.randomUUID().toString());
final CountDownLatch finishCount = new CountDownLatch(NUM_OF_THREADS);
List<Exception> exceptionHolder = Collections.synchronizedList(new ArrayList<Exception>(1));
List<Boolean> statusList = Collections.synchronizedList(new ArrayList<Boolean>(1));
List<MPSubscriberThread> threads = new ArrayList<MPSubscriberThread>();
for(int i=0; i<NUM_OF_THREADS; i++) {
MPSubscriberThread thread = new MPSubscriberThread(sc, pd, id, exceptionHolder, statusList, finishCount);
threads.add(thread);
}
for(MPSubscriberThread thread:threads) {
thread.start();
}
// sleep until threads should have terminated/excepted
try {
finishCount.await(120, TimeUnit.SECONDS);
} catch (InterruptedException e) {
log.error("", e);
Assert.fail();
}
for(Exception e:exceptionHolder) {
log.error("Excpetion during concurrent subscription: ", e);
}
assertTrue("It throws an exception in test", exceptionHolder.isEmpty());
assertEquals("Thread(s) did not finish", NUM_OF_THREADS, statusList.size());
assertTrue("Subscriber does not exists", NotificationsManager.getInstance().isSubscribed(id, sc));
}
private class MPSubscriberThread extends Thread {
private final SubscriptionContext sc;
private final PublisherData pd;
private final Identity id;
private final List<Exception> exceptionHolder;
private final List<Boolean> statusList;
private final CountDownLatch countDown;
public MPSubscriberThread(SubscriptionContext sc, PublisherData pd, Identity id,
List<Exception> exceptionHolder, List<Boolean> statusList, CountDownLatch countDown) {
this.sc = sc;
this.pd = pd;
this.id = id;
this.exceptionHolder = exceptionHolder;
this.statusList = statusList;
this.countDown = countDown;
}
@Override
public void run() {
try {
Thread.sleep(10);
for(int i=5; i-->0; ) {
//subscribe
notificationManager.subscribe(id, sc, pd);
//mark as read
notificationManager.markSubscriberRead(id, sc);
//update email date
Publisher publisher = notificationManager.getPublisher(sc);
Subscriber subscriber = notificationManager.getSubscriber(id, publisher);
List<Subscriber> subscribersToUpdate = Collections.singletonList(subscriber);
((NotificationsManagerImpl)notificationManager).updateSubscriberLatestEmail(subscribersToUpdate);
dbInstance.closeSession();
}
statusList.add(Boolean.TRUE);
} catch (Exception ex) {
exceptionHolder.add(ex);// no exception should happen
} finally {
countDown.countDown();
dbInstance.closeSession();
}
}
}
/**
* Test synchronized 'findOrCreatePublisher' triggered by method 'subscribe'.
* Start 10 threads which call 'subscribe' with same SubscriptionContext.
*/
@Test
public void testConcurrentFindOrCreatePublisher() {
final int NUM_OF_THREADS = 10;
PublisherData pd = new PublisherData("Forum", "e.g. forumdata=keyofforum", null );
SubscriptionContext sc = new SubscriptionContext("Course", new Long(1238778565), UUID.randomUUID().toString().replace("-", ""));
final CountDownLatch finishCount = new CountDownLatch(NUM_OF_THREADS);
List<Exception> exceptionHolder = Collections.synchronizedList(new ArrayList<Exception>(1));
List<Boolean> statusList = Collections.synchronizedList(new ArrayList<Boolean>(1));
List<SubscribeThread> threads = new ArrayList<SubscribeThread>();
for(int i=0; i<NUM_OF_THREADS; i++) {
Identity id = JunitTestHelper.createAndPersistIdentityAsUser("fci-" + i + "-" + UUID.randomUUID().toString());
SubscribeThread thread = new SubscribeThread(sc, pd, id, exceptionHolder, statusList, finishCount);
threads.add(thread);
}
for(SubscribeThread thread:threads) {
thread.start();
}
// sleep until threads should have terminated/excepted
try {
finishCount.await(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
log.error("", e);
Assert.fail();
}
assertTrue("It throws an exception in test", exceptionHolder.isEmpty());
assertEquals("Thread(s) did not finish", NUM_OF_THREADS, statusList.size());
for(SubscribeThread thread:threads) {
assertTrue("Subscriber does not exists", NotificationsManager.getInstance().isSubscribed(thread.getIdentity(), sc));
}
}
private class SubscribeThread extends Thread {
private final SubscriptionContext sc;
private final PublisherData pd;
private final Identity id;
private final List<Exception> exceptionHolder;
private final List<Boolean> statusList;
private final CountDownLatch countDown;
public SubscribeThread(SubscriptionContext sc, PublisherData pd, Identity id,
List<Exception> exceptionHolder, List<Boolean> statusList, CountDownLatch countDown) {
this.sc = sc;
this.pd = pd;
this.id = id;
this.exceptionHolder = exceptionHolder;
this.statusList = statusList;
this.countDown = countDown;
}
public Identity getIdentity() {
return id;
}
@Override
public void run() {
try {
Thread.sleep(10);
for(int i=5; i-->0; ) {
notificationManager.subscribe(id, sc, pd);
dbInstance.closeSession();
}
statusList.add(Boolean.TRUE);
} catch (Exception ex) {
exceptionHolder.add(ex);// no exception should happen
} finally {
countDown.countDown();
dbInstance.closeSession();
}
}
}
}