001: /*
002: * Copyright (C) 2003, 2004 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 com.thoughtworks.acceptance.objects.StandardObject;
015: import com.thoughtworks.xstream.converters.reflection.ReflectionConverter;
016: import com.thoughtworks.xstream.core.JVM;
017: import com.thoughtworks.xstream.io.xml.XppReader;
018:
019: import java.io.StringReader;
020:
021: public class CustomClassesTest extends AbstractAcceptanceTest {
022:
023: public static class SamplePerson extends StandardObject {
024: int anInt;
025: String firstName;
026: String lastName;
027: transient String aComment = "";
028: }
029:
030: public void testCustomObjectWithBasicFields() {
031:
032: xstream.alias("friend", SamplePerson.class);
033:
034: SamplePerson person = new SamplePerson();
035: person.anInt = 3;
036: person.firstName = "Joe";
037: person.lastName = "Walnes";
038:
039: String expected = "<friend>\n" + " <anInt>3</anInt>\n"
040: + " <firstName>Joe</firstName>\n"
041: + " <lastName>Walnes</lastName>\n" + "</friend>";
042:
043: assertBothWays(person, expected);
044:
045: }
046:
047: public static class SamplePersonHolder {
048: String aString;
049: SamplePerson brother;
050:
051: public boolean equals(Object obj) {
052: SamplePersonHolder containerObject = (SamplePersonHolder) obj;
053: return (aString == null ? containerObject.aString == null
054: : aString.equals(containerObject.aString))
055: && brother.equals(containerObject.brother);
056: }
057: }
058:
059: public void testCustomObjectWithCustomObjectField() {
060: xstream.alias("friend", SamplePerson.class);
061: xstream.alias("personHolder", SamplePersonHolder.class);
062:
063: SamplePersonHolder personHolder = new SamplePersonHolder();
064: personHolder.aString = "hello world";
065:
066: SamplePerson person = new SamplePerson();
067: person.anInt = 3;
068: person.firstName = "Joe";
069: person.lastName = "Walnes";
070:
071: personHolder.brother = person;
072:
073: String expected = "<personHolder>\n"
074: + " <aString>hello world</aString>\n"
075: + " <brother>\n" + " <anInt>3</anInt>\n"
076: + " <firstName>Joe</firstName>\n"
077: + " <lastName>Walnes</lastName>\n"
078: + " </brother>\n" + "</personHolder>";
079:
080: assertBothWays(personHolder, expected);
081:
082: }
083:
084: public void testCustomObjectWithCustomObjectFieldsSetToNull() {
085: xstream.alias("friend", SamplePerson.class);
086: xstream.alias("personHolder", SamplePersonHolder.class);
087:
088: SamplePersonHolder personHolder = new SamplePersonHolder();
089: personHolder.aString = null;
090:
091: SamplePerson person = new SamplePerson();
092: person.anInt = 3;
093: person.firstName = "Joe";
094: person.lastName = null;
095:
096: personHolder.brother = person;
097:
098: String expected = "<personHolder>\n" + " <brother>\n"
099: + " <anInt>3</anInt>\n"
100: + " <firstName>Joe</firstName>\n" + " </brother>\n"
101: + "</personHolder>";
102:
103: assertBothWays(personHolder, expected);
104:
105: }
106:
107: public void testCustomObjectCanBeInstantiatedExternallyBeforeDeserialization() {
108: xstream.alias("friend", SamplePerson.class);
109: xstream.alias("personHolder", SamplePersonHolder.class);
110:
111: String xml = "<personHolder>\n"
112: + " <aString>hello world</aString>\n"
113: + " <brother>\n" + " <anInt>3</anInt>\n"
114: + " <firstName>Joe</firstName>\n"
115: + " <lastName>Walnes</lastName>\n"
116: + " </brother>\n" + "</personHolder>";
117:
118: // execute
119: SamplePersonHolder alreadyInstantiated = new SamplePersonHolder();
120: xstream.unmarshal(new XppReader(new StringReader(xml)),
121: alreadyInstantiated);
122:
123: // verify
124: SamplePersonHolder expectedResult = new SamplePersonHolder();
125: expectedResult.aString = "hello world";
126:
127: SamplePerson expectedPerson = new SamplePerson();
128: expectedPerson.anInt = 3;
129: expectedPerson.firstName = "Joe";
130: expectedPerson.lastName = "Walnes";
131: expectedResult.brother = expectedPerson;
132:
133: assertEquals(expectedResult, alreadyInstantiated);
134: }
135:
136: public void testCustomObjectWillNotUnmarshalTransientFields() {
137:
138: xstream.alias("friend", SamplePerson.class);
139:
140: String xml = "<friend>\n" + " <anInt>3</anInt>\n"
141: + " <firstName>Joe</firstName>\n"
142: + " <lastName>Walnes</lastName>\n"
143: + " <aComment>XStream Despot</aComment>\n"
144: + "</friend>";
145:
146: SamplePerson person = (SamplePerson) xstream.fromXML(xml);
147: if (JVM.is14()) {
148: assertNull(person.aComment);
149: } else {
150: assertEquals("", person.aComment);
151: }
152: }
153:
154: static class Joe extends SamplePerson {
155: boolean aBoolean;
156: }
157:
158: public void testCustomObjectWillNotUnmarshalInheritedTransientFields() {
159:
160: xstream.alias("joe", Joe.class);
161:
162: String xml = "<joe>\n" + " <anInt>3</anInt>\n"
163: + " <firstName>Joe</firstName>\n"
164: + " <lastName>Walnes</lastName>\n"
165: + " <aComment>XStream Despot</aComment>\n"
166: + " <aBoolean>true</aBoolean>\n" + "</joe>";
167:
168: Joe joe = (Joe) xstream.fromXML(xml);
169: if (JVM.is14()) {
170: assertNull(joe.aComment);
171: } else {
172: assertEquals("", joe.aComment);
173: }
174: }
175:
176: public void testCustomObjectWillNotUnmarshalTransientFieldsFromAttributes() {
177:
178: xstream.alias("friend", SamplePerson.class);
179:
180: String xml = "<friend aComment='XStream Despot'>\n"
181: + " <anInt>3</anInt>\n"
182: + " <firstName>Joe</firstName>\n"
183: + " <lastName>Walnes</lastName>\n" + "</friend>";
184:
185: // without attribute definition
186: SamplePerson person = (SamplePerson) xstream.fromXML(xml);
187: if (JVM.is14()) {
188: assertNull(person.aComment);
189: } else {
190: assertEquals("", person.aComment);
191: }
192:
193: xstream.useAttributeFor("aComment", String.class);
194:
195: // with attribute definition
196: person = (SamplePerson) xstream.fromXML(xml);
197: if (JVM.is14()) {
198: assertNull(person.aComment);
199: } else {
200: assertEquals("", person.aComment);
201: }
202: }
203:
204: public void testNullObjectsDoNotHaveFieldsWritten() {
205:
206: xstream.alias("cls", WithSomeFields.class);
207:
208: WithSomeFields obj = new WithSomeFields();
209:
210: String expected = "<cls/>";
211:
212: assertBothWays(obj, expected);
213: }
214:
215: public void testEmptyStringsAreNotTreatedAsNulls() {
216: xstream.alias("cls", WithSomeFields.class);
217:
218: WithSomeFields obj = new WithSomeFields();
219: obj.b = "";
220:
221: String expected = "" + "<cls>\n" + " <b></b>\n" + "</cls>";
222:
223: assertBothWays(obj, expected);
224: }
225:
226: public static class WithSomeFields extends StandardObject {
227: Object a;
228: String b;
229: }
230:
231: public void testNullsAreDistinguishedFromEmptyStrings() {
232: LotsOfStrings in = new LotsOfStrings();
233: in.a = ".";
234: in.b = "";
235: in.c = null;
236:
237: String xml = xstream.toXML(in);
238: LotsOfStrings out = (LotsOfStrings) xstream.fromXML(xml);
239:
240: assertEquals(".", out.a);
241: assertEquals("", out.b);
242: assertNull(out.c);
243: }
244:
245: public static class LotsOfStrings {
246: String a;
247: String b;
248: String c;
249: }
250:
251: public void testFieldWithObjectType() {
252: String expected = "" + "<thing>\n" + " <one>1.0</one>\n"
253: + " <two class=\"double\">2.0</two>\n" + "</thing>";
254: xstream.alias("thing", FieldWithObjectType.class);
255:
256: assertBothWays(new FieldWithObjectType(), expected);
257: }
258:
259: public static class FieldWithObjectType extends StandardObject {
260: Double one = new Double(1.0);
261: Object two = new Double(2.0);
262: }
263:
264: public void testFailsFastIfFieldIsDefinedTwice() {
265: String input = "" + "<thing>\n" + " <one>1.0</one>\n"
266: + " <one>2.0</one>\n" + "</thing>";
267: xstream.alias("thing", FieldWithObjectType.class);
268:
269: try {
270:
271: xstream.fromXML(input);
272: fail("Expected exception");
273:
274: } catch (ReflectionConverter.DuplicateFieldException expected) {
275: assertEquals("one", expected.getShortMessage());
276: }
277: }
278:
279: public static class TransientInitializingClass extends
280: StandardObject {
281: private transient String s = "";
282:
283: private Object readResolve() {
284: this .s = "foo";
285: return this ;
286: }
287: }
288:
289: public void testCustomObjectWithTransientFieldInitialization() {
290:
291: xstream.alias("tran", TransientInitializingClass.class);
292:
293: TransientInitializingClass tran = new TransientInitializingClass();
294:
295: String expected = "<tran/>";
296:
297: TransientInitializingClass serialized = (TransientInitializingClass) assertBothWays(
298: tran, expected);
299: assertEquals("foo", serialized.s);
300: }
301: }
|