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.xstream;
013:
014: import com.thoughtworks.acceptance.objects.StandardObject;
015: import com.thoughtworks.acceptance.someobjects.FunnyConstructor;
016: import com.thoughtworks.acceptance.someobjects.Handler;
017: import com.thoughtworks.acceptance.someobjects.HandlerManager;
018: import com.thoughtworks.acceptance.someobjects.Protocol;
019: import com.thoughtworks.acceptance.someobjects.U;
020: import com.thoughtworks.acceptance.someobjects.WithList;
021: import com.thoughtworks.acceptance.someobjects.X;
022: import com.thoughtworks.acceptance.someobjects.Y;
023: import com.thoughtworks.xstream.converters.Converter;
024: import com.thoughtworks.xstream.converters.MarshallingContext;
025: import com.thoughtworks.xstream.converters.UnmarshallingContext;
026: import com.thoughtworks.xstream.core.JVM;
027: import com.thoughtworks.xstream.io.HierarchicalStreamReader;
028: import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
029: import com.thoughtworks.xstream.io.StreamException;
030: import com.thoughtworks.xstream.io.xml.AbstractDocumentReader;
031: import com.thoughtworks.xstream.io.xml.Dom4JDriver;
032:
033: import junit.framework.TestCase;
034:
035: import org.dom4j.Element;
036:
037: import java.io.IOException;
038: import java.io.ObjectOutputStream;
039: import java.io.StringReader;
040: import java.io.StringWriter;
041:
042: public class XStreamTest extends TestCase {
043:
044: private transient XStream xstream;
045:
046: protected void setUp() throws Exception {
047: super .setUp();
048: xstream = new XStream();
049: xstream.alias("x", X.class);
050: xstream.alias("y", Y.class);
051: xstream.alias("funny", FunnyConstructor.class);
052: xstream.alias("with-list", WithList.class);
053: }
054:
055: public void testUnmarshalsObjectFromXmlWithUnderscores() {
056: String xml = "<u-u>" + " <u-f>foo</u-f>" + " <u_f>_foo</u_f>"
057: + "</u-u>";
058:
059: xstream.alias("u-u", U.class);
060: xstream.aliasField("u-f", U.class, "aStr");
061: xstream.aliasField("u_f", U.class, "a_Str");
062: U u = (U) xstream.fromXML(xml);
063:
064: assertEquals("foo", u.aStr);
065: assertEquals("_foo", u.a_Str);
066: }
067:
068: public void testUnmarshalsObjectFromXmlWhichClassContainsUnderscores() {
069: String xml = "<com.thoughtworks.xstream.XStreamTest_-U_U>"
070: + " <aStr>custom value</aStr>"
071: + "</com.thoughtworks.xstream.XStreamTest_-U_U>";
072:
073: U_U u = (U_U) xstream.fromXML(xml);
074:
075: assertEquals("custom value", u.aStr);
076: }
077:
078: public void testUnmarshalsObjectFromXmlWithUnderscoresWithoutAliasingFields() {
079: String xml = "<u-u>" + " <a_Str>custom value</a_Str>"
080: + "</u-u>";
081:
082: xstream.alias("u-u", U.class);
083:
084: U u = (U) xstream.fromXML(xml);
085:
086: assertEquals("custom value", u.a_Str);
087: }
088:
089: public static class U_U {
090: String aStr;
091: }
092:
093: public void testUnmarshalsObjectFromXml() {
094:
095: String xml = "<x>" + " <aStr>joe</aStr>"
096: + " <anInt>8</anInt>" + " <innerObj>"
097: + " <yField>walnes</yField>" + " </innerObj>"
098: + "</x>";
099:
100: X x = (X) xstream.fromXML(xml);
101:
102: assertEquals("joe", x.aStr);
103: assertEquals(8, x.anInt);
104: assertEquals("walnes", x.innerObj.yField);
105: }
106:
107: public void testMarshalsObjectToXml() {
108: X x = new X();
109: x.anInt = 9;
110: x.aStr = "zzz";
111: x.innerObj = new Y();
112: x.innerObj.yField = "ooo";
113:
114: String expected = "<x>\n" + " <aStr>zzz</aStr>\n"
115: + " <anInt>9</anInt>\n" + " <innerObj>\n"
116: + " <yField>ooo</yField>\n" + " </innerObj>\n"
117: + "</x>";
118:
119: assertEquals(xstream.fromXML(expected), x);
120: }
121:
122: public void testUnmarshalsClassWithoutDefaultConstructor() {
123: if (!JVM.is14())
124: return;
125:
126: String xml = "<funny>" + " <i>999</i>" + "</funny>";
127:
128: FunnyConstructor funnyConstructor = (FunnyConstructor) xstream
129: .fromXML(xml);
130:
131: assertEquals(999, funnyConstructor.i);
132: }
133:
134: public void testHandlesLists() {
135: WithList original = new WithList();
136: Y y = new Y();
137: y.yField = "a";
138: original.things.add(y);
139: original.things.add(new X(3));
140: original.things.add(new X(1));
141:
142: String xml = xstream.toXML(original);
143:
144: String expected = "<with-list>\n" + " <things>\n"
145: + " <y>\n" + " <yField>a</yField>\n"
146: + " </y>\n" + " <x>\n"
147: + " <anInt>3</anInt>\n" + " </x>\n"
148: + " <x>\n" + " <anInt>1</anInt>\n"
149: + " </x>\n" + " </things>\n" + "</with-list>";
150:
151: assertEquals(expected, xml);
152:
153: WithList result = (WithList) xstream.fromXML(xml);
154: assertEquals(original, result);
155:
156: }
157:
158: public void testCanHandleNonStaticPrivateInnerClass() {
159: if (!JVM.is14())
160: return;
161:
162: NonStaticInnerClass obj = new NonStaticInnerClass();
163: obj.field = 3;
164:
165: xstream.alias("inner", NonStaticInnerClass.class);
166:
167: String xml = xstream.toXML(obj);
168:
169: String expected = ""
170: + "<inner>\n"
171: + " <field>3</field>\n"
172: + " <outer-class>\n"
173: + " <fName>testCanHandleNonStaticPrivateInnerClass</fName>\n"
174: + " </outer-class>\n" + "</inner>";
175:
176: assertEquals(xstream.fromXML(expected), obj);
177:
178: NonStaticInnerClass result = (NonStaticInnerClass) xstream
179: .fromXML(xml);
180: assertEquals(obj.field, result.field);
181: }
182:
183: public void testClassWithoutMappingUsesFullyQualifiedName() {
184: Person obj = new Person();
185:
186: String xml = xstream.toXML(obj);
187:
188: String expected = "<com.thoughtworks.xstream.XStreamTest_-Person/>";
189:
190: assertEquals(expected, xml);
191:
192: Person result = (Person) xstream.fromXML(xml);
193: assertEquals(obj, result);
194: }
195:
196: private class NonStaticInnerClass extends StandardObject {
197: int field;
198: }
199:
200: public void testCanBeBeUsedMultipleTimesWithSameInstance() {
201: Y obj = new Y();
202: obj.yField = "x";
203:
204: assertEquals(xstream.toXML(obj), xstream.toXML(obj));
205: }
206:
207: public void testAccessToUnderlyingDom4JImplementation()
208: throws Exception {
209:
210: String xml = "<person>" + " <firstName>jason</firstName>"
211: + " <lastName>van Zyl</lastName>" + " <element>"
212: + " <foo>bar</foo>" + " </element>" + "</person>";
213:
214: xstream.registerConverter(new ElementConverter());
215: xstream.alias("person", Person.class);
216:
217: Dom4JDriver driver = new Dom4JDriver();
218: Person person = (Person) xstream.unmarshal(driver
219: .createReader(new StringReader(xml)));
220:
221: assertEquals("jason", person.firstName);
222: assertEquals("van Zyl", person.lastName);
223: assertNotNull(person.element);
224: assertEquals("bar", person.element.element("foo").getText());
225: }
226:
227: public static class Person extends StandardObject {
228: String firstName;
229: String lastName;
230: Element element;
231: }
232:
233: private class ElementConverter implements Converter {
234:
235: public boolean canConvert(Class type) {
236: return Element.class.isAssignableFrom(type);
237: }
238:
239: public void marshal(Object source,
240: HierarchicalStreamWriter writer,
241: MarshallingContext context) {
242: }
243:
244: public Object unmarshal(HierarchicalStreamReader reader,
245: UnmarshallingContext context) {
246:
247: AbstractDocumentReader documentReader = (AbstractDocumentReader) reader
248: .underlyingReader();
249: Element element = (Element) documentReader.getCurrent();
250:
251: while (reader.hasMoreChildren()) {
252: reader.moveDown();
253: reader.moveUp();
254: }
255:
256: return element;
257: }
258: }
259:
260: public void testPopulationOfAnObjectGraphStartingWithALiveRootObject()
261: throws Exception {
262:
263: String xml = "<component>" + " <host>host</host>"
264: + " <port>8000</port>" + "</component>";
265:
266: xstream.alias("component", Component.class);
267:
268: Component component0 = new Component();
269: Component component1 = (Component) xstream.fromXML(xml,
270: component0);
271: assertSame(component0, component1);
272: assertEquals("host", component0.host);
273: assertEquals(8000, component0.port);
274: }
275:
276: static class Component {
277: String host;
278: int port;
279: }
280:
281: public void testPopulationOfThisAsRootObject() throws Exception {
282:
283: String xml = "" + "<component>\n" + " <host>host</host>\n"
284: + " <port>8000</port>\n" + "</component>";
285:
286: xstream.alias("component", SelfSerializingComponent.class);
287: SelfSerializingComponent component = new SelfSerializingComponent();
288: component.host = "host";
289: component.port = 8000;
290: assertEquals(xml, component.toXML(xstream));
291: component.host = "foo";
292: component.port = -1;
293: component.fromXML(xstream, xml);
294: assertEquals("host", component.host);
295: assertEquals(8000, component.port);
296: }
297:
298: static class SelfSerializingComponent extends Component {
299: String toXML(XStream xstream) {
300: return xstream.toXML(this );
301: }
302:
303: void fromXML(XStream xstream, String xml) {
304: xstream.fromXML(xml, this );
305: }
306: }
307:
308: public void testUnmarshalsWhenAllImplementationsAreSpecifiedUsingAClassIdentifier()
309: throws Exception {
310:
311: String xml = "<handlerManager class='com.thoughtworks.acceptance.someobjects.HandlerManager'>"
312: + " <handlers>"
313: + " <handler class='com.thoughtworks.acceptance.someobjects.Handler'>"
314: + " <protocol class='com.thoughtworks.acceptance.someobjects.Protocol'>"
315: + " <id>foo</id> "
316: + " </protocol> "
317: + " </handler>"
318: + " </handlers>"
319: + "</handlerManager>";
320:
321: HandlerManager hm = (HandlerManager) xstream.fromXML(xml);
322: Handler h = (Handler) hm.getHandlers().get(0);
323: Protocol p = h.getProtocol();
324: assertEquals("foo", p.getId());
325: }
326:
327: public void testObjectOutputStreamCloseTwice() throws IOException {
328: ObjectOutputStream oout = xstream
329: .createObjectOutputStream(new StringWriter());
330: oout.writeObject(new Integer(1));
331: oout.close();
332: oout.close();
333: }
334:
335: public void testObjectOutputStreamCloseAndFlush()
336: throws IOException {
337: ObjectOutputStream oout = xstream
338: .createObjectOutputStream(new StringWriter());
339: oout.writeObject(new Integer(1));
340: oout.close();
341: try {
342: oout.flush();
343: fail("Closing and flushing should throw a StreamException");
344: } catch (StreamException e) {
345: // ok
346: }
347: }
348:
349: public void testObjectOutputStreamCloseAndWrite()
350: throws IOException {
351: ObjectOutputStream oout = xstream
352: .createObjectOutputStream(new StringWriter());
353: oout.writeObject(new Integer(1));
354: oout.close();
355: try {
356: oout.writeObject(new Integer(2));
357: fail("Closing and writing should throw a StreamException");
358: } catch (StreamException e) {
359: // ok
360: }
361: }
362:
363: }
|