/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.ignite.internal.processors.query.h2.database;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.UUID;
import junit.framework.TestCase;
import org.apache.commons.io.Charsets;
import org.apache.ignite.configuration.MemoryPolicyConfiguration;
import org.apache.ignite.internal.mem.unsafe.UnsafeMemoryProvider;
import org.apache.ignite.internal.pagemem.PageIdAllocator;
import org.apache.ignite.internal.pagemem.PageMemory;
import org.apache.ignite.internal.pagemem.impl.PageMemoryNoStoreImpl;
import org.apache.ignite.internal.processors.cache.database.MemoryMetricsImpl;
import org.apache.ignite.logger.java.JavaLogger;
import org.h2.result.SortOrder;
import org.h2.value.CompareMode;
import org.h2.value.Value;
import org.h2.value.ValueBoolean;
import org.h2.value.ValueByte;
import org.h2.value.ValueBytes;
import org.h2.value.ValueDate;
import org.h2.value.ValueDouble;
import org.h2.value.ValueFloat;
import org.h2.value.ValueInt;
import org.h2.value.ValueLong;
import org.h2.value.ValueNull;
import org.h2.value.ValueShort;
import org.h2.value.ValueString;
import org.h2.value.ValueTime;
import org.h2.value.ValueTimestamp;
import org.h2.value.ValueUuid;
/**
* Simple tests for {@link InlineIndexHelper}.
*/
public class InlineIndexHelperTest extends TestCase {
/** */
private static final int CACHE_ID = 42;
/** */
private static final int PAGE_SIZE = 1024;
/** */
private static final long MB = 1024;
/** */
private static final int CPUS = Runtime.getRuntime().availableProcessors();
/** Test utf-8 string cutting. */
public void testConvert() {
// 8 bytes total: 1b, 1b, 3b, 3b.
byte[] bytes = InlineIndexHelper.trimUTF8("00\u20ac\u20ac".getBytes(Charsets.UTF_8), 7);
assertEquals(5, bytes.length);
String s = new String(bytes);
assertEquals(3, s.length());
bytes = InlineIndexHelper.trimUTF8("aaaaaa".getBytes(Charsets.UTF_8), 4);
assertEquals(4, bytes.length);
}
/** Limit is too small to cut */
public void testStringCut() {
// 6 bytes total: 3b, 3b.
byte[] bytes = InlineIndexHelper.trimUTF8("\u20ac\u20ac".getBytes(Charsets.UTF_8), 2);
assertNull(bytes);
}
/** Test on String values compare */
public void testRelyOnCompare() {
InlineIndexHelper ha = new InlineIndexHelper(Value.STRING, 0, SortOrder.ASCENDING);
// same size
assertFalse(getRes(ha, "aabb", "aabb"));
// second string is shorter
assertTrue(getRes(ha, "aabb", "aac"));
assertTrue(getRes(ha, "aabb", "aaa"));
// second string is longer
assertTrue(getRes(ha, "aabb", "aaaaaa"));
assertFalse(getRes(ha, "aaa", "aaaaaa"));
// one is null
assertTrue(getRes(ha, "a", null));
assertTrue(getRes(ha, null, "a"));
assertTrue(getRes(ha, null, null));
}
/** Test on Bytes values compare */
public void testRelyOnCompareBytes() {
InlineIndexHelper ha = new InlineIndexHelper(Value.BYTES, 0, SortOrder.ASCENDING);
// same size
assertFalse(getResBytes(ha, new byte[] {1, 2, 3, 4}, new byte[] {1, 2, 3, 4}));
// second aray is shorter
assertTrue(getResBytes(ha, new byte[] {1, 2, 2, 2}, new byte[] {1, 1, 2}));
assertTrue(getResBytes(ha, new byte[] {1, 1, 1, 2}, new byte[] {1, 1, 2}));
// second array is longer
assertTrue(getResBytes(ha, new byte[] {1, 2}, new byte[] {1, 1, 1}));
assertFalse(getResBytes(ha, new byte[] {1, 1}, new byte[] {1, 1, 2}));
// one is null
assertTrue(getResBytes(ha, new byte[] {1, 2, 3, 4}, null));
assertTrue(getResBytes(ha, null, new byte[] {1, 2, 3, 4}));
assertTrue(getResBytes(ha, null, null));
}
/** */
public void testStringTruncate() throws Exception {
MemoryPolicyConfiguration plcCfg = new MemoryPolicyConfiguration().setMaxSize(1024 * MB);
JavaLogger log = new JavaLogger();
PageMemory pageMem = new PageMemoryNoStoreImpl(log,
new UnsafeMemoryProvider(log),
null,
PAGE_SIZE,
plcCfg,
new MemoryMetricsImpl(plcCfg),
false);
pageMem.start();
long pageId = 0L;
long page = 0L;
try {
pageId = pageMem.allocatePage(CACHE_ID, 1, PageIdAllocator.FLAG_DATA);
page = pageMem.acquirePage(CACHE_ID, pageId);
long pageAddr = pageMem.readLock(CACHE_ID, pageId, page);
int off = 0;
InlineIndexHelper ih = new InlineIndexHelper(Value.STRING, 1, 0);
ih.put(pageAddr, off, ValueString.get("aaaaaaa"), 3 + 5);
assertFalse(ih.isValueFull(pageAddr, off));
assertEquals("aaaaa", ih.get(pageAddr, off, 3 + 5).getString());
ih.put(pageAddr, off, ValueString.get("aaa"), 3 + 5);
assertTrue(ih.isValueFull(pageAddr, off));
assertEquals("aaa", ih.get(pageAddr, off, 3 + 5).getString());
}
finally {
if (page != 0L)
pageMem.releasePage(CACHE_ID, pageId, page);
pageMem.stop();
}
}
/** */
public void testBytes() throws Exception {
MemoryPolicyConfiguration plcCfg = new MemoryPolicyConfiguration().setMaxSize(1024 * MB);
JavaLogger log = new JavaLogger();
PageMemory pageMem = new PageMemoryNoStoreImpl(log,
new UnsafeMemoryProvider(log),
null,
PAGE_SIZE,
plcCfg,
new MemoryMetricsImpl(plcCfg),
false);
pageMem.start();
long pageId = 0L;
long page = 0L;
try {
pageId = pageMem.allocatePage(CACHE_ID, 1, PageIdAllocator.FLAG_DATA);
page = pageMem.acquirePage(CACHE_ID, pageId);
long pageAddr = pageMem.readLock(CACHE_ID, pageId, page);
int off = 0;
InlineIndexHelper ih = new InlineIndexHelper(Value.BYTES, 1, 0);
ih.put(pageAddr, off, ValueBytes.get(new byte[] {1, 2, 3, 4, 5}), 3 + 3);
assertFalse(ih.isValueFull(pageAddr, off));
assertTrue(Arrays.equals(new byte[] {1, 2, 3}, ih.get(pageAddr, off, 3 + 5).getBytes()));
ih.put(pageAddr, off, ValueBytes.get(new byte[] {1, 2, 3, 4, 5}), 3 + 5);
assertTrue(ih.isValueFull(pageAddr, off));
assertTrue(Arrays.equals(new byte[] {1, 2, 3, 4, 5}, ih.get(pageAddr, off, 3 + 5).getBytes()));
}
finally {
if (page != 0L)
pageMem.releasePage(CACHE_ID, pageId, page);
pageMem.stop();
}
}
/** */
public void testNull() throws Exception {
testPutGet(ValueInt.get(-1), ValueNull.INSTANCE, ValueInt.get(3));
}
/** */
public void testBoolean() throws Exception {
testPutGet(ValueBoolean.get(true), ValueBoolean.get(false), ValueBoolean.get(true));
}
/** */
public void testByte() throws Exception {
testPutGet(ValueByte.get((byte)-1), ValueByte.get((byte)2), ValueByte.get((byte)3));
}
/** */
public void testShort() throws Exception {
testPutGet(ValueShort.get((short)-32000), ValueShort.get((short)2), ValueShort.get((short)3));
}
/** */
public void testInt() throws Exception {
testPutGet(ValueInt.get(-1), ValueInt.get(2), ValueInt.get(3));
}
/** */
public void testLong() throws Exception {
testPutGet(ValueLong.get(-1), ValueLong.get(2), ValueLong.get(3));
}
/** */
public void testFloat() throws Exception {
testPutGet(ValueFloat.get(1.1f), ValueFloat.get(2.2f), ValueFloat.get(1.1f));
}
/** */
public void testDouble() throws Exception {
testPutGet(ValueDouble.get(1.1f), ValueDouble.get(2.2f), ValueDouble.get(1.1f));
}
/** */
public void testDate() throws Exception {
testPutGet(ValueDate.get(Date.valueOf("2017-02-20")),
ValueDate.get(Date.valueOf("2017-02-21")),
ValueDate.get(Date.valueOf("2017-02-19")));
}
/** */
public void testTime() throws Exception {
testPutGet(ValueTime.get(Time.valueOf("10:01:01")),
ValueTime.get(Time.valueOf("11:02:02")),
ValueTime.get(Time.valueOf("12:03:03")));
}
/** */
public void testTimestamp() throws Exception {
testPutGet(ValueTimestamp.get(Timestamp.valueOf("2017-02-20 10:01:01")),
ValueTimestamp.get(Timestamp.valueOf("2017-02-20 10:01:01")),
ValueTimestamp.get(Timestamp.valueOf("2017-02-20 10:01:01")));
}
/** */
public void testUUID() throws Exception {
testPutGet(ValueUuid.get(UUID.randomUUID().toString()),
ValueUuid.get(UUID.randomUUID().toString()),
ValueUuid.get(UUID.randomUUID().toString()));
}
/** */
private void testPutGet(Value v1, Value v2, Value v3) throws Exception {
MemoryPolicyConfiguration plcCfg = new MemoryPolicyConfiguration().setMaxSize(1024 * MB);
JavaLogger log = new JavaLogger();
PageMemory pageMem = new PageMemoryNoStoreImpl(log,
new UnsafeMemoryProvider(log),
null,
PAGE_SIZE,
plcCfg,
new MemoryMetricsImpl(plcCfg),
false);
pageMem.start();
long pageId = 0L;
long page = 0L;
try {
pageId = pageMem.allocatePage(CACHE_ID, 1, PageIdAllocator.FLAG_DATA);
page = pageMem.acquirePage(CACHE_ID, pageId);
long pageAddr = pageMem.readLock(CACHE_ID, pageId, page);
int off = 0;
int max = 255;
InlineIndexHelper ih = new InlineIndexHelper(v1.getType(), 1, 0);
off += ih.put(pageAddr, off, v1, max - off);
off += ih.put(pageAddr, off, v2, max - off);
off += ih.put(pageAddr, off, v3, max - off);
Value v11 = ih.get(pageAddr, 0, max);
Value v22 = ih.get(pageAddr, ih.fullSize(pageAddr, 0), max);
assertEquals(v1.getObject(), v11.getObject());
assertEquals(v2.getObject(), v22.getObject());
}
finally {
if (page != 0L)
pageMem.releasePage(CACHE_ID, pageId, page);
pageMem.stop();
}
}
/** */
private boolean getRes(InlineIndexHelper ha, String s1, String s2) {
Value v1 = s1 == null ? ValueNull.INSTANCE : ValueString.get(s1);
Value v2 = s2 == null ? ValueNull.INSTANCE : ValueString.get(s2);
int c = v1.compareTypeSafe(v2, CompareMode.getInstance(CompareMode.DEFAULT, 0));
return ha.canRelyOnCompare(c, v1, v2);
}
/** */
private boolean getResBytes(InlineIndexHelper ha, byte[] b1, byte[] b2) {
Value v1 = b1 == null ? ValueNull.INSTANCE : ValueBytes.get(b1);
Value v2 = b2 == null ? ValueNull.INSTANCE : ValueBytes.get(b2);
int c = v1.compareTypeSafe(v2, CompareMode.getInstance(CompareMode.DEFAULT, 0));
return ha.canRelyOnCompare(c, v1, v2);
}
}