package org.mockejb.jms.test;

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

import org.mockejb.jms.MessageImpl;
import org.mockejb.jms.MockQueue;

import java.util.Enumeration;

/**
 * Tests <code>MessageImpl</code>.
 * 
 * @author Dimitar Gospodinov
 */
public class MessageImplTest extends TestCase {

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

    public void testHeaderFields() throws JMSException {

        String jmsCorrelationId = "CorrelationId";
        int jmsDeliveryMode = DeliveryMode.NON_PERSISTENT;
        Destination jmsDestination = new MockQueue("Destination");
        long jmsExpiration = 6789;
        String jmsMessageId = "ID:MyID";
        int jmsPriority = 6;
        Destination jmsReplyTo = new MockQueue("ReplyToQueue");
        long jmsTimestamp = 12345;
        String jmsType = "MyType";

        Message msg = new MessageImpl();

        msg.setJMSCorrelationID(jmsCorrelationId);
        msg.setJMSDeliveryMode(jmsDeliveryMode);
        msg.setJMSDestination(jmsDestination);
        msg.setJMSExpiration(jmsExpiration);
        msg.setJMSMessageID(jmsMessageId);
        msg.setJMSPriority(jmsPriority);
        msg.setJMSReplyTo(jmsReplyTo);
        msg.setJMSTimestamp(jmsTimestamp);
        msg.setJMSType(jmsType);

        assertEquals(jmsCorrelationId, msg.getJMSCorrelationID());
        assertEquals(jmsDeliveryMode, msg.getJMSDeliveryMode());
        assertSame(jmsDestination, msg.getJMSDestination());
        assertEquals(jmsExpiration, msg.getJMSExpiration());
        assertEquals(jmsMessageId, msg.getJMSMessageID());
        assertEquals(jmsPriority, msg.getJMSPriority());
        assertSame(jmsReplyTo, msg.getJMSReplyTo());
        assertEquals(jmsTimestamp, msg.getJMSTimestamp());
        assertEquals(jmsType, msg.getJMSType());

        assertFalse(msg.getJMSRedelivered());
        msg.setJMSRedelivered(true);
        assertFalse(msg.getJMSRedelivered());

        Message msg1 = new MessageImpl(msg);
        assertEquals(msg1.getJMSCorrelationID(), msg.getJMSCorrelationID());
        assertEquals(msg1.getJMSDeliveryMode(), msg.getJMSDeliveryMode());
        assertSame(msg1.getJMSDestination(), msg.getJMSDestination());
        assertEquals(msg1.getJMSExpiration(), msg.getJMSExpiration());
        assertEquals(msg1.getJMSMessageID(), msg.getJMSMessageID());
        assertEquals(msg1.getJMSPriority(), msg.getJMSPriority());
        assertSame(msg1.getJMSReplyTo(), msg.getJMSReplyTo());
        assertEquals(msg1.getJMSTimestamp(), msg.getJMSTimestamp());
        assertEquals(msg1.getJMSType(), msg.getJMSType());
        assertEquals(msg1.getJMSRedelivered(), msg.getJMSRedelivered());
    }

    public void testProperties() throws JMSException {
        Message msg = new MessageImpl();

        assertFalse(msg.getPropertyNames().hasMoreElements());
        assertNull(msg.getObjectProperty("some name"));

        msg.setBooleanProperty("boolean", false);
        msg.setByteProperty("byte", (byte) 127);
        msg.setShortProperty("short", (short) 8192);
        msg.setShortProperty("short", (short) 8193);
        msg.setIntProperty("int", 65536);
        msg.setLongProperty("long", 400111000111L);
        msg.setFloatProperty("float", (float) 34.8);
        msg.setDoubleProperty("double", 23232311111.8821);
        msg.setStringProperty("string", "str_val");
        Object obj = Long.valueOf("900111000111");
        msg.setObjectProperty("obj_long", obj);
        msg.setBooleanProperty("boolean1", true);

        checkProperties(msg, obj);
        checkProperties(new MessageImpl(msg), obj);

        msg.clearProperties();
        assertFalse(msg.getPropertyNames().hasMoreElements());
        
        try {
            msg.setObjectProperty("obj", new Object());
            fail();
        } catch (MessageFormatException ex) {
        }
    }

    private void checkProperties(Message msg, Object objPropertyValue)
        throws JMSException {
        Enumeration e = msg.getPropertyNames();
        int i = 0;
        while (e.hasMoreElements()) {
            String name = (String) e.nextElement();
            if (name.equals("boolean")) {
                assertFalse(msg.getBooleanProperty("boolean"));
            } else if (name.equals("byte")) {
                assertEquals(msg.getByteProperty("byte"), (byte) 127);
            } else if (name.equals("short")) {
                assertEquals(msg.getShortProperty("short"), (short) 8193);
            } else if (name.equals("int")) {
                assertEquals(msg.getIntProperty("int"), 65536);
            } else if (name.equals("long")) {
                assertEquals(msg.getLongProperty("long"), 400111000111L);
            } else if (name.equals("float")) {
                assertEquals(
                    msg.getFloatProperty("float"),
                    (float) 34.8,
                    (float) 0.1);
            } else if (name.equals("double")) {
                assertEquals(
                    msg.getDoubleProperty("double"),
                    23232311111.8821,
                    0.0001);
            } else if (name.equals("string")) {
                assertEquals(msg.getStringProperty("string"), "str_val");
            } else if (name.equals("obj_long")) {
                assertSame(msg.getObjectProperty("obj_long"), objPropertyValue);
            } else if (name.equals("boolean1")) {
                assertTrue(msg.getBooleanProperty("boolean1"));
            } else {
                fail();
            }
            i++;
        }
        assertEquals(i, 10);
    }

    public void testBooleanProperty() throws JMSException {
        Message msg = new MessageImpl();

        msg.setBooleanProperty("boolean", true);
        assertTrue(msg.propertyExists("boolean"));
        assertTrue(msg.getBooleanProperty("boolean"));
        assertEquals(msg.getStringProperty("boolean"), "true");
        assertTrue(msg.getObjectProperty("boolean") instanceof Boolean);
        assertTrue(((Boolean) msg.getObjectProperty("boolean")).booleanValue());

        msg.setBooleanProperty("boolean", false);
        assertFalse(msg.getBooleanProperty("boolean"));

        msg.setObjectProperty("boolean", Boolean.FALSE);
        assertFalse(msg.getBooleanProperty("boolean"));

        try {
            msg.getByteProperty("boolean");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getShortProperty("boolean");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getIntProperty("boolean");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getLongProperty("boolean");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getFloatProperty("boolean");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getDoubleProperty("boolean");
            fail();
        } catch (MessageFormatException ex) {
        }

        Message msg1 = new MessageImpl(msg);
        assertTrue(msg1.propertyExists("boolean"));
        assertFalse(msg1.getBooleanProperty("boolean"));
    }

    public void testByteProperty() throws JMSException {
        Message msg = new MessageImpl();

        msg.setByteProperty("byte", (byte) 127);
        assertTrue(msg.propertyExists("byte"));
        assertEquals(msg.getByteProperty("byte"), (byte) 127);
        assertEquals(msg.getShortProperty("byte"), (short) 127);
        assertEquals(msg.getIntProperty("byte"), 127);
        assertEquals(msg.getLongProperty("byte"), 127L);
        assertEquals(
            msg.getStringProperty("byte"),
            Byte.valueOf("127").toString());
        assertTrue(msg.getObjectProperty("byte") instanceof Byte);
        assertEquals(
            ((Byte) msg.getObjectProperty("byte")).byteValue(),
            (byte) 127);

        msg.setObjectProperty("byte", new Byte((byte) 126));
        assertEquals(msg.getByteProperty("byte"), (byte) 126);

        try {
            msg.getBooleanProperty("byte");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getFloatProperty("byte");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getDoubleProperty("byte");
            fail();
        } catch (MessageFormatException ex) {
        }

        msg.setByteProperty("byte", (byte) 125);
        assertEquals(msg.getByteProperty("byte"), (byte) 125);

        Message msg1 = new MessageImpl(msg);
        assertTrue(msg1.propertyExists("byte"));
        assertEquals(msg1.getByteProperty("byte"), (byte) 125);
    }

    public void testShortProperty() throws JMSException {
        Message msg = new MessageImpl();
        msg.setShortProperty("short", (short) 29000);
        assertTrue(msg.propertyExists("short"));
        assertEquals(msg.getShortProperty("short"), (short) 29000);
        assertEquals(msg.getIntProperty("short"), 29000);
        assertEquals(msg.getLongProperty("short"), 29000L);
        assertEquals(
            msg.getStringProperty("short"),
            Short.valueOf("29000").toString());
        assertTrue(msg.getObjectProperty("short") instanceof Short);
        assertEquals(
            ((Short) msg.getObjectProperty("short")).shortValue(),
            (short) 29000);

        msg.setObjectProperty("short", new Short((short) 29001));
        assertTrue(msg.getObjectProperty("short") instanceof Short);
        assertEquals(
            ((Short) msg.getObjectProperty("short")).shortValue(),
            (short) 29001);

        try {
            msg.getBooleanProperty("short");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getByteProperty("short");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getFloatProperty("short");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getDoubleProperty("short");
            fail();
        } catch (MessageFormatException ex) {
        }

        msg.setShortProperty("short", (short) 29002);
        assertEquals(msg.getShortProperty("short"), (short) 29002);

        Message msg1 = new MessageImpl(msg);
        assertTrue(msg1.propertyExists("short"));
        assertEquals(msg1.getShortProperty("short"), (short) 29002);
    }

    public void testIntProperty() throws JMSException {
        Message msg = new MessageImpl();
        msg.setIntProperty("int", 120000);
        assertTrue(msg.propertyExists("int"));
        assertEquals(msg.getIntProperty("int"), 120000);
        assertEquals(msg.getLongProperty("int"), 120000L);
        assertEquals(
            msg.getStringProperty("int"),
            Integer.valueOf("120000").toString());
        assertTrue(msg.getObjectProperty("int") instanceof Integer);
        assertEquals(
            ((Integer) msg.getObjectProperty("int")).intValue(),
            120000);

        msg.setObjectProperty("int", new Integer(120001));
        assertTrue(msg.getObjectProperty("int") instanceof Integer);
        assertEquals(
            ((Integer) msg.getObjectProperty("int")).intValue(),
            120001);

        try {
            msg.getBooleanProperty("int");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getByteProperty("int");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getShortProperty("int");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getFloatProperty("int");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getDoubleProperty("int");
            fail();
        } catch (MessageFormatException ex) {
        }

        msg.setIntProperty("int", 240000);
        assertEquals(msg.getIntProperty("int"), 240000);

        Message msg1 = new MessageImpl(msg);
        assertTrue(msg1.propertyExists("int"));
        assertEquals(msg1.getIntProperty("int"), 240000);
    }

    public void testLongProperty() throws JMSException {
        Message msg = new MessageImpl();
        msg.setLongProperty("long", 222200002222L);
        assertTrue(msg.propertyExists("long"));
        assertEquals(msg.getLongProperty("long"), 222200002222L);
        assertEquals(
            msg.getStringProperty("long"),
            Long.valueOf("222200002222").toString());
        assertTrue(msg.getObjectProperty("long") instanceof Long);
        assertEquals(
            ((Long) msg.getObjectProperty("long")).longValue(),
            222200002222L);

        msg.setObjectProperty("long", new Long(222299992222L));
        assertTrue(msg.getObjectProperty("long") instanceof Long);
        assertEquals(
            ((Long) msg.getObjectProperty("long")).longValue(),
            222299992222L);

        try {
            msg.getBooleanProperty("long");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getByteProperty("long");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getShortProperty("long");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getIntProperty("long");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getFloatProperty("long");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getDoubleProperty("long");
            fail();
        } catch (MessageFormatException ex) {
        }

        msg.setLongProperty("long", 222288882222L);
        assertEquals(msg.getLongProperty("long"), 222288882222L);

        Message msg1 = new MessageImpl(msg);
        assertTrue(msg1.propertyExists("long"));
        assertEquals(msg1.getLongProperty("long"), 222288882222L);
    }

    public void testFloatProperty() throws JMSException {
        Message msg = new MessageImpl();
        msg.setFloatProperty("float", (float) 1678.1234);
        assertTrue(msg.propertyExists("float"));
        assertEquals(
            msg.getFloatProperty("float"),
            (float) 1678.1234,
            (float) 0.0001);
        assertEquals(msg.getDoubleProperty("float"), 1678.1234, 0.0001);
        assertEquals(
            msg.getStringProperty("float"),
            Float.valueOf("1678.1234").toString());
        assertTrue(msg.getObjectProperty("float") instanceof Float);
        assertEquals(
            ((Float) msg.getObjectProperty("float")).floatValue(),
            (float) 1678.1234,
            (float) 0.0001);

        msg.setObjectProperty("float", new Float((float) 1778.1234));
        assertTrue(msg.getObjectProperty("float") instanceof Float);
        assertEquals(
            ((Float) msg.getObjectProperty("float")).floatValue(),
            (float) 1778.1234,
            (float) 0.0001);

        try {
            msg.getBooleanProperty("float");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getByteProperty("float");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getShortProperty("float");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getIntProperty("float");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getLongProperty("float");
            fail();
        } catch (MessageFormatException ex) {
        }

        msg.setFloatProperty("float", (float) 1677.1004);
        assertEquals(msg.getFloatProperty("float"), (float) 1677.1004, 0.0001);

        Message msg1 = new MessageImpl(msg);
        assertTrue(msg1.propertyExists("float"));
        assertEquals(msg1.getFloatProperty("float"), (float) 1677.1004, 0.0001);
    }

    public void testDoubleProperty() throws JMSException {
        Message msg = new MessageImpl();
        msg.setDoubleProperty("double", 9.989667788E304);
        assertTrue(msg.propertyExists("double"));
        assertEquals(
            msg.getDoubleProperty("double"),
            9.989667788E304,
            0.000000001E304);
        assertEquals(
            msg.getStringProperty("double"),
            Double.valueOf("9.989667788E304").toString());
        assertTrue(msg.getObjectProperty("double") instanceof Double);
        assertEquals(
            ((Double) msg.getObjectProperty("double")).doubleValue(),
            9.989667788E304,
            0.000000001E304);

        msg.setObjectProperty("double", new Double(9.911111788E304));
        assertTrue(msg.getObjectProperty("double") instanceof Double);
        assertEquals(
            ((Double) msg.getObjectProperty("double")).doubleValue(),
            9.911111788E304,
            0.000000001E304);

        try {
            msg.getBooleanProperty("double");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getByteProperty("double");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getShortProperty("double");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getIntProperty("double");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getLongProperty("double");
            fail();
        } catch (MessageFormatException ex) {
        }
        try {
            msg.getFloatProperty("double");
            fail();
        } catch (MessageFormatException ex) {
        }

        msg.setDoubleProperty("double", -8.7654321E-303);
        assertEquals(
            msg.getDoubleProperty("double"),
            -8.7654321E-303,
            0.0000001E-303);

        Message msg1 = new MessageImpl(msg);
        assertTrue(msg1.propertyExists("double"));
        assertEquals(
            msg1.getDoubleProperty("double"),
            -8.7654321E-303,
            0.0000001E-303);
    }

    public void testStringProperty() throws JMSException {
        Message msg = new MessageImpl();
        msg.setStringProperty("string", "123");
        assertTrue(msg.propertyExists("string"));
        assertEquals(msg.getStringProperty("string"), "123");
        assertEquals(
            msg.getByteProperty("string"),
            Byte.valueOf("123").byteValue());
        assertTrue(msg.getObjectProperty("string") instanceof String);
        assertEquals(msg.getObjectProperty("string").toString(), "123");

        msg.setObjectProperty("string", "124");
        assertTrue(msg.getObjectProperty("string") instanceof String);
        assertEquals(msg.getObjectProperty("string").toString(), "124");

        assertEquals(
            msg.getShortProperty("string"),
            Short.valueOf("124").shortValue());

        assertEquals(
            msg.getIntProperty("string"),
            Integer.valueOf("124").intValue());

        assertEquals(
            msg.getLongProperty("string"),
            Long.valueOf("124").longValue());

        msg.setStringProperty("string", "123.55");
        assertEquals(
            msg.getFloatProperty("string"),
            Float.valueOf("123.55").floatValue(),
            0.01);
        assertEquals(
            msg.getDoubleProperty("string"),
            Double.valueOf("123.55").doubleValue(),
            0.01);

        msg.setStringProperty("string", Boolean.valueOf("true").toString());
        assertTrue(msg.getBooleanProperty("string"));

        msg.setIntProperty("string", -5555);
        assertEquals(msg.getIntProperty("string"), -5555);
        assertEquals(msg.getStringProperty("string"), Integer.toString(-5555));

        Message msg1 = new MessageImpl(msg);
        assertTrue(msg1.propertyExists("string"));
        assertEquals(msg1.getStringProperty("string"), Integer.toString(-5555));
    }
}