1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2002,2008 Oracle.  All rights reserved.
5 *
6 * $Id: TupleBindingTest.java,v 12.9 2008/02/07 17:12:30 mark Exp $
7 */
8
9package com.sleepycat.bind.tuple.test;
10
11import junit.framework.Test;
12import junit.framework.TestCase;
13import junit.framework.TestSuite;
14import java.math.BigInteger;
15
16import com.sleepycat.bind.EntityBinding;
17import com.sleepycat.bind.EntryBinding;
18import com.sleepycat.bind.tuple.BooleanBinding;
19import com.sleepycat.bind.tuple.ByteBinding;
20import com.sleepycat.bind.tuple.CharacterBinding;
21import com.sleepycat.bind.tuple.DoubleBinding;
22import com.sleepycat.bind.tuple.FloatBinding;
23import com.sleepycat.bind.tuple.IntegerBinding;
24import com.sleepycat.bind.tuple.LongBinding;
25import com.sleepycat.bind.tuple.ShortBinding;
26import com.sleepycat.bind.tuple.BigIntegerBinding;
27import com.sleepycat.bind.tuple.SortedDoubleBinding;
28import com.sleepycat.bind.tuple.SortedFloatBinding;
29import com.sleepycat.bind.tuple.StringBinding;
30import com.sleepycat.bind.tuple.TupleBinding;
31import com.sleepycat.bind.tuple.TupleInput;
32import com.sleepycat.bind.tuple.TupleInputBinding;
33import com.sleepycat.bind.tuple.TupleMarshalledBinding;
34import com.sleepycat.bind.tuple.TupleOutput;
35import com.sleepycat.bind.tuple.TupleTupleMarshalledBinding;
36import com.sleepycat.db.DatabaseEntry;
37import com.sleepycat.util.FastOutputStream;
38import com.sleepycat.util.ExceptionUnwrapper;
39import com.sleepycat.util.test.SharedTestUtils;
40
41/**
42 * @author Mark Hayes
43 */
44public class TupleBindingTest extends TestCase {
45
46    private DatabaseEntry buffer;
47    private DatabaseEntry keyBuffer;
48
49    public static void main(String[] args)
50        throws Exception {
51
52        junit.framework.TestResult tr =
53            junit.textui.TestRunner.run(suite());
54        if (tr.errorCount() > 0 ||
55            tr.failureCount() > 0) {
56            System.exit(1);
57        } else {
58            System.exit(0);
59        }
60    }
61
62    public static Test suite()
63        throws Exception {
64
65        TestSuite suite = new TestSuite(TupleBindingTest.class);
66        return suite;
67    }
68
69    public TupleBindingTest(String name) {
70
71        super(name);
72    }
73
74    public void setUp() {
75
76        SharedTestUtils.printTestName("TupleBindingTest." + getName());
77        buffer = new DatabaseEntry();
78        keyBuffer = new DatabaseEntry();
79    }
80
81    public void tearDown() {
82
83        /* Ensure that GC can cleanup. */
84        buffer = null;
85        keyBuffer = null;
86    }
87
88    public void runTest()
89        throws Throwable {
90
91        try {
92            super.runTest();
93        } catch (Exception e) {
94            throw ExceptionUnwrapper.unwrap(e);
95        }
96    }
97
98    private void primitiveBindingTest(Class primitiveCls, Class compareCls,
99                                      Object val, int byteSize) {
100
101        TupleBinding binding = TupleBinding.getPrimitiveBinding(primitiveCls);
102
103        /* Test standard object binding. */
104
105        binding.objectToEntry(val, buffer);
106        assertEquals(byteSize, buffer.getSize());
107
108        Object val2 = binding.entryToObject(buffer);
109        assertSame(compareCls, val2.getClass());
110        assertEquals(val, val2);
111
112        Object valWithWrongCls = (primitiveCls == String.class)
113                      ? ((Object) new Integer(0)) : ((Object) new String(""));
114        try {
115            binding.objectToEntry(valWithWrongCls, buffer);
116        }
117        catch (ClassCastException expected) {}
118
119        /* Test nested tuple binding. */
120	forMoreCoverageTest(binding, val);
121    }
122
123    private void forMoreCoverageTest(TupleBinding val1,Object val2) {
124
125        TupleOutput output = new TupleOutput();
126        output.writeString("abc");
127        val1.objectToEntry(val2, output);
128        output.writeString("xyz");
129
130        TupleInput input = new TupleInput(output);
131        assertEquals("abc", input.readString());
132        Object val3 = val1.entryToObject(input);
133        assertEquals("xyz", input.readString());
134
135        assertEquals(0, input.available());
136        assertSame(val2.getClass(), val3.getClass());
137        assertEquals(val2, val3);
138    }
139
140    public void testPrimitiveBindings() {
141
142        primitiveBindingTest(String.class, String.class,
143                             "abc", 4);
144
145        primitiveBindingTest(Character.class, Character.class,
146                             new Character('a'), 2);
147        primitiveBindingTest(Boolean.class, Boolean.class,
148                             new Boolean(true), 1);
149        primitiveBindingTest(Byte.class, Byte.class,
150                             new Byte((byte) 123), 1);
151        primitiveBindingTest(Short.class, Short.class,
152                             new Short((short) 123), 2);
153        primitiveBindingTest(Integer.class, Integer.class,
154                             new Integer(123), 4);
155	primitiveBindingTest(Long.class, Long.class,
156                             new Long(123), 8);
157        primitiveBindingTest(Float.class, Float.class,
158                             new Float(123.123), 4);
159        primitiveBindingTest(Double.class, Double.class,
160                             new Double(123.123), 8);
161
162        primitiveBindingTest(Character.TYPE, Character.class,
163                             new Character('a'), 2);
164        primitiveBindingTest(Boolean.TYPE, Boolean.class,
165                             new Boolean(true), 1);
166        primitiveBindingTest(Byte.TYPE, Byte.class,
167                             new Byte((byte) 123), 1);
168        primitiveBindingTest(Short.TYPE, Short.class,
169                             new Short((short) 123), 2);
170        primitiveBindingTest(Integer.TYPE, Integer.class,
171                             new Integer(123), 4);
172        primitiveBindingTest(Long.TYPE, Long.class,
173                             new Long(123), 8);
174        primitiveBindingTest(Float.TYPE, Float.class,
175                             new Float(123.123), 4);
176        primitiveBindingTest(Double.TYPE, Double.class,
177                             new Double(123.123), 8);
178
179        DatabaseEntry entry = new DatabaseEntry();
180
181        StringBinding.stringToEntry("abc", entry);
182	assertEquals(4, entry.getData().length);
183        assertEquals("abc", StringBinding.entryToString(entry));
184
185        new StringBinding().objectToEntry("abc", entry);
186	assertEquals(4, entry.getData().length);
187
188        StringBinding.stringToEntry(null, entry);
189	assertEquals(2, entry.getData().length);
190        assertEquals(null, StringBinding.entryToString(entry));
191
192        new StringBinding().objectToEntry(null, entry);
193	assertEquals(2, entry.getData().length);
194
195        CharacterBinding.charToEntry('a', entry);
196	assertEquals(2, entry.getData().length);
197        assertEquals('a', CharacterBinding.entryToChar(entry));
198
199        new CharacterBinding().objectToEntry(new Character('a'), entry);
200	assertEquals(2, entry.getData().length);
201
202        BooleanBinding.booleanToEntry(true, entry);
203	assertEquals(1, entry.getData().length);
204        assertEquals(true, BooleanBinding.entryToBoolean(entry));
205
206        new BooleanBinding().objectToEntry(Boolean.TRUE, entry);
207	assertEquals(1, entry.getData().length);
208
209        ByteBinding.byteToEntry((byte) 123, entry);
210	assertEquals(1, entry.getData().length);
211        assertEquals((byte) 123, ByteBinding.entryToByte(entry));
212
213        ShortBinding.shortToEntry((short) 123, entry);
214	assertEquals(2, entry.getData().length);
215        assertEquals((short) 123, ShortBinding.entryToShort(entry));
216
217        new ByteBinding().objectToEntry(new Byte((byte) 123), entry);
218	assertEquals(1, entry.getData().length);
219
220        IntegerBinding.intToEntry(123, entry);
221	assertEquals(4, entry.getData().length);
222        assertEquals(123, IntegerBinding.entryToInt(entry));
223
224        new IntegerBinding().objectToEntry(new Integer(123), entry);
225	assertEquals(4, entry.getData().length);
226
227        LongBinding.longToEntry(123, entry);
228	assertEquals(8, entry.getData().length);
229        assertEquals(123, LongBinding.entryToLong(entry));
230
231        new LongBinding().objectToEntry(new Long(123), entry);
232	assertEquals(8, entry.getData().length);
233
234        FloatBinding.floatToEntry((float) 123.123, entry);
235	assertEquals(4, entry.getData().length);
236        assertTrue(((float) 123.123) == FloatBinding.entryToFloat(entry));
237
238        new FloatBinding().objectToEntry(new Float((float) 123.123), entry);
239	assertEquals(4, entry.getData().length);
240
241        DoubleBinding.doubleToEntry(123.123, entry);
242	assertEquals(8, entry.getData().length);
243        assertTrue(123.123 == DoubleBinding.entryToDouble(entry));
244
245        new DoubleBinding().objectToEntry(new Double(123.123), entry);
246	assertEquals(8, entry.getData().length);
247
248        BigIntegerBinding.bigIntegerToEntry
249                (new BigInteger("1234567890123456"), entry);
250        assertEquals(9, entry.getData().length);
251        assertTrue((new BigInteger("1234567890123456")).equals
252		   (BigIntegerBinding.entryToBigInteger(entry)));
253
254        new BigIntegerBinding().objectToEntry
255                (new BigInteger("1234567890123456"), entry);
256        assertEquals(9, entry.getData().length);
257        forMoreCoverageTest(new BigIntegerBinding(),
258                            new BigInteger("1234567890123456"));
259
260        SortedFloatBinding.floatToEntry((float) 123.123, entry);
261	assertEquals(4, entry.getData().length);
262        assertTrue(((float) 123.123) ==
263                   SortedFloatBinding.entryToFloat(entry));
264
265        new SortedFloatBinding().objectToEntry
266            (new Float((float) 123.123), entry);
267	assertEquals(4, entry.getData().length);
268        forMoreCoverageTest(new SortedFloatBinding(),
269                            new Float((float) 123.123));
270
271        SortedDoubleBinding.doubleToEntry(123.123, entry);
272	assertEquals(8, entry.getData().length);
273        assertTrue(123.123 == SortedDoubleBinding.entryToDouble(entry));
274
275        new SortedDoubleBinding().objectToEntry(new Double(123.123), entry);
276	assertEquals(8, entry.getData().length);
277        forMoreCoverageTest(new SortedDoubleBinding(),
278                            new Double(123.123));
279    }
280
281    public void testTupleInputBinding() {
282
283        EntryBinding binding = new TupleInputBinding();
284
285        TupleOutput out = new TupleOutput();
286        out.writeString("abc");
287        binding.objectToEntry(new TupleInput(out), buffer);
288        assertEquals(4, buffer.getSize());
289
290        Object result = binding.entryToObject(buffer);
291        assertTrue(result instanceof TupleInput);
292        TupleInput in = (TupleInput) result;
293        assertEquals("abc", in.readString());
294        assertEquals(0, in.available());
295    }
296
297    // also tests TupleBinding since TupleMarshalledBinding extends it
298    public void testTupleMarshalledBinding() {
299
300        EntryBinding binding =
301            new TupleMarshalledBinding(MarshalledObject.class);
302
303        MarshalledObject val = new MarshalledObject("abc", "", "", "");
304        binding.objectToEntry(val, buffer);
305        assertEquals(val.expectedDataLength(), buffer.getSize());
306
307        Object result = binding.entryToObject(buffer);
308        assertTrue(result instanceof MarshalledObject);
309        val = (MarshalledObject) result;
310        assertEquals("abc", val.getData());
311    }
312
313    // also tests TupleTupleBinding since TupleTupleMarshalledBinding extends
314    // it
315    public void testTupleTupleMarshalledBinding() {
316
317        EntityBinding binding =
318            new TupleTupleMarshalledBinding(MarshalledObject.class);
319
320        MarshalledObject val = new MarshalledObject("abc", "primary",
321                                                    "index1", "index2");
322        binding.objectToData(val, buffer);
323        assertEquals(val.expectedDataLength(), buffer.getSize());
324        binding.objectToKey(val, keyBuffer);
325        assertEquals(val.expectedKeyLength(), keyBuffer.getSize());
326
327        Object result = binding.entryToObject(keyBuffer, buffer);
328        assertTrue(result instanceof MarshalledObject);
329        val = (MarshalledObject) result;
330        assertEquals("abc", val.getData());
331        assertEquals("primary", val.getPrimaryKey());
332        assertEquals("index1", val.getIndexKey1());
333        assertEquals("index2", val.getIndexKey2());
334    }
335
336    public void testBufferSize() {
337
338        CaptureSizeBinding binding = new CaptureSizeBinding();
339
340        binding.objectToEntry("x", buffer);
341        assertEquals("x", binding.entryToObject(buffer));
342        assertEquals(FastOutputStream.DEFAULT_INIT_SIZE, binding.bufSize);
343
344        binding.setTupleBufferSize(1000);
345        binding.objectToEntry("x", buffer);
346        assertEquals("x", binding.entryToObject(buffer));
347        assertEquals(1000, binding.bufSize);
348    }
349
350    private class CaptureSizeBinding extends TupleBinding {
351
352        int bufSize;
353
354        CaptureSizeBinding() {
355            super();
356        }
357
358        public TupleOutput getTupleOutput(Object object) {
359            TupleOutput out = super.getTupleOutput(object);
360            bufSize = out.getBufferBytes().length;
361            return out;
362        }
363
364        public Object entryToObject(TupleInput input) {
365            return input.readString();
366        }
367
368        public void objectToEntry(Object object, TupleOutput output) {
369            assertEquals(bufSize, output.getBufferBytes().length);
370            output.writeString((String) object);
371        }
372    }
373
374    public void testBufferOverride() {
375
376        TupleOutput out = new TupleOutput(new byte[10]);
377        CachedOutputBinding binding = new CachedOutputBinding(out);
378
379        binding.used = false;
380        binding.objectToEntry("x", buffer);
381        assertEquals("x", binding.entryToObject(buffer));
382        assertTrue(binding.used);
383
384        binding.used = false;
385        binding.objectToEntry("aaaaaaaaaaaaaaaaaaaaaa", buffer);
386        assertEquals("aaaaaaaaaaaaaaaaaaaaaa", binding.entryToObject(buffer));
387        assertTrue(binding.used);
388
389        binding.used = false;
390        binding.objectToEntry("x", buffer);
391        assertEquals("x", binding.entryToObject(buffer));
392        assertTrue(binding.used);
393    }
394
395    private class CachedOutputBinding extends TupleBinding {
396
397        TupleOutput out;
398        boolean used;
399
400        CachedOutputBinding(TupleOutput out) {
401            super();
402            this.out = out;
403        }
404
405        public TupleOutput getTupleOutput(Object object) {
406            out.reset();
407            used = true;
408            return out;
409        }
410
411        public Object entryToObject(TupleInput input) {
412            return input.readString();
413        }
414
415        public void objectToEntry(Object object, TupleOutput output) {
416            assertSame(out, output);
417            output.writeString((String) object);
418        }
419    }
420}
421