/**
* Copyright 2005-2012 Akiban Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.persistit.unit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import junit.framework.Assert;
import org.junit.Test;
import com.persistit.Buffer;
import com.persistit.Key;
import com.persistit.KeyState;
import com.persistit.PersistitUnitTestCase;
import com.persistit.TestShim;
import com.persistit.exception.InvalidKeyException;
import com.persistit.exception.KeyTooLongException;
import com.persistit.exception.MissingKeySegmentException;
public class KeyTest1 extends PersistitUnitTestCase {
private long lv1;
private long lv2;
private float fv1;
private float fv2;
private double dv1;
private double dv2;
private final static long[] TEST_LONGS = { 0, 1, 2, 3, 123, 126, 127, 128, 129, 130, 131, 132, 250, 251, 252, 253,
254, 255, 256, 257, 258, 259, 260, 4094, 4095, 4096, 4097, 4098, 16383, 16384, 16385, 0x1FFFFEL, 0x1FFFFFL,
0x200000L, 0x3FFFFFFFFFEL, 0x3FFFFFFFFFFL, 0x2000000000000L, 0x1FFFFFFFFFFFFL, 0x1FFFFFFFFFFFEL,
Integer.MAX_VALUE - 2, Integer.MAX_VALUE - 1, Integer.MAX_VALUE + 0, Integer.MAX_VALUE + 1,
Integer.MAX_VALUE + 2, Integer.MAX_VALUE + 3, Long.MIN_VALUE, Long.MIN_VALUE + 1, Long.MIN_VALUE + 2,
Long.MAX_VALUE, Long.MAX_VALUE - 1, Long.MAX_VALUE - 2, };
private final static float[] TEST_FLOATS = { 0.0F, 1.0F, 2.0F, 12345.0F, 0.0003F, 1.2345E-10F, 1.12345E-20F, 0.0F,
-1.0F, -2.0F, -12345.0F, -0.0003F, -1.2345E-10F, -1.12345E-20F, Float.MAX_VALUE, Float.MIN_VALUE,
Float.MAX_VALUE / 2.0F, Float.MAX_VALUE / 3.0F, Float.MAX_VALUE / 4.0F, Float.MIN_VALUE / 2.0F,
Float.MIN_VALUE / 3.0F, Float.MIN_VALUE / 4.0F, Float.NaN, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY };
private final static double[] TEST_DOUBLES = { 0.0, 1.0, 2.0, 12345.0, 0.0003, 1.2345E-10, 1.12345E-20, 0.0, -1.0,
-2.0, -12345.0, -0.0003, -1.2345E-10, -1.12345E-20, Double.MAX_VALUE, Double.MIN_VALUE,
Double.MAX_VALUE / 2.0, Double.MAX_VALUE / 3.0, Double.MAX_VALUE / 4.0, Double.MIN_VALUE / 2.0,
Double.MIN_VALUE / 3.0, Double.MIN_VALUE / 4.0, Double.NaN, Double.NEGATIVE_INFINITY,
Double.POSITIVE_INFINITY };
private final static Object[] TEST_OBJECTS = new Object[] { null, true, false, (byte) 1, (char) 2, (short) 3, 4,
(long) 5, 6.0f, 7.0d, "This is a String", new Date(), new BigInteger("1"), new BigDecimal("2.2") };
@Test
public void test1() {
System.out.print("test1 ");
for (int index = 0; index < TEST_LONGS.length; index++) {
for (int m = -1; m <= 1; m += 2) {
lv1 = TEST_LONGS[index] * m;
final Key key1 = new Key(_persistit);
key1.clear();
key1.append(lv1);
key1.indexTo(0);
lv2 = key1.decodeLong();
assertEquals(lv1, lv2);
lv1 = -lv1;
key1.to(lv1);
key1.reset();
lv2 = key1.decodeLong();
assertEquals(lv1, lv2);
Assert.assertNull(t1a(lv1));
Assert.assertNull(t1a(-lv1));
}
}
System.out.println("- done");
}
private String t1a(final long lv) {
final Key key1 = new Key(_persistit);
key1.clear().append((byte) lv);
if (key1.indexTo(0).decodeByte() != (byte) lv) {
return "byte " + (byte) lv;
}
if (!(new Byte((byte) lv)).equals(key1.indexTo(0).decode())) {
return "Byte " + (byte) lv;
}
key1.clear().append((short) lv);
if (key1.indexTo(0).decodeShort() != (short) lv) {
return "short " + (short) lv;
}
if (!(new Short((short) lv)).equals(key1.indexTo(0).decode())) {
return "Short " + (short) lv;
}
key1.clear().append((char) lv);
if (key1.indexTo(0).decodeChar() != (char) lv) {
return "char " + (char) lv;
}
if (!(new Character((char) lv)).equals(key1.indexTo(0).decode())) {
return "Character " + (char) lv;
}
key1.clear().append((int) lv);
if (key1.indexTo(0).decodeInt() != (int) lv) {
return "int " + (int) lv;
}
if (!(new Integer((int) lv)).equals(key1.indexTo(0).decode())) {
return "Integer " + (int) lv;
}
key1.clear().append(lv);
if (key1.indexTo(0).decodeLong() != lv) {
return "long " + lv;
}
if (!(new Long(lv)).equals(key1.indexTo(0).decode())) {
return "Long " + lv;
}
return null;
}
@Test
public void test2() {
final Key key1 = new Key(_persistit);
final Key key2 = new Key(_persistit);
System.out.print("test2 ");
for (int i1 = 0; i1 < TEST_LONGS.length; i1++) {
for (int i2 = 0; i2 < TEST_LONGS.length; i2++) {
for (int s = 0; s < 4; s++) {
lv1 = TEST_LONGS[i1];
lv2 = TEST_LONGS[i2];
if ((s & 1) != 0) {
lv1 = -lv1;
}
if ((s & 2) != 0) {
lv2 = -lv2;
}
key1.clear();
key1.append(lv1);
key2.clear();
key2.append(lv2);
final int compare = key1.compareTo(key2);
final boolean result = ((compare == 0) && (lv1 == lv2)) || ((compare > 0) && (lv1 > lv2))
|| ((compare < 0) && (lv1 < lv2));
assertTrue(result);
}
}
}
System.out.println("- done");
}
@Test
public void test3() {
final Key key1 = new Key(_persistit);
System.out.print("test3 ");
for (int index = 0; index < TEST_FLOATS.length; index++) {
fv1 = TEST_FLOATS[index];
key1.clear();
key1.append(fv1);
key1.indexTo(0);
fv2 = key1.decodeFloat();
assertTrue(floatEquals(fv1, fv2));
fv1 = -fv1;
key1.to(fv1);
key1.indexTo(0);
fv2 = key1.decodeFloat();
assertTrue(floatEquals(fv1, fv2));
}
System.out.println("- done");
}
@Test
public void test4() {
final Key key1 = new Key(_persistit);
final Key key2 = new Key(_persistit);
System.out.print("test4 ");
for (int i1 = 0; i1 < TEST_FLOATS.length; i1++) {
for (int i2 = 0; i2 < TEST_FLOATS.length; i2++) {
for (int s = 0; s < 4; s++) {
fv1 = TEST_FLOATS[i1];
fv2 = TEST_FLOATS[i2];
if ((s & 1) != 0) {
fv1 = -fv1;
}
if ((s & 2) != 0) {
fv2 = -fv2;
}
key1.clear();
key1.append(fv1);
key2.clear();
key2.append(fv2);
final int compare = key1.compareTo(key2);
// Can't use static Float.compare on JDK 1.3.1
final Float f1 = new Float(fv1);
final Float f2 = new Float(fv2);
final boolean result = ((compare == 0) && (f1.compareTo(f2) == 0))
|| ((compare > 0) && (f1.compareTo(f2) > 0)) || ((compare < 0) && (f1.compareTo(f2) < 0));
assertTrue(result);
}
}
}
System.out.println("- done");
}
private static boolean floatEquals(final float f1, final float f2) {
if (Float.isNaN(f1)) {
return Float.isNaN(f2);
}
if (Float.isInfinite(f1)) {
return Float.isInfinite(f2);
}
return f1 == f2;
}
@Test
public void test5() {
final Key key1 = new Key(_persistit);
System.out.print("test5 ");
for (int index = 0; index < TEST_DOUBLES.length; index++) {
dv1 = TEST_DOUBLES[index];
key1.clear();
key1.append(dv1);
key1.reset();
dv2 = key1.decodeDouble();
assertTrue(doubleEquals(dv1, dv2));
dv1 = -dv1;
key1.to(dv1);
key1.reset();
dv2 = key1.decodeDouble();
assertTrue(doubleEquals(dv1, dv2));
}
System.out.println("- done");
}
@Test
public void test6() {
final Key key1 = new Key(_persistit);
final Key key2 = new Key(_persistit);
System.out.print("test6 ");
for (int i1 = 0; i1 < TEST_DOUBLES.length; i1++) {
for (int i2 = 0; i2 < TEST_DOUBLES.length; i2++) {
for (int s = 0; s < 4; s++) {
dv1 = TEST_DOUBLES[i1];
dv2 = TEST_DOUBLES[i2];
if ((s & 1) != 0) {
dv1 = -dv1;
}
if ((s & 2) != 0) {
dv2 = -dv2;
}
key1.clear();
key1.append(dv1);
key2.clear();
key2.append(dv2);
final int compare = key1.compareTo(key2);
// Can't use static Double.compare on JDK1.3.1
final Double d1 = new Double(dv1);
final Double d2 = new Double(dv2);
final boolean result = ((compare == 0) && (d1.compareTo(d2) == 0))
|| ((compare > 0) && (d1.compareTo(d2) > 0)) || ((compare < 0) && (d1.compareTo(d2) < 0));
assertTrue(result);
}
}
}
System.out.println("- done");
}
/**
* Verify key type ordering
*
*/
@Test
public void test7() {
final Key key1 = new Key(_persistit);
final Key key2 = new Key(_persistit);
System.out.print("test7 ");
key1.to(Key.BEFORE);
key2.to(null);
assertTrue(key2.compareTo(key1) > 0);
key1.to(null);
key2.to(false);
assertTrue(key2.compareTo(key1) > 0);
key1.to(false);
key2.to(true);
assertTrue(key2.compareTo(key1) > 0);
key1.to(true);
key2.to((byte) 0);
assertTrue(key2.compareTo(key1) > 0);
key1.to((byte) 0);
key2.to((byte) -1);
assertTrue(key2.compareTo(key1) < 0);
key1.to((byte) 1);
key2.to((byte) -1);
assertTrue(key2.compareTo(key1) < 0);
key1.to((byte) 1);
key2.clear().append(new Byte((byte) 1));
assertTrue(key2.compareTo(key1) == 0);
key1.to(new Byte((byte) 1));
key2.to((short) 1);
assertTrue(key2.compareTo(key1) > 0);
key1.to((short) 1);
key2.to((char) 1);
assertTrue(key2.compareTo(key1) > 0);
key1.to((char) 1);
key2.to(1);
assertTrue(key2.compareTo(key1) > 0);
key1.to(1);
key2.to((long) 1);
assertTrue(key2.compareTo(key1) > 0);
key1.to((long) 1);
key2.to((float) 1.0);
assertTrue(key2.compareTo(key1) > 0);
key1.to((float) 1.0);
key2.to(1.0);
assertTrue(key2.compareTo(key1) > 0);
key1.to(1.0);
key2.to(new byte[10]);
assertTrue(key2.compareTo(key1) > 0);
key1.to(new byte[10]);
key2.to(new byte[] { -1, -1 });
assertTrue(key2.compareTo(key1) > 0);
key1.to(new byte[] { -1, -1 });
key2.to("x");
assertTrue(key2.compareTo(key1) > 0);
key1.to("x");
key2.to("y");
assertTrue(key2.compareTo(key1) > 0);
key1.to("y");
key2.to("\u0199y");
assertTrue(key2.compareTo(key1) > 0);
key1.to("\u0199y");
key2.to("\u0200y");
assertTrue(key2.compareTo(key1) > 0);
System.out.println("- done");
}
// Note: this test has been run with INCREMENT = 1 (i.e., every int value),
// that's too slow (5 minutes) for unit tests in normal builds.
//
private static final int INCREMENT = 1237;
@Test
public void test8() {
final Key key1 = new Key(_persistit);
System.out.print("test8 ");
final int start = Integer.MIN_VALUE;
final int end = Integer.MAX_VALUE - INCREMENT;
for (int u = start; u < end; u += INCREMENT) {
if ((u % 100000000) == 0) {
System.out.print(" " + u);
}
key1.clear().append(u);
final int v = key1.reset().decodeInt();
if (u != v) {
assertEquals(u, v);
}
}
System.out.println("- done");
}
@Test
public void test9() {
final Key key1 = new Key(_persistit);
System.out.print("test9 ");
final int start = 0;
final int end = 10000000;
for (int u = start; u < end; u++) {
if ((u % 10000000) == 0) {
System.out.print(" " + u);
}
int k = (u * 123) % end;
if (k < 0) {
k += end;
}
if (k < 0) {
System.out.println("at u=" + u + " k=" + k);
break;
}
key1.to(k);
final int v = key1.reset().decodeInt();
if (k != -v) {
assertEquals(k, v);
}
}
System.out.println("- done");
}
@Test
public void test10() {
final Key key1 = new Key(_persistit);
System.out.print("test10 ");
for (int index = 0; index < TEST_LONGS.length; index++) {
lv1 = TEST_LONGS[index];
key1.clear();
BigInteger biv1 = BigInteger.valueOf(lv1);
key1.append(biv1);
key1.indexTo(0);
BigInteger biv2 = key1.decodeBigInteger();
assertEquals(biv1, biv2);
lv1 = -lv1;
biv1 = BigInteger.valueOf(lv1);
key1.to(biv1);
key1.indexTo(0);
biv2 = key1.decodeBigInteger();
assertEquals(biv1, biv2);
Assert.assertNull(t1a(lv1));
Assert.assertNull(t1a(-lv1));
}
System.out.println("- done");
}
@Test
public void test11() {
final Key key1 = new Key(_persistit);
final Key key2 = new Key(_persistit);
System.out.print("test11 ");
for (int i1 = 0; i1 < TEST_LONGS.length; i1++) {
for (int i2 = 0; i2 < TEST_LONGS.length; i2++) {
for (int s = 0; s < 4; s++) {
lv1 = TEST_LONGS[i1];
lv2 = TEST_LONGS[i2];
if ((s & 1) != 0) {
lv1 = -lv1;
}
if ((s & 2) != 0) {
lv2 = -lv2;
}
final BigInteger biv1 = BigInteger.valueOf(lv1);
final BigInteger biv2 = BigInteger.valueOf(lv2);
key1.clear();
key1.append(biv1);
key2.clear();
key2.append(biv2);
final int compare = key1.compareTo(key2);
final boolean result = ((compare == 0) && (lv1 == lv2)) || ((compare > 0) && (lv1 > lv2))
|| ((compare < 0) && (lv1 < lv2));
assertTrue(result);
}
}
}
System.out.println("- done");
}
@Test
public void test12() {
System.out.print("test12 ");
final Key key = new Key(_persistit);
final StringBuilder sb = new StringBuilder();
sb.setLength(0);
sb.append("1");
for (int j = 0; j < 200; j++) {
sb.append("0");
final BigInteger bi1 = new BigInteger(sb.toString());
key.clear().append(bi1);
final BigInteger bi2 = (BigInteger) key.reset().decode();
assertTrue(bi2.compareTo(bi1) == 0);
}
sb.setLength(0);
sb.append("-1");
for (int j = 0; j < 200; j++) {
sb.append("0");
final BigInteger bi1 = new BigInteger(sb.toString());
key.clear().append(bi1);
final BigInteger bi2 = (BigInteger) key.reset().decode();
assertTrue(bi2.compareTo(bi1) == 0);
}
System.out.println("- done");
}
@Test
public void test13() {
System.out.print("test13 ");
final StringBuilder sb = new StringBuilder();
final Key key = new Key(_persistit);
sb.setLength(0);
sb.append("0.");
for (int j = 0; j < 200; j++) {
sb.append("9");
final BigDecimal bi1 = new BigDecimal(sb.toString());
key.clear().append(bi1);
final BigDecimal bi2 = (BigDecimal) key.reset().decode();
assertTrue(bi2.compareTo(bi1) == 0);
}
for (int a = 0; a < 50; a++) {
for (int b = 0; b < 50; b++) {
sb.setLength(0);
sb.append("5");
for (int i = 0; i < b; i++) {
sb.append("0");
}
sb.append(".");
for (int i = 0; i < a; i++) {
sb.append("0");
}
sb.append("5");
final BigDecimal bi1 = new BigDecimal(sb.toString());
key.clear().append(bi1);
final BigDecimal bi2 = (BigDecimal) key.reset().decode();
assertTrue(bi2.compareTo(bi1) == 0);
}
}
for (int a = 0; a < 50; a++) {
for (int b = 0; b < 50; b++) {
sb.setLength(0);
sb.append("-5");
for (int i = 0; i < b; i++) {
sb.append("0");
}
sb.append(".");
for (int i = 0; i < a; i++) {
sb.append("0");
}
sb.append("5");
final BigDecimal bi1 = new BigDecimal(sb.toString());
key.clear().append(bi1);
final BigDecimal bi2 = (BigDecimal) key.reset().decode();
assertTrue(bi2.compareTo(bi1) == 0);
}
}
for (int a = 0; a < 50; a++) {
for (int b = 0; b < 50; b++) {
sb.setLength(0);
sb.append("-5");
for (int i = 0; i < b; i++) {
sb.append("0");
}
sb.append(".");
for (int i = 0; i < a; i++) {
sb.append("0");
}
sb.append("0");
final BigDecimal bi1 = new BigDecimal(sb.toString());
key.clear().append(bi1);
final BigDecimal bi2 = (BigDecimal) key.reset().decode();
assertTrue(bi2.compareTo(bi1) == 0);
}
}
System.out.println("- done");
}
@Test
public void test14() {
final Key key1 = new Key(_persistit);
final Key key2 = new Key(_persistit);
key1.clear().append("a").append("b").append(1).append(2);
key2.clear().append("a").append("b").append(2).append(1);
assertEquals(7, key1.firstUniqueByteIndex(key2));
assertEquals(2, key1.firstUniqueSegmentDepth(key2));
}
/*
* Test the equals methods in Key and KeyState
*/
@Test
public void testKeyEquality() {
final Key key1 = new Key(_persistit);
final Key key2 = new Key(_persistit);
key1.clear().to(5);
key2.clear().to(5);
assertEquals(key1, key2);
KeyState ks = new KeyState(key2);
assertEquals(key1, ks);
assertEquals(key2, ks);
key1.clear().to("PADRAIG");
key2.clear().to("PADRAIG");
assertEquals(key1, key2);
ks = new KeyState(key2);
assertEquals(ks, key2);
assertEquals(ks, key1);
}
@Test
public void testIndexTo() {
final Key key1 = new Key(_persistit);
key1.clear().append("a").append("b").append("c").append("d");
assertEquals("a", key1.indexTo(0).decodeString());
assertEquals("b", key1.indexTo(1).decodeString());
assertEquals("c", key1.indexTo(2).decodeString());
assertEquals("d", key1.indexTo(3).decodeString());
assertEquals(key1.getEncodedSize(), key1.indexTo(4).getIndex());
assertEquals(key1.getEncodedSize(), key1.indexTo(5).getIndex());
assertEquals("d", key1.indexTo(-1).decodeString());
assertEquals("c", key1.indexTo(-2).decodeString());
assertEquals("b", key1.indexTo(-3).decodeString());
assertEquals("a", key1.indexTo(-4).decodeString());
assertEquals("a", key1.indexTo(-5).decodeString());
assertEquals("a", key1.indexTo(-6).decodeString());
}
@Test
public void testIsNull() {
final Key key1 = new Key(_persistit);
key1.clear().append(null);
assertTrue("seg0 is null: " + key1, key1.indexTo(0).isNull());
key1.clear().append(1);
assertFalse("seg0 is not null: " + key1, key1.indexTo(0).isNull());
key1.clear().append(5L).append(null);
assertTrue("seg1 is null: " + key1, key1.indexTo(1).isNull());
key1.clear().append("abc");
assertFalse("seg0 is not null:" + key1, key1.indexTo(0).isNull());
key1.clear().append(BigInteger.valueOf(42)).append(null);
assertTrue("seg1 is null: " + key1, key1.indexTo(1).isNull());
try {
key1.clear().reset().isNull();
Assert.fail("Expected MissingKeySegmentException!");
} catch (final MissingKeySegmentException e) {
// expected
}
}
@Test
public void testSkipNull() {
final Key key1 = new Key(_persistit);
key1.clear().append(null).append(1).append(2).append(null).append(null).append(5);
key1.reset();
assertTrue("seg0 is null: " + key1, key1.isNull(true));
assertFalse("seg1 is not null: " + key1, key1.isNull(true));
assertEquals("expect seg1 value", 1, key1.decode());
assertFalse("seg2 is not null: " + key1, key1.isNull(true));
assertEquals("expect seg2 value", 2, key1.decode());
assertTrue("seg3 is null: " + key1, key1.isNull(true));
assertTrue("seg4 is null: " + key1, key1.isNull(true));
assertFalse("seg5 is not null:" + key1, key1.isNull(true));
assertFalse("seg5 is not null:" + key1, key1.isNull(true));
assertFalse("seg5 is not null:" + key1, key1.isNull(true));
assertEquals("expect seg5 value", 5, key1.decodeInt());
try {
key1.isNull(true);
Assert.fail("Expected MissingKeySegmentException!");
} catch (final MissingKeySegmentException e) {
// expected
}
}
@Test
public void testFirstUniqueSegmentDepth() {
final Key key1 = new Key(_persistit);
final Key key2 = new Key(_persistit);
key1.append("a").append("b").append("c");
key2.append("a").append("b").append("d");
assertEquals("Incorrect depth", 2, key1.firstUniqueSegmentDepth(key2));
assertEquals("Incorrect depth", 2, key2.firstUniqueSegmentDepth(key1));
key1.cut();
assertEquals("Incorrect depth", 2, key1.firstUniqueSegmentDepth(key2));
assertEquals("Incorrect depth", 2, key2.firstUniqueSegmentDepth(key1));
key2.cut();
assertEquals("Incorrect depth", 2, key1.firstUniqueSegmentDepth(key2));
assertEquals("Incorrect depth", 2, key2.firstUniqueSegmentDepth(key1));
key2.cut();
assertEquals("Incorrect depth", 1, key1.firstUniqueSegmentDepth(key2));
assertEquals("Incorrect depth", 1, key2.firstUniqueSegmentDepth(key1));
}
@Test
public void testValidForAppendLeftEdge() {
final Key key1 = newKey();
Key.LEFT_GUARD_KEY.copyTo(key1);
try {
TestShim.testValidForAppend(key1);
fail("Expected IllegalArgumentException");
} catch (final IllegalArgumentException e) {
// expected
}
}
@Test
public void testValidForAppendRightEdge() {
final Key key1 = newKey();
Key.RIGHT_GUARD_KEY.copyTo(key1);
try {
TestShim.testValidForAppend(key1);
fail("Expected IllegalArgumentException");
} catch (final IllegalArgumentException e) {
// expected
}
}
@Test
public void testValidForAppendBefore() {
final Key key1 = newKey();
key1.clear().append(Key.BEFORE);
try {
TestShim.testValidForAppend(key1);
fail("Expected IllegalArgumentException");
} catch (final IllegalArgumentException e) {
// expected
}
}
@Test
public void testValidForAppendAfter() {
final Key key1 = newKey();
key1.append(Key.AFTER);
try {
TestShim.testValidForAppend(key1);
fail("Expected IllegalArgumentException");
} catch (final IllegalArgumentException e) {
// expected
}
}
@Test
public void testValidForAppendInvalidFinalSegment() {
final Key key1 = newKey();
appendInvalidSegment(key1);
try {
TestShim.testValidForAppend(key1);
fail("Expected IllegalArgumentException");
} catch (final IllegalArgumentException e) {
// expected
}
}
@Test
public void testValidForStoreAndFetchEmptyKey() {
final Key key1 = newKey();
try {
TestShim.testValidForStoreAndFetch(key1, Buffer.MIN_BUFFER_SIZE);
fail("Expected InvalidKeyException");
} catch (final InvalidKeyException e) {
// Expected
}
}
@Test
public void testValidForStoreAndFetchBeforeKey() {
final Key key1 = newKey();
key1.append(Key.BEFORE);
try {
TestShim.testValidForStoreAndFetch(key1, Buffer.MIN_BUFFER_SIZE);
fail("Expected InvalidKeyException");
} catch (final InvalidKeyException e) {
// Expected
}
}
@Test
public void testValidForStoreAndFetchInvalidFinalSegment() {
final Key key1 = newKey();
appendInvalidSegment(key1);
try {
TestShim.testValidForStoreAndFetch(key1, Buffer.MAX_BUFFER_SIZE);
fail("Expected InvalidKeyException");
} catch (final InvalidKeyException e) {
// expected
}
}
@Test
public void testValidForStoreAndFetchAfterKey() {
final Key key1 = newKey();
key1.append(Key.AFTER);
try {
TestShim.testValidForStoreAndFetch(key1, Buffer.MIN_BUFFER_SIZE);
fail("Expected InvalidKeyException");
} catch (final InvalidKeyException e) {
// Expected
}
}
@Test
public void testValidForStoreAndFetchKeyTooLarge() {
final Key key1 = new Key(_persistit);
final int BMIN = Buffer.MIN_BUFFER_SIZE;
final int BMAX = Buffer.MAX_BUFFER_SIZE;
final int KMAX = key1.getMaximumSize();
for (int bsize = BMIN; bsize <= BMAX && bsize < KMAX; bsize *= 2) {
key1.clear();
key1.setEncodedSize(bsize + 1);
try {
TestShim.testValidForStoreAndFetch(key1, bsize);
fail("Expected IllegalArgumentException for buffer buffer size " + bsize);
} catch (final InvalidKeyException e) {
// Expected
}
}
}
@Test
public void testValidForTraverseEmptyKey() {
final Key key1 = newKey();
try {
TestShim.testValidForTraverse(key1);
fail("Expected InvalidKeyException");
} catch (final InvalidKeyException e) {
// Expected
}
}
@Test
public void testNudgeDeeperFullKey() {
final Key key1 = newKey();
fillKey(key1);
final long gen1 = key1.getGeneration();
final int fullSize = key1.getEncodedSize();
TestShim.nudgeDeeper(key1);
final long gen2 = key1.getGeneration();
final int nudge1Size = key1.getEncodedSize();
assertEquals("can nudge when key is full", fullSize + 1, nudge1Size);
assertTrue("Generation changed after successful nudge", gen2 > gen1);
TestShim.nudgeDeeper(key1);
final long gen3 = key1.getGeneration();
final int nudge2Size = key1.getEncodedSize();
assertEquals("cannot nudge full key twice", fullSize + 1, nudge2Size);
assertEquals("Generation did not change after unsuccessful nudge", gen2, gen3);
}
@Test
public void testNudgeLeftRightNoChangeSpecialKeys() {
final Key key1 = newKey();
final Key key2 = newKey();
Key.LEFT_GUARD_KEY.copyTo(key1);
TestShim.nudgeLeft(key1);
assertEquals("no nudgeLeft LEFT_GUARD", 0, Key.LEFT_GUARD_KEY.compareTo(key1));
TestShim.nudgeRight(key1);
assertEquals("no nudgeRight LEFT_GUARD", 0, Key.LEFT_GUARD_KEY.compareTo(key1));
Key.RIGHT_GUARD_KEY.copyTo(key1);
TestShim.nudgeLeft(key1);
assertEquals("no nudgeLeft RIGHT_GUARD", 0, Key.RIGHT_GUARD_KEY.compareTo(key1));
TestShim.nudgeRight(key1);
assertEquals("no nudgeRight RIGHT_GUARD", 0, Key.RIGHT_GUARD_KEY.compareTo(key1));
key1.clear().append(Key.BEFORE);
key1.copyTo(key2);
TestShim.nudgeLeft(key1);
assertEquals("no nudgeLeft BEFORE", 0, key2.compareTo(key1));
TestShim.nudgeRight(key1);
assertEquals("no nudgeRight BEFORE", 0, key2.compareTo(key1));
key1.clear().append(Key.AFTER);
key1.copyTo(key2);
TestShim.nudgeLeft(key1);
assertEquals("no nudgeLeft AFTER", 0, key2.compareTo(key1));
TestShim.nudgeRight(key1);
assertEquals("no nudgeRight AFTER", 0, key2.compareTo(key1));
}
@Test
public void testNudgeLeftRightFullKey() {
final Key key1 = newKey();
fillKey(key1);
final Key key2 = newKey();
key1.copyTo(key2);
TestShim.nudgeLeft(key1);
assertTrue("nudgeLeft on full key compares less", key1.compareTo(key2) < 0);
key2.copyTo(key1);
TestShim.nudgeRight(key1);
assertTrue("nudgeRight on full key compares greater", key1.compareTo(key2) > 0);
}
@Test
public void testNonAsciiString() {
final String[] strings = { "\u0000\u0001\u0000\u0001", // small, <= 0x01
"asdf", // ascii
"\u03A3\u03A4\u03A6\u03A8", // medium, <= 0x7FF (greek capital
// sigma, tau, phi, psi)
"\u2654\u2655\u2656\u2657", // large, (white chess king, queen,
// rook, bishop)
};
final Key key1 = newKey();
for (final String s : strings) {
assertEquals("character count", 4, s.length());
key1.clear().append(s);
final String decoded = key1.decodeString();
assertEquals("append and decode", s, decoded);
}
}
@Test
public void testCompareKeySegment() throws Exception {
final Key key1 = newKey();
final Key key2 = newKey();
key1.append(1).append(2).append(3).append("abc");
key2.append(3).append(2).append(1).append("abcd");
key1.indexTo(1);
key2.indexTo(1);
assertTrue("Should be == 0", 0 == key1.compareKeySegment(key2));
assertTrue("Should be == 0", 0 == key2.compareKeySegment(key1));
key1.indexTo(0);
assertTrue("Should be < 0", 0 > key1.compareKeySegment(key2));
assertTrue("Should be > 0", 0 < key2.compareKeySegment(key1));
key1.indexTo(2);
assertTrue("Should be > 0", 0 < key1.compareKeySegment(key2));
assertTrue("Should be < 0", 0 > key2.compareKeySegment(key1));
key1.indexTo(3);
assertTrue("Should be > 0", 0 < key1.compareKeySegment(key2));
assertTrue("Should be < 0", 0 > key2.compareKeySegment(key1));
key2.indexTo(3);
assertTrue("Should be < 0", 0 > key1.compareKeySegment(key2));
assertTrue("Should be > 0", 0 < key2.compareKeySegment(key1));
}
@Test
public void testAppendKeySegment() throws Exception {
final Key key1 = newKey();
final Key key2 = newKey();
key1.append(1).append(2).append(3).append("abc");
key1.indexTo(3);
key2.appendKeySegment(key1);
key1.indexTo(2);
key2.appendKeySegment(key1);
key1.indexTo(1);
key2.appendKeySegment(key1);
key1.indexTo(0);
key2.appendKeySegment(key1);
assertEquals("Key value incorrect", "{\"abc\",3,2,1}", key2.toString());
key1.indexTo(3);
key1.appendKeySegment(key1);
assertEquals("Key value incorrect", "{1,2,3,\"abc\",\"abc\"}", key1.toString());
}
@Test
public void testKeyTooLong() throws Exception {
for (int maxSize = 1; maxSize < 99; maxSize++) {
mainLoop: for (final Object value : TEST_OBJECTS) {
final Key key = new Key(_persistit, maxSize);
// Every appended value consumes at least 2 bytes
for (int i = 0; i < 50; i++) {
try {
key.append(value);
} catch (final KeyTooLongException e) {
continue mainLoop;
}
}
fail("Should have thrown a KeyTooLongException for maxSize=" + maxSize + " and value " + value);
}
}
}
private static boolean doubleEquals(final double f1, final double f2) {
if (Double.isNaN(f1)) {
return Double.isNaN(f2);
}
if (Double.isInfinite(f1)) {
return Double.isInfinite(f2);
}
return f1 == f2;
}
private Key newKey() {
return new Key(_persistit);
}
private static Key appendInvalidSegment(final Key key) {
key.append("asdf");
assertTrue("encoded size > 1", key.getEncodedSize() > 1);
key.setEncodedSize(key.getEncodedSize() - 1);
return key;
}
private static void fillKey(final Key key) {
final byte[] array = new byte[key.getMaximumSize() - 2];
for (int i = 0; i < array.length; ++i) {
array[i] = 10;
}
key.clear().append(array);
assertEquals("encoded size is max size", key.getEncodedSize(), key.getMaximumSize());
}
}