Repository: qpid-interop-test Updated Branches: refs/heads/master 6d0d60388 -> 77eba676f
QPIDIT-1: Intial commit of qpid-jms shim Project: http://git-wip-us.apache.org/repos/asf/qpid-interop-test/repo Commit: http://git-wip-us.apache.org/repos/asf/qpid-interop-test/commit/77eba676 Tree: http://git-wip-us.apache.org/repos/asf/qpid-interop-test/tree/77eba676 Diff: http://git-wip-us.apache.org/repos/asf/qpid-interop-test/diff/77eba676 Branch: refs/heads/master Commit: 77eba676f7653c3bdb1ea44d1e1c6cb81f47a932 Parents: 6d0d603 Author: Kim van der Riet <[email protected]> Authored: Wed Jul 8 23:29:14 2015 -0400 Committer: Kim van der Riet <[email protected]> Committed: Wed Jul 8 23:29:14 2015 -0400 ---------------------------------------------------------------------- jars/README | 3 + jars/slf4j-nop-1.5.6.jar | Bin 0 -> 5283 bytes shims/qpid-jms/java-build.sh | 13 + shims/qpid-jms/java-clean.sh | 5 + .../interop_test/shim/ProtonJmsReceiver.java | 269 +++++++++++++++++++ .../qpid/interop_test/shim/ProtonJmsSender.java | 258 ++++++++++++++++++ shims/qpid-proton-python/src/proton-python-send | 2 +- .../types/simple_type_tests.py | 117 +++++--- 8 files changed, 625 insertions(+), 42 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/77eba676/jars/README ---------------------------------------------------------------------- diff --git a/jars/README b/jars/README new file mode 100644 index 0000000..4aea73f --- /dev/null +++ b/jars/README @@ -0,0 +1,3 @@ +This directory is a temporary landing place for jars that need to be included +in the java CLASSPATH. Once this project has been Maven-ized, it is expected +that this will be handled automatically by Maven and this dir will go away. \ No newline at end of file http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/77eba676/jars/slf4j-nop-1.5.6.jar ---------------------------------------------------------------------- diff --git a/jars/slf4j-nop-1.5.6.jar b/jars/slf4j-nop-1.5.6.jar new file mode 100644 index 0000000..71fda42 Binary files /dev/null and b/jars/slf4j-nop-1.5.6.jar differ http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/77eba676/shims/qpid-jms/java-build.sh ---------------------------------------------------------------------- diff --git a/shims/qpid-jms/java-build.sh b/shims/qpid-jms/java-build.sh new file mode 100755 index 0000000..78f5bfa --- /dev/null +++ b/shims/qpid-jms/java-build.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# JARS +JMS_API=${HOME}/.m2/repository/org/apache/geronimo/specs/geronimo-jms_1.1_spec/1.1.1/geronimo-jms_1.1_spec-1.1.1.jar:${HOME}/.m2/repository/org/apache/qpid/qpid-jms-client/0.4.0-SNAPSHOT/qpid-jms-client-0.4.0-SNAPSHOT.jar +CLASSPATH=${JMS_API} + +BASEPATH=org/apache/qpid/interop_test/shim +SRCPATH=src/main/java/${BASEPATH} +TARGETPATH=target + +mkdir -p ${TARGETPATH}/classes +javac -cp ${CLASSPATH} -d ${TARGETPATH}/classes ${SRCPATH}/ProtonJmsSender.java ${SRCPATH}/ProtonJmsReceiver.java +jar -cf ${TARGETPATH}/qpid-jms-shim.jar -C ${TARGETPATH}/classes ${BASEPATH}/ProtonJmsSender.class -C ${TARGETPATH}/classes ${BASEPATH}/ProtonJmsSender\$1.class -C ${TARGETPATH}/classes ${BASEPATH}/ProtonJmsSender\$MyExceptionListener.class -C ${TARGETPATH}/classes ${BASEPATH}/ProtonJmsReceiver.class -C ${TARGETPATH}/classes ${BASEPATH}/ProtonJmsReceiver\$1.class -C ${TARGETPATH}/classes ${BASEPATH}/ProtonJmsReceiver\$MyExceptionListener.class http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/77eba676/shims/qpid-jms/java-clean.sh ---------------------------------------------------------------------- diff --git a/shims/qpid-jms/java-clean.sh b/shims/qpid-jms/java-clean.sh new file mode 100755 index 0000000..7fc8be1 --- /dev/null +++ b/shims/qpid-jms/java-clean.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +TARGETPATH=target + +rm -rf ${TARGETPATH}/*.jar ${TARGETPATH}/classes/* http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/77eba676/shims/qpid-jms/src/main/java/org/apache/qpid/interop_test/shim/ProtonJmsReceiver.java ---------------------------------------------------------------------- diff --git a/shims/qpid-jms/src/main/java/org/apache/qpid/interop_test/shim/ProtonJmsReceiver.java b/shims/qpid-jms/src/main/java/org/apache/qpid/interop_test/shim/ProtonJmsReceiver.java new file mode 100644 index 0000000..4710025 --- /dev/null +++ b/shims/qpid-jms/src/main/java/org/apache/qpid/interop_test/shim/ProtonJmsReceiver.java @@ -0,0 +1,269 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.qpid.interop_test.shim; + +import java.math.BigDecimal; +import java.util.UUID; +import java.util.Vector; +import javax.jms.BytesMessage; +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.ExceptionListener; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.ObjectMessage; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; +import javax.naming.Context; +import javax.naming.InitialContext; +import org.apache.qpid.jms.JmsConnectionFactory; + +public class ProtonJmsReceiver { + private static final String USER = "guest"; + private static final String PASSWORD = "guest"; + private static final int TIMEOUT = 1000; + private static final String[] SUPPORTED_AMQP_TYPES = {"null", + "boolean", + "ubyte", + "ushort", + "uint", + "ulong", + "byte", + "short", + "int", + "long", + "float", + "double", + "decimal32", + "decimal64", + "decimal128", + "char", + "timestamp", + "uuid", + "binary", + "string", + "symbol", + "list", + "map", + "array"}; + + public static void main(String[] args) throws Exception { + if (args.length < 4) { + System.out.println("ProtonJmsReceiver: Insufficient number of arguments"); + System.out.println("ProtonJmsReceiver: Expected arguments: broker_address, queue_name, amqp_type, num_test_values"); + System.exit(1); + } + String brokerAddress = "amqp://" + args[0]; + String queueName = args[1]; + String amqpType = args[2]; + int numTestValues = Integer.parseInt(args[3]); + Connection connection = null; + + try { + ConnectionFactory factory = (ConnectionFactory)new JmsConnectionFactory(brokerAddress); + + connection = factory.createConnection(USER, PASSWORD); + connection.setExceptionListener(new MyExceptionListener()); + connection.start(); + + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + Queue queue = session.createQueue(queueName); + + MessageConsumer messageConsumer = session.createConsumer(queue); + + Vector<String> outList = new Vector<String>(); + outList.add(amqpType); + if (isSupportedAmqpType(amqpType)) { + int actualCount = 0; + Message message = null; + for (int i = 1; i <= numTestValues; i++, actualCount++) { + message = messageConsumer.receive(TIMEOUT); + if (message == null) + break; + switch (amqpType) { + case "null": + long bodyLength = ((BytesMessage)message).getBodyLength(); + if (bodyLength == 0L) { + outList.add("None"); + } else { + throw new Exception("ProtonJmsReceiver: JMS BytesMessage size error: Expected 0 bytes, read " + bodyLength); + } + break; + case "boolean": + String bs = String.valueOf(((BytesMessage)message).readBoolean()); + outList.add(Character.toUpperCase(bs.charAt(0)) + bs.substring(1)); + break; + case "ubyte": + byte byteValue = ((BytesMessage)message).readByte(); + short ubyteValue = (short)(byteValue & 0xff); + outList.add(String.valueOf(ubyteValue)); + break; + case "ushort": + { + byte[] byteArray = new byte[2]; + int numBytes = ((BytesMessage)message).readBytes(byteArray); + if (numBytes != 2) { + // TODO: numBytes == -1 means no more bytes in stream - add error message for this case? + throw new Exception("ProtonJmsReceiver: JMS BytesMessage size error: Exptected 2 bytes, read " + numBytes); + } + int ushortValue = 0; + for (int j=0; j<byteArray.length; j++) { + ushortValue = (ushortValue << 8) + (byteArray[j] & 0xff); + } + outList.add(String.valueOf(ushortValue)); + break; + } + case "uint": + { + byte[] byteArray = new byte[4]; + int numBytes = ((BytesMessage)message).readBytes(byteArray); + if (numBytes != 4) { + // TODO: numBytes == -1 means no more bytes in stream - add error message for this case? + throw new Exception("ProtonJmsReceiver: JMS BytesMessage size error: Exptected 4 bytes, read " + numBytes); + } + long uintValue = 0; + for (int j=0; j<byteArray.length; j++) { + uintValue = (uintValue << 8) + (byteArray[j] & 0xff); + } + outList.add(String.valueOf(uintValue)); + break; + } + case "ulong": + case "timestamp": + { + // TODO: Tidy this ugliness up - perhaps use of vector<byte>? + byte[] byteArray = new byte[8]; + int numBytes = ((BytesMessage)message).readBytes(byteArray); + if (numBytes != 8) { + // TODO: numBytes == -1 means no more bytes in stream - add error message for this case? + throw new Exception("ProtonJmsReceiver: JMS BytesMessage size error: Exptected 8 bytes, read " + numBytes); + } + // TODO: shortcut in use here - this byte array should go through a Java type that can represent this as a number - such as BigInteger. + outList.add(String.format("0x%02x%02x%02x%02x%02x%02x%02x%02x", byteArray[0], byteArray[1], + byteArray[2], byteArray[3], byteArray[4], byteArray[5], byteArray[6], byteArray[7])); + break; + } + case "byte": + outList.add(String.valueOf(((BytesMessage)message).readByte())); + break; + case "short": + outList.add(String.valueOf(((BytesMessage)message).readShort())); + break; + case "int": + outList.add(String.valueOf(((BytesMessage)message).readInt())); + break; + case "long": + outList.add(String.valueOf(((BytesMessage)message).readLong())); + break; + case "float": + float f = ((BytesMessage)message).readFloat(); + int i0 = Float.floatToRawIntBits(f); + outList.add(String.format("0x%8s", Integer.toHexString(i0)).replace(' ', '0')); + break; + case "double": + double d = ((BytesMessage)message).readDouble(); + long l = Double.doubleToRawLongBits(d); + outList.add(String.format("0x%16s", Long.toHexString(l)).replace(' ', '0')); + break; + case "decimal32": + BigDecimal bd32 = (BigDecimal)((ObjectMessage)message).getObject(); + outList.add(bd32.toString()); + break; + case "decimal64": + BigDecimal bd64 = (BigDecimal)((ObjectMessage)message).getObject(); + outList.add(bd64.toString()); + break; + case "decimal128": + BigDecimal bd128 = (BigDecimal)((ObjectMessage)message).getObject(); + outList.add(bd128.toString()); + break; + case "char": + outList.add(String.format("%c", ((BytesMessage)message).readChar())); + break; + case "uuid": + UUID uuid = (UUID)((ObjectMessage)message).getObject(); + outList.add(uuid.toString()); + break; + case "binary": + BytesMessage bm = (BytesMessage)message; + int msgLen = (int)bm.getBodyLength(); + byte[] ba = new byte[msgLen]; + if (bm.readBytes(ba) == msgLen) { + outList.add(new String(ba)); + } else { + // TODO: Raise exception or error here: size mismatch + } + break; + case "string": + outList.add(((TextMessage)message).getText()); + break; + case "symbol": + outList.add(((BytesMessage)message).readUTF()); + break; + case "list": + break; + case "map": + break; + case "array": + break; + default: + // Internal error, should never happen if SUPPORTED_AMQP_TYPES matches this case stmt + connection.close(); + throw new Exception("ProtonJmsReceiver: Internal error: unsupported AMQP type \"" + amqpType + "\""); + } + } + } else { + System.out.println("ERROR: ProtonJmsReceiver: AMQP type \"" + amqpType + "\" is not supported"); + connection.close(); + System.exit(1); + } + + connection.close(); + + // No exception, print results + for (int i=0; i<outList.size(); i++) { + System.out.println(outList.get(i)); + } + } catch (Exception exp) { + if (connection != null) + connection.close(); + System.out.println("Caught exception, exiting."); + exp.printStackTrace(System.out); + System.exit(1); + } + } + + protected static boolean isSupportedAmqpType(String amqpType) { + for (String supportedAmqpType: SUPPORTED_AMQP_TYPES) { + if (amqpType.equals(supportedAmqpType)) + return true; + } + return false; + } + + private static class MyExceptionListener implements ExceptionListener { + @Override + public void onException(JMSException exception) { + System.out.println("Connection ExceptionListener fired, exiting."); + exception.printStackTrace(System.out); + System.exit(1); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/77eba676/shims/qpid-jms/src/main/java/org/apache/qpid/interop_test/shim/ProtonJmsSender.java ---------------------------------------------------------------------- diff --git a/shims/qpid-jms/src/main/java/org/apache/qpid/interop_test/shim/ProtonJmsSender.java b/shims/qpid-jms/src/main/java/org/apache/qpid/interop_test/shim/ProtonJmsSender.java new file mode 100644 index 0000000..3507fbd --- /dev/null +++ b/shims/qpid-jms/src/main/java/org/apache/qpid/interop_test/shim/ProtonJmsSender.java @@ -0,0 +1,258 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.qpid.interop_test.shim; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.MathContext; +import java.util.Arrays; +import java.util.UUID; +import javax.jms.BytesMessage; +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.DeliveryMode; +import javax.jms.ExceptionListener; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageProducer; +import javax.jms.ObjectMessage; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; +import javax.naming.Context; +import javax.naming.InitialContext; +import org.apache.qpid.jms.JmsConnectionFactory; + +public class ProtonJmsSender { + private static final String USER = "guest"; + private static final String PASSWORD = "guest"; + private static final String[] SUPPORTED_AMQP_TYPES = {"null", + "boolean", + "ubyte", + "ushort", + "uint", + "ulong", + "byte", + "short", + "int", + "long", + "float", + "double", + "decimal32", + "decimal64", + "decimal128", + "char", + "timestamp", + "uuid", + "binary", + "string", + "symbol", + "list", + "map", + "array"}; + + public static void main(String[] args) throws Exception { + if (args.length < 4) { + System.out.println("ProtonJmsSender: Insufficient number of arguments"); + System.out.println("ProtonJmsSender: Expected arguments: broker_address, queue_name, amqp_type, test_val, test_val, ..."); + System.exit(1); + } + String brokerAddress = "amqp://" + args[0]; + String queueName = args[1]; + String amqpType = args[2]; + String[] testValueList = Arrays.copyOfRange(args, 3, args.length); // Use remaining args as test values + + try { + ConnectionFactory factory = (ConnectionFactory)new JmsConnectionFactory(brokerAddress); + + Connection connection = factory.createConnection(); + connection.setExceptionListener(new MyExceptionListener()); + connection.start(); + + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + Queue queue = session.createQueue(queueName); + + MessageProducer messageProducer = session.createProducer(queue); + + if (isSupportedAmqpType(amqpType)) { + Message message = null; + for (String testValueStr : testValueList) { + switch (amqpType) { + case "null": + message = session.createBytesMessage(); + break; + case "boolean": + message = session.createBytesMessage(); + ((BytesMessage)message).writeBoolean(Boolean.parseBoolean(testValueStr)); + break; + case "ubyte": + { + byte testValue = (byte)Short.parseShort(testValueStr); + message = session.createBytesMessage(); + ((BytesMessage)message).writeByte(testValue); + break; + } + case "ushort": + { + int testValue = Integer.parseInt(testValueStr); + byte[] byteArray = new byte[2]; + byteArray[0] = (byte)(testValue >> 8); + byteArray[1] = (byte)(testValue); + message = session.createBytesMessage(); + ((BytesMessage)message).writeBytes(byteArray); + break; + } + case "uint": + { + long testValue = Long.parseLong(testValueStr); + byte[] byteArray = new byte[4]; + byteArray[0] = (byte)(testValue >> 24); + byteArray[1] = (byte)(testValue >> 16); + byteArray[2] = (byte)(testValue >> 8); + byteArray[3] = (byte)(testValue); + message = session.createBytesMessage(); + ((BytesMessage)message).writeBytes(byteArray); + break; + } + case "ulong": + { + // TODO: Tidy this ugliness up - perhaps use of vector<byte>? + BigInteger testValue = new BigInteger(testValueStr); + byte[] bigIntArray = testValue.toByteArray(); // may be 1 to 9 bytes depending on number + byte[] byteArray = {0, 0, 0, 0, 0, 0, 0, 0}; + int effectiveBigIntArrayLen = bigIntArray.length > 8 ? 8 : bigIntArray.length; // Cap length at 8 + int bigIntArrayOffs = bigIntArray.length > 8 ? bigIntArray.length - 8 : 0; // Offset when length > 8 + for (int i=0; i<bigIntArray.length && i < 8; i++) + byteArray[8 - effectiveBigIntArrayLen + i] = bigIntArray[bigIntArrayOffs + i]; + message = session.createBytesMessage(); + ((BytesMessage)message).writeBytes(byteArray); + break; + } + case "byte": + message = session.createBytesMessage(); + ((BytesMessage)message).writeByte(Byte.parseByte(testValueStr)); + break; + case "short": + message = session.createBytesMessage(); + ((BytesMessage)message).writeShort(Short.parseShort(testValueStr)); + break; + case "int": + message = session.createBytesMessage(); + ((BytesMessage)message).writeInt(Integer.parseInt(testValueStr)); + break; + case "long": + case "timestamp": + message = session.createBytesMessage(); + ((BytesMessage)message).writeLong(Long.parseLong(testValueStr)); + break; + case "float": + Long i = Long.parseLong(testValueStr.substring(2), 16); + message = session.createBytesMessage(); + ((BytesMessage)message).writeFloat(Float.intBitsToFloat(i.intValue())); + break; + case "double": + Long l1 = Long.parseLong(testValueStr.substring(2, 3), 16) << 60; + Long l2 = Long.parseLong(testValueStr.substring(3), 16); + message = session.createBytesMessage(); + ((BytesMessage)message).writeDouble(Double.longBitsToDouble(l1 | l2)); + break; + case "decimal32": + BigDecimal bd32 = new BigDecimal(testValueStr, MathContext.DECIMAL32); + message = session.createObjectMessage(); + ((ObjectMessage)message).setObject(bd32); + break; + case "decimal64": + BigDecimal bd64 = new BigDecimal(testValueStr, MathContext.DECIMAL64); + message = session.createObjectMessage(); + ((ObjectMessage)message).setObject(bd64); + break; + case "decimal128": + BigDecimal bd128 = new BigDecimal(testValueStr, MathContext.DECIMAL128); + message = session.createObjectMessage(); + ((ObjectMessage)message).setObject(bd128); + break; + case "char": + char c = 0; + if (testValueStr.length() == 1) // Single char + c = testValueStr.charAt(0); + else if (testValueStr.length() == 6) // unicode format + c = (char)Integer.parseInt(testValueStr, 16); + message = session.createBytesMessage(); + ((BytesMessage)message).writeChar(c); + break; + case "uuid": + UUID uuid = UUID.fromString(testValueStr); + message = session.createObjectMessage(); + ((ObjectMessage)message).setObject(uuid); + break; + case "binary": + message = session.createBytesMessage(); + byte[] byteArray = testValueStr.getBytes(); + ((BytesMessage)message).writeBytes(byteArray, 0, byteArray.length); + break; + case "string": + message = session.createTextMessage(testValueStr); + break; + case "symbol": + message = session.createBytesMessage(); + ((BytesMessage)message).writeUTF(testValueStr); + break; + case "list": + break; + case "map": + break; + case "array": + break; + default: + // Internal error, should never happen if SUPPORTED_AMQP_TYPES matches this case stmt + connection.close(); + throw new Exception("ProtonJmsSender: Internal error: unsupported AMQP type \"" + amqpType + "\""); + } + messageProducer.send(message, DeliveryMode.NON_PERSISTENT, Message.DEFAULT_PRIORITY, Message.DEFAULT_TIME_TO_LIVE); + } + } else { + System.out.println("ERROR: ProtonJmsSender: AMQP type \"" + amqpType + "\" is not supported"); + connection.close(); + System.exit(1); + } + + connection.close(); + } catch (Exception exp) { + System.out.println("Caught exception, exiting."); + exp.printStackTrace(System.out); + System.exit(1); + } + } + + protected static boolean isSupportedAmqpType(String amqpType) { + for (String supportedAmqpType: SUPPORTED_AMQP_TYPES) { + if (amqpType.equals(supportedAmqpType)) + return true; + } + return false; + } + + private static class MyExceptionListener implements ExceptionListener { + @Override + public void onException(JMSException exception) { + System.out.println("Connection ExceptionListener fired, exiting."); + exception.printStackTrace(System.out); + System.exit(1); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/77eba676/shims/qpid-proton-python/src/proton-python-send ---------------------------------------------------------------------- diff --git a/shims/qpid-proton-python/src/proton-python-send b/shims/qpid-proton-python/src/proton-python-send index 2b8703d..eb1c52c 100755 --- a/shims/qpid-proton-python/src/proton-python-send +++ b/shims/qpid-proton-python/src/proton-python-send @@ -88,7 +88,7 @@ class Sender(MessagingHandler): elif self.amqp_type == 'decimal64': return Message(id=(self.sent+1), body=decimal64(literal_eval(test_value))) elif self.amqp_type == 'decimal128': - return Message(id=(self.sent+1), body=decimal128(test_value.decode('hex'))) + return Message(id=(self.sent+1), body=decimal128(literal_eval(test_value))) elif self.amqp_type == 'char': return Message(id=(self.sent+1), body=char(test_value)) elif self.amqp_type == 'timestamp': http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/77eba676/src/py/qpid-interop-test/types/simple_type_tests.py ---------------------------------------------------------------------- diff --git a/src/py/qpid-interop-test/types/simple_type_tests.py b/src/py/qpid-interop-test/types/simple_type_tests.py index 2e3fc20..48e1195 100755 --- a/src/py/qpid-interop-test/types/simple_type_tests.py +++ b/src/py/qpid-interop-test/types/simple_type_tests.py @@ -28,16 +28,15 @@ import unittest from ast import literal_eval from itertools import product -from os import getenv +from os import getenv, path from proton import char, int32, symbol, timestamp, ulong from shim_utils import StrToObj -from subprocess import check_output +from subprocess import check_output, CalledProcessError from time import mktime, time from uuid import UUID, uuid4 QPID_INTEROP_TEST_HOME = getenv('QPID_INTEROP_TEST_HOME') # TODO - propose a sensible default when installation details are worked out - class SimpleTypeTestError(StandardError): """ Error class for use in simpe AMQP type tests @@ -58,7 +57,7 @@ class AmqpPrimitiveTypes(object): 'ushort': [0x0, 0x7fff, 0x8000, 0xffff], 'uint': [0x0, 0x7fffffff, 0x80000000, 0xffffffff], 'ulong': [0x0, 0x01, 0xff, 0x100, 0x7fffffffffffffff, 0x8000000000000000, 0xffffffffffffffff], - 'byte': [0x0, 0x7f, 0x80, 0xff], + 'byte': [-0x80, -0x01, 0x0, 0x7f], 'short': [-0x8000, -0x1, 0x0, 0x7fff], 'int': [-0x80000000, -0x1, 0x0, 0x7fffffff], 'long': [-0x8000000000000000, -0x81, -0x80, -0x01, 0x0, 0x7f, 0x80, 0x7fffffffffffffff], @@ -78,8 +77,8 @@ class AmqpPrimitiveTypes(object): '0xff7fffff', # Largest negative normalized number '0x7f800000', # +Infinity '0xff800000', # -Infinity - '0x7fffffff', # +NaN - '0xffffffff'], # -NaN + '0x7fc00000', # +NaN + '0xffc00000'], # -NaN 'double': ['0x0000000000000000', # 0.0 '0x8000000000000000', # -0.0 '0x400921fb54442eea', # pi (3.14159265359) positive decimal @@ -94,32 +93,30 @@ class AmqpPrimitiveTypes(object): '0xffefffffffffffff', # Largest negative normalized number '0x7ff0000000000000', # +Infinity '0xfff0000000000000', # -Infinity - '0x7fffffffffffffff', # +NaN - '0xffffffffffffffff'], # -NaN - 'decimal32': [0, 100, -1000],#, - 'decimal64': [0, 100, -1000],#, - #'decimal128': [b'00000000000000000000000000000000', - # b'00000000000000000000000000000100', - # b'0102030405060708090a0b0c0d0e0f00'], - #'char': [u'a', u'Z', u'0', u'\x01', u'\x7f'], #TODO: Char value \x00 causes problems in check_output(), find another solution + '0x7ff8000000000000', # +NaN + '0xfff8000000000000'], # -NaN + 'decimal32': [0, 100, -1000.001, 3.14159, 1.234e+56], + 'decimal64': [0, 100, -1000.001, 3.14159, 1.234e+56], +# 'decimal128': [0, 100, -1000.001, 3.14159, 1.234e+56], # Hangs python shim, ok in jms shim +# 'char': [u'a', u'Z', u'\u0001', u'\u007f'], # Hangs python shim, ok in jms shim # timestamp must be in milliseconds since the unix epoch 'timestamp': [0, int(mktime((2000, 1, 1, 0, 0, 0, 5, 1, 0))*1000), int(time()*1000)], 'uuid': [UUID(int=0x0), UUID('00010203-0405-0607-0809-0a0b0c0d0e0f'), uuid4()], - 'binary': [bytes(), bytes(12345), b'Hello, world!', b'\x01\x02\x03\x04\x05\xff', - b'The quick brown fox jumped over the lazy cow 0123456789' * 1000], + 'binary': [bytes(), bytes(12345), b'Hello, world!', b'\x01\x02\x03\x04\x05abcde\x80\x81\xfe\xff'], + #b'The quick brown fox jumped over the lazy dog 0123456789.' * 1000], # strings must be unicode to comply with AMQP spec 'string': [u'', u'Hello, world!', u'"Hello, world!"', u"Charlie's peach", - u'The quick brown fox jumped over the lazy cow 0123456789' * 1000], + u'The quick brown fox jumped over the lazy dog 0123456789.' * 1000], 'symbol': ['', 'myDomain.123', 'domain.0123456789.' * 1000], - 'list': [[], - [1, -2, 3.14], - [u'a', u'b', u'c'], - [ulong(12345), timestamp(int(time()*1000)), int32(-25), uuid4(), symbol('a.b.c')], - [[], None, [1,2,3], {1:'one', 2:'two', 3:'three', 4:True, 5:False, 6:None}, True, False, char(u'5')], - [[],[[],[[],[],[]],[]],[]], - [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] * 1000], - 'map': [{}, {1:u'one', 2:u'two'}, {None:None, 1:1, '2':'2', True:False, False:True}]#, - #'array': [[], [1,2,3], ['Hello', 'world']] +# 'list': [[], +# [1, -2, 3.14], +# [u'a', u'b', u'c'], +# [ulong(12345), timestamp(int(time()*1000)), int32(-25), uuid4(), symbol('a.b.c')], +# [[], None, [1,2,3], {1:'one', 2:'two', 3:'three', 4:True, 5:False, 6:None}, True, False, char(u'5')], +# [[],[[],[[],[],[]],[]],[]], +# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] * 1000]#, + #'map': [{}, {1:u'one', 2:u'two'}, {None:None, 1:1, '2':'2', True:False, False:True}]#, # TODO: Bug in handling maps + #'array': [[], [1,2,3], ['Hello', 'world']] # TODO: Not yet implemented } @staticmethod @@ -198,24 +195,31 @@ class Shim(object): Abstract shim class, parent of all shims. """ NAME = None - ENV = [] - SHIM_LOC = None SEND = None RECEIVE = None + USE_SHELL = False def send(self, broker_addr, queue_name, amqp_type, test_value_list): """ Send the values of type amqp_type in test_value_list to queue queue_name. Return output (if any) from stdout. """ - arg_list = [self.SEND, broker_addr, queue_name, amqp_type] + arg_list = [] + arg_list.extend(self.SEND) + arg_list.extend([broker_addr, queue_name, amqp_type]) for test_value in test_value_list: if amqp_type == 'string' or amqp_type == 'char' or amqp_type == 'float' or amqp_type == 'double': arg_list.append(test_value) # Not using str() on strings preserves the unicode prefix u'...' else: arg_list.append(str(test_value)) - #print - #print '>>>', arg_list - return check_output(arg_list) + try: + #print + #print '>>>', arg_list + return check_output(arg_list, shell=self.USE_SHELL) + except CalledProcessError as e: + return str(e) + '\n\nOutput:\n' + e.output + except Exception as e: + return str(e) + def receive(self, broker_addr, queue_name, amqp_type, num_test_values): """ @@ -223,10 +227,15 @@ class Shim(object): from stdout is the AMQP type, then the rest is assumed to be the returned test value list. Otherwise error output is assumed. """ + output = '' try: - arg_list = [self.RECEIVE, broker_addr, queue_name, amqp_type, str(num_test_values)] + arg_list = [] + arg_list.extend(self.RECEIVE) + arg_list.extend([broker_addr, queue_name, amqp_type, str(num_test_values)]) + #print #print '>>>', arg_list output = check_output(arg_list) + #print '<<<', output str_tvl = output.split('\n')[0:-1] # remove trailing \n if str_tvl[0] == amqp_type: received_test_value_list = [] @@ -244,6 +253,7 @@ class Shim(object): amqp_type == 'long' or \ amqp_type == 'decimal32' or \ amqp_type == 'decimal64' or \ + amqp_type == 'decimal128' or \ amqp_type == 'timestamp': received_test_value_list.append(literal_eval(stv)) # Non-string types not using literal_evel @@ -254,7 +264,6 @@ class Shim(object): # String and float types used as-is elif amqp_type == 'float' or \ amqp_type == 'double' or \ - amqp_type == 'decimal128' or \ amqp_type == 'char' or \ amqp_type == 'string' or \ amqp_type == 'symbol': @@ -267,8 +276,10 @@ class Shim(object): return received_test_value_list else: return output # return error string + except CalledProcessError as e: + return str(e) + '\n\n' + e.output except Exception as e: - return str(e) + '\n' + output + return str(e) class ProtonPythonShim(Shim): @@ -276,9 +287,9 @@ class ProtonPythonShim(Shim): Shim for qpid-proton Python client """ NAME = 'ProtonPython' - SHIM_LOC = QPID_INTEROP_TEST_HOME + '/shims/qpid-proton-python/src/' - SEND = SHIM_LOC + 'proton-python-send' - RECEIVE = SHIM_LOC + 'proton-python-receive' + SHIM_LOC = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-proton-python', 'src') + SEND = [path.join(SHIM_LOC, 'proton-python-send')] + RECEIVE = [path.join(SHIM_LOC, 'proton-python-receive')] class QpidJmsShim(Shim): @@ -286,9 +297,29 @@ class QpidJmsShim(Shim): Shim for qpid-jms JMS client """ NAME = 'QpidJms' - SHIM_LOC = '/shims/qpid-jms/src/main/java/' - SEND = SHIM_LOC + 'org/apache/qpid/qpid-interop-test/shim/ProtonJmsReceiver' - RECEIVE = SHIM_LOC + 'org/apache/qpid/qpid-interop-test/shim/ProtonJmsReceiver' + + # Installed qpid versions + QPID_JMS_VER = '0.4.0-SNAPSHOT' + QPID_PROTON_J_VER = '0.10-SNAPSHOT' + + # Classpath components + QPID_INTEROP_TEST_SHIM_JAR = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-jms', 'target', 'qpid-jms-shim.jar') + MAVEN_REPO_PATH = path.join(getenv('HOME'), '.m2', 'repository') + JMS_API_JAR = path.join(MAVEN_REPO_PATH, 'org', 'apache', 'geronimo', 'specs', 'geronimo-jms_1.1_spec', '1.1.1', + 'geronimo-jms_1.1_spec-1.1.1.jar') + JMS_IMPL_JAR = path.join(MAVEN_REPO_PATH, 'org', 'apache', 'qpid', 'qpid-jms-client', QPID_JMS_VER, + 'qpid-jms-client-' + QPID_JMS_VER + '.jar') + LOGGER_API_JAR = path.join(MAVEN_REPO_PATH, 'org', 'slf4j', 'slf4j-api', '1.5.6', 'slf4j-api-1.5.6.jar') + LOGGER_IMPL_JAR = path.join(QPID_INTEROP_TEST_HOME, 'jars', 'slf4j-nop-1.5.6.jar') + PROTON_J_JAR = path.join(MAVEN_REPO_PATH, 'org', 'apache', 'qpid', 'proton-j', QPID_PROTON_J_VER, + 'proton-j-' + QPID_PROTON_J_VER + '.jar') + NETTY_JAR = path.join(MAVEN_REPO_PATH, 'io', 'netty', 'netty-all', '4.0.17.Final', 'netty-all-4.0.17.Final.jar') + + CLASSPATH = ':'.join([QPID_INTEROP_TEST_SHIM_JAR, JMS_API_JAR, JMS_IMPL_JAR, LOGGER_API_JAR, LOGGER_IMPL_JAR, PROTON_J_JAR, NETTY_JAR]) + JAVA_HOME = getenv('JAVA_HOME', '/usr/bin') # Default only works in Linux + JAVA_EXEC = path.join(JAVA_HOME, 'java') + SEND = [JAVA_EXEC, '-cp', CLASSPATH, 'org.apache.qpid.interop_test.shim.ProtonJmsSender'] + RECEIVE = [JAVA_EXEC, '-cp', CLASSPATH, 'org.apache.qpid.interop_test.shim.ProtonJmsReceiver'] # SHIM_MAP contains an instance of each client language shim that is to be tested as a part of this test. For @@ -297,6 +328,10 @@ class QpidJmsShim(Shim): # # As new shims are added, add them into this map to have them included in the test cases. SHIM_MAP = {ProtonPythonShim.NAME: ProtonPythonShim()} +#SHIM_MAP = {QpidJmsShim.NAME: QpidJmsShim()} +#SHIM_MAP = {ProtonPythonShim.NAME: ProtonPythonShim(), +# QpidJmsShim.NAME: QpidJmsShim() +# } class TestOptions(object): --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
