package org.mockejb.jms.test;

import javax.jms.*;
import javax.naming.*;

import junit.framework.TestCase;

import org.mockejb.jndi.*;
import org.mockejb.jms.*;
import org.mockejb.interceptor.*;

/**
 * @author Dimitar Gospodinov
 */
public class ConsumersTest extends TestCase {

    private MockQueue mockQueue = null;
    private final AspectSystem aspSys = AspectSystemFactory.getAspectSystem();
    private final InvocationRecorder recorder = new InvocationRecorder();

    public ConsumersTest(String name) {
        super(name);
    }

    protected void setUp() throws Exception {
        MockContextFactory.setAsInitial();
        Context c = new InitialContext();

        mockQueue = new MockQueue("TestQueue");
        c.bind("TestQueue", mockQueue);
        QueueConnectionFactory connFactory = new QueueConnectionFactoryImpl();
        c.bind("QueueConnFactory", connFactory);

        // Send three messages
        QueueConnection conn = connFactory.createQueueConnection();
        QueueSession sess =
            conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
        QueueSender sender = sess.createSender(mockQueue);

        sender.send(new TextMessageImpl("Message 1"));
        sender.send(new MessageImpl());
        sender.send(new TextMessageImpl("Message 2"));
        conn.close();
        
        // Setup invocation recorder
        aspSys.add(new MethodPatternPointcut("javax.jms.MessageListener.onMessage"), recorder); 
    }

    protected void tearDown() throws Exception {
        mockQueue.clear();
        aspSys.clear();
        MockContextFactory.revertSetAsInitial();
    }

    public void testSynchronousReceive() throws Exception {

        Context c = new InitialContext();

        Queue queue = (Queue) c.lookup("TestQueue");
        QueueConnectionFactory connFactory =
            (QueueConnectionFactory) c.lookup("QueueConnFactory");

        QueueConnection conn = connFactory.createQueueConnection();
        QueueSession sess =
            conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
        QueueReceiver receiver = sess.createReceiver(queue);

        conn.start();

        Message m = receiver.receive();
        assertTrue(m instanceof TextMessage);
        TextMessage tm = (TextMessage) m;
        assertTrue(tm.getText().equals("Message 1"));
        try {
            tm.setText("Something");
            fail();
        } catch (MessageNotWriteableException ex) {
        }
        m = receiver.receive();
        assertTrue(m instanceof Message);
        try {
            m.setBooleanProperty("prop", false);
            fail();
        } catch (MessageNotWriteableException ex) {
        }
        m = receiver.receive();
        assertTrue(m instanceof TextMessage);
        tm = (TextMessage) m;
        assertTrue(tm.getText().equals("Message 2"));
        assertNull(receiver.receive(11));
        assertNull(receiver.receiveNoWait());
        conn.close();
    }

    public void testAsynchronousReceive() throws Exception {
        Context c = new InitialContext();

        Queue queue = (Queue) c.lookup("TestQueue");
        QueueConnectionFactory connFactory =
            (QueueConnectionFactory) c.lookup("QueueConnFactory");

        QueueConnection conn = connFactory.createQueueConnection();
        QueueSession sess =
            conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
        QueueReceiver receiver = sess.createReceiver(queue);

        receiver.setMessageListener(new TestListener());

        conn.start();
        assertEquals(recorder.getMethodInvocationList().size(), 3);
        conn.close();
    }

}