| /* |
| * 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.iotdb.tsfile.read.reader; |
| |
| import org.apache.iotdb.tsfile.common.conf.TSFileConfig; |
| import org.apache.iotdb.tsfile.encoding.decoder.Decoder; |
| import org.apache.iotdb.tsfile.encoding.decoder.DeltaBinaryDecoder; |
| import org.apache.iotdb.tsfile.encoding.decoder.DoublePrecisionDecoderV1; |
| import org.apache.iotdb.tsfile.encoding.decoder.IntRleDecoder; |
| import org.apache.iotdb.tsfile.encoding.decoder.LongRleDecoder; |
| import org.apache.iotdb.tsfile.encoding.decoder.PlainDecoder; |
| import org.apache.iotdb.tsfile.encoding.decoder.SinglePrecisionDecoderV1; |
| import org.apache.iotdb.tsfile.encoding.encoder.DeltaBinaryEncoder; |
| import org.apache.iotdb.tsfile.encoding.encoder.DoublePrecisionEncoderV1; |
| import org.apache.iotdb.tsfile.encoding.encoder.Encoder; |
| import org.apache.iotdb.tsfile.encoding.encoder.IntRleEncoder; |
| import org.apache.iotdb.tsfile.encoding.encoder.LongRleEncoder; |
| import org.apache.iotdb.tsfile.encoding.encoder.PlainEncoder; |
| import org.apache.iotdb.tsfile.encoding.encoder.SinglePrecisionEncoderV1; |
| import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType; |
| import org.apache.iotdb.tsfile.read.common.BatchData; |
| import org.apache.iotdb.tsfile.read.common.TimeRange; |
| import org.apache.iotdb.tsfile.read.reader.page.PageReader; |
| import org.apache.iotdb.tsfile.utils.Binary; |
| import org.apache.iotdb.tsfile.write.page.PageWriter; |
| |
| import org.junit.Assert; |
| import org.junit.Test; |
| |
| import java.io.IOException; |
| import java.nio.ByteBuffer; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| public class PageReaderTest { |
| |
| private static final int POINTS_COUNT_IN_ONE_PAGE = 1000000; |
| |
| @Test |
| public void testLong() { |
| |
| LoopWriteReadTest test = |
| new LoopWriteReadTest( |
| "Test INT64", |
| new LongRleEncoder(), |
| new LongRleDecoder(), |
| TSDataType.INT64, |
| POINTS_COUNT_IN_ONE_PAGE) { |
| @Override |
| public Object generateValueByIndex(int i) { |
| return Long.MAX_VALUE - i; |
| } |
| }; |
| test.test(TSDataType.INT64); |
| } |
| |
| @Test |
| public void testBoolean() { |
| LoopWriteReadTest test = |
| new LoopWriteReadTest( |
| "Test Boolean", |
| new IntRleEncoder(), |
| new IntRleDecoder(), |
| TSDataType.BOOLEAN, |
| POINTS_COUNT_IN_ONE_PAGE) { |
| @Override |
| public Object generateValueByIndex(int i) { |
| return i % 3 == 0; |
| } |
| }; |
| test.test(TSDataType.BOOLEAN); |
| } |
| |
| @Test |
| public void testInt() { |
| LoopWriteReadTest test = |
| new LoopWriteReadTest( |
| "Test INT32", |
| new IntRleEncoder(), |
| new IntRleDecoder(), |
| TSDataType.INT32, |
| POINTS_COUNT_IN_ONE_PAGE) { |
| @Override |
| public Object generateValueByIndex(int i) { |
| return i; |
| } |
| }; |
| test.test(TSDataType.INT32); |
| } |
| |
| @Test |
| public void testFloat() { |
| LoopWriteReadTest test = |
| new LoopWriteReadTest( |
| "Test FLOAT", |
| new SinglePrecisionEncoderV1(), |
| new SinglePrecisionDecoderV1(), |
| TSDataType.FLOAT, |
| POINTS_COUNT_IN_ONE_PAGE) { |
| @Override |
| public Object generateValueByIndex(int i) { |
| return (float) i / 10 - (float) i / 100; |
| } |
| }; |
| test.test(TSDataType.FLOAT); |
| |
| LoopWriteReadTest test2 = |
| new LoopWriteReadTest( |
| "Test FLOAT", |
| new SinglePrecisionEncoderV1(), |
| new SinglePrecisionDecoderV1(), |
| TSDataType.FLOAT, |
| POINTS_COUNT_IN_ONE_PAGE) { |
| @Override |
| public Object generateValueByIndex(int i) { |
| return (float) i / 100 - (float) i / 10; |
| } |
| }; |
| test2.test(TSDataType.FLOAT); |
| } |
| |
| @Test |
| public void testDouble() { |
| LoopWriteReadTest test = |
| new LoopWriteReadTest( |
| "Test Double", |
| new DoublePrecisionEncoderV1(), |
| new DoublePrecisionDecoderV1(), |
| TSDataType.DOUBLE, |
| POINTS_COUNT_IN_ONE_PAGE) { |
| @Override |
| public Object generateValueByIndex(int i) { |
| return (double) i / 10 - (double) i / 100; |
| } |
| }; |
| test.test(TSDataType.DOUBLE); |
| |
| LoopWriteReadTest test2 = |
| new LoopWriteReadTest( |
| "Test Double", |
| new DoublePrecisionEncoderV1(), |
| new DoublePrecisionDecoderV1(), |
| TSDataType.DOUBLE, |
| POINTS_COUNT_IN_ONE_PAGE) { |
| @Override |
| public Object generateValueByIndex(int i) { |
| return (double) i / 1000 - (double) i / 100; |
| } |
| }; |
| test2.test(TSDataType.DOUBLE); |
| } |
| |
| @Test |
| public void testBinary() { |
| LoopWriteReadTest test = |
| new LoopWriteReadTest( |
| "Test Double", |
| new PlainEncoder(TSDataType.TEXT, 1000), |
| new PlainDecoder(), |
| TSDataType.TEXT, |
| POINTS_COUNT_IN_ONE_PAGE) { |
| @Override |
| public Object generateValueByIndex(int i) { |
| return new Binary("TEST TEXT" + i, TSFileConfig.STRING_CHARSET); |
| } |
| }; |
| test.test(TSDataType.TEXT); |
| } |
| |
| private abstract static class LoopWriteReadTest { |
| |
| private Encoder encoder; |
| private Decoder decoder; |
| private TSDataType dataType; |
| private PageWriter pageWriter; |
| private String name; |
| private int count; |
| |
| public LoopWriteReadTest( |
| String name, Encoder encoder, Decoder decoder, TSDataType dataType, int count) { |
| this.name = name; |
| this.encoder = encoder; |
| this.decoder = decoder; |
| this.dataType = dataType; |
| this.count = count; |
| } |
| |
| public void test(TSDataType dataType) { |
| try { |
| pageWriter = new PageWriter(); |
| pageWriter.setTimeEncoder(new DeltaBinaryEncoder.LongDeltaEncoder()); |
| pageWriter.setValueEncoder(this.encoder); |
| pageWriter.initStatistics(dataType); |
| writeData(); |
| |
| ByteBuffer page = ByteBuffer.wrap(pageWriter.getUncompressedBytes().array()); |
| |
| PageReader pageReader = |
| new PageReader(page, dataType, decoder, new DeltaBinaryDecoder.LongDeltaDecoder()); |
| |
| int index = 0; |
| BatchData data = pageReader.getAllSatisfiedPageData(); |
| Assert.assertNotNull(data); |
| |
| while (data.hasCurrent()) { |
| Assert.assertEquals(Long.valueOf(index), (Long) data.currentTime()); |
| Assert.assertEquals(generateValueByIndex(index), data.currentValue()); |
| data.next(); |
| index++; |
| } |
| Assert.assertEquals(count, index); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| Assert.fail("Fail when executing test: [" + name + "]"); |
| } |
| } |
| |
| public void testDelete(TSDataType dataType) { |
| try { |
| pageWriter = new PageWriter(); |
| pageWriter.setTimeEncoder(new DeltaBinaryEncoder.LongDeltaEncoder()); |
| pageWriter.setValueEncoder(this.encoder); |
| pageWriter.initStatistics(dataType); |
| writeData(); |
| |
| ByteBuffer page = ByteBuffer.wrap(pageWriter.getUncompressedBytes().array()); |
| |
| PageReader pageReader = |
| new PageReader(page, dataType, decoder, new DeltaBinaryDecoder.LongDeltaDecoder()); |
| |
| int index = 0; |
| List<TimeRange> deleteIntervals = new ArrayList<>(); |
| deleteIntervals.add(new TimeRange(5, 10)); |
| deleteIntervals.add(new TimeRange(20, 30)); |
| deleteIntervals.add(new TimeRange(50, 70)); |
| pageReader.setDeleteIntervalList(deleteIntervals); |
| BatchData data = pageReader.getAllSatisfiedPageData(); |
| Assert.assertNotNull(data); |
| |
| for (TimeRange range : pageReader.getDeleteIntervalList()) { |
| while (data.hasCurrent()) { |
| Assert.assertEquals(Long.valueOf(index), (Long) data.currentTime()); |
| Assert.assertEquals(generateValueByIndex(index), data.currentValue()); |
| data.next(); |
| index++; |
| if (index == range.getMin()) { |
| index = (int) (range.getMax() + 1); |
| break; |
| } |
| } |
| } |
| } catch (IOException e) { |
| e.printStackTrace(); |
| Assert.fail("Fail when executing test: [" + name + "]"); |
| } |
| } |
| |
| private void writeData() { |
| for (int i = 0; i < count; i++) { |
| switch (dataType) { |
| case BOOLEAN: |
| pageWriter.write(i, (Boolean) generateValueByIndex(i)); |
| break; |
| case INT32: |
| pageWriter.write(i, (Integer) generateValueByIndex(i)); |
| break; |
| case INT64: |
| pageWriter.write(i, (Long) generateValueByIndex(i)); |
| break; |
| case FLOAT: |
| pageWriter.write(i, (Float) generateValueByIndex(i)); |
| break; |
| case DOUBLE: |
| pageWriter.write(i, (Double) generateValueByIndex(i)); |
| break; |
| case TEXT: |
| pageWriter.write(i, (Binary) generateValueByIndex(i)); |
| break; |
| } |
| } |
| } |
| |
| public abstract Object generateValueByIndex(int i); |
| } |
| |
| @Test |
| public void testPageDelete() { |
| LoopWriteReadTest test = |
| new LoopWriteReadTest( |
| "Test INT64", new LongRleEncoder(), new LongRleDecoder(), TSDataType.INT64, 100) { |
| @Override |
| public Object generateValueByIndex(int i) { |
| return Long.MAX_VALUE - i; |
| } |
| }; |
| test.testDelete(TSDataType.INT64); |
| } |
| } |