/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2002, 2015 Oracle and/or its affiliates. All rights reserved.
*
*/
package com.sleepycat.bind.tuple.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.math.BigDecimal;
import java.math.BigInteger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.sleepycat.bind.EntityBinding;
import com.sleepycat.bind.EntryBinding;
import com.sleepycat.bind.tuple.BigDecimalBinding;
import com.sleepycat.bind.tuple.BigIntegerBinding;
import com.sleepycat.bind.tuple.BooleanBinding;
import com.sleepycat.bind.tuple.ByteBinding;
import com.sleepycat.bind.tuple.CharacterBinding;
import com.sleepycat.bind.tuple.DoubleBinding;
import com.sleepycat.bind.tuple.FloatBinding;
import com.sleepycat.bind.tuple.IntegerBinding;
import com.sleepycat.bind.tuple.LongBinding;
import com.sleepycat.bind.tuple.PackedIntegerBinding;
import com.sleepycat.bind.tuple.PackedLongBinding;
import com.sleepycat.bind.tuple.ShortBinding;
import com.sleepycat.bind.tuple.SortedBigDecimalBinding;
import com.sleepycat.bind.tuple.SortedDoubleBinding;
import com.sleepycat.bind.tuple.SortedFloatBinding;
import com.sleepycat.bind.tuple.SortedPackedIntegerBinding;
import com.sleepycat.bind.tuple.SortedPackedLongBinding;
import com.sleepycat.bind.tuple.StringBinding;
import com.sleepycat.bind.tuple.TupleBinding;
import com.sleepycat.bind.tuple.TupleInput;
import com.sleepycat.bind.tuple.TupleInputBinding;
import com.sleepycat.bind.tuple.TupleMarshalledBinding;
import com.sleepycat.bind.tuple.TupleOutput;
import com.sleepycat.bind.tuple.TupleTupleMarshalledBinding;
import com.sleepycat.db.DatabaseEntry;
import com.sleepycat.util.FastOutputStream;
/**
* @author Mark Hayes
*/
public class TupleBindingTest {
private DatabaseEntry buffer;
private DatabaseEntry keyBuffer;
@Before
public void setUp() {
buffer = new DatabaseEntry();
keyBuffer = new DatabaseEntry();
}
@After
public void tearDown() {
/* Ensure that GC can cleanup. */
buffer = null;
keyBuffer = null;
}
private void primitiveBindingTest(Class primitiveCls, Class compareCls,
Object val, int byteSize) {
TupleBinding binding = TupleBinding.getPrimitiveBinding(primitiveCls);
/* Test standard object binding. */
binding.objectToEntry(val, buffer);
assertEquals(byteSize, buffer.getSize());
Object val2 = binding.entryToObject(buffer);
assertSame(compareCls, val2.getClass());
assertEquals(val, val2);
Object valWithWrongCls = (primitiveCls == String.class)
? ((Object) new Integer(0)) : ((Object) new String(""));
try {
binding.objectToEntry(valWithWrongCls, buffer);
}
catch (ClassCastException expected) {}
/* Test nested tuple binding. */
forMoreCoverageTest(binding, val);
}
private void forMoreCoverageTest(TupleBinding val1,Object val2) {
TupleOutput output = new TupleOutput();
output.writeString("abc");
val1.objectToEntry(val2, output);
output.writeString("xyz");
TupleInput input = new TupleInput(output);
assertEquals("abc", input.readString());
Object val3 = val1.entryToObject(input);
assertEquals("xyz", input.readString());
assertEquals(0, input.available());
assertSame(val2.getClass(), val3.getClass());
assertEquals(val2, val3);
}
@Test
public void testPrimitiveBindings() {
primitiveBindingTest(String.class, String.class,
"abc", 4);
primitiveBindingTest(Character.class, Character.class,
new Character('a'), 2);
primitiveBindingTest(Boolean.class, Boolean.class,
new Boolean(true), 1);
primitiveBindingTest(Byte.class, Byte.class,
new Byte((byte) 123), 1);
primitiveBindingTest(Short.class, Short.class,
new Short((short) 123), 2);
primitiveBindingTest(Integer.class, Integer.class,
new Integer(123), 4);
primitiveBindingTest(Long.class, Long.class,
new Long(123), 8);
primitiveBindingTest(Float.class, Float.class,
new Float(123.123), 4);
primitiveBindingTest(Double.class, Double.class,
new Double(123.123), 8);
primitiveBindingTest(Character.TYPE, Character.class,
new Character('a'), 2);
primitiveBindingTest(Boolean.TYPE, Boolean.class,
new Boolean(true), 1);
primitiveBindingTest(Byte.TYPE, Byte.class,
new Byte((byte) 123), 1);
primitiveBindingTest(Short.TYPE, Short.class,
new Short((short) 123), 2);
primitiveBindingTest(Integer.TYPE, Integer.class,
new Integer(123), 4);
primitiveBindingTest(Long.TYPE, Long.class,
new Long(123), 8);
primitiveBindingTest(Float.TYPE, Float.class,
new Float(123.123), 4);
primitiveBindingTest(Double.TYPE, Double.class,
new Double(123.123), 8);
DatabaseEntry entry = new DatabaseEntry();
StringBinding.stringToEntry("abc", entry);
assertEquals(4, entry.getData().length);
assertEquals("abc", StringBinding.entryToString(entry));
new StringBinding().objectToEntry("abc", entry);
assertEquals(4, entry.getData().length);
StringBinding.stringToEntry(null, entry);
assertEquals(2, entry.getData().length);
assertEquals(null, StringBinding.entryToString(entry));
new StringBinding().objectToEntry(null, entry);
assertEquals(2, entry.getData().length);
CharacterBinding.charToEntry('a', entry);
assertEquals(2, entry.getData().length);
assertEquals('a', CharacterBinding.entryToChar(entry));
new CharacterBinding().objectToEntry(new Character('a'), entry);
assertEquals(2, entry.getData().length);
BooleanBinding.booleanToEntry(true, entry);
assertEquals(1, entry.getData().length);
assertEquals(true, BooleanBinding.entryToBoolean(entry));
new BooleanBinding().objectToEntry(Boolean.TRUE, entry);
assertEquals(1, entry.getData().length);
ByteBinding.byteToEntry((byte) 123, entry);
assertEquals(1, entry.getData().length);
assertEquals((byte) 123, ByteBinding.entryToByte(entry));
ShortBinding.shortToEntry((short) 123, entry);
assertEquals(2, entry.getData().length);
assertEquals((short) 123, ShortBinding.entryToShort(entry));
new ByteBinding().objectToEntry(new Byte((byte) 123), entry);
assertEquals(1, entry.getData().length);
IntegerBinding.intToEntry(123, entry);
assertEquals(4, entry.getData().length);
assertEquals(123, IntegerBinding.entryToInt(entry));
new IntegerBinding().objectToEntry(new Integer(123), entry);
assertEquals(4, entry.getData().length);
LongBinding.longToEntry(123, entry);
assertEquals(8, entry.getData().length);
assertEquals(123, LongBinding.entryToLong(entry));
new LongBinding().objectToEntry(new Long(123), entry);
assertEquals(8, entry.getData().length);
FloatBinding.floatToEntry((float) 123.123, entry);
assertEquals(4, entry.getData().length);
assertTrue(((float) 123.123) == FloatBinding.entryToFloat(entry));
new FloatBinding().objectToEntry(new Float((float) 123.123), entry);
assertEquals(4, entry.getData().length);
DoubleBinding.doubleToEntry(123.123, entry);
assertEquals(8, entry.getData().length);
assertTrue(123.123 == DoubleBinding.entryToDouble(entry));
new DoubleBinding().objectToEntry(new Double(123.123), entry);
assertEquals(8, entry.getData().length);
BigIntegerBinding.bigIntegerToEntry
(new BigInteger("1234567890123456"), entry);
assertEquals(9, entry.getData().length);
assertTrue((new BigInteger("1234567890123456")).equals
(BigIntegerBinding.entryToBigInteger(entry)));
new BigIntegerBinding().objectToEntry
(new BigInteger("1234567890123456"), entry);
assertEquals(9, entry.getData().length);
forMoreCoverageTest(new BigIntegerBinding(),
new BigInteger("1234567890123456"));
SortedFloatBinding.floatToEntry((float) 123.123, entry);
assertEquals(4, entry.getData().length);
assertTrue(((float) 123.123) ==
SortedFloatBinding.entryToFloat(entry));
new SortedFloatBinding().objectToEntry
(new Float((float) 123.123), entry);
assertEquals(4, entry.getData().length);
forMoreCoverageTest(new SortedFloatBinding(),
new Float((float) 123.123));
SortedDoubleBinding.doubleToEntry(123.123, entry);
assertEquals(8, entry.getData().length);
assertTrue(123.123 == SortedDoubleBinding.entryToDouble(entry));
new SortedDoubleBinding().objectToEntry(new Double(123.123), entry);
assertEquals(8, entry.getData().length);
forMoreCoverageTest(new SortedDoubleBinding(),
new Double(123.123));
PackedIntegerBinding.intToEntry(1234, entry);
assertEquals(5, entry.getData().length);
assertTrue(1234 == PackedIntegerBinding.entryToInt(entry));
new PackedIntegerBinding().objectToEntry
(new Integer(1234), entry);
assertEquals(5, entry.getData().length);
forMoreCoverageTest(new PackedIntegerBinding(),
new Integer(1234));
PackedLongBinding.longToEntry(1234, entry);
assertEquals(9, entry.getData().length);
assertTrue(1234 == PackedLongBinding.entryToLong(entry));
new PackedLongBinding().objectToEntry(new Long(1234), entry);
assertEquals(9, entry.getData().length);
forMoreCoverageTest(new PackedLongBinding(), new Long(1234));
BigDecimalBinding.bigDecimalToEntry
(new BigDecimal("123456789.123456789"), entry);
assertEquals(5 * 2 + new BigDecimal("123456789.123456789").
unscaledValue().toByteArray().length,
entry.getData().length);
assertTrue((new BigDecimal("123456789.123456789")).equals
(BigDecimalBinding.entryToBigDecimal(entry)));
SortedPackedIntegerBinding.intToEntry(1234, entry);
assertEquals(5, entry.getData().length);
assertTrue(1234 == SortedPackedIntegerBinding.entryToInt(entry));
new SortedPackedIntegerBinding().objectToEntry
(new Integer(1234), entry);
assertEquals(5, entry.getData().length);
forMoreCoverageTest(new SortedPackedIntegerBinding(),
new Integer(1234));
SortedPackedLongBinding.longToEntry(1234, entry);
assertEquals(9, entry.getData().length);
assertTrue(1234 == SortedPackedLongBinding.entryToLong(entry));
new SortedPackedLongBinding().objectToEntry(new Long(1234), entry);
assertEquals(9, entry.getData().length);
forMoreCoverageTest(new SortedPackedLongBinding(), new Long(1234));
BigDecimalBinding.bigDecimalToEntry
(new BigDecimal("123456789.123456789"), entry);
assertEquals(5 * 2 + new BigDecimal("123456789.123456789").
unscaledValue().toByteArray().length,
entry.getData().length);
assertTrue((new BigDecimal("123456789.123456789")).equals
(BigDecimalBinding.entryToBigDecimal(entry)));
new BigDecimalBinding().objectToEntry
(new BigDecimal("123456789.123456789"), entry);
assertEquals(5 * 2 + new BigDecimal("123456789.123456789").
unscaledValue().toByteArray().length,
entry.getData().length);
forMoreCoverageTest(new BigDecimalBinding(),
new BigDecimal("123456789.123456789"));
SortedBigDecimalBinding.bigDecimalToEntry
(new BigDecimal("123456789.123456"), entry);
assertEquals(1 + 5 + 5 * 2 + 1, entry.getData().length);
assertEquals(0,(new BigDecimal("123456789.123456")).compareTo
(SortedBigDecimalBinding.entryToBigDecimal(entry)));
new SortedBigDecimalBinding().objectToEntry
(new BigDecimal("123456789.123456E100"), entry);
assertEquals(1 + 5 + 5 * 2 + 1, entry.getData().length);
forMoreCoverageTest(new SortedBigDecimalBinding(),
new BigDecimal("123456789.123456"));
}
@Test
public void testTupleInputBinding() {
EntryBinding binding = new TupleInputBinding();
TupleOutput out = new TupleOutput();
out.writeString("abc");
binding.objectToEntry(new TupleInput(out), buffer);
assertEquals(4, buffer.getSize());
Object result = binding.entryToObject(buffer);
assertTrue(result instanceof TupleInput);
TupleInput in = (TupleInput) result;
assertEquals("abc", in.readString());
assertEquals(0, in.available());
}
// also tests TupleBinding since TupleMarshalledBinding extends it
@Test
public void testTupleMarshalledBinding() {
EntryBinding binding =
new TupleMarshalledBinding(MarshalledObject.class);
MarshalledObject val = new MarshalledObject("abc", "", "", "");
binding.objectToEntry(val, buffer);
assertEquals(val.expectedDataLength(), buffer.getSize());
Object result = binding.entryToObject(buffer);
assertTrue(result instanceof MarshalledObject);
val = (MarshalledObject) result;
assertEquals("abc", val.getData());
}
// also tests TupleTupleBinding since TupleTupleMarshalledBinding extends
// it
@Test
public void testTupleTupleMarshalledBinding() {
EntityBinding binding =
new TupleTupleMarshalledBinding(MarshalledObject.class);
MarshalledObject val = new MarshalledObject("abc", "primary",
"index1", "index2");
binding.objectToData(val, buffer);
assertEquals(val.expectedDataLength(), buffer.getSize());
binding.objectToKey(val, keyBuffer);
assertEquals(val.expectedKeyLength(), keyBuffer.getSize());
Object result = binding.entryToObject(keyBuffer, buffer);
assertTrue(result instanceof MarshalledObject);
val = (MarshalledObject) result;
assertEquals("abc", val.getData());
assertEquals("primary", val.getPrimaryKey());
assertEquals("index1", val.getIndexKey1());
assertEquals("index2", val.getIndexKey2());
}
@Test
public void testBufferSize() {
CaptureSizeBinding binding = new CaptureSizeBinding();
binding.objectToEntry("x", buffer);
assertEquals("x", binding.entryToObject(buffer));
assertEquals(FastOutputStream.DEFAULT_INIT_SIZE, binding.bufSize);
binding.setTupleBufferSize(1000);
binding.objectToEntry("x", buffer);
assertEquals("x", binding.entryToObject(buffer));
assertEquals(1000, binding.bufSize);
}
private class CaptureSizeBinding extends TupleBinding {
int bufSize;
CaptureSizeBinding() {
super();
}
@Override
public TupleOutput getTupleOutput(Object object) {
TupleOutput out = super.getTupleOutput(object);
bufSize = out.getBufferBytes().length;
return out;
}
@Override
public Object entryToObject(TupleInput input) {
return input.readString();
}
@Override
public void objectToEntry(Object object, TupleOutput output) {
assertEquals(bufSize, output.getBufferBytes().length);
output.writeString((String) object);
}
}
@Test
public void testBufferOverride() {
TupleOutput out = new TupleOutput(new byte[10]);
CachedOutputBinding binding = new CachedOutputBinding(out);
binding.used = false;
binding.objectToEntry("x", buffer);
assertEquals("x", binding.entryToObject(buffer));
assertTrue(binding.used);
binding.used = false;
binding.objectToEntry("aaaaaaaaaaaaaaaaaaaaaa", buffer);
assertEquals("aaaaaaaaaaaaaaaaaaaaaa", binding.entryToObject(buffer));
assertTrue(binding.used);
binding.used = false;
binding.objectToEntry("x", buffer);
assertEquals("x", binding.entryToObject(buffer));
assertTrue(binding.used);
}
private class CachedOutputBinding extends TupleBinding {
TupleOutput out;
boolean used;
CachedOutputBinding(TupleOutput out) {
super();
this.out = out;
}
@Override
public TupleOutput getTupleOutput(Object object) {
out.reset();
used = true;
return out;
}
@Override
public Object entryToObject(TupleInput input) {
return input.readString();
}
@Override
public void objectToEntry(Object object, TupleOutput output) {
assertSame(out, output);
output.writeString((String) object);
}
}
}