/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License, Version
* 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html). Initial Developer: H2 Group
*/
package org.h2.test.store;
import java.nio.ByteBuffer;
import java.util.HashMap;
import org.h2.dev.store.btree.DataUtils;
import org.h2.test.TestBase;
/**
* Test utility classes.
*/
public class TestDataUtils extends TestBase {
/**
* Run just this test.
*
* @param a ignored
*/
public static void main(String... a) throws Exception {
TestBase.createCaller().init().test();
}
public void test() throws Exception {
testMap();
testMaxShortVarIntVarLong();
testVarIntVarLong();
testCheckValue();
testPagePos();
testEncodeLength();
}
private void testMap() {
StringBuilder buff = new StringBuilder();
DataUtils.appendMap(buff, "", "");
DataUtils.appendMap(buff, "a", "1");
DataUtils.appendMap(buff, "b", ",");
DataUtils.appendMap(buff, "c", "1,2");
DataUtils.appendMap(buff, "d", "\"test\"");
assertEquals(":,a:1,b:\",\",c:\"1,2\",d:\"\\\"test\\\"\"", buff.toString());
HashMap<String, String> m = DataUtils.parseMap(buff.toString());
assertEquals(5, m.size());
assertEquals("", m.get(""));
assertEquals("1", m.get("a"));
assertEquals(",", m.get("b"));
assertEquals("1,2", m.get("c"));
assertEquals("\"test\"", m.get("d"));
}
private void testMaxShortVarIntVarLong() {
ByteBuffer buff = ByteBuffer.allocate(100);
DataUtils.writeVarInt(buff, DataUtils.COMPRESSED_VAR_INT_MAX);
assertEquals(3, buff.position());
buff.rewind();
DataUtils.writeVarInt(buff, DataUtils.COMPRESSED_VAR_INT_MAX + 1);
assertEquals(4, buff.position());
buff.rewind();
DataUtils.writeVarLong(buff, DataUtils.COMPRESSED_VAR_LONG_MAX);
assertEquals(7, buff.position());
buff.rewind();
DataUtils.writeVarLong(buff, DataUtils.COMPRESSED_VAR_LONG_MAX + 1);
assertEquals(8, buff.position());
buff.rewind();
}
private void testVarIntVarLong() {
ByteBuffer buff = ByteBuffer.allocate(100);
for (long x = 0; x < 1000; x++) {
testVarIntVarLong(buff, x);
testVarIntVarLong(buff, -x);
}
for (long x = Long.MIN_VALUE, i = 0; i < 1000; x++, i++) {
testVarIntVarLong(buff, x);
}
for (long x = Long.MAX_VALUE, i = 0; i < 1000; x--, i++) {
testVarIntVarLong(buff, x);
}
for (int shift = 0; shift < 64; shift++) {
for (long x = 250; x < 260; x++) {
testVarIntVarLong(buff, x << shift);
testVarIntVarLong(buff, -(x << shift));
}
}
// invalid varInt / varLong
// should work, but not read far too much
for (int i = 0; i < 50; i++) {
buff.put((byte) 255);
}
buff.flip();
assertEquals(-1, DataUtils.readVarInt(buff));
assertEquals(5, buff.position());
buff.rewind();
assertEquals(-1, DataUtils.readVarLong(buff));
assertEquals(10, buff.position());
}
private void testVarIntVarLong(ByteBuffer buff, long x) {
int len;
DataUtils.writeVarLong(buff, x);
len = buff.position();
buff.flip();
long y = DataUtils.readVarLong(buff);
assertEquals(y, x);
assertEquals(len, buff.position());
assertEquals(len, DataUtils.getVarLongLen(x));
buff.clear();
int intX = (int) x;
DataUtils.writeVarInt(buff, intX);
len = buff.position();
buff.flip();
int intY = DataUtils.readVarInt(buff);
assertEquals(intY, intX);
assertEquals(len, buff.position());
assertEquals(len, DataUtils.getVarIntLen(intX));
buff.clear();
}
private void testCheckValue() {
// 0 xor 0 = 0
assertEquals(0, DataUtils.getCheckValue(0));
// 1111... xor 1111... = 0
assertEquals(0, DataUtils.getCheckValue(-1));
// 0 xor 1111... = 1111...
assertEquals((short) -1, DataUtils.getCheckValue(-1 >>> 16));
// 1111... xor 0 = 1111...
assertEquals((short) -1, DataUtils.getCheckValue(-1 << 16));
// 0 xor 1000... = 1000...
assertEquals((short) (1 << 15), DataUtils.getCheckValue(1 << 15));
// 1000... xor 0 = 1000...
assertEquals((short) (1 << 15), DataUtils.getCheckValue(1 << 31));
}
private void testPagePos() {
assertEquals(0, DataUtils.PAGE_TYPE_LEAF);
assertEquals(1, DataUtils.PAGE_TYPE_NODE);
for (int i = 0; i < 67000000; i++) {
long pos = DataUtils.getPagePos(i, 3, 128, 1);
assertEquals(i, DataUtils.getPageChunkId(pos));
assertEquals(3, DataUtils.getPageOffset(pos));
assertEquals(128, DataUtils.getPageMaxLength(pos));
assertEquals(1, DataUtils.getPageType(pos));
}
for (int type = 0; type <= 1; type++) {
for (int chunkId = 0; chunkId < 67000000; chunkId += 670000) {
for (long offset = 0; offset < Integer.MAX_VALUE; offset += Integer.MAX_VALUE / 100) {
for (int length = 0; length < 2000000; length += 200000) {
long pos = DataUtils.getPagePos(chunkId, (int) offset, length, type);
assertEquals(chunkId, DataUtils.getPageChunkId(pos));
assertEquals(offset, DataUtils.getPageOffset(pos));
assertTrue(DataUtils.getPageMaxLength(pos) >= length);
assertTrue(DataUtils.getPageType(pos) == type);
}
}
}
}
}
private void testEncodeLength() {
int lastCode = 0;
assertEquals(0, DataUtils.encodeLength(32));
assertEquals(1, DataUtils.encodeLength(33));
assertEquals(1, DataUtils.encodeLength(48));
assertEquals(2, DataUtils.encodeLength(49));
assertEquals(30, DataUtils.encodeLength(1024 * 1024));
assertEquals(31, DataUtils.encodeLength(1024 * 1024 + 1));
for (int i = 1024 * 1024 + 1; i < 100 * 1024 * 1024; i += 1024) {
int code = DataUtils.encodeLength(i);
assertEquals(31, code);
}
for (int i = 0; i < 2 * 1024 * 1024; i++) {
int code = DataUtils.encodeLength(i);
assertTrue(code <= 31 && code >= 0);
assertTrue(code >= lastCode);
if (code > lastCode) {
lastCode = code;
}
int max = DataUtils.getPageMaxLength(code << 1);
assertTrue(max >= i && max >= 32);
}
}
}