/**
*
* Copyright 2004 Protique Ltd
*
* 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.codehaus.activemq.transport;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import junit.framework.TestCase;
import org.codehaus.activemq.io.WireFormat;
import org.codehaus.activemq.io.impl.DefaultWireFormat;
import org.codehaus.activemq.message.ActiveMQMessage;
import org.codehaus.activemq.message.KeepAlive;
import org.codehaus.activemq.message.Packet;
import org.codehaus.activemq.message.PacketListener;
import org.codehaus.activemq.message.Receipt;
import org.codehaus.activemq.message.ReceiptHolder;
import org.codehaus.activemq.util.IdGenerator;
import EDU.oswego.cs.dl.util.concurrent.Slot;
/**
* @version $Revision: 1.13 $
*/
public class TransportChannelTestSupport extends TestCase implements PacketListener, TransportChannelListener {
protected int TEST_SIZE = 100;
protected Object mutex;
protected TransportChannel sender;
protected TransportChannel receiver;
protected TransportServerChannel server;
protected ArrayList packets;
protected List exceptions = new Vector();
protected boolean sendReceipts = false;
private IdGenerator idGenerator = new IdGenerator();
protected WireFormat wireFormat = new DefaultWireFormat();
private boolean closeReceiver = true;
public TransportChannelTestSupport(String name) {
super(name);
}
/*
* test for Receipt send(Packet, int)
*/
public void testSendPacket() throws Exception {
System.out.println("Sending packets");
List tmpList = (List) packets.clone();
for (int i = 0; i < TEST_SIZE; i++) {
Packet packet = (Packet)tmpList.get(i);
sender.asyncSend(packet);
}
System.out.println("Sent: " + TEST_SIZE + " packets");
for (int i = 0; i < 10; i++) {
synchronized (mutex) {
if (!packets.isEmpty()) {
mutex.wait(500);
}
}
}
assertTrue("Packets not consumed, still have: " + packets.size() + " packet(s) unconsumed", packets.isEmpty());
assertTrue("Exceptions were thrown: " + exceptions, exceptions.size() == 0);
}
public void testAsyncSendWithReceipt() throws Exception {
sendReceipts = true;
Packet packet = new KeepAlive();
packet.setId((short)1);
ReceiptHolder rh = sender.asyncSendWithReceipt(packet);
Receipt result = rh.getReceipt(5000);
if (result == null) fail("Should have gotten receipt");
}
public void testRpc() throws Exception {
sendReceipts = true;
List tmpList = (List) packets.clone();
for (int i = 0; i < TEST_SIZE; i++) {
Packet packet = (Packet) tmpList.get(i);
Receipt receipt = sender.send(packet, 4000);
assertTrue("Receipt should not be null!", receipt != null);
System.out.println("Got receipt: " + receipt + " for packet: " + packet);
}
}
public void testForceDisconnect() throws Exception {
// Exceptions following the disconnect are allowed to be either hidden
// (e.g by a reliable transport) or shown to the client. Accept either
// and swallow
// any exceptions throws by this particular test
sender.setExceptionListener(new ExceptionListener() {
public void onException(JMSException arg0) {
;
}
});
if (receiver != null) {
receiver.setExceptionListener(new ExceptionListener() {
public void onException(JMSException e) {
}
});
}
// Send some data down the channel.
testAsyncSendWithReceipt();
// Test disconnect. This will be fatal for most channels, but reliable
// channels
// should be able to recover from it. In any case transportConnected
// should be false
// immediately after the disconnect
final Slot disconnectEvent = new Slot();
sender.addTransportStatusEventListener(new TransportStatusEventListener() {
public void statusChanged(TransportStatusEvent e) {
if( e.getChannelStatus() == TransportStatusEvent.DISCONNECTED ) {
try {
disconnectEvent.offer(e, 1000);
} catch (InterruptedException e1) {
}
}
}
});
sender.forceDisconnect();
assertNotNull("Should have received state change notification", disconnectEvent.poll(1000*30));
assertFalse("Should be disconnected", sender.isTransportConnected());
//there could ber exceptions thrown - which are valid for a force disconnect
//so clear them so tearDown() will pass
exceptions.clear();
}
public void consume(Packet packet) {
System.out.println("Received packet: " + packet);
if (sendReceipts) {
// lets send a receipt
Receipt receipt = new Receipt();
receipt.setId(idGenerator.getNextShortSequence());
receipt.setCorrelationId(packet.getId());
try {
receiver.asyncSend(receipt);
} catch (JMSException e) {
logMessage("Sending receipt: " + receipt + " for packet: " + packet, e);
}
} else {
packets.remove(packet);
if (packets.isEmpty()) {
synchronized (mutex) {
mutex.notify();
}
}
}
}
/**
* Assume that sender and receiver are created before we're invoked
*/
protected void setUp() throws Exception {
super.setUp();
assertTrue("sender must be constructed in the TestCase before setUp() is invoked", sender != null);
assertTrue("receiver or server must be constructed in the TestCase before setUp() is invoked", receiver != null
|| server != null);
mutex = new Object();
sender.setExceptionListener(new ExceptionListener() {
public void onException(JMSException ex) {
String message = "Sender got an exception:";
logMessage(message, ex);
}
});
sender.setPacketListener(new PacketListener() {
public void consume(Packet packet) {
System.err.println("Error - sender received a packet: " + packet);
exceptions.add(packet);
}
});
sender.setClientID("sender");
sender.start();
packets = new ArrayList(TEST_SIZE);
for (int i = 0; i < TEST_SIZE; i++) {
ActiveMQMessage test = new ActiveMQMessage();
test.setJMSMessageID("test:"+i);
test.setExternalMessageId(true);
packets.add(test);
}
}
protected void tearDown() throws Exception {
//getting exceptions when peers stop is acceptable
if (receiver != null)
receiver.setExceptionListener(null);
super.tearDown();
System.out.println("Stopping sender");
sender.stop();
if (receiver == null) {
System.out.println("No receiver created!");
} else {
if (closeReceiver) {
System.out.println("Stopping receiver");
//assertTrue("No receiver created!", receiver != null);
receiver.stop();
} else {
System.out.println("Receiver will be closed by the server");
}
}
if (server != null) {
System.out.println("Stopping server");
server.stop();
}
assertTrue("Exceptions were thrown: " + exceptions, exceptions.size() == 0);
}
protected void configureServer() throws JMSException {
if (server != null) {
server.setTransportChannelListener(this);
server.start();
System.out.println("Server has started");
// lets wait a little for the server to startup
/*
* try { Thread.sleep(500); } catch (InterruptedException e) {
* System.out.println("Caught: " + e); e.printStackTrace(); }
*/
}
}
protected void configureReceiver() {
receiver.setPacketListener(this);
receiver.setExceptionListener(new ExceptionListener() {
public void onException(JMSException ex) {
logMessage("Receiver got an exception:", ex);
}
});
receiver.setClientID("receiver");
try {
receiver.start();
} catch (JMSException e) {
logMessage("Failure starting receiver: ", e);
}
System.out.println("Receiver has started");
}
protected void createSenderAndReceiver(String string) throws URISyntaxException, JMSException {
URI uri = new URI(string);
sender = TransportChannelProvider.create(wireFormat, uri);
receiver = TransportChannelProvider.create(wireFormat, uri);
if (receiver != null) {
configureReceiver();
}
}
protected void createSenderAndServer(String subject) throws URISyntaxException, JMSException {
URI uri = new URI(subject);
server = TransportServerChannelProvider.create(wireFormat, uri);
configureServer();
sender = TransportChannelProvider.create(wireFormat, uri);
}
protected void logMessage(String message, JMSException ex) {
System.err.println(message);
ex.printStackTrace();
Throwable t = ex.getLinkedException();
if (t != null && t != ex) {
System.out.println("Reason: " + t);
t.printStackTrace();
}
exceptions.add(ex);
}
public void addClient(TransportChannel channel) {
this.receiver = channel;
this.closeReceiver = false;
System.out.println("addClient() with receiver: " + receiver);
assertTrue("Should have received a receiver by now", receiver != null);
configureReceiver();
}
public void removeClient(TransportChannel channel) {
}
}