001: /*
002: * Copyright (C) 2003, 2004, 2005, 2006 Joe Walnes.
003: * Copyright (C) 2006, 2007 XStream Committers.
004: * All rights reserved.
005: *
006: * The software in this package is published under the terms of the BSD
007: * style license a copy of which has been included with this distribution in
008: * the LICENSE.txt file.
009: *
010: * Created on 26. September 2003 by Joe Walnes
011: */
012: package com.thoughtworks.acceptance;
013:
014: import java.lang.reflect.Array;
015: import java.io.ByteArrayOutputStream;
016: import java.io.ByteArrayInputStream;
017: import java.io.StringReader;
018: import java.io.StringWriter;
019:
020: import junit.framework.AssertionFailedError;
021: import junit.framework.TestCase;
022:
023: import javax.xml.transform.Transformer;
024: import javax.xml.transform.TransformerException;
025: import javax.xml.transform.TransformerFactory;
026: import javax.xml.transform.stream.StreamResult;
027: import javax.xml.transform.stream.StreamSource;
028:
029: import com.thoughtworks.xstream.XStream;
030: import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
031: import com.thoughtworks.xstream.io.binary.BinaryStreamWriter;
032: import com.thoughtworks.xstream.io.binary.BinaryStreamReader;
033: import com.thoughtworks.xstream.io.xml.XppDriver;
034:
035: public abstract class AbstractAcceptanceTest extends TestCase {
036:
037: protected transient XStream xstream = createXStream();
038:
039: protected XStream createXStream() {
040: return new XStream(createDriver());
041: }
042:
043: protected HierarchicalStreamDriver createDriver() {
044: // if the system property is set, use it to load the driver
045: String driver = null;
046: try {
047: driver = System.getProperty("xstream.driver");
048: if (driver != null) {
049: System.out.println("Using driver: " + driver);
050: Class type = Class.forName(driver);
051: return (HierarchicalStreamDriver) type.newInstance();
052: }
053: } catch (Exception e) {
054: throw new RuntimeException("Could not load driver: "
055: + driver);
056: }
057: return new XppDriver();
058: }
059:
060: protected Object assertBothWaysNormalized(Object root, String xml,
061: final String match, final String templateSelect,
062: final String sortSelect) {
063: try {
064: // First, serialize the object to XML and check it matches the expected XML.
065: String resultXml = normalizedXML(toXML(root),
066: new String[] { match }, templateSelect, sortSelect);
067: assertEquals(normalizedXML(xml, new String[] { match },
068: templateSelect, sortSelect), resultXml);
069:
070: // Now deserialize the XML back into the object and check it equals the original
071: // object.
072: Object resultRoot = xstream.fromXML(resultXml);
073: assertObjectsEqual(root, resultRoot);
074:
075: // While we're at it, let's check the binary serialization works...
076: assertBinarySerialization(root);
077:
078: return resultRoot;
079:
080: } catch (TransformerException e) {
081: throw new AssertionFailedError("Cannot normalize XML: "
082: + e.getMessage());
083: // .initCause(e); ... still JDK 1.3
084: }
085: }
086:
087: protected Object assertBothWays(Object root, String xml) {
088:
089: // First, serialize the object to XML and check it matches the expected XML.
090: String resultXml = toXML(root);
091: assertEquals(xml, resultXml);
092:
093: // Now deserialize the XML back into the object and check it equals the original object.
094: Object resultRoot = xstream.fromXML(resultXml);
095: assertObjectsEqual(root, resultRoot);
096:
097: // While we're at it, let's check the binary serialization works...
098: assertBinarySerialization(root);
099:
100: return resultRoot;
101: }
102:
103: private void assertBinarySerialization(Object root) {
104: // Serialize as binary
105: ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
106: xstream.marshal(root, new BinaryStreamWriter(outputStream));
107:
108: // Deserialize the binary and check it equals the original object.
109: ByteArrayInputStream inputStream = new ByteArrayInputStream(
110: outputStream.toByteArray());
111: Object binaryResult = xstream.unmarshal(new BinaryStreamReader(
112: inputStream));
113: assertObjectsEqual(root, binaryResult);
114: }
115:
116: protected Object assertWithAsymmetricalXml(Object root,
117: String inXml, String outXml) {
118: String resultXml = toXML(root);
119: assertEquals(outXml, resultXml);
120: Object resultRoot = xstream.fromXML(inXml);
121: assertObjectsEqual(root, resultRoot);
122: return resultRoot;
123: }
124:
125: /**
126: * Allow derived classes to decide how to turn the object into XML text
127: */
128: protected String toXML(Object root) {
129: return xstream.toXML(root);
130: }
131:
132: /**
133: * More descriptive version of assertEquals
134: */
135: protected void assertObjectsEqual(Object expected, Object actual) {
136: if (expected == null) {
137: assertNull(actual);
138: } else {
139: assertNotNull("Should not be null", actual);
140: if (actual.getClass().isArray()) {
141: assertArrayEquals(expected, actual);
142: } else {
143: // assertEquals(expected.getClass(), actual.getClass());
144: if (!expected.equals(actual)) {
145: assertEquals("Object deserialization failed",
146: "DESERIALIZED OBJECT\n"
147: + xstream.toXML(expected),
148: "DESERIALIZED OBJECT\n"
149: + xstream.toXML(actual));
150: }
151: }
152: }
153: }
154:
155: protected void assertArrayEquals(Object expected, Object actual) {
156: assertEquals(Array.getLength(expected), Array.getLength(actual));
157: for (int i = 0; i < Array.getLength(expected); i++) {
158: assertEquals(Array.get(expected, i), Array.get(actual, i));
159: }
160: }
161:
162: protected void assertByteArrayEquals(byte expected[], byte actual[]) {
163: assertEquals(dumpBytes(expected), dumpBytes(actual));
164: }
165:
166: private String dumpBytes(byte bytes[]) {
167: StringBuffer result = new StringBuffer();
168: for (int i = 0; i < bytes.length; i++) {
169: result.append(bytes[i]).append(' ');
170: if (bytes[i] < 100)
171: result.append(' ');
172: if (bytes[i] < 10)
173: result.append(' ');
174: if (bytes[i] >= 0)
175: result.append(' ');
176: if (i % 16 == 15)
177: result.append('\n');
178: }
179: return result.toString();
180: }
181:
182: protected String normalizedXML(final String xml,
183: final String[] matches, final String templateSelect,
184: final String sortSelect) throws TransformerException {
185: final StringBuffer match = new StringBuffer();
186: for (int i = 0; i < matches.length; i++) {
187: if (i > 0) {
188: match.append('|');
189: }
190: match.append(matches[i]);
191: }
192: final StringBuffer sort = new StringBuffer();
193: if (sortSelect != null) {
194: sort.append(" select=\"");
195: sort.append(sortSelect);
196: sort.append('"');
197: }
198:
199: final TransformerFactory transformerFactory = TransformerFactory
200: .newInstance();
201: final Transformer transformer = transformerFactory
202: .newTransformer(new StreamSource(
203: new StringReader(
204: ""
205: + "<?xml version=\"1.0\"?>\n"
206: + "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n"
207: + "<xsl:template match=\""
208: + match.toString()
209: + "\">\n"
210: + " <xsl:copy>\n"
211: + " <xsl:apply-templates select=\""
212: + templateSelect
213: + "\">\n"
214: + " <xsl:sort"
215: + sort.toString()
216: + "/>\n"
217: + " </xsl:apply-templates>\n"
218: + " </xsl:copy>\n"
219: + "</xsl:template>\n"
220: + "<xsl:template match=\"@*|node()\">\n"
221: + " <xsl:copy>\n"
222: + " <xsl:apply-templates select=\"@*|node()\"/>\n"
223: + " </xsl:copy>\n"
224: + "</xsl:template>\n"
225: + "</xsl:stylesheet>")));
226: final StringWriter writer = new StringWriter();
227: transformer.transform(new StreamSource(new StringReader(xml)),
228: new StreamResult(writer));
229: return writer.toString();
230: }
231: }
|