001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.object.dna.impl;
006:
007: import org.apache.commons.io.IOUtils;
008:
009: import com.tc.bytes.TCByteBuffer;
010: import com.tc.io.TCByteBufferInputStream;
011: import com.tc.io.TCByteBufferOutputStream;
012: import com.tc.io.serializer.TCObjectInputStream;
013: import com.tc.object.ObjectID;
014: import com.tc.object.bytecode.MockClassProvider;
015: import com.tc.object.dna.api.DNAEncoding;
016: import com.tc.object.loaders.ClassProvider;
017:
018: import java.io.ByteArrayInputStream;
019: import java.io.ByteArrayOutputStream;
020: import java.math.BigDecimal;
021: import java.math.BigInteger;
022: import java.util.ArrayList;
023: import java.util.Arrays;
024: import java.util.Iterator;
025: import java.util.List;
026: import java.util.Random;
027:
028: import junit.framework.TestCase;
029:
030: public class DNAEncodingTest extends TestCase {
031:
032: Random rnd = new Random();
033: ClassProvider classProvider = new MockClassProvider();
034:
035: public void testZeroLengthByteArray() throws Exception {
036: TCByteBufferOutputStream output = new TCByteBufferOutputStream();
037:
038: byte[] b = new byte[] {};
039:
040: DNAEncoding encoding = getApplicatorEncoding();
041: encoding.encode(b, output);
042:
043: // The bug this test is for only happens if DNAEncoding gets back -1 from the input stream upon being asked to read
044: // 0 bytes from a stream that is at EOF. ByteArrayInputStream happens to be one implemented in such a way
045: ByteArrayOutputStream baos = new ByteArrayOutputStream();
046: IOUtils.copy(new TCByteBufferInputStream(output.toArray()),
047: baos);
048: TCObjectInputStream input = new TCObjectInputStream(
049: new ByteArrayInputStream(baos.toByteArray()));
050:
051: assertTrue(Arrays.equals(b, (byte[]) encoding.decode(input)));
052:
053: assertEquals(0, input.available());
054: }
055:
056: public void testNonPrimitiveArrays2() throws Exception {
057: TCByteBufferOutputStream output = new TCByteBufferOutputStream();
058:
059: Integer[] array = new Integer[] { new Integer(43),
060: new Integer(-1) };
061: ObjectID[] array2 = new ObjectID[] {};
062:
063: DNAEncoding encoding = getApplicatorEncoding();
064: encoding.encodeArray(array, output);
065: encoding.encodeArray(array2, output);
066:
067: TCByteBufferInputStream input = new TCByteBufferInputStream(
068: output.toArray());
069:
070: assertTrue(Arrays.equals(array, (Object[]) encoding
071: .decode(input)));
072: assertTrue(Arrays.equals(array2, (Object[]) encoding
073: .decode(input)));
074:
075: assertEquals(0, input.available());
076: }
077:
078: private DNAEncoding getApplicatorEncoding() {
079: return new DNAEncodingImpl(classProvider);
080: }
081:
082: public void testNonPrimitiveArrays() throws Exception {
083: TCByteBufferOutputStream output = new TCByteBufferOutputStream();
084:
085: Object[] array = new Object[] { new ObjectID(12),
086: new Integer(34), new Double(Math.PI), ObjectID.NULL_ID,
087: new Long(Long.MIN_VALUE + 34), "timmy" };
088:
089: DNAEncoding encoding = getApplicatorEncoding();
090: encoding.encodeArray(array, output);
091:
092: TCByteBufferInputStream input = new TCByteBufferInputStream(
093: output.toArray());
094:
095: assertTrue(Arrays.equals(array, (Object[]) encoding
096: .decode(input)));
097:
098: assertEquals(0, input.available());
099: }
100:
101: public void testNullArray() throws Exception {
102: TCByteBufferOutputStream output = new TCByteBufferOutputStream();
103:
104: DNAEncoding encoding = getApplicatorEncoding();
105: encoding.encodeArray(null, output);
106: TCByteBufferInputStream input = new TCByteBufferInputStream(
107: output.toArray());
108:
109: assertNull(encoding.decode(input));
110:
111: assertEquals(0, input.available());
112: }
113:
114: public void testPrimitiveArrays() throws Exception {
115:
116: DNAEncoding encoding = getApplicatorEncoding();
117: for (int iter = 0; iter < 250; iter++) {
118: TCByteBufferOutputStream output = new TCByteBufferOutputStream();
119:
120: byte[] b = makeByteArray();
121: char[] c = makeCharArray();
122: double[] d = makeDoubleArray();
123: float[] f = makeFloatArray();
124: int[] i = makeIntArray();
125: long[] j = makeLongArray();
126: short[] s = makeShortArray();
127: boolean[] z = makeBooleanArray();
128:
129: encoding.encodeArray(b, output);
130: encoding.encodeArray(c, output);
131: encoding.encodeArray(d, output);
132: encoding.encodeArray(f, output);
133: encoding.encodeArray(i, output);
134: encoding.encodeArray(j, output);
135: encoding.encodeArray(s, output);
136: encoding.encodeArray(z, output);
137:
138: TCByteBufferInputStream input = new TCByteBufferInputStream(
139: output.toArray());
140:
141: assertTrue(Arrays
142: .equals(b, (byte[]) encoding.decode(input)));
143: assertTrue(Arrays
144: .equals(c, (char[]) encoding.decode(input)));
145: assertTrue(Arrays.equals(d, (double[]) encoding
146: .decode(input)));
147: assertTrue(Arrays.equals(f, (float[]) encoding
148: .decode(input)));
149: assertTrue(Arrays.equals(i, (int[]) encoding.decode(input)));
150: assertTrue(Arrays
151: .equals(j, (long[]) encoding.decode(input)));
152: assertTrue(Arrays.equals(s, (short[]) encoding
153: .decode(input)));
154: assertTrue(Arrays.equals(z, (boolean[]) encoding
155: .decode(input)));
156:
157: assertEquals(0, input.available());
158: }
159: }
160:
161: private short[] makeShortArray() {
162: short[] rv = new short[rnd.nextInt(10)];
163: for (int i = 0; i < rv.length; i++) {
164: rv[i] = (short) rnd.nextInt();
165: }
166: return rv;
167: }
168:
169: private long[] makeLongArray() {
170: long[] rv = new long[rnd.nextInt(10)];
171: for (int i = 0; i < rv.length; i++) {
172: rv[i] = rnd.nextLong();
173: }
174: return rv;
175: }
176:
177: private int[] makeIntArray() {
178: int[] rv = new int[rnd.nextInt(10)];
179: for (int i = 0; i < rv.length; i++) {
180: rv[i] = rnd.nextInt();
181: }
182: return rv;
183: }
184:
185: private float[] makeFloatArray() {
186: float[] rv = new float[rnd.nextInt(10)];
187: for (int i = 0; i < rv.length; i++) {
188: rv[i] = rnd.nextFloat();
189: }
190:
191: return rv;
192: }
193:
194: private double[] makeDoubleArray() {
195: double[] rv = new double[rnd.nextInt(10)];
196: for (int i = 0; i < rv.length; i++) {
197: rv[i] = rnd.nextDouble();
198: }
199:
200: return rv;
201: }
202:
203: private char[] makeCharArray() {
204: char[] rv = new char[rnd.nextInt(10)];
205: for (int i = 0; i < rv.length; i++) {
206: rv[i] = new Character((char) rnd
207: .nextInt(Character.MAX_VALUE)).charValue();
208: }
209: return rv;
210: }
211:
212: private byte[] makeByteArray() {
213: byte[] rv = new byte[rnd.nextInt(10)];
214: for (int i = 0; i < rv.length; i++) {
215: rv[i] = (byte) rnd.nextInt();
216: }
217: return rv;
218: }
219:
220: private boolean[] makeBooleanArray() {
221: boolean[] rv = new boolean[rnd.nextInt(10)];
222: for (int i = 0; i < rv.length; i++) {
223: rv[i] = rnd.nextBoolean();
224: }
225: return rv;
226: }
227:
228: public void testCompressedStringDecoding() throws Exception {
229: TCByteBufferOutputStream output = new TCByteBufferOutputStream();
230:
231: DNAEncoding encoding = getApplicatorEncoding();
232: String bigString = getBigString(100000);
233: encoding.encode(bigString, output);
234:
235: TCByteBuffer[] data = output.toArray();
236:
237: encoding = getStorageEncoder();
238: TCByteBufferInputStream input = new TCByteBufferInputStream(
239: data);
240: UTF8ByteDataHolder decoded = (UTF8ByteDataHolder) encoding
241: .decode(input);
242:
243: assertTrue(decoded.isCompressed());
244: assertEquals(bigString.getBytes("UTF-8").length, decoded
245: .getUnCompressedStringLength());
246: System.err.println("Compressed String length = "
247: + decoded.getBytes().length);
248: assertEquals(bigString, decoded.asString());
249:
250: output = new TCByteBufferOutputStream();
251: encoding.encode(decoded, output);
252: TCByteBuffer[] data2 = output.toArray();
253: input = new TCByteBufferInputStream(data2);
254: UTF8ByteDataHolder decoded2 = (UTF8ByteDataHolder) encoding
255: .decode(input);
256: assertEquals(decoded, decoded2);
257:
258: encoding = getApplicatorEncoding();
259: input = new TCByteBufferInputStream(data);
260: String str = (String) encoding.decode(input);
261: assertEquals(bigString, str);
262:
263: input = new TCByteBufferInputStream(data2);
264: str = (String) encoding.decode(input);
265: assertEquals(bigString, str);
266:
267: }
268:
269: private String getBigString(int length) {
270: String sample = "mold for Big String";
271: StringBuffer sb = new StringBuffer();
272: while (sb.length() < length) {
273: sb.append(sample);
274: }
275: return sb.toString();
276: }
277:
278: public void testStringDecode() throws Exception {
279: TCByteBufferOutputStream output = new TCByteBufferOutputStream();
280:
281: DNAEncoding encoding = getApplicatorEncoding();
282: encoding.encode("timmy", output);
283: UTF8ByteDataHolder orgUTF;
284: encoding.encode((orgUTF = new UTF8ByteDataHolder("teck"
285: .getBytes("UTF-8"))), output);
286:
287: TCByteBuffer[] data = output.toArray();
288:
289: encoding = getStorageEncoder();
290: TCByteBufferInputStream input = new TCByteBufferInputStream(
291: data);
292: UTF8ByteDataHolder decoded = (UTF8ByteDataHolder) encoding
293: .decode(input);
294: assertTrue(Arrays.equals("timmy".getBytes("UTF-8"), decoded
295: .getBytes()));
296: decoded = (UTF8ByteDataHolder) encoding.decode(input);
297: assertTrue(Arrays.equals("teck".getBytes("UTF-8"), decoded
298: .getBytes()));
299: assertEquals(0, input.available());
300:
301: encoding = getApplicatorEncoding();
302: input = new TCByteBufferInputStream(data);
303: String str = (String) encoding.decode(input);
304: assertEquals("timmy", str);
305: str = (String) encoding.decode(input);
306: assertEquals("teck", str);
307: assertEquals(0, input.available());
308:
309: encoding = getSerializerEncoder();
310: input = new TCByteBufferInputStream(data);
311: str = (String) encoding.decode(input);
312: assertEquals("timmy", str);
313: decoded = (UTF8ByteDataHolder) encoding.decode(input);
314: assertEquals(orgUTF, decoded);
315: assertEquals(0, input.available());
316: }
317:
318: private DNAEncoding getStorageEncoder() {
319: return new DNAEncodingImpl(DNAEncoding.STORAGE);
320: }
321:
322: private DNAEncoding getSerializerEncoder() {
323: return new DNAEncodingImpl(DNAEncoding.SERIALIZER);
324: }
325:
326: public void testClassExpand() throws Exception {
327: TCByteBufferOutputStream output = new TCByteBufferOutputStream();
328:
329: DNAEncoding encoding = getApplicatorEncoding();
330: encoding.encode(getClass(), output);
331: Class c = Object.class;
332: UTF8ByteDataHolder name = new UTF8ByteDataHolder(c.getName());
333: UTF8ByteDataHolder def = new UTF8ByteDataHolder(classProvider
334: .getLoaderDescriptionFor(c));
335: ClassInstance ci = new ClassInstance(name, def);
336: encoding.encode(ci, output);
337:
338: TCByteBuffer[] data = output.toArray();
339:
340: encoding = getStorageEncoder();
341: TCByteBufferInputStream input = new TCByteBufferInputStream(
342: data);
343: ClassInstance holder = (ClassInstance) encoding.decode(input);
344: assertEquals(getClass().getName(), holder.getName().asString());
345: assertEquals(classProvider.getLoaderDescriptionFor(getClass()),
346: holder.getLoaderDef().asString());
347:
348: holder = (ClassInstance) encoding.decode(input);
349: assertEquals(name, holder.getName());
350: assertEquals(def, holder.getLoaderDef());
351:
352: assertEquals(0, input.available());
353:
354: encoding = getApplicatorEncoding();
355: input = new TCByteBufferInputStream(data);
356: c = (Class) encoding.decode(input);
357: assertEquals(getClass(), c);
358: c = (Class) encoding.decode(input);
359: assertEquals(Object.class, c);
360: assertEquals(0, input.available());
361:
362: }
363:
364: public void testClassSerialize() throws Exception {
365: TCByteBufferOutputStream output = new TCByteBufferOutputStream();
366:
367: DNAEncoding encoding = getSerializerEncoder();
368: encoding.encode(getClass(), output);
369: Class c = Object.class;
370: UTF8ByteDataHolder name = new UTF8ByteDataHolder(c.getName());
371: UTF8ByteDataHolder def = new UTF8ByteDataHolder(classProvider
372: .getLoaderDescriptionFor(c));
373: ClassInstance ci = new ClassInstance(name, def);
374: encoding.encode(ci, output);
375:
376: TCByteBuffer[] data = output.toArray();
377:
378: encoding = getSerializerEncoder();
379: TCByteBufferInputStream input = new TCByteBufferInputStream(
380: data);
381: c = (Class) encoding.decode(input);
382: assertEquals(getClass(), c);
383: ClassInstance holder = (ClassInstance) encoding.decode(input);
384: assertEquals(ci, holder);
385: assertEquals(0, input.available());
386: }
387:
388: public void testBasic() throws Exception {
389: TCByteBufferOutputStream output = new TCByteBufferOutputStream();
390:
391: List data = new ArrayList();
392: data.add(new ObjectID(1));
393: data.add("one");
394: data.add(new Boolean(true));
395: data.add("two");
396: data.add(new Byte((byte) 42));
397: data.add("three");
398: data.add(new Character('\t'));
399: data.add("four");
400: data.add(new Double(Math.PI));
401: data.add("five");
402: data.add(new Float(Math.E));
403: data.add("six");
404: data.add(new Integer(Integer.MAX_VALUE));
405: data.add("seven");
406: data.add(new Long(System.currentTimeMillis() % 17));
407: data.add("eight");
408: data.add(new Short((short) -1));
409: data.add("nine");
410: data.add(new BigInteger(512, new Random()));
411: data.add("ten");
412: data.add(new BigDecimal(84564547.45465478d));
413:
414: DNAEncoding encoding = getApplicatorEncoding();
415: for (Iterator i = data.iterator(); i.hasNext();) {
416: encoding.encode(i.next(), output);
417: }
418:
419: TCByteBufferInputStream input = new TCByteBufferInputStream(
420: output.toArray());
421: for (Iterator i = data.iterator(); i.hasNext();) {
422: Object orig = i.next();
423: Object decoded = encoding.decode(input);
424:
425: assertEquals(orig, decoded);
426: }
427:
428: assertEquals(0, input.available());
429: }
430:
431: }
|