001: /*
002: * All content copyright (c) 2003-2007 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.object.walker;
006:
007: import org.apache.commons.io.IOUtils;
008: import org.apache.commons.lang.ClassUtils;
009:
010: import java.io.ByteArrayOutputStream;
011: import java.io.IOException;
012: import java.io.InputStream;
013: import java.util.AbstractList;
014: import java.util.AbstractMap;
015: import java.util.ArrayList;
016: import java.util.Arrays;
017: import java.util.Collection;
018: import java.util.HashMap;
019: import java.util.HashSet;
020: import java.util.LinkedHashMap;
021: import java.util.LinkedList;
022: import java.util.Map;
023: import java.util.Set;
024: import java.util.TreeMap;
025:
026: import junit.framework.TestCase;
027:
028: public class BasicWalkerTest extends TestCase {
029:
030: public void helper(Object root, String fileNamePrefix)
031: throws IOException {
032: WalkTest test = new MyWalkTestImpl();
033:
034: MyOutputSink sink = new MyOutputSink();
035:
036: ObjectGraphWalker t = new ObjectGraphWalker(root, test,
037: new PrintVisitor(sink, test, new MyValueFormatter()));
038: t.walk();
039:
040: String output = sink.buffer.toString();
041: System.err.println(output);
042: validate(fileNamePrefix, output);
043: }
044:
045: public void test() throws IOException {
046: Root r = new Root();
047: r.m.put("timmy", new Foo());
048: r.m.put("yo", null);
049: r.m.put("foo", new Foo());
050: r.m.put("foo foo", new Foo(new Foo()));
051:
052: helper(r, ClassUtils.getShortClassName(getClass()));
053: }
054:
055: public void testArrayListSubclass() throws IOException {
056: helper(new ArrayListSubclass(), "ArrayListSubclassWalkerTest");
057: }
058:
059: public void testAbstractListSubclass() throws IOException {
060: helper(new AbstractListSubclass(),
061: "AbstractListSubclassWalkerTest");
062: }
063:
064: public void testHashMapSubclass() throws IOException {
065: helper(new HashMapSubclass(), "HashMapSubclassWalkerTest");
066: }
067:
068: public void testAbstractMapSubclass() throws IOException {
069: helper(new AbstractMapSubclass(),
070: "AbstractMapSubclassWalkerTest");
071: }
072:
073: private void validate(String name, String output)
074: throws IOException {
075: String expected = getExpected(name);
076:
077: expected = expected.replaceAll("\r", "");
078: output = output.replaceAll("\r", "");
079:
080: assertEquals(expected, output);
081: }
082:
083: private String getExpected(String name) throws IOException {
084: String resource = name + "-output.txt";
085: ByteArrayOutputStream baos = new ByteArrayOutputStream();
086:
087: InputStream in = null;
088: try {
089: in = getClass().getResourceAsStream(resource);
090: if (in == null) {
091: fail("missing resource: " + resource);
092: }
093: IOUtils.copy(in, baos);
094: } finally {
095: if (in != null) {
096: try {
097: in.close();
098: } catch (Exception e) {
099: throw new RuntimeException(e);
100: }
101: }
102: }
103:
104: baos.flush();
105: return new String(baos.toByteArray());
106: }
107:
108: private static class MyOutputSink implements
109: PrintVisitor.OutputSink {
110: final StringBuffer buffer = new StringBuffer();
111:
112: public void output(String line) {
113: buffer.append(line + "\n");
114: }
115: }
116:
117: private static class MyValueFormatter implements
118: PrintVisitor.ValueFormatter {
119:
120: public String format(Object o) {
121: if (o instanceof String) {
122: return "\"" + o + "\"";
123: }
124: return String.valueOf(o);
125: }
126:
127: public String valueAdornment(MemberValue value) {
128: return null;
129: }
130:
131: }
132:
133: private static class MyWalkTestImpl implements WalkTest {
134: private static Set logicalTypes = new HashSet();
135:
136: static {
137: logicalTypes.add(ArrayList.class);
138: logicalTypes.add(HashMap.class);
139: logicalTypes.add(TreeMap.class);
140: logicalTypes.add(LinkedHashMap.class);
141: logicalTypes.add(LinkedList.class);
142: }
143:
144: public boolean includeFieldsForType(Class type) {
145: return !logicalTypes.contains(type);
146: }
147:
148: public boolean shouldTraverse(MemberValue value) {
149: Object val = value.getValueObject();
150:
151: if ((val == null) || val.getClass().isPrimitive()) {
152: return false;
153: }
154:
155: if (val.getClass() == String.class)
156: return false;
157: if (val.getClass() == Class.class)
158: return false;
159:
160: if (val.getClass() == Byte.class)
161: return false;
162: if (val.getClass() == Boolean.class)
163: return false;
164: if (val.getClass() == Character.class)
165: return false;
166: if (val.getClass() == Double.class)
167: return false;
168: if (val.getClass() == Integer.class)
169: return false;
170: if (val.getClass() == Long.class)
171: return false;
172: if (val.getClass() == Short.class)
173: return false;
174: if (val.getClass() == Float.class)
175: return false;
176:
177: return true;
178: }
179: }
180:
181: private static class Root {
182: int i = 12;
183: Map m = new LinkedHashMap();
184: String s = "root";
185: Object b = new B();
186: int[] intArray = new int[] { 1, 2, 3 };
187: Object[] objArray = new Object[] { this , new Foo(),
188: new Integer(3) };
189: Object self = this ;
190: Object[][] multi = new Object[][] {
191: { "timmy", new Integer(4) }, { null, null },
192: { null, this } };
193:
194: double[] emptyArray = new double[] {};
195: HashMap emptyMap = new HashMap();
196: LinkedList emptyList = new LinkedList();
197:
198: Class clazz = getClass();
199:
200: Collection c = new ArrayList();
201: {
202: c.add(new Foo(new Foo()));
203: Map tm = new TreeMap();
204: tm.put("key", new Foo());
205: tm.put("k", null);
206: c.add(tm);
207: c.add(c);
208: c.add(null);
209: c.add(new Double(Math.PI));
210: }
211: }
212:
213: private static class B extends A {
214: // this variable is "shadowed" on purpose, please do not rename them to remove the eclipse warning
215: private int i = 1;
216: }
217:
218: private static class A {
219: // this variable is "shadowed" on purpose, please do not rename them to remove the eclipse warning
220: private int i = 0;
221: }
222:
223: private static class Foo {
224: private final int i = next();
225:
226: private final Foo next;
227:
228: public Foo() {
229: this (null);
230: }
231:
232: public Foo(Foo foo) {
233: this .next = foo;
234: }
235:
236: public int getI() {
237: return i;
238: }
239:
240: public Foo getNext() {
241: return next;
242: }
243:
244: private static int num = 0;
245:
246: private synchronized static int next() {
247: return num++;
248: }
249: }
250:
251: private static class ArrayListSubclass extends ArrayList {
252: private int iVal;
253: private String sVal;
254:
255: public int getIVal() {
256: return iVal;
257: }
258:
259: public void setIVal(int val) {
260: iVal = val;
261: }
262:
263: public String getSVal() {
264: return sVal;
265: }
266:
267: public void setSVal(String val) {
268: sVal = val;
269: }
270:
271: ArrayListSubclass() {
272: super ();
273: addAll(Arrays.asList(new String[] { "foo", "bar" }));
274: iVal = 42;
275: sVal = "timmy";
276: }
277:
278: }
279:
280: private static class AbstractListSubclass extends AbstractList {
281: private int iVal;
282: private String sVal;
283:
284: AbstractListSubclass() {
285: iVal = 42;
286: sVal = "timmy";
287: }
288:
289: public Object get(int index) {
290: return null;
291: }
292:
293: public int size() {
294: return 0;
295: }
296:
297: public int getIVal() {
298: return iVal;
299: }
300:
301: public void setIVal(int val) {
302: iVal = val;
303: }
304:
305: public String getSVal() {
306: return sVal;
307: }
308:
309: public void setSVal(String val) {
310: sVal = val;
311: }
312:
313: }
314:
315: private static class HashMapSubclass extends LinkedHashMap {
316: private int iVal;
317: private String sVal;
318:
319: public int getIVal() {
320: return iVal;
321: }
322:
323: public void setIVal(int val) {
324: iVal = val;
325: }
326:
327: public String getSVal() {
328: return sVal;
329: }
330:
331: public void setSVal(String val) {
332: sVal = val;
333: }
334:
335: HashMapSubclass() {
336: super ();
337: put("sVal", "timmy");
338: put("iVal", new Integer(42));
339: iVal = 42;
340: sVal = "timmy";
341: }
342:
343: }
344:
345: private static class AbstractMapSubclass extends AbstractMap {
346: private int iVal;
347: private String sVal;
348:
349: AbstractMapSubclass() {
350: iVal = 42;
351: sVal = "timmy";
352: }
353:
354: public int getIVal() {
355: return iVal;
356: }
357:
358: public void setIVal(int val) {
359: iVal = val;
360: }
361:
362: public String getSVal() {
363: return sVal;
364: }
365:
366: public void setSVal(String val) {
367: sVal = val;
368: }
369:
370: public Set entrySet() {
371: return new HashSet();
372: }
373:
374: }
375:
376: }
|