/**
* Copyright (C) 2009-2013 FoundationDB, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.foundationdb.server;
import com.foundationdb.server.types.TClass;
import com.foundationdb.server.types.mcompat.mtypes.MBinary;
import com.foundationdb.server.types.mcompat.mtypes.MNumeric;
import com.foundationdb.server.types.mcompat.mtypes.MString;
import com.foundationdb.server.types.value.ValueSources;
import com.persistit.Persistit;
import com.persistit.Value;
import org.junit.Test;
import java.math.BigDecimal;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public final class PersistitValueValueSourceTest {
@Test
public void testSkippingNulls() {
PersistitValueValueSource source = createSource(new ValueInit() {
@Override
public void putValues(Value value) {
value.putNull();
value.put(1234L);
}
});
readyAndCheck(source, null);
readyAndCheck(source, MNumeric.BIGINT);
assertEquals("source value", 1234L, source.getInt64());
}
@Test
public void sameRefTwice() {
// see https://bugs.launchpad.net/akiban-persistit/+bug/1073357
// The problem happens when a Value has the same object reference twice -- that is, two objects that are
// == each other (not just equals). The second object would result in value.getType() == Object, instead of
// the value's more specific type.
// A String, a Long and a byte[] walk into a bar. Bartender says to them, "I Value you as customers."
// The next day they walk back into the same bar, and he says, "now I Object!"
PersistitValueValueSource source = createSource(new ValueInit() {
@Override
public void putValues(Value value) {
String stringRef = "foo";
long longVal = 456L;
byte[] bytesRef = new byte[]{1, 2, 3};
value.put(stringRef);
value.put(longVal);
value.put(bytesRef);
value.put(stringRef);
value.put(longVal);
value.put(bytesRef);
}
});
// first set
readyAndCheck(source, MString.VARCHAR);
assertEquals("source value", "foo", source.getString());
readyAndCheck(source, MNumeric.BIGINT);
assertEquals("source value", 456L, source.getInt64());
readyAndCheck(source, MBinary.VARBINARY);
assertArrayEquals("source value", new byte[] {1, 2, 3}, source.getBytes());
// second set
readyAndCheck(source, MString.VARCHAR);
assertEquals("source value", "foo", source.getString());
readyAndCheck(source, MNumeric.BIGINT);
assertEquals("source value", 456L, source.getInt64());
readyAndCheck(source, MBinary.VARBINARY);
assertArrayEquals("source value", new byte[] {1, 2, 3}, source.getBytes());
}
@Test
public void getBigDecimalTwice() {
PersistitValueValueSource source = createSource(new ValueInit() {
@Override
public void putValues(Value value) {
value.putBigDecimal(BigDecimal.ONE);
}
});
source.getReady(MNumeric.DECIMAL.instance(false));
assertEquals("source value", BigDecimal.ONE, source.getObject());
assertEquals("source value", BigDecimal.ONE, source.getObject());
}
private void readyAndCheck(PersistitValueValueSource source, TClass underlying) {
source.getReady(underlying == null ? null : underlying.instance(true));
if (underlying == null) {
assertTrue("source should be null", source.isNull());
}
else {
assertFalse("source should not be null", source.isNull());
assertEquals("source UnderlyingType", underlying, ValueSources.tClass(source));
}
}
private PersistitValueValueSource createSource(ValueInit values) {
Value value = new Value((Persistit)null);
value.setStreamMode(true);
values.putValues(value);
value.setStreamMode(false); // need to reset the Value before reading
value.setStreamMode(true);
PersistitValueValueSource source = new PersistitValueValueSource();
source.attach(value);
return source;
}
private interface ValueInit {
void putValues(Value value);
}
}