/*
* #%L
* carewebframework
* %%
* Copyright (C) 2008 - 2016 Regenstrief Institute, Inc.
* %%
* 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.
*
* This Source Code Form is also subject to the terms of the Health-Related
* Additional Disclaimer of Warranty and Limitation of Liability available at
*
* http://www.carewebframework.org/licensing/disclaimer.
*
* #L%
*/
package org.carewebframework.api.test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.carewebframework.api.messaging.ConsumerService;
import org.carewebframework.api.messaging.IMessageConsumer.IMessageCallback;
import org.carewebframework.api.messaging.IMessageProducer;
import org.carewebframework.api.messaging.Message;
import org.carewebframework.api.messaging.ProducerService;
import org.junit.Test;
public class MessagingTest extends CommonTest {
private static final Log log = LogFactory.getLog(MessagingTest.class);
protected static int pollingInterval = 500;
private static final String CHANNEL1 = "channel1";
private static final String CHANNEL2 = "channel2";
private int messageCount;
private final List<Message> messages = Collections.synchronizedList(new ArrayList<>());
private AssertionError assertionError;
private ConsumerService consumerService;
private ProducerService producerService;
private final Class<? extends IMessageProducer> producerClass;
private final IMessageCallback callback = new IMessageCallback() {
@Override
public void onMessage(String channel, Message message) {
try {
log.info("Received on channel " + channel + ": " + message);
assertTrue(" : unexpected message", messages.remove(message));
} catch (AssertionError e) {
if (assertionError == null) {
assertionError = e;
}
}
}
};
public MessagingTest(Class<? extends IMessageProducer> producerClass) {
this.producerClass = producerClass;
}
public MessagingTest() {
this(null);
}
@Test
public void testMessaging() {
publishMessages();
}
private void publishMessages() {
publish(CHANNEL1, false);
publish(CHANNEL2, false);
subscribe(CHANNEL1, true);
publish(CHANNEL1, true);
publish(CHANNEL2, false);
subscribe(CHANNEL1, false);
publish(CHANNEL1, false);
publish(CHANNEL2, false);
subscribe(CHANNEL2, true);
publish(CHANNEL1, false);
publish(CHANNEL2, true);
subscribe(CHANNEL1, true);
subscribe(CHANNEL2, false);
publish(CHANNEL1, true);
publish(CHANNEL2, false);
subscribe(CHANNEL1, false);
publish(CHANNEL1, false);
publish(CHANNEL2, false);
doWait(30);
}
private void checkAssertion() {
if (assertionError != null) {
throw assertionError;
}
}
private void subscribe(String channel, boolean subscribe) {
doWait(30); // Wait for delivery of outstanding messages.
if (subscribe) {
getConsumerService().subscribe(channel, callback);
} else {
getConsumerService().unsubscribe(channel, callback);
}
}
/**
* Publish a message.
*
* @param channel The channel on which to publish.
* @param shouldReceive Indicates whether or not the message should be received.
*/
private void publish(String channel, boolean shouldReceive) {
Message message = new Message("test", "Test Message");
message.setMetadata("count", ++messageCount);
if (shouldReceive) {
messages.add(message);
}
log.info("Sending: " + message);
if (producerClass != null) {
getProducerService().publish(channel, message, producerClass);
} else {
getProducerService().publish(channel, message);
}
}
private void doWait(int count) {
checkAssertion();
while (count-- > 0 && !messages.isEmpty()) {
try {
Thread.sleep(pollingInterval);
} catch (InterruptedException e) {
continue;
}
}
if (!messages.isEmpty()) {
undeliveredMessages();
}
}
/**
* Verify all undelivered messages.
*/
private void undeliveredMessages() {
StringBuilder sb = new StringBuilder();
while (!messages.isEmpty()) {
Message message = messages.remove(0);
sb.append(message + ": was not received.\n");
}
assertFalse(sb.toString(), sb.length() > 0);
}
private ConsumerService getConsumerService() {
return consumerService == null ? consumerService = (ConsumerService) appContext.getBean("messageConsumerService")
: consumerService;
}
private ProducerService getProducerService() {
return producerService == null ? producerService = (ProducerService) appContext.getBean("messageProducerService")
: producerService;
}
}