diff options
author | James Ahlborn <jtahlborn@yahoo.com> | 2012-06-14 03:34:45 +0000 |
---|---|---|
committer | James Ahlborn <jtahlborn@yahoo.com> | 2012-06-14 03:34:45 +0000 |
commit | acdd431dcf6417e90c01429fb546a08c541e0676 (patch) | |
tree | cba8f6f798ecc3d375ef9c1ca86f065484915b54 | |
parent | fb3533f16221e78f9f9af42cef5153e72d7285bd (diff) | |
download | jackcess-acdd431dcf6417e90c01429fb546a08c541e0676.tar.gz jackcess-acdd431dcf6417e90c01429fb546a08c541e0676.zip |
add codechandler unit test
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@629 f203690c-595d-4dc9-a70b-905162fa7fd2
-rw-r--r-- | test/src/java/com/healthmarketscience/jackcess/CodecHandlerTest.java | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/test/src/java/com/healthmarketscience/jackcess/CodecHandlerTest.java b/test/src/java/com/healthmarketscience/jackcess/CodecHandlerTest.java new file mode 100644 index 0000000..119a6e3 --- /dev/null +++ b/test/src/java/com/healthmarketscience/jackcess/CodecHandlerTest.java @@ -0,0 +1,276 @@ +/* +Copyright (c) 2012 Health Market Science, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA + +You can contact Health Market Science at info@healthmarketscience.com +or at the following address: + +Health Market Science +2700 Horizon Drive +Suite 200 +King of Prussia, PA 19406 +*/ + +package com.healthmarketscience.jackcess; + +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.charset.Charset; +import java.util.Iterator; +import java.util.Map; + +import static com.healthmarketscience.jackcess.JetFormatTest.*; +import junit.framework.TestCase; + +/** + * + * @author James Ahlborn + */ +public class CodecHandlerTest extends TestCase +{ + private static final CodecProvider SIMPLE_PROVIDER = new CodecProvider() { + public CodecHandler createHandler(PageChannel channel, Charset charset) + throws IOException + { + return new SimpleCodecHandler(channel); + } + }; + private static final CodecProvider FULL_PROVIDER = new CodecProvider() { + public CodecHandler createHandler(PageChannel channel, Charset charset) + throws IOException + { + return new FullCodecHandler(channel); + } + }; + + + public CodecHandlerTest(String name) throws Exception { + super(name); + } + + public void testCodecHandler() throws Exception + { + doTestCodecHandler(true); + doTestCodecHandler(false); + } + + private static void doTestCodecHandler(boolean simple) throws Exception + { + for(Database.FileFormat ff : SUPPORTED_FILEFORMATS) { + Database db = DatabaseTest.create(ff); + int pageSize = db.getFormat().PAGE_SIZE; + File dbFile = db.getFile(); + db.close(); + + // apply encoding to file + encodeFile(dbFile, pageSize, simple); + + db = Database.open(dbFile, false, Database.DEFAULT_AUTO_SYNC, null, null, + (simple ? SIMPLE_PROVIDER : FULL_PROVIDER)); + + Table t1 = new TableBuilder("test1") + .addColumn(new ColumnBuilder("id", DataType.LONG).setAutoNumber(true)) + .addColumn(new ColumnBuilder("data", DataType.TEXT).setLength(250)) + .setPrimaryKey("id") + .addIndex(new IndexBuilder("data_idx").addColumns("data")) + .toTable(db); + + Table t2 = new TableBuilder("test2") + .addColumn(new ColumnBuilder("id", DataType.LONG).setAutoNumber(true)) + .addColumn(new ColumnBuilder("data", DataType.TEXT).setLength(250)) + .setPrimaryKey("id") + .addIndex(new IndexBuilder("data_idx").addColumns("data")) + .toTable(db); + + int autonum = 1; + for(int i = 1; i < 2; ++i) { + writeData(t1, t2, autonum, autonum + 100); + autonum += 100; + } + + db.close(); + } + } + + private static void writeData(Table t1, Table t2, int start, int end) + throws Exception + { + for(int i = start; i < end; ++i) { + t1.addRow(null, "rowdata-" + i + DatabaseTest.createString(100)); + t2.addRow(null, "rowdata-" + i + DatabaseTest.createString(100)); + } + + Cursor c1 = new CursorBuilder(t1).setIndex(t1.getPrimaryKeyIndex()) + .toCursor(); + Cursor c2 = new CursorBuilder(t2).setIndex(t2.getPrimaryKeyIndex()) + .toCursor(); + + Iterator<Map<String,Object>> i1 = c1.iterator(); + Iterator<Map<String,Object>> i2 = c2.reverseIterable().iterator(); + + int t1rows = 0; + int t2rows = 0; + while(i1.hasNext() || i2.hasNext()) { + if(i1.hasNext()) { + checkRow(i1.next()); + i1.remove(); + ++t1rows; + } + if(i2.hasNext()) { + checkRow(i2.next()); + i2.remove(); + ++t2rows; + } + } + + assertEquals(100, t1rows); + assertEquals(100, t2rows); + } + + private static void checkRow(Map<String,Object> row) + { + int id = (Integer)row.get("id"); + String value = (String)row.get("data"); + String valuePrefix = "rowdata-" + id; + assertTrue(value.startsWith(valuePrefix)); + assertEquals(valuePrefix.length() + 100, value.length()); + } + + private static void encodeFile(File dbFile, int pageSize, boolean simple) + throws Exception + { + long dbLen = dbFile.length(); + FileChannel fileChannel = new RandomAccessFile(dbFile, "rw").getChannel(); + ByteBuffer bb = ByteBuffer.allocate(pageSize) + .order(PageChannel.DEFAULT_BYTE_ORDER); + for(long offset = pageSize; offset < dbLen; offset += pageSize) { + + bb.clear(); + fileChannel.read(bb, offset); + + int pageNumber = (int)(offset / pageSize); + if(simple) { + simpleEncode(bb.array(), bb.array(), pageNumber, 0, pageSize); + } else { + fullEncode(bb.array(), bb.array(), pageNumber); + } + + bb.rewind(); + fileChannel.write(bb, offset); + } + fileChannel.close(); + } + + private static void simpleEncode(byte[] inBuffer, byte[] outBuffer, + int pageNumber, int offset, int limit) { + for(int i = offset; i < limit; ++i) { + int mask = (i + pageNumber) % 256; + outBuffer[i] = (byte)(inBuffer[i] ^ mask); + } + } + + private static void simpleDecode(byte[] inBuffer, byte[] outBuffer, + int pageNumber) { + simpleEncode(inBuffer, outBuffer, pageNumber, 0, inBuffer.length); + } + + private static void fullEncode(byte[] inBuffer, byte[] outBuffer, + int pageNumber) { + int accum = 0; + for(int i = 0; i < inBuffer.length; ++i) { + int mask = (i + pageNumber + accum) % 256; + accum += inBuffer[i]; + outBuffer[i] = (byte)(inBuffer[i] ^ mask); + } + } + + private static void fullDecode(byte[] inBuffer, byte[] outBuffer, + int pageNumber) { + int accum = 0; + for(int i = 0; i < inBuffer.length; ++i) { + int mask = (i + pageNumber + accum) % 256; + outBuffer[i] = (byte)(inBuffer[i] ^ mask); + accum += outBuffer[i]; + } + } + + private static final class SimpleCodecHandler implements CodecHandler + { + private final TempBufferHolder _bufH = TempBufferHolder.newHolder( + TempBufferHolder.Type.HARD, true); + private final PageChannel _channel; + + private SimpleCodecHandler(PageChannel channel) { + _channel = channel; + } + + public boolean canEncodePartialPage() { + return true; + } + + public void decodePage(ByteBuffer page, int pageNumber) throws IOException { + byte[] arr = page.array(); + simpleDecode(arr, arr, pageNumber); + } + + public ByteBuffer encodePage(ByteBuffer page, int pageNumber, + int pageOffset) + throws IOException + { + ByteBuffer bb = _bufH.getPageBuffer(_channel); + simpleEncode(page.array(), bb.array(), pageNumber, pageOffset, + page.limit()); + return bb; + } + } + + private static final class FullCodecHandler implements CodecHandler + { + private final TempBufferHolder _bufH = TempBufferHolder.newHolder( + TempBufferHolder.Type.HARD, true); + private final PageChannel _channel; + + private FullCodecHandler(PageChannel channel) { + _channel = channel; + } + + public boolean canEncodePartialPage() { + return false; + } + + public void decodePage(ByteBuffer page, int pageNumber) throws IOException { + byte[] arr = page.array(); + fullDecode(arr, arr, pageNumber); + } + + public ByteBuffer encodePage(ByteBuffer page, int pageNumber, + int pageOffset) + throws IOException + { + assertEquals(0, pageOffset); + assertEquals(_channel.getFormat().PAGE_SIZE, page.limit()); + + ByteBuffer bb = _bufH.getPageBuffer(_channel); + fullEncode(page.array(), bb.array(), pageNumber); + return bb; + } + } + +} |