summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Ahlborn <jtahlborn@yahoo.com>2012-06-14 03:34:45 +0000
committerJames Ahlborn <jtahlborn@yahoo.com>2012-06-14 03:34:45 +0000
commitacdd431dcf6417e90c01429fb546a08c541e0676 (patch)
treecba8f6f798ecc3d375ef9c1ca86f065484915b54
parentfb3533f16221e78f9f9af42cef5153e72d7285bd (diff)
downloadjackcess-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.java276
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;
+ }
+ }
+
+}