package org.mortbay.cometd; import java.security.SecureRandom; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Queue; import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import junit.framework.TestCase; import org.cometd.Client; import org.cometd.DeliverListener; import org.cometd.Message; import org.cometd.MessageListener; import org.cometd.QueueListener; /** * @author athena * */ public class ClientImplTest extends TestCase { protected StandaloneClient _client; protected Message _message; protected void setUp() throws Exception { _client = new StandaloneClient(); _message = new MessageImpl(); } /* * QueueListener examples */ public void testDeleteWhenFullQueue() throws Exception { Message delete = m("delete", "a"); Message keep = m("keep", "b"); Message add = m("add", "c"); _client.setMaxQueue(2); _client.addListener(new DeleteWhenFullQueueListener()); _client.deliver(delete); _client.deliver(keep); _client.deliver(add); assertEquals(resultsList(keep,add), _client.takeMessages()); } public void testDiscardNewMessageQueue() throws Exception { Message keep1 = m("keep1", "a"); Message keep2 = m("keep2", "b"); Message discard = m("discard", "c"); _client.setMaxQueue(2); _client.addListener(new DiscardNewMessageQueueListener()); _client.deliver(keep1); _client.deliver(keep2); _client.deliver(discard); assertEquals(resultsList(keep1, keep2), _client.takeMessages()); } public void testModifyExistingMessagesQueue() throws Exception { Message keep = m("keep", "a"); Message delete = m("delete", "b"); Message add = m("add", "c"); _client.setMaxQueue(2); _client.addListener(new ModifyExistingMessagesQueueListener()); _client.deliver(keep); _client.deliver(delete); _client.deliver(add); assertEquals(resultsList(keep, add), _client.takeMessages()); } // TODO: improve this test? public void testTakeWhileQueueing() throws Exception { _client.setMaxQueue(2); _client.addListener(new DeleteWhenFullQueueListener()); Message[] m = new Message[5]; for (int i = 0; i < m.length; ++i) { m[i] = m(i + "", i+""); } (new Thread() { public void run() { while (true ) { _client.getQueue().poll(); try { Thread.sleep(100); } catch (Exception e) {} } } }).start(); for (Message message : m) { _client.deliver(message); } assertEquals(resultsList(m[m.length-2], m[m.length-1]),_client.takeMessages()); } public void testId() throws Exception { AbstractBayeux bayeux = new BayeuxStub(); //bayeux.setNodeId("nodeid"); _client = new StandaloneClient(bayeux); // TODO } public void testMessageListener() throws Exception { _message.put("key","value"); _client.addListener(new CheckMessageListener(_message)); _client.addListener(new CheckMessageListener(_message)); _client.deliver(_message); } public void testRemoveListener() throws Exception { // TODO } public void testDeliverListener() throws Exception { final boolean[] called = {false}; _client.addListener(new DeliverListener() { public void deliver(Client client, Queue<Message> queue) { called[0]=true; } }); Message ping = m("ping", "hello"); _client.deliver(ping); assertFalse(called[0]); _client.doDeliverListeners(); assertTrue(called[0]); } /* // TODO: make sure this works properly. I think there's a chance of a deadlock public void testTakeMessage() throws Exception { Message[] messages = { m("a", "apple"), m("b", "bapple"), m("c", "capple"), m("d", "dapple"), m("e", "eapple"), m("f", "fapple") }; final CountDownLatch todo = new CountDownLatch(messages.length); // temporary variable to avoid error with abstract lists not implementing remove List<Message> messageList = new ArrayList<Message>(); messageList.addAll(Arrays.asList(messages)); _client.returnMessages(messageList); final ClientImpl threadClient = _client; for(int i = 0; i < _client.getMessages(); ++i) { final int x = i; (new Thread() { public void run() { try { int sleep = 10; Thread.sleep(sleep); } catch (InterruptedException e) { e.printStackTrace(); } Message message = threadClient.takeMessage(); todo.countDown(); // System.out.print(todo.getCount() + " -- "); // System.out.println(x + " in thread client: " + message + "; "+threadClient.getMessages() + " left"); } }).start(); } todo.await(5, TimeUnit.SECONDS); } */ private Message m(String key, String value) { Message message = new MessageImpl(); message.put(key, value); return message; } private List<Message> resultsList(Message m1, Message m2) { return Arrays.asList(new Message[] {m1, m2}); } class StandaloneClient extends ClientImpl { public StandaloneClient() { super(new BayeuxStub(), "standalone"); } public StandaloneClient(AbstractBayeux bayeux) { super(bayeux, "standalone"); } /* * Warn for methods that require a proper Bayeux object */ @Override public void deliver(Client from, String toChannel, Object data, String id) { System.err.println("Method unsupported!"); } public void deliver(Message message) { doDelivery(null, message); } @Override public void remove(boolean timeout) { System.err.println("Method unsupported!"); } @Override public void setBrowserId(String id) { System.err.println("Method unsupported!"); } } /* * stub out and use to initialize a "standalone" client */ static class BayeuxStub extends AbstractBayeux { public BayeuxStub() { try { _random=SecureRandom.getInstance("SHA1PRNG"); } catch (Exception e) { _random=new Random(); } // lacks the context hashcode from AbstractBayeux#initialize() _random.setSeed(_random.nextLong()^hashCode()^Runtime.getRuntime().freeMemory()); } public ClientImpl newRemoteClient() { return null; } } static class DeleteWhenFullQueueListener implements QueueListener { public boolean queueMaxed(Client client, Message message) { client.getQueue().poll(); return true; } } static class DiscardNewMessageQueueListener implements QueueListener { public boolean queueMaxed(Client client, Message message) { return false; } } static class ModifyExistingMessagesQueueListener implements QueueListener { public boolean queueMaxed(Client client, Message message) { Iterator<Message> queueIterator = client.getQueue().iterator(); boolean removed = false; while(queueIterator.hasNext()) { Message m = queueIterator.next(); if(m.get("delete")!=null) { queueIterator.remove(); removed=true; } } return removed; } } static class CheckMessageListener implements MessageListener { Message _message; public CheckMessageListener(Message message) { _message = message; } public void deliver(Client fromClient, Client toClient, Message msg) { assertEquals(_message, msg); } } }