blob: 85024920a5691ad21e7b8553bf0c29a9cabd5369 [file] [log] [blame]
/**
* 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.activemq.openwire;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import org.apache.activemq.command.ActiveMQDestination;
import org.apache.activemq.command.ActiveMQMessage;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTextMessage;
import org.apache.activemq.command.BrokerId;
import org.apache.activemq.command.BrokerInfo;
import org.apache.activemq.command.ConnectionId;
import org.apache.activemq.command.ConsumerId;
import org.apache.activemq.command.DataStructure;
import org.apache.activemq.command.LocalTransactionId;
import org.apache.activemq.command.Message;
import org.apache.activemq.command.MessageAck;
import org.apache.activemq.command.MessageId;
import org.apache.activemq.command.NetworkBridgeFilter;
import org.apache.activemq.command.ProducerId;
import org.apache.activemq.command.SessionId;
import org.apache.activemq.command.TransactionId;
import org.apache.activemq.filter.BooleanExpression;
import org.apache.activemq.openwire.v1.ActiveMQTextMessageTest;
import org.apache.activemq.openwire.v1.BrokerInfoTest;
import org.apache.activemq.openwire.v1.MessageAckTest;
import org.apache.activemq.test.TestSupport;
import org.apache.activemq.util.ByteSequence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class DataFileGeneratorTestSupport extends TestSupport {
protected static final Object[] EMPTY_ARGUMENTS = {};
private static final Logger LOG = LoggerFactory.getLogger(DataFileGeneratorTestSupport.class);
private static final Throwable SINGLETON_EXCEPTION = new Exception("shared exception");
private static final File MODULE_BASE_DIR;
private static final File CONTROL_DIR;
static {
File basedir = null;
try {
URL resource = DataFileGeneratorTestSupport.class.getResource("DataFileGeneratorTestSupport.class");
URI baseURI = new URI(resource.toString()).resolve("../../../../..");
basedir = new File(baseURI).getCanonicalFile();
} catch (Exception e) {
throw new RuntimeException(e);
}
MODULE_BASE_DIR = basedir;
CONTROL_DIR = new File(MODULE_BASE_DIR, "src/test/resources/openwire-control");
}
private int counter;
private OpenWireFormat openWireformat;
public void xtestControlFileIsValid() throws Exception {
generateControlFile();
assertControlFileIsEqual();
}
public void testGenerateAndReParsingIsTheSame() throws Exception {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
DataOutputStream ds = new DataOutputStream(buffer);
Object expected = createObject();
LOG.info("Created: " + expected);
openWireformat.marshal(expected, ds);
ds.close();
// now lets try parse it back again
ByteArrayInputStream in = new ByteArrayInputStream(buffer.toByteArray());
DataInputStream dis = new DataInputStream(in);
Object actual = openWireformat.unmarshal(dis);
assertBeansEqual("", new HashSet<Object>(), expected, actual);
LOG.info("Parsed: " + actual);
}
protected void assertBeansEqual(String message, Set<Object> comparedObjects, Object expected, Object actual) throws Exception {
assertNotNull("Actual object should be equal to: " + expected + " but was null", actual);
if (comparedObjects.contains(expected)) {
return;
}
comparedObjects.add(expected);
Class<? extends Object> type = expected.getClass();
assertEquals("Should be of same type", type, actual.getClass());
BeanInfo beanInfo = Introspector.getBeanInfo(type);
PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
for (int i = 0; i < descriptors.length; i++) {
PropertyDescriptor descriptor = descriptors[i];
Method method = descriptor.getReadMethod();
if (method != null) {
String name = descriptor.getName();
Object expectedValue = null;
Object actualValue = null;
try {
expectedValue = method.invoke(expected, EMPTY_ARGUMENTS);
actualValue = method.invoke(actual, EMPTY_ARGUMENTS);
} catch (Exception e) {
LOG.info("Failed to access property: " + name);
}
assertPropertyValuesEqual(message + name, comparedObjects, expectedValue, actualValue);
}
}
}
protected void assertPropertyValuesEqual(String name, Set<Object> comparedObjects, Object expectedValue, Object actualValue) throws Exception {
String message = "Property " + name + " not equal";
if (expectedValue == null) {
assertNull("Property " + name + " should be null", actualValue);
} else if (expectedValue instanceof Object[]) {
assertArrayEqual(message, comparedObjects, (Object[])expectedValue, (Object[])actualValue);
} else if (expectedValue.getClass().isArray()) {
assertPrimitiveArrayEqual(message, comparedObjects, expectedValue, actualValue);
} else {
if (expectedValue instanceof Exception) {
assertExceptionsEqual(message, (Exception)expectedValue, actualValue);
} else if (expectedValue instanceof ByteSequence) {
assertByteSequencesEqual(message, (ByteSequence)expectedValue, actualValue);
} else if (expectedValue instanceof DataStructure) {
assertBeansEqual(message + name, comparedObjects, expectedValue, actualValue);
} else if (expectedValue instanceof Enumeration) {
assertEnumerationEqual(message + name, comparedObjects, (Enumeration)expectedValue, (Enumeration)actualValue);
} else {
assertEquals(message, expectedValue, actualValue);
}
}
}
protected void assertArrayEqual(String message, Set<Object> comparedObjects, Object[] expected, Object[] actual) throws Exception {
assertEquals(message + ". Array length", expected.length, actual.length);
for (int i = 0; i < expected.length; i++) {
assertPropertyValuesEqual(message + ". element: " + i, comparedObjects, expected[i], actual[i]);
}
}
protected void assertEnumerationEqual(String message, Set<Object> comparedObjects, Enumeration expected, Enumeration actual) throws Exception {
while (expected.hasMoreElements()) {
Object expectedElem = expected.nextElement();
Object actualElem = actual.nextElement();
assertPropertyValuesEqual(message + ". element: " + expectedElem, comparedObjects, expectedElem, actualElem);
}
}
protected void assertPrimitiveArrayEqual(String message, Set<Object> comparedObjects, Object expected, Object actual) throws ArrayIndexOutOfBoundsException, IllegalArgumentException,
Exception {
int length = Array.getLength(expected);
assertEquals(message + ". Array length", length, Array.getLength(actual));
for (int i = 0; i < length; i++) {
assertPropertyValuesEqual(message + ". element: " + i, comparedObjects, Array.get(expected, i), Array.get(actual, i));
}
}
protected void assertByteSequencesEqual(String message, ByteSequence expected, Object actualValue) {
assertTrue(message + ". Actual value should be a ByteSequence but was: " + actualValue, actualValue instanceof ByteSequence);
ByteSequence actual = (ByteSequence)actualValue;
int length = expected.getLength();
assertEquals(message + ". Length", length, actual.getLength());
int offset = expected.getOffset();
assertEquals(message + ". Offset", offset, actual.getOffset());
byte[] data = expected.getData();
byte[] actualData = actual.getData();
for (int i = 0; i < length; i++) {
assertEquals(message + ". Offset " + i, data[offset + i], actualData[offset + i]);
}
}
protected void assertExceptionsEqual(String message, Exception expected, Object actualValue) {
assertTrue(message + ". Actual value should be an exception but was: " + actualValue, actualValue instanceof Exception);
Exception actual = (Exception)actualValue;
assertEquals(message, expected.getMessage(), actual.getMessage());
}
protected void setUp() throws Exception {
super.setUp();
openWireformat = createOpenWireFormat();
}
public void generateControlFile() throws Exception {
CONTROL_DIR.mkdirs();
File dataFile = new File(CONTROL_DIR, getClass().getName() + ".bin");
FileOutputStream os = new FileOutputStream(dataFile);
DataOutputStream ds = new DataOutputStream(os);
openWireformat.marshal(createObject(), ds);
ds.close();
}
public InputStream generateInputStream() throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
DataOutputStream ds = new DataOutputStream(os);
openWireformat.marshal(createObject(), ds);
ds.close();
return new ByteArrayInputStream(os.toByteArray());
}
public void assertControlFileIsEqual() throws Exception {
File dataFile = new File(CONTROL_DIR, getClass().getName() + ".bin");
FileInputStream is1 = new FileInputStream(dataFile);
int pos = 0;
try {
InputStream is2 = generateInputStream();
int a = is1.read();
int b = is2.read();
pos++;
assertEquals("Data does not match control file: " + dataFile + " at byte position " + pos, a, b);
while (a >= 0 && b >= 0) {
a = is1.read();
b = is2.read();
pos++;
assertEquals("Data does not match control file: " + dataFile + " at byte position " + pos, a, b);
}
is2.close();
} finally {
is1.close();
}
}
protected abstract Object createObject() throws Exception;
protected void populateObject(Object info) throws Exception {
// empty method to allow derived classes to call super
// to simplify generated code
}
protected OpenWireFormat createOpenWireFormat() {
OpenWireFormat wf = new OpenWireFormat();
wf.setCacheEnabled(true);
wf.setStackTraceEnabled(false);
wf.setVersion(OpenWireFormat.DEFAULT_VERSION);
return wf;
}
protected BrokerId createBrokerId(String text) {
return new BrokerId(text);
}
protected TransactionId createTransactionId(String string) {
return new LocalTransactionId(createConnectionId(string), ++counter);
}
protected ConnectionId createConnectionId(String string) {
return new ConnectionId(string);
}
protected SessionId createSessionId(String string) {
return new SessionId(createConnectionId(string), ++counter);
}
protected ProducerId createProducerId(String string) {
return new ProducerId(createSessionId(string), ++counter);
}
protected ConsumerId createConsumerId(String string) {
return new ConsumerId(createSessionId(string), ++counter);
}
protected MessageId createMessageId(String string) {
return new MessageId(createProducerId(string), ++counter);
}
protected ActiveMQDestination createActiveMQDestination(String string) {
return new ActiveMQQueue(string);
}
protected Message createMessage(String string) throws Exception {
ActiveMQTextMessage message = (ActiveMQTextMessage)ActiveMQTextMessageTest.SINGLETON.createObject();
message.setText(string);
return message;
}
protected BrokerInfo createBrokerInfo(String string) throws Exception {
return (BrokerInfo)BrokerInfoTest.SINGLETON.createObject();
}
protected MessageAck createMessageAck(String string) throws Exception {
return (MessageAck)MessageAckTest.SINGLETON.createObject();
}
protected DataStructure createDataStructure(String string) throws Exception {
return createBrokerInfo(string);
}
protected Throwable createThrowable(String string) {
// we have issues with stack frames not being equal so share the same
// exception each time
return SINGLETON_EXCEPTION;
}
protected BooleanExpression createBooleanExpression(String string) {
return new NetworkBridgeFilter(new BrokerId(string), 10);
}
}