package org.mockejb.jms.test;

import junit.framework.TestCase;
import javax.jms.*;

import org.mockejb.jms.BytesMessageImpl;
import org.mockejb.jms.MessageUtility;
import org.mockejb.jms.MockQueue;
import org.mockejb.jms.QueueConnectionFactoryImpl;
import org.mockejb.jms.TextMessageImpl;

/**
 * Tests sending messages to a <code>Queue</code>.
 * 
 * @author Dimitar Gospodinov
 */
public class QueueTest extends TestCase {

    private QueueConnectionFactoryImpl queueFactory =
        new QueueConnectionFactoryImpl();
    private QueueConnection queueConnection;
    private MockQueue queue;
    
    public QueueTest(String name) {
        super(name);
    }

    protected void setUp() throws Exception {
        queueConnection = queueFactory.createQueueConnection();
        queue = new MockQueue("Test Queue");
    }

    protected void tearDown() throws Exception {
        super.tearDown();
        queueConnection = null;
        queue = null;
    }

    public void testQueueSession() throws JMSException {
        QueueSession session =
                    queueConnection.createQueueSession(
                        false,
                        Session.CLIENT_ACKNOWLEDGE);

       assertFalse(session.getTransacted());
       // Uncomment if using JMS 1.1 or later
       // assertEquals(session.getAcknowledgeMode(), Session.CLIENT_ACKNOWLEDGE);
       
       session =
                   queueConnection.createQueueSession(
                       true,
                       Session.AUTO_ACKNOWLEDGE);

      assertTrue(session.getTransacted());
      // Uncomment if using JMS 1.1 or later
      //assertEquals(session.getAcknowledgeMode(), Session.AUTO_ACKNOWLEDGE);
    }

    public void testQueueSender() throws JMSException {
        QueueSession session =
            queueConnection.createQueueSession(
                false,
                Session.CLIENT_ACKNOWLEDGE);
        QueueSender sender = session.createSender(queue);

        // Default priority should be 4
        assertEquals(sender.getPriority(), 4);
        sender.setPriority(5);
        assertEquals(sender.getPriority(), 5);
        // Default expiration should be 0 (message never expires)
        assertEquals(sender.getTimeToLive(), 0);
        sender.setTimeToLive(7777888899991111L);
        assertEquals(sender.getTimeToLive(), 7777888899991111L);
        // Default delivery mode should be DeliveryMode.PERSISTENT
        assertEquals(sender.getDeliveryMode(), DeliveryMode.PERSISTENT);
        sender.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
        assertEquals(sender.getDeliveryMode(), DeliveryMode.NON_PERSISTENT);
        
        assertSame(sender.getQueue(), queue);
        // Uncomment if using JMS 1.1 or later
        // assertSame(sender.getDestination(), queue);
    }

    public void testQueue() throws JMSException {

        QueueSession session =
            queueConnection.createQueueSession(
                false,
                Session.AUTO_ACKNOWLEDGE);
        QueueSender sender = session.createSender(queue);

        TextMessage textMsg = session.createTextMessage();
        assertNull(textMsg.getText());
        textMsg.setText("TextMessage:1");
        textMsg.setJMSType("TestType:1");
        
        BytesMessage bytesMsg = session.createBytesMessage();
    
        bytesMsg.writeBytes(new byte[]{0, 1, 2, 3, 4, 5, 6});
        bytesMsg.setJMSType("TestType:2");

        Message[] sentMsgs = new Message[4];
        
        sender.send(textMsg);
        sentMsgs[1] = new TextMessageImpl(textMsg);
                
        sender.send(bytesMsg, DeliveryMode.PERSISTENT, 9, 100);
        sentMsgs[0] = new BytesMessageImpl(bytesMsg);
        
        try {
            bytesMsg.readByte();
            fail();
        } catch (MessageNotReadableException ex) {
        }
        
        assertNotNull(textMsg.getJMSMessageID());
        assertSame(textMsg.getJMSDestination(), queue);
        assertEquals(textMsg.getJMSExpiration(), sender.getTimeToLive());
        assertEquals(textMsg.getJMSType(), "TestType:1");
        assertEquals(textMsg.getJMSDeliveryMode(), sender.getDeliveryMode());
        
        assertNotNull(bytesMsg.getJMSMessageID());
        assertSame(bytesMsg.getJMSDestination(), queue);
        assertEquals(bytesMsg.getJMSType(), "TestType:2");
        assertEquals(bytesMsg.getJMSDeliveryMode(), DeliveryMode.PERSISTENT);
                
        bytesMsg.writeBytes(new byte[]{0, 1, 2, 3, 4, 5, 6}, 0, 4);
        bytesMsg.reset();
        sender.send(bytesMsg, DeliveryMode.NON_PERSISTENT, 1, 1000);
        sentMsgs[3] = new BytesMessageImpl(bytesMsg);
        
        try {
            bytesMsg.writeBoolean(false);
            fail();
        } catch (MessageNotWriteableException ex){}

        byte[] bytes1 = new byte[11];
        assertEquals(bytesMsg.readBytes(bytes1), 11);
        assertEquals(bytesMsg.readBytes(bytes1), -1);
        assertTrue(MessageUtility.compare(bytes1, new byte[]{0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3}));

        textMsg.clearBody();
        sender.send(textMsg);
        sentMsgs[2] = textMsg;

        // Examine the queue
        assertEquals(queue.size(), 4);
        for (int i = 0; i < 4; i++) {
            assertTrue(MessageUtility.compare(queue.getMessageAt(i), sentMsgs[i]));
        }
    }

}