From d1a79d0064632cca220409abb799ab1757c6caa7 Mon Sep 17 00:00:00 2001 From: James Ahlborn Date: Tue, 30 Jul 2013 02:17:15 +0000 Subject: merge branch jackcess-2 changes through r759 git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@760 f203690c-595d-4dc9-a70b-905162fa7fd2 --- .../healthmarketscience/jackcess/BigIndexTest.java | 63 +- .../jackcess/CodecHandlerTest.java | 279 ------- .../jackcess/ComplexColumnTest.java | 13 +- .../jackcess/CursorBuilderTest.java | 25 +- .../healthmarketscience/jackcess/CursorTest.java | 211 ++++-- .../healthmarketscience/jackcess/DatabaseTest.java | 210 ++++-- .../jackcess/ErrorHandlerTest.java | 184 ----- .../healthmarketscience/jackcess/ExportTest.java | 134 ---- .../jackcess/FKEnforcerTest.java | 138 ---- .../healthmarketscience/jackcess/ImportTest.java | 327 --------- .../jackcess/IndexCodesTest.java | 792 -------------------- .../healthmarketscience/jackcess/IndexTest.java | 90 ++- .../jackcess/JetFormatTest.java | 240 ------- .../healthmarketscience/jackcess/JoinerTest.java | 206 ------ .../jackcess/MemFileChannelTest.java | 162 ----- .../jackcess/PropertiesTest.java | 17 +- .../jackcess/RelationshipTest.java | 9 +- .../jackcess/RowFilterTest.java | 112 --- .../healthmarketscience/jackcess/TableTest.java | 86 ++- .../healthmarketscience/jackcess/UsageMapTest.java | 53 -- .../jackcess/impl/CodecHandlerTest.java | 304 ++++++++ .../jackcess/impl/FKEnforcerTest.java | 144 ++++ .../jackcess/impl/IndexCodesTest.java | 798 +++++++++++++++++++++ .../jackcess/impl/JetFormatTest.java | 243 +++++++ .../jackcess/impl/UsageMapTest.java | 54 ++ .../jackcess/impl/scsu/CompressMain.java | 574 +++++++++++++++ .../jackcess/impl/scsu/CompressTest.java | 47 ++ .../jackcess/query/QueryTest.java | 21 +- .../jackcess/scsu/CompressMain.java | 574 --------------- .../jackcess/scsu/CompressTest.java | 47 -- .../jackcess/util/ErrorHandlerTest.java | 195 +++++ .../jackcess/util/ExportTest.java | 139 ++++ .../jackcess/util/ImportTest.java | 333 +++++++++ .../jackcess/util/JoinerTest.java | 209 ++++++ .../jackcess/util/MemFileChannelTest.java | 164 +++++ .../jackcess/util/RowFilterTest.java | 114 +++ 36 files changed, 3782 insertions(+), 3529 deletions(-) delete mode 100644 test/src/java/com/healthmarketscience/jackcess/CodecHandlerTest.java delete mode 100644 test/src/java/com/healthmarketscience/jackcess/ErrorHandlerTest.java delete mode 100644 test/src/java/com/healthmarketscience/jackcess/ExportTest.java delete mode 100644 test/src/java/com/healthmarketscience/jackcess/FKEnforcerTest.java delete mode 100644 test/src/java/com/healthmarketscience/jackcess/ImportTest.java delete mode 100644 test/src/java/com/healthmarketscience/jackcess/IndexCodesTest.java delete mode 100644 test/src/java/com/healthmarketscience/jackcess/JetFormatTest.java delete mode 100644 test/src/java/com/healthmarketscience/jackcess/JoinerTest.java delete mode 100644 test/src/java/com/healthmarketscience/jackcess/MemFileChannelTest.java delete mode 100644 test/src/java/com/healthmarketscience/jackcess/RowFilterTest.java delete mode 100644 test/src/java/com/healthmarketscience/jackcess/UsageMapTest.java create mode 100644 test/src/java/com/healthmarketscience/jackcess/impl/CodecHandlerTest.java create mode 100644 test/src/java/com/healthmarketscience/jackcess/impl/FKEnforcerTest.java create mode 100644 test/src/java/com/healthmarketscience/jackcess/impl/IndexCodesTest.java create mode 100644 test/src/java/com/healthmarketscience/jackcess/impl/JetFormatTest.java create mode 100644 test/src/java/com/healthmarketscience/jackcess/impl/UsageMapTest.java create mode 100644 test/src/java/com/healthmarketscience/jackcess/impl/scsu/CompressMain.java create mode 100644 test/src/java/com/healthmarketscience/jackcess/impl/scsu/CompressTest.java delete mode 100644 test/src/java/com/healthmarketscience/jackcess/scsu/CompressMain.java delete mode 100644 test/src/java/com/healthmarketscience/jackcess/scsu/CompressTest.java create mode 100644 test/src/java/com/healthmarketscience/jackcess/util/ErrorHandlerTest.java create mode 100644 test/src/java/com/healthmarketscience/jackcess/util/ExportTest.java create mode 100644 test/src/java/com/healthmarketscience/jackcess/util/ImportTest.java create mode 100644 test/src/java/com/healthmarketscience/jackcess/util/JoinerTest.java create mode 100644 test/src/java/com/healthmarketscience/jackcess/util/MemFileChannelTest.java create mode 100644 test/src/java/com/healthmarketscience/jackcess/util/RowFilterTest.java (limited to 'test/src') diff --git a/test/src/java/com/healthmarketscience/jackcess/BigIndexTest.java b/test/src/java/com/healthmarketscience/jackcess/BigIndexTest.java index f6d1c0a..70d63d8 100644 --- a/test/src/java/com/healthmarketscience/jackcess/BigIndexTest.java +++ b/test/src/java/com/healthmarketscience/jackcess/BigIndexTest.java @@ -35,43 +35,26 @@ import java.util.Random; import junit.framework.TestCase; import static com.healthmarketscience.jackcess.DatabaseTest.*; -import static com.healthmarketscience.jackcess.JetFormatTest.*; - +import static com.healthmarketscience.jackcess.impl.JetFormatTest.*; +import com.healthmarketscience.jackcess.impl.TableImpl; +import com.healthmarketscience.jackcess.impl.IndexImpl; /** * @author james */ public class BigIndexTest extends TestCase { - private String _oldBigIndexValue = null; - public BigIndexTest(String name) { super(name); } - - @Override - protected void setUp() { - _oldBigIndexValue = System.getProperty(Database.USE_BIG_INDEX_PROPERTY); - System.setProperty(Database.USE_BIG_INDEX_PROPERTY, - Boolean.TRUE.toString()); - } - - @Override - protected void tearDown() { - if (_oldBigIndexValue != null) { - System.setProperty(Database.USE_BIG_INDEX_PROPERTY, _oldBigIndexValue); - } else { - System.clearProperty(Database.USE_BIG_INDEX_PROPERTY); - } - } public void testComplexIndex() throws Exception { for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.COMP_INDEX, true)) { // this file has an index with "compressed" entries and node pages Database db = open(testDB); - Table t = db.getTable("Table1"); - Index index = t.getIndex("CD_AGENTE"); + TableImpl t = (TableImpl)db.getTable("Table1"); + IndexImpl index = t.getIndex("CD_AGENTE"); assertFalse(index.isInitialized()); assertEquals(512, countRows(t)); assertEquals(512, index.getIndexData().getEntryCount()); @@ -84,8 +67,8 @@ public class BigIndexTest extends TestCase { for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.BIG_INDEX)) { // this file has an index with "compressed" entries and node pages Database db = open(testDB); - Table t = db.getTable("Table1"); - Index index = t.getIndex("col1"); + TableImpl t = (TableImpl)db.getTable("Table1"); + IndexImpl index = t.getIndex("col1"); assertFalse(index.isInitialized()); assertEquals(0, countRows(t)); assertEquals(0, index.getIndexData().getEntryCount()); @@ -98,12 +81,9 @@ public class BigIndexTest extends TestCase { // copy to temp file and attempt to edit db = openCopy(testDB); - t = db.getTable("Table1"); + t = (TableImpl)db.getTable("Table1"); index = t.getIndex("col1"); - System.out.println("BigIndexTest: Index type: " + - index.getIndexData().getClass()); - // add 2,000 (pseudo) random entries to the table Random rand = new Random(13L); for(int i = 0; i < 2000; ++i) { @@ -131,10 +111,13 @@ public class BigIndexTest extends TestCase { } } - ((BigIndexData)index.getIndexData()).validate(); + index.getIndexData().validate(); db.flush(); - t = db.getTable("Table1"); + t = null; + System.gc(); + + t = (TableImpl)db.getTable("Table1"); index = t.getIndex("col1"); // make sure all entries are there and correctly ordered @@ -142,7 +125,7 @@ public class BigIndexTest extends TestCase { String prevValue = firstValue; int rowCount = 0; List firstTwo = new ArrayList(); - for(Map row : Cursor.createIndexCursor(t, index)) { + for(Map row : CursorBuilder.createCursor(t, index)) { String origVal = (String)row.get("col1"); String val = origVal; if(val == null) { @@ -159,10 +142,10 @@ public class BigIndexTest extends TestCase { assertEquals(2000, rowCount); - ((BigIndexData)index.getIndexData()).validate(); + index.getIndexData().validate(); // delete an entry in the middle - Cursor cursor = Cursor.createIndexCursor(t, index); + Cursor cursor = CursorBuilder.createCursor(t, index); for(int i = 0; i < (rowCount / 2); ++i) { assertTrue(cursor.moveToNextRow()); } @@ -176,17 +159,17 @@ public class BigIndexTest extends TestCase { cursor.deleteCurrentRow(); } - ((BigIndexData)index.getIndexData()).validate(); + index.getIndexData().validate(); List found = new ArrayList(); - for(Map row : Cursor.createIndexCursor(t, index)) { + for(Map row : CursorBuilder.createCursor(t, index)) { found.add((String)row.get("col1")); } assertEquals(firstTwo, found); // remove remaining entries - cursor = Cursor.createCursor(t); + cursor = CursorBuilder.createCursor(t); for(int i = 0; i < 2; ++i) { assertTrue(cursor.moveToNextRow()); cursor.deleteCurrentRow(); @@ -195,7 +178,7 @@ public class BigIndexTest extends TestCase { assertFalse(cursor.moveToNextRow()); assertFalse(cursor.moveToPreviousRow()); - ((BigIndexData)index.getIndexData()).validate(); + index.getIndexData().validate(); // add 50 (pseudo) random entries to the table rand = new Random(42L); @@ -208,14 +191,14 @@ public class BigIndexTest extends TestCase { t.addRow(nextVal, "this is some row data " + nextInt); } - ((BigIndexData)index.getIndexData()).validate(); + index.getIndexData().validate(); - cursor = Cursor.createIndexCursor(t, index); + cursor = CursorBuilder.createCursor(t, index); while(cursor.moveToNextRow()) { cursor.deleteCurrentRow(); } - ((BigIndexData)index.getIndexData()).validate(); + index.getIndexData().validate(); db.close(); diff --git a/test/src/java/com/healthmarketscience/jackcess/CodecHandlerTest.java b/test/src/java/com/healthmarketscience/jackcess/CodecHandlerTest.java deleted file mode 100644 index edcbf09..0000000 --- a/test/src/java/com/healthmarketscience/jackcess/CodecHandlerTest.java +++ /dev/null @@ -1,279 +0,0 @@ -/* -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 = new DatabaseBuilder(dbFile) - .setCodecProvider(simple ? SIMPLE_PROVIDER : FULL_PROVIDER) - .open(); - - 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> i1 = c1.iterator(); - Iterator> 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 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); - bb.clear(); - 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); - bb.clear(); - fullEncode(page.array(), bb.array(), pageNumber); - return bb; - } - } - -} diff --git a/test/src/java/com/healthmarketscience/jackcess/ComplexColumnTest.java b/test/src/java/com/healthmarketscience/jackcess/ComplexColumnTest.java index 8fea667..173a53c 100644 --- a/test/src/java/com/healthmarketscience/jackcess/ComplexColumnTest.java +++ b/test/src/java/com/healthmarketscience/jackcess/ComplexColumnTest.java @@ -26,13 +26,16 @@ import java.util.List; import java.util.Map; import static com.healthmarketscience.jackcess.DatabaseTest.*; -import static com.healthmarketscience.jackcess.JetFormatTest.*; import com.healthmarketscience.jackcess.complex.Attachment; import com.healthmarketscience.jackcess.complex.ComplexDataType; import com.healthmarketscience.jackcess.complex.ComplexValueForeignKey; import com.healthmarketscience.jackcess.complex.SingleValue; import com.healthmarketscience.jackcess.complex.UnsupportedValue; import com.healthmarketscience.jackcess.complex.Version; +import com.healthmarketscience.jackcess.impl.ByteUtil; +import com.healthmarketscience.jackcess.impl.ColumnImpl; +import static com.healthmarketscience.jackcess.impl.JetFormatTest.*; +import com.healthmarketscience.jackcess.impl.PageChannel; import junit.framework.TestCase; @@ -97,7 +100,7 @@ public class ComplexColumnTest extends TestCase checkVersions(row8ValFk.get(), row8ValFk, "row8-memo", "row8-memo", upTime); - Cursor cursor = Cursor.createCursor(t1); + Cursor cursor = CursorBuilder.createCursor(t1); assertTrue(cursor.findFirstRow(t1.getColumn("id"), "row3")); ComplexValueForeignKey row3ValFk = (ComplexValueForeignKey) cursor.getCurrentRowValue(verCol); @@ -196,7 +199,7 @@ public class ComplexColumnTest extends TestCase checkAttachments(row8ValFk.get(), row8ValFk, "test_data.txt", "test_data2.txt"); - Cursor cursor = Cursor.createCursor(t1); + Cursor cursor = CursorBuilder.createCursor(t1); assertTrue(cursor.findFirstRow(t1.getColumn("id"), "row4")); ComplexValueForeignKey row4ValFk = (ComplexValueForeignKey) cursor.getCurrentRowValue(col); @@ -277,7 +280,7 @@ public class ComplexColumnTest extends TestCase row8ValFk.addMultiValue("value2"); checkMultiValues(row8ValFk.get(), row8ValFk, "value1", "value2"); - Cursor cursor = Cursor.createCursor(t1); + Cursor cursor = CursorBuilder.createCursor(t1); assertTrue(cursor.findFirstRow(t1.getColumn("id"), "row2")); ComplexValueForeignKey row2ValFk = (ComplexValueForeignKey) cursor.getCurrentRowValue(col); @@ -425,7 +428,7 @@ public class ComplexColumnTest extends TestCase UnsupportedValue v = values.get(i); assertEquals(1, v.getValues().size()); Object rv = v.get("Value"); - assertTrue(Column.isRawData(rv)); + assertTrue(ColumnImpl.isRawData(rv)); assertEquals(value, rv.toString()); } } diff --git a/test/src/java/com/healthmarketscience/jackcess/CursorBuilderTest.java b/test/src/java/com/healthmarketscience/jackcess/CursorBuilderTest.java index c1872fa..26d22e7 100644 --- a/test/src/java/com/healthmarketscience/jackcess/CursorBuilderTest.java +++ b/test/src/java/com/healthmarketscience/jackcess/CursorBuilderTest.java @@ -29,7 +29,8 @@ package com.healthmarketscience.jackcess; import junit.framework.TestCase; -import static com.healthmarketscience.jackcess.JetFormatTest.*; +import static com.healthmarketscience.jackcess.impl.JetFormatTest.*; +import com.healthmarketscience.jackcess.impl.IndexImpl; /** * @author James Ahlborn @@ -59,20 +60,20 @@ public class CursorBuilderTest extends TestCase { Database db = CursorTest.createTestIndexTable(indexCursorDB); Table table = db.getTable("test"); - Index idx = table.getIndexes().get(0); + IndexImpl idx = (IndexImpl)table.getIndexes().get(0); - Cursor expected = Cursor.createCursor(table); + Cursor expected = CursorBuilder.createCursor(table); Cursor found = new CursorBuilder(table).toCursor(); assertCursor(expected, found); - expected = Cursor.createIndexCursor(table, idx); + expected = CursorBuilder.createCursor(table, idx); found = new CursorBuilder(table) .setIndex(idx) .toCursor(); assertCursor(expected, found); - expected = Cursor.createIndexCursor(table, idx); + expected = CursorBuilder.createCursor(table, idx); found = new CursorBuilder(table) .setIndexByName("id") .toCursor(); @@ -86,7 +87,7 @@ public class CursorBuilderTest extends TestCase { // success } - expected = Cursor.createIndexCursor(table, idx); + expected = CursorBuilder.createCursor(table, idx); found = new CursorBuilder(table) .setIndexByColumns(table.getColumn("id")) .toCursor(); @@ -108,21 +109,21 @@ public class CursorBuilderTest extends TestCase { // success } - expected = Cursor.createCursor(table); + expected = CursorBuilder.createCursor(table); expected.beforeFirst(); found = new CursorBuilder(table) .beforeFirst() .toCursor(); assertCursor(expected, found); - expected = Cursor.createCursor(table); + expected = CursorBuilder.createCursor(table); expected.afterLast(); found = new CursorBuilder(table) .afterLast() .toCursor(); assertCursor(expected, found); - expected = Cursor.createCursor(table); + expected = CursorBuilder.createCursor(table); expected.moveNextRows(2); Cursor.Savepoint sp = expected.getSavepoint(); found = new CursorBuilder(table) @@ -131,7 +132,7 @@ public class CursorBuilderTest extends TestCase { .toCursor(); assertCursor(expected, found); - expected = Cursor.createIndexCursor(table, idx); + expected = CursorBuilder.createCursor(table, idx); expected.moveNextRows(2); sp = expected.getSavepoint(); found = new CursorBuilder(table) @@ -141,7 +142,7 @@ public class CursorBuilderTest extends TestCase { .toCursor(); assertCursor(expected, found); - expected = Cursor.createIndexCursor(table, idx, + expected = CursorBuilder.createCursor(table, idx, idx.constructIndexRowFromEntry(3), null); found = new CursorBuilder(table) @@ -150,7 +151,7 @@ public class CursorBuilderTest extends TestCase { .toCursor(); assertCursor(expected, found); - expected = Cursor.createIndexCursor(table, idx, + expected = CursorBuilder.createCursor(table, idx, idx.constructIndexRowFromEntry(3), false, idx.constructIndexRowFromEntry(7), diff --git a/test/src/java/com/healthmarketscience/jackcess/CursorTest.java b/test/src/java/com/healthmarketscience/jackcess/CursorTest.java index 897cf53..59de129 100644 --- a/test/src/java/com/healthmarketscience/jackcess/CursorTest.java +++ b/test/src/java/com/healthmarketscience/jackcess/CursorTest.java @@ -38,7 +38,13 @@ import java.util.TreeSet; import static com.healthmarketscience.jackcess.Database.*; import static com.healthmarketscience.jackcess.DatabaseTest.*; -import static com.healthmarketscience.jackcess.JetFormatTest.*; +import com.healthmarketscience.jackcess.impl.JetFormatTest; +import static com.healthmarketscience.jackcess.impl.JetFormatTest.*; +import com.healthmarketscience.jackcess.impl.RowIdImpl; +import com.healthmarketscience.jackcess.util.CaseInsensitiveColumnMatcher; +import com.healthmarketscience.jackcess.util.ColumnMatcher; +import com.healthmarketscience.jackcess.util.RowFilterTest; +import com.healthmarketscience.jackcess.util.SimpleColumnMatcher; import junit.framework.TestCase; /** @@ -170,7 +176,7 @@ public class CursorTest extends TestCase { int type) throws Exception { - return new CursorBuilder(table) + return table.newCursor() .setIndex(idx) .setStartEntry(3 - type) .setStartRowInclusive(type == 0) @@ -181,16 +187,17 @@ public class CursorTest extends TestCase { public void testRowId() throws Exception { // test special cases - RowId rowId1 = new RowId(1, 2); - RowId rowId2 = new RowId(1, 3); - RowId rowId3 = new RowId(2, 1); + RowIdImpl rowId1 = new RowIdImpl(1, 2); + RowIdImpl rowId2 = new RowIdImpl(1, 3); + RowIdImpl rowId3 = new RowIdImpl(2, 1); - List sortedRowIds = new ArrayList(new TreeSet( - Arrays.asList(rowId1, rowId2, rowId3, RowId.FIRST_ROW_ID, - RowId.LAST_ROW_ID))); + List sortedRowIds = + new ArrayList(new TreeSet( + Arrays.asList(rowId1, rowId2, rowId3, RowIdImpl.FIRST_ROW_ID, + RowIdImpl.LAST_ROW_ID))); - assertEquals(Arrays.asList(RowId.FIRST_ROW_ID, rowId1, rowId2, rowId3, - RowId.LAST_ROW_ID), + assertEquals(Arrays.asList(RowIdImpl.FIRST_ROW_ID, rowId1, rowId2, rowId3, + RowIdImpl.LAST_ROW_ID), sortedRowIds); } @@ -199,7 +206,7 @@ public class CursorTest extends TestCase { Database db = createTestTable(fileFormat); Table table = db.getTable("test"); - Cursor cursor = Cursor.createCursor(table); + Cursor cursor = CursorBuilder.createCursor(table); doTestSimple(cursor, null); db.close(); } @@ -226,7 +233,7 @@ public class CursorTest extends TestCase { Database db = createTestTable(fileFormat); Table table = db.getTable("test"); - Cursor cursor = Cursor.createCursor(table); + Cursor cursor = CursorBuilder.createCursor(table); doTestMove(cursor, null); db.close(); @@ -280,12 +287,55 @@ public class CursorTest extends TestCase { assertEquals(expectedRow, cursor.getCurrentRow()); } + public void testMoveNoReset() throws Exception { + for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) { + Database db = createTestTable(fileFormat); + + Table table = db.getTable("test"); + Cursor cursor = CursorBuilder.createCursor(table); + doTestMoveNoReset(cursor); + + db.close(); + } + } + + private static void doTestMoveNoReset(Cursor cursor) + throws Exception + { + List> expectedRows = createTestTableData(); + List> foundRows = new ArrayList>(); + + Iterator iter = cursor.newIterable().iterator(); + + for(int i = 0; i < 6; ++i) { + foundRows.add(iter.next()); + } + + iter = cursor.newIterable().reset(false).reverse().iterator(); + iter.next(); + Map row = iter.next(); + assertEquals(expectedRows.get(4), row); + + iter = cursor.newIterable().reset(false).iterator(); + iter.next(); + row = iter.next(); + assertEquals(expectedRows.get(5), row); + iter.next(); + + iter = cursor.newIterable().reset(false).iterator(); + for(int i = 6; i < 10; ++i) { + foundRows.add(iter.next()); + } + + assertEquals(expectedRows, foundRows); + } + public void testSearch() throws Exception { for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) { Database db = createTestTable(fileFormat); Table table = db.getTable("test"); - Cursor cursor = Cursor.createCursor(table); + Cursor cursor = CursorBuilder.createCursor(table); doTestSearch(table, cursor, null, 42, -13); db.close(); @@ -338,28 +388,28 @@ public class CursorTest extends TestCase { } assertEquals("data" + 5, - Cursor.findValue(table, + CursorBuilder.findValue(table, table.getColumn("value"), table.getColumn("id"), 5)); assertEquals(createExpectedRow("id", 5, "value", "data" + 5), - Cursor.findRow(table, + CursorBuilder.findRow(table, createExpectedRow("id", 5))); if(index != null) { assertEquals("data" + 5, - Cursor.findValue(table, index, + CursorBuilder.findValue(table, index, table.getColumn("value"), table.getColumn("id"), 5)); assertEquals(createExpectedRow("id", 5, "value", "data" + 5), - Cursor.findRow(table, index, + CursorBuilder.findRow(table, index, createExpectedRow("id", 5))); - assertNull(Cursor.findValue(table, index, + assertNull(CursorBuilder.findValue(table, index, table.getColumn("value"), table.getColumn("id"), -17)); - assertNull(Cursor.findRow(table, index, + assertNull(CursorBuilder.findRow(table, index, createExpectedRow("id", 13))); } } @@ -369,7 +419,7 @@ public class CursorTest extends TestCase { Database db = createTestTable(fileFormat); Table table = db.getTable("test"); - Cursor cursor = Cursor.createCursor(table); + Cursor cursor = CursorBuilder.createCursor(table); doTestReverse(cursor, null); db.close(); @@ -387,7 +437,7 @@ public class CursorTest extends TestCase { List> foundRows = new ArrayList>(); - for(Map row : cursor.reverseIterable()) { + for(Map row : cursor.newIterable().reverse()) { foundRows.add(row); } assertEquals(expectedRows, foundRows); @@ -399,8 +449,8 @@ public class CursorTest extends TestCase { Table table = db.getTable("test"); - Cursor cursor1 = Cursor.createCursor(table); - Cursor cursor2 = Cursor.createCursor(table); + Cursor cursor1 = CursorBuilder.createCursor(table); + Cursor cursor2 = CursorBuilder.createCursor(table); doTestLiveAddition(table, cursor1, cursor2, 11); db.close(); @@ -440,10 +490,10 @@ public class CursorTest extends TestCase { Table table = db.getTable("test"); - Cursor cursor1 = Cursor.createCursor(table); - Cursor cursor2 = Cursor.createCursor(table); - Cursor cursor3 = Cursor.createCursor(table); - Cursor cursor4 = Cursor.createCursor(table); + Cursor cursor1 = CursorBuilder.createCursor(table); + Cursor cursor2 = CursorBuilder.createCursor(table); + Cursor cursor3 = CursorBuilder.createCursor(table); + Cursor cursor4 = CursorBuilder.createCursor(table); doTestLiveDeletion(cursor1, cursor2, cursor3, cursor4, 1); db.close(); @@ -536,7 +586,7 @@ public class CursorTest extends TestCase { assertTable(createUnorderedTestTableData(), table); - Cursor cursor = Cursor.createIndexCursor(table, idx); + Cursor cursor = CursorBuilder.createCursor(table, idx); doTestSimple(cursor, null); db.close(); @@ -549,7 +599,7 @@ public class CursorTest extends TestCase { Table table = db.getTable("test"); Index idx = table.getIndexes().get(0); - Cursor cursor = Cursor.createIndexCursor(table, idx); + Cursor cursor = CursorBuilder.createCursor(table, idx); doTestMove(cursor, null); db.close(); @@ -562,7 +612,7 @@ public class CursorTest extends TestCase { Table table = db.getTable("test"); Index idx = table.getIndexes().get(0); - Cursor cursor = Cursor.createIndexCursor(table, idx); + Cursor cursor = CursorBuilder.createCursor(table, idx); doTestReverse(cursor, null); db.close(); @@ -575,7 +625,7 @@ public class CursorTest extends TestCase { Table table = db.getTable("test"); Index idx = table.getIndexes().get(0); - Cursor cursor = Cursor.createIndexCursor(table, idx); + Cursor cursor = CursorBuilder.createCursor(table, idx); doTestSearch(table, cursor, idx, 42, -13); db.close(); @@ -589,8 +639,8 @@ public class CursorTest extends TestCase { Table table = db.getTable("test"); Index idx = table.getIndexes().get(0); - Cursor cursor1 = Cursor.createIndexCursor(table, idx); - Cursor cursor2 = Cursor.createIndexCursor(table, idx); + Cursor cursor1 = CursorBuilder.createCursor(table, idx); + Cursor cursor2 = CursorBuilder.createCursor(table, idx); doTestLiveAddition(table, cursor1, cursor2, 11); db.close(); @@ -604,10 +654,10 @@ public class CursorTest extends TestCase { Table table = db.getTable("test"); Index idx = table.getIndexes().get(0); - Cursor cursor1 = Cursor.createIndexCursor(table, idx); - Cursor cursor2 = Cursor.createIndexCursor(table, idx); - Cursor cursor3 = Cursor.createIndexCursor(table, idx); - Cursor cursor4 = Cursor.createIndexCursor(table, idx); + Cursor cursor1 = CursorBuilder.createCursor(table, idx); + Cursor cursor2 = CursorBuilder.createCursor(table, idx); + Cursor cursor3 = CursorBuilder.createCursor(table, idx); + Cursor cursor4 = CursorBuilder.createCursor(table, idx); doTestLiveDeletion(cursor1, cursor2, cursor3, cursor4, 1); db.close(); @@ -734,7 +784,7 @@ public class CursorTest extends TestCase { Database db = createDupeTestTable(fileFormat); Table table = db.getTable("test"); - Cursor cursor = Cursor.createCursor(table); + Cursor cursor = CursorBuilder.createCursor(table); doTestFindAll(table, cursor, null); @@ -748,7 +798,7 @@ public class CursorTest extends TestCase { Table table = db.getTable("test"); Index idx = table.getIndexes().get(0); - Cursor cursor = Cursor.createIndexCursor(table, idx); + Cursor cursor = CursorBuilder.createCursor(table, idx); doTestFindAll(table, cursor, idx); @@ -759,11 +809,10 @@ public class CursorTest extends TestCase { private static void doTestFindAll(Table table, Cursor cursor, Index index) throws Exception { - Column valCol = table.getColumn("value"); - List> rows = RowFilterTest.toList( - cursor.columnMatchIterable(valCol, "data2")); + List> rows = RowFilterTest.toList( + cursor.newIterable().setMatchPattern("value", "data2")); - List> expectedRows = null; + List> expectedRows = null; if(index == null) { expectedRows = @@ -794,8 +843,9 @@ public class CursorTest extends TestCase { } assertEquals(expectedRows, rows); + Column valCol = table.getColumn("value"); rows = RowFilterTest.toList( - cursor.columnMatchIterable(valCol, "data4")); + cursor.newIterable().setMatchPattern(valCol, "data4")); if(index == null) { expectedRows = @@ -815,12 +865,13 @@ public class CursorTest extends TestCase { assertEquals(expectedRows, rows); rows = RowFilterTest.toList( - cursor.columnMatchIterable(valCol, "data9")); + cursor.newIterable().setMatchPattern(valCol, "data9")); assertTrue(rows.isEmpty()); rows = RowFilterTest.toList( - cursor.rowMatchIterable(Collections.singletonMap("id", 8))); + cursor.newIterable().setMatchPattern( + Collections.singletonMap("id", 8))); expectedRows = createExpectedTable( @@ -832,22 +883,23 @@ public class CursorTest extends TestCase { for(Map row : table) { - expectedRows = new ArrayList>(); + List> tmpRows = new ArrayList>(); for(Map tmpRow : cursor) { if(row.equals(tmpRow)) { - expectedRows.add(tmpRow); + tmpRows.add(tmpRow); } } + expectedRows = tmpRows; assertFalse(expectedRows.isEmpty()); - rows = RowFilterTest.toList(cursor.rowMatchIterable(row)); + rows = RowFilterTest.toList(cursor.newIterable().setMatchPattern(row)); assertEquals(expectedRows, rows); } rows = RowFilterTest.toList( - cursor.rowMatchIterable(createExpectedRow( - "id", 8, "value", "data13"))); + cursor.newIterable().addMatchPattern("id", 8) + .addMatchPattern("value", "data13")); assertTrue(rows.isEmpty()); } @@ -859,8 +911,8 @@ public class CursorTest extends TestCase { Table table = db.getTable("test"); Index idx = table.getIndexes().get(0); - Cursor tCursor = Cursor.createCursor(table); - Cursor iCursor = Cursor.createIndexCursor(table, idx); + Cursor tCursor = CursorBuilder.createCursor(table); + Cursor iCursor = CursorBuilder.createCursor(table, idx); Cursor.Savepoint tSave = tCursor.getSavepoint(); Cursor.Savepoint iSave = iCursor.getSavepoint(); @@ -882,8 +934,8 @@ public class CursorTest extends TestCase { // success } - Cursor tCursor2 = Cursor.createCursor(table); - Cursor iCursor2 = Cursor.createIndexCursor(table, idx); + Cursor tCursor2 = CursorBuilder.createCursor(table); + Cursor iCursor2 = CursorBuilder.createCursor(table, idx); tCursor2.restoreSavepoint(tSave); iCursor2.restoreSavepoint(iSave); @@ -892,7 +944,7 @@ public class CursorTest extends TestCase { } } - public void testColmnMatcher() throws Exception { + public void testColumnMatcher() throws Exception { for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) { @@ -903,7 +955,7 @@ public class CursorTest extends TestCase { doTestMatchers(table, SimpleColumnMatcher.INSTANCE, false); doTestMatchers(table, CaseInsensitiveColumnMatcher.INSTANCE, true); - Cursor cursor = Cursor.createCursor(table); + Cursor cursor = CursorBuilder.createCursor(table); doTestMatcher(table, cursor, SimpleColumnMatcher.INSTANCE, false); doTestMatcher(table, cursor, CaseInsensitiveColumnMatcher.INSTANCE, true); @@ -989,6 +1041,28 @@ public class CursorTest extends TestCase { "value", "data" + 4), cursor.getCurrentRow()); } + + assertEquals(Arrays.asList(createExpectedRow("id", 4, + "value", "data" + 4)), + RowFilterTest.toList( + cursor.newIterable() + .setMatchPattern("value", "data4") + .setColumnMatcher(SimpleColumnMatcher.INSTANCE))); + + assertEquals(Arrays.asList(createExpectedRow("id", 3, + "value", "data" + 3)), + RowFilterTest.toList( + cursor.newIterable() + .setMatchPattern("value", "DaTa3") + .setColumnMatcher(CaseInsensitiveColumnMatcher.INSTANCE))); + + assertEquals(Arrays.asList(createExpectedRow("id", 2, + "value", "data" + 2)), + RowFilterTest.toList( + cursor.newIterable() + .addMatchPattern("value", "DaTa2") + .addMatchPattern("id", 2) + .setColumnMatcher(CaseInsensitiveColumnMatcher.INSTANCE))); } public void testIndexCursor() throws Exception @@ -998,7 +1072,7 @@ public class CursorTest extends TestCase { Database db = open(testDB); Table t1 = db.getTable("Table1"); Index idx = t1.getIndex(IndexBuilder.PRIMARY_KEY_NAME); - IndexCursor cursor = IndexCursor.createCursor(t1, idx); + IndexCursor cursor = CursorBuilder.createCursor(t1, idx); assertFalse(cursor.findFirstRowByEntry(-1)); cursor.findClosestRowByEntry(-1); @@ -1025,18 +1099,19 @@ public class CursorTest extends TestCase { Database db = openCopy(testDB); Table t1 = db.getTable("Table1"); Index idx = t1.getIndex("Table2Table1"); - IndexCursor cursor = IndexCursor.createCursor(t1, idx); + IndexCursor cursor = CursorBuilder.createCursor(t1, idx); List expectedData = new ArrayList(); - for(Map row : cursor.entryIterable( - Arrays.asList("data"), 1)) { + for(Map row : cursor.newEntryIterable(1) + .addColumnNames("data")) { expectedData.add((String)row.get("data")); } assertEquals(Arrays.asList("baz11", "baz11-2"), expectedData); expectedData = new ArrayList(); - for(Iterator> iter = cursor.entryIterator(1); + for(Iterator> iter = + cursor.newEntryIterable(1).iterator(); iter.hasNext(); ) { expectedData.add((String)iter.next().get("data")); iter.remove(); @@ -1060,8 +1135,8 @@ public class CursorTest extends TestCase { assertEquals(Arrays.asList("baz11", "baz11-2"), expectedData); expectedData = new ArrayList(); - for(Map row : cursor.entryIterable( - Arrays.asList("data"), 1)) { + for(Map row : cursor.newEntryIterable(1) + .addColumnNames("data")) { expectedData.add((String)row.get("data")); } @@ -1077,10 +1152,10 @@ public class CursorTest extends TestCase { Database db = openCopy(testDB); Table t1 = db.getTable("Table1"); - Cursor cursor = Cursor.createCursor(t1); + Cursor cursor = CursorBuilder.createCursor(t1); List expectedData = new ArrayList(); - for(Map row : cursor.iterable( + for(Map row : cursor.newIterable().setColumnNames( Arrays.asList("otherfk1", "data"))) { if(row.get("otherfk1").equals(1)) { expectedData.add((String)row.get("data")); @@ -1090,7 +1165,7 @@ public class CursorTest extends TestCase { assertEquals(Arrays.asList("baz11", "baz11-2"), expectedData); expectedData = new ArrayList(); - for(Iterator> iter = cursor.iterator(); + for(Iterator> iter = cursor.iterator(); iter.hasNext(); ) { Map row = iter.next(); if(row.get("otherfk1").equals(1)) { @@ -1117,7 +1192,7 @@ public class CursorTest extends TestCase { assertEquals(Arrays.asList("baz11", "baz11-2"), expectedData); expectedData = new ArrayList(); - for(Map row : cursor.iterable( + for(Map row : cursor.newIterable().setColumnNames( Arrays.asList("otherfk1", "data"))) { if(row.get("otherfk1").equals(1)) { expectedData.add((String)row.get("data")); diff --git a/test/src/java/com/healthmarketscience/jackcess/DatabaseTest.java b/test/src/java/com/healthmarketscience/jackcess/DatabaseTest.java index e73661f..eef4ecb 100644 --- a/test/src/java/com/healthmarketscience/jackcess/DatabaseTest.java +++ b/test/src/java/com/healthmarketscience/jackcess/DatabaseTest.java @@ -57,10 +57,23 @@ import java.util.TreeSet; import java.util.UUID; import static com.healthmarketscience.jackcess.Database.*; -import static com.healthmarketscience.jackcess.JetFormatTest.*; import com.healthmarketscience.jackcess.complex.ComplexValueForeignKey; +import com.healthmarketscience.jackcess.impl.ByteUtil; +import com.healthmarketscience.jackcess.impl.ColumnImpl; +import com.healthmarketscience.jackcess.impl.DatabaseImpl; +import com.healthmarketscience.jackcess.impl.IndexData; +import com.healthmarketscience.jackcess.impl.IndexImpl; +import com.healthmarketscience.jackcess.impl.JetFormat; +import static com.healthmarketscience.jackcess.impl.JetFormatTest.*; +import com.healthmarketscience.jackcess.impl.RowIdImpl; +import com.healthmarketscience.jackcess.impl.RowImpl; +import com.healthmarketscience.jackcess.impl.TableImpl; +import com.healthmarketscience.jackcess.util.LinkResolver; +import com.healthmarketscience.jackcess.util.MemFileChannel; +import com.healthmarketscience.jackcess.util.RowFilterTest; import junit.framework.TestCase; + /** * @author Tim McCune */ @@ -90,8 +103,9 @@ public class DatabaseTest extends TestCase { : null); final Database db = new DatabaseBuilder(file).setReadOnly(true) .setAutoSync(_autoSync).setChannel(channel).open(); - assertEquals("Wrong JetFormat.", fileFormat.getJetFormat(), - db.getFormat()); + assertEquals("Wrong JetFormat.", + DatabaseImpl.getFileFormatDetails(fileFormat).getFormat(), + ((DatabaseImpl)db).getFormat()); assertEquals("Wrong FileFormat.", fileFormat, db.getFileFormat()); return db; } @@ -151,8 +165,9 @@ public class DatabaseTest extends TestCase { File tmp = createTempFile(keep); copyFile(file, tmp); Database db = new DatabaseBuilder(tmp).setAutoSync(_autoSync).open(); - assertEquals("Wrong JetFormat.", fileFormat.getJetFormat(), - db.getFormat()); + assertEquals("Wrong JetFormat.", + DatabaseImpl.getFileFormatDetails(fileFormat).getFormat(), + ((DatabaseImpl)db).getFormat()); assertEquals("Wrong FileFormat.", fileFormat, db.getFileFormat()); return db; } @@ -163,7 +178,7 @@ public class DatabaseTest extends TestCase { Database db = create(fileFormat); try { - db.createTable("test", Collections.emptyList()); + ((DatabaseImpl)db).createTable("test", Collections.emptyList()); fail("created table with no columns?"); } catch(IllegalArgumentException e) { // success @@ -231,7 +246,7 @@ public class DatabaseTest extends TestCase { public void testGetColumns() throws Exception { for (final TestDB testDB : SUPPORTED_DBS_TEST_FOR_READ) { - List columns = open(testDB).getTable("Table1").getColumns(); + List columns = open(testDB).getTable("Table1").getColumns(); assertEquals(9, columns.size()); checkColumn(columns, 0, "A", DataType.TEXT); checkColumn(columns, 1, "B", DataType.TEXT); @@ -245,8 +260,8 @@ public class DatabaseTest extends TestCase { } } - static void checkColumn(List columns, int columnNumber, String name, - DataType dataType) + static void checkColumn(List columns, int columnNumber, + String name, DataType dataType) throws Exception { Column column = columns.get(columnNumber); @@ -396,17 +411,19 @@ public class DatabaseTest extends TestCase { for (final FileFormat fileFormat : SUPPORTED_FILEFORMATS) { Database db = create(fileFormat); createTestTable(db); - Object[] row1 = createTestRow("Tim1"); - Object[] row2 = createTestRow("Tim2"); - Object[] row3 = createTestRow("Tim3"); + Map row1 = createTestRowMap("Tim1"); + Map row2 = createTestRowMap("Tim2"); + Map row3 = createTestRowMap("Tim3"); Table table = db.getTable("Test"); - table.addRows(Arrays.asList(row1, row2, row3)); + @SuppressWarnings("unchecked") + List> rows = Arrays.asList(row1, row2, row3); + table.addRowsFromMaps(rows); assertRowCount(3, table); table.reset(); table.getNextRow(); table.getNextRow(); - table.deleteCurrentRow(); + table.getDefaultCursor().deleteCurrentRow(); table.reset(); @@ -429,17 +446,17 @@ public class DatabaseTest extends TestCase { assertRowCount(10, table); table.reset(); table.getNextRow(); - table.deleteCurrentRow(); + table.getDefaultCursor().deleteCurrentRow(); assertRowCount(9, table); table.reset(); table.getNextRow(); - table.deleteCurrentRow(); + table.getDefaultCursor().deleteCurrentRow(); assertRowCount(8, table); table.reset(); for (int i = 0; i < 8; i++) { table.getNextRow(); } - table.deleteCurrentRow(); + table.getDefaultCursor().deleteCurrentRow(); assertRowCount(7, table); table.addRow(row); assertRowCount(8, table); @@ -447,7 +464,7 @@ public class DatabaseTest extends TestCase { for (int i = 0; i < 3; i++) { table.getNextRow(); } - table.deleteCurrentRow(); + table.getDefaultCursor().deleteCurrentRow(); assertRowCount(7, table); table.reset(); assertEquals(2, table.getNextRow().get("D")); @@ -456,6 +473,38 @@ public class DatabaseTest extends TestCase { } } + public void testDeleteRow() throws Exception { + + // make sure correct row is deleted + for (final FileFormat fileFormat : SUPPORTED_FILEFORMATS) { + Database db = create(fileFormat); + createTestTable(db); + Table table = db.getTable("Test"); + for(int i = 0; i < 10; ++i) { + table.addRowFromMap(createTestRowMap("Tim" + i)); + } + assertRowCount(10, table); + + table.reset(); + + List rows = RowFilterTest.toList(table); + + Row r1 = rows.remove(7); + Row r2 = rows.remove(3); + assertEquals(8, rows.size()); + + assertSame(r2, table.deleteRow(r2)); + assertSame(r1, table.deleteRow(r1)); + + assertTable(rows, table); + + table.deleteRow(r2); + table.deleteRow(r1); + + assertTable(rows, table); + } + } + public void testReadLongValue() throws Exception { for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.TEST2, true)) { @@ -711,9 +760,9 @@ public class DatabaseTest extends TestCase { for (final FileFormat fileFormat : SUPPORTED_FILEFORMATS) { Database db = create(fileFormat); - Column col = new ColumnBuilder("A", DataType.NUMERIC) + ColumnBuilder col = new ColumnBuilder("A", DataType.NUMERIC) .setScale(4).setPrecision(8).toColumn(); - assertTrue(col.isVariableLength()); + assertTrue(col.getType().isVariableLength()); Table table = new TableBuilder("test") .addColumn(col) @@ -809,7 +858,7 @@ public class DatabaseTest extends TestCase { public void testMultiPageTableDef() throws Exception { for (final TestDB testDB : SUPPORTED_DBS_TEST_FOR_READ) { - List columns = open(testDB).getTable("Table2").getColumns(); + List columns = open(testDB).getTable("Table2").getColumns(); assertEquals(89, columns.size()); } } @@ -875,7 +924,7 @@ public class DatabaseTest extends TestCase { Database db = openCopy(testDB); Table t = db.getTable("jobDB1"); - assertTrue(t.getOwnedPagesCursor().getUsageMap().toString() + assertTrue(((TableImpl)t).getOwnedPagesCursor().getUsageMap().toString() .startsWith("(InlineHandler)")); String lval = createNonAsciiString(255); // "--255 chars long text--"; @@ -890,7 +939,7 @@ public class DatabaseTest extends TestCase { } assertEquals(1000, ids.size()); - assertTrue(t.getOwnedPagesCursor().getUsageMap().toString() + assertTrue(((TableImpl)t).getOwnedPagesCursor().getUsageMap().toString() .startsWith("(ReferenceHandler)")); db.close(); @@ -904,7 +953,7 @@ public class DatabaseTest extends TestCase { final int numColumns = 90; - List columns = new ArrayList(); + List columns = new ArrayList(); List colNames = new ArrayList(); for(int i = 0; i < numColumns; ++i) { String colName = "MyColumnName" + i; @@ -912,7 +961,7 @@ public class DatabaseTest extends TestCase { columns.add(new ColumnBuilder(colName, DataType.TEXT).toColumn()); } - db.createTable("test", columns); + ((DatabaseImpl)db).createTable("test", columns); Table t = db.getTable("test"); @@ -963,18 +1012,29 @@ public class DatabaseTest extends TestCase { private void doTestAutoNumber(Table table) throws Exception { - table.addRow(null, "row1"); - table.addRow(13, "row2"); - table.addRow("flubber", "row3"); + Object[] row = {null, "row1"}; + assertSame(row, table.addRow(row)); + assertEquals(1, ((Integer)row[0]).intValue()); + row = table.addRow(13, "row2"); + assertEquals(2, ((Integer)row[0]).intValue()); + row = table.addRow("flubber", "row3"); + assertEquals(3, ((Integer)row[0]).intValue()); table.reset(); - table.addRow(Column.AUTO_NUMBER, "row4"); - table.addRow(Column.AUTO_NUMBER, "row5"); + row = table.addRow(Column.AUTO_NUMBER, "row4"); + assertEquals(4, ((Integer)row[0]).intValue()); + row = table.addRow(Column.AUTO_NUMBER, "row5"); + assertEquals(5, ((Integer)row[0]).intValue()); + + Object[] smallRow = {Column.AUTO_NUMBER}; + row = table.addRow(smallRow); + assertNotSame(row, smallRow); + assertEquals(6, ((Integer)row[0]).intValue()); table.reset(); - List> expectedRows = + List> expectedRows = createExpectedTable( createExpectedRow( "a", 1, @@ -990,7 +1050,10 @@ public class DatabaseTest extends TestCase { "b", "row4"), createExpectedRow( "a", 5, - "b", "row5")); + "b", "row5"), + createExpectedRow( + "a", 6, + "b", null)); assertTable(expectedRows, table); } @@ -1119,7 +1182,7 @@ public class DatabaseTest extends TestCase { t.addRow("row" + i, Column.AUTO_NUMBER, "initial data"); } - Cursor c = Cursor.createCursor(t); + Cursor c = CursorBuilder.createCursor(t); c.reset(); c.moveNextRows(2); Map row = c.getCurrentRow(); @@ -1129,7 +1192,15 @@ public class DatabaseTest extends TestCase { "data", "initial data"), row); - c.updateCurrentRow(Column.KEEP_VALUE, Column.AUTO_NUMBER, "new data"); + Map newRow = createExpectedRow( + "name", Column.KEEP_VALUE, + "id", Column.AUTO_NUMBER, + "data", "new data"); + assertSame(newRow, c.updateCurrentRowFromMap(newRow)); + assertEquals(createExpectedRow("name", "row1", + "id", 2, + "data", "new data"), + newRow); c.moveNextRows(3); row = c.getCurrentRow(); @@ -1187,6 +1258,23 @@ public class DatabaseTest extends TestCase { "data", newText), row); + List rows = RowFilterTest.toList(t); + assertEquals(50, rows.size()); + + for(Row r : rows) { + r.put("data", "final data " + r.get("id")); + } + + for(Row r : rows) { + assertSame(r, t.updateRow(r)); + } + + t.reset(); + + for(Row r : t) { + assertEquals("final data " + r.get("id"), r.get("data")); + } + db.close(); } } @@ -1222,8 +1310,8 @@ public class DatabaseTest extends TestCase { for (final TestDB testDB : SUPPORTED_DBS_TEST_FOR_READ) { Database db = open(testDB); - assertEquals(db.getFormat().DEFAULT_SORT_ORDER, - db.getDefaultSortOrder()); + assertEquals(((DatabaseImpl)db).getFormat().DEFAULT_SORT_ORDER, + ((DatabaseImpl)db).getDefaultSortOrder()); db.close(); } } @@ -1275,7 +1363,7 @@ public class DatabaseTest extends TestCase { public Database resolveLinkedDatabase(Database linkerdb, String dbName) throws IOException { assertEquals(linkeeDbName, dbName); - return Database.open(linkeeFile); + return DatabaseBuilder.open(linkeeFile); } }); @@ -1286,7 +1374,7 @@ public class DatabaseTest extends TestCase { assertNotNull(linkeeDb); assertEquals(linkeeFile, linkeeDb.getFile()); - List> expectedRows = + List> expectedRows = createExpectedTable( createExpectedRow( "ID", 1, @@ -1323,9 +1411,9 @@ public class DatabaseTest extends TestCase { private static void doTestTimeZone(final TimeZone tz) throws Exception { - Column col = new Column(true, null) { + ColumnImpl col = new ColumnImpl(null, DataType.SHORT_DATE_TIME, 0, 0, 0) { @Override - Calendar getCalendar() { return Calendar.getInstance(tz); } + protected Calendar getCalendar() { return Calendar.getInstance(tz); } }; SimpleDateFormat df = new SimpleDateFormat("yyyy.MM.dd"); @@ -1353,7 +1441,7 @@ public class DatabaseTest extends TestCase { private void checkRawValue(String expected, Object val) { if(expected != null) { - assertTrue(Column.isRawData(val)); + assertTrue(ColumnImpl.isRawData(val)); assertEquals(expected, val.toString()); } else { assertNull(val); @@ -1369,6 +1457,12 @@ public class DatabaseTest extends TestCase { return createTestRow("Tim"); } + static Map createTestRowMap(String col1Val) { + return createExpectedRow("A", col1Val, "B", "R", "C", "McCune", + "D", 1234, "E", (byte) 0xad, "F", 555.66d, + "G", 777.88f, "H", (short) 999, "I", new Date()); + } + static void createTestTable(Database db) throws Exception { new TableBuilder("test") .addColumn(new ColumnBuilder("A", DataType.TEXT)) @@ -1383,7 +1477,7 @@ public class DatabaseTest extends TestCase { .toTable(db); } - static String createString(int len) { + public static String createString(int len) { return createString(len, 'a'); } @@ -1406,21 +1500,25 @@ public class DatabaseTest extends TestCase { assertEquals(expectedRowCount, table.getRowCount()); } - static int countRows(Table table) throws Exception { + public static int countRows(Table table) throws Exception { int rtn = 0; - for(Map row : Cursor.createCursor(table)) { + for(Map row : CursorBuilder.createCursor(table)) { rtn++; } return rtn; } - static void assertTable(List> expectedTable, Table table) + public static void assertTable( + List> expectedTable, + Table table) + throws IOException { - assertCursor(expectedTable, Cursor.createCursor(table)); + assertCursor(expectedTable, CursorBuilder.createCursor(table)); } - static void assertCursor(List> expectedTable, - Cursor cursor) + public static void assertCursor( + List> expectedTable, + Cursor cursor) { List> foundTable = new ArrayList>(); @@ -1430,8 +1528,8 @@ public class DatabaseTest extends TestCase { assertEquals(expectedTable, foundTable); } - static Map createExpectedRow(Object... rowElements) { - Map row = new LinkedHashMap(); + public static RowImpl createExpectedRow(Object... rowElements) { + RowImpl row = new RowImpl((RowIdImpl)null); for(int i = 0; i < rowElements.length; i += 2) { row.put((String)rowElements[i], rowElements[i + 1]); @@ -1440,8 +1538,8 @@ public class DatabaseTest extends TestCase { } @SuppressWarnings("unchecked") - static List> createExpectedTable(Map... rows) { - return Arrays.>asList(rows); + public static List createExpectedTable(Row... rows) { + return Arrays.asList(rows); } static void dumpDatabase(Database mdb) throws Exception { @@ -1475,7 +1573,7 @@ public class DatabaseTest extends TestCase { static void dumpTable(Table table, PrintWriter writer) throws Exception { // make sure all indexes are read for(Index index : table.getIndexes()) { - index.initialize(); + ((IndexImpl)index).initialize(); } writer.println("TABLE: " + table.getName()); @@ -1484,7 +1582,7 @@ public class DatabaseTest extends TestCase { colNames.add(col.getName()); } writer.println("COLUMNS: " + colNames); - for(Map row : Cursor.createCursor(table)) { + for(Map row : CursorBuilder.createCursor(table)) { writer.println(massageRow(row)); } } @@ -1515,7 +1613,7 @@ public class DatabaseTest extends TestCase { static void dumpIndex(Index index, PrintWriter writer) throws Exception { writer.println("INDEX: " + index); - IndexData.EntryCursor ec = index.cursor(); + IndexData.EntryCursor ec = ((IndexImpl)index).cursor(); IndexData.Entry lastE = ec.getLastEntry(); IndexData.Entry e = null; while((e = ec.getNextEntry()) != lastE) { @@ -1570,7 +1668,7 @@ public class DatabaseTest extends TestCase { return tmp; } - static byte[] toByteArray(File file) + public static byte[] toByteArray(File file) throws IOException { // FIXME should really be using commons io IOUtils here, but don't want diff --git a/test/src/java/com/healthmarketscience/jackcess/ErrorHandlerTest.java b/test/src/java/com/healthmarketscience/jackcess/ErrorHandlerTest.java deleted file mode 100644 index afffdd5..0000000 --- a/test/src/java/com/healthmarketscience/jackcess/ErrorHandlerTest.java +++ /dev/null @@ -1,184 +0,0 @@ -/* -Copyright (c) 2007 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.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.nio.ByteOrder; -import java.util.List; - -import junit.framework.TestCase; - -import static com.healthmarketscience.jackcess.Database.*; -import static com.healthmarketscience.jackcess.DatabaseTest.*; - -/** - * @author James Ahlborn - */ -public class ErrorHandlerTest extends TestCase -{ - - public ErrorHandlerTest(String name) { - super(name); - } - - public void testErrorHandler() throws Exception - { - for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) { - Database db = create(fileFormat); - - Table table = - new TableBuilder("test") - .addColumn(new ColumnBuilder("col", DataType.TEXT)) - .addColumn(new ColumnBuilder("val", DataType.LONG)) - .toTable(db); - - table.addRow("row1", 1); - table.addRow("row2", 2); - table.addRow("row3", 3); - - assertTable(createExpectedTable( - createExpectedRow("col", "row1", - "val", 1), - createExpectedRow("col", "row2", - "val", 2), - createExpectedRow("col", "row3", - "val", 3)), - table); - - - replaceColumn(table, "val"); - - table.reset(); - try { - table.getNextRow(); - fail("IOException should have been thrown"); - } catch(IOException e) { - // success - } - - table.reset(); - table.setErrorHandler(new ReplacementErrorHandler()); - - assertTable(createExpectedTable( - createExpectedRow("col", "row1", - "val", null), - createExpectedRow("col", "row2", - "val", null), - createExpectedRow("col", "row3", - "val", null)), - table); - - Cursor c1 = Cursor.createCursor(table); - Cursor c2 = Cursor.createCursor(table); - Cursor c3 = Cursor.createCursor(table); - - c2.setErrorHandler(new DebugErrorHandler("#error")); - c3.setErrorHandler(Database.DEFAULT_ERROR_HANDLER); - - assertCursor(createExpectedTable( - createExpectedRow("col", "row1", - "val", null), - createExpectedRow("col", "row2", - "val", null), - createExpectedRow("col", "row3", - "val", null)), - c1); - - assertCursor(createExpectedTable( - createExpectedRow("col", "row1", - "val", "#error"), - createExpectedRow("col", "row2", - "val", "#error"), - createExpectedRow("col", "row3", - "val", "#error")), - c2); - - try { - c3.getNextRow(); - fail("IOException should have been thrown"); - } catch(IOException e) { - // success - } - - table.setErrorHandler(null); - c1.setErrorHandler(null); - c1.reset(); - try { - c1.getNextRow(); - fail("IOException should have been thrown"); - } catch(IOException e) { - // success - } - - - db.close(); - } - } - - @SuppressWarnings("unchecked") - private void replaceColumn(Table t, String colName) throws Exception - { - Field colsField = Table.class.getDeclaredField("_columns"); - colsField.setAccessible(true); - List cols = (List)colsField.get(t); - - Column srcCol = null; - Column destCol = new BogusColumn(t); - for(int i = 0; i < cols.size(); ++i) { - srcCol = cols.get(i); - if(srcCol.getName().equals(colName)) { - cols.set(i, destCol); - break; - } - } - - // copy fields from source to dest - for(Field f : Column.class.getDeclaredFields()) { - if(!Modifier.isFinal(f.getModifiers())) { - f.setAccessible(true); - f.set(destCol, f.get(srcCol)); - } - } - - } - - private static class BogusColumn extends Column - { - private BogusColumn(Table table) { - super(true, table); - } - - @Override - public Object read(byte[] data, ByteOrder order) throws IOException { - throw new IOException("bogus column"); - } - } - -} diff --git a/test/src/java/com/healthmarketscience/jackcess/ExportTest.java b/test/src/java/com/healthmarketscience/jackcess/ExportTest.java deleted file mode 100644 index 7046b8b..0000000 --- a/test/src/java/com/healthmarketscience/jackcess/ExportTest.java +++ /dev/null @@ -1,134 +0,0 @@ -/* -Copyright (c) 2007 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.BufferedWriter; -import java.io.StringWriter; -import java.text.DateFormat; -import java.text.SimpleDateFormat; - -import junit.framework.TestCase; -import org.apache.commons.lang.SystemUtils; -import java.util.Date; - -import static com.healthmarketscience.jackcess.Database.*; -import static com.healthmarketscience.jackcess.DatabaseTest.*; - -/** - * - * @author James Ahlborn - */ -public class ExportTest extends TestCase -{ - private static final String NL = SystemUtils.LINE_SEPARATOR; - - - public ExportTest(String name) { - super(name); - } - - public void testExportToFile() throws Exception - { - DateFormat df = new SimpleDateFormat("yyyyMMdd HH:mm:ss"); - df.setTimeZone(TEST_TZ); - - for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) { - Database db = create(fileFormat); - db.setTimeZone(TEST_TZ); - - Table t = new TableBuilder("test") - .addColumn(new ColumnBuilder("col1", DataType.TEXT)) - .addColumn(new ColumnBuilder("col2", DataType.LONG)) - .addColumn(new ColumnBuilder("col3", DataType.DOUBLE)) - .addColumn(new ColumnBuilder("col4", DataType.OLE)) - .addColumn(new ColumnBuilder("col5", DataType.BOOLEAN)) - .addColumn(new ColumnBuilder("col6", DataType.SHORT_DATE_TIME)) - .toTable(db); - - Date testDate = df.parse("19801231 00:00:00"); - t.addRow("some text||some more", 13, 13.25, createString(30).getBytes(), - true, testDate); - - t.addRow("crazy'data\"here", -345, -0.000345, createString(7).getBytes(), - true, null); - - t.addRow("C:\\temp\\some_file.txt", 25, 0.0, null, false, null); - - StringWriter out = new StringWriter(); - - new ExportUtil.Builder(db, "test") - .exportWriter(new BufferedWriter(out)); - - String expected = - "some text||some more,13,13.25,\"61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78\n79 7A 61 62 63 64\",true," + testDate + NL + - "\"crazy'data\"\"here\",-345,-3.45E-4,61 62 63 64 65 66 67,true," + NL + - "C:\\temp\\some_file.txt,25,0.0,,false," + NL; - - assertEquals(expected, out.toString()); - - out = new StringWriter(); - - new ExportUtil.Builder(db, "test") - .setHeader(true) - .setDelimiter("||") - .setQuote('\'') - .exportWriter(new BufferedWriter(out)); - - expected = - "col1||col2||col3||col4||col5||col6" + NL + - "'some text||some more'||13||13.25||'61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78\n79 7A 61 62 63 64'||true||" + testDate + NL + - "'crazy''data\"here'||-345||-3.45E-4||61 62 63 64 65 66 67||true||" + NL + - "C:\\temp\\some_file.txt||25||0.0||||false||" + NL; - assertEquals(expected, out.toString()); - - ExportFilter oddFilter = new SimpleExportFilter() { - private int _num; - @Override - public Object[] filterRow(Object[] row) { - if((_num++ % 2) == 1) { - return null; - } - return row; - } - }; - - out = new StringWriter(); - - new ExportUtil.Builder(db, "test") - .setFilter(oddFilter) - .exportWriter(new BufferedWriter(out)); - - expected = - "some text||some more,13,13.25,\"61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78\n79 7A 61 62 63 64\",true," + testDate + NL + - "C:\\temp\\some_file.txt,25,0.0,,false," + NL; - - assertEquals(expected, out.toString()); - } - } - -} diff --git a/test/src/java/com/healthmarketscience/jackcess/FKEnforcerTest.java b/test/src/java/com/healthmarketscience/jackcess/FKEnforcerTest.java deleted file mode 100644 index 9dd0c88..0000000 --- a/test/src/java/com/healthmarketscience/jackcess/FKEnforcerTest.java +++ /dev/null @@ -1,138 +0,0 @@ -/* -Copyright (c) 2012 James Ahlborn - -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 -*/ - -package com.healthmarketscience.jackcess; - -import java.io.IOException; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import static com.healthmarketscience.jackcess.DatabaseTest.*; -import static com.healthmarketscience.jackcess.JetFormatTest.*; -import junit.framework.TestCase; - -/** - * - * @author James Ahlborn - */ -public class FKEnforcerTest extends TestCase -{ - - public FKEnforcerTest(String name) throws Exception { - super(name); - } - - public void testNoEnforceForeignKeys() throws Exception { - for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.INDEX)) { - - Database db = openCopy(testDB); - Table t1 = db.getTable("Table1"); - Table t2 = db.getTable("Table2"); - Table t3 = db.getTable("Table3"); - - t1.addRow(20, 0, 20, "some data", 20); - - Cursor c = Cursor.createCursor(t2); - c.moveToNextRow(); - c.updateCurrentRow(30, "foo30"); - - c = Cursor.createCursor(t3); - c.moveToNextRow(); - c.deleteCurrentRow(); - - db.close(); - } - - } - - public void testEnforceForeignKeys() throws Exception { - for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.INDEX)) { - - Database db = openCopy(testDB); - db.setEnforceForeignKeys(true); - Table t1 = db.getTable("Table1"); - Table t2 = db.getTable("Table2"); - Table t3 = db.getTable("Table3"); - - try { - t1.addRow(20, 0, 20, "some data", 20); - fail("IOException should have been thrown"); - } catch(IOException ignored) { - // success - assertTrue(ignored.getMessage().contains("Table1[otherfk2]")); - } - - try { - Cursor c = Cursor.createCursor(t2); - c.moveToNextRow(); - c.updateCurrentRow(30, "foo30"); - fail("IOException should have been thrown"); - } catch(IOException ignored) { - // success - assertTrue(ignored.getMessage().contains("Table2[id]")); - } - - try { - Cursor c = Cursor.createCursor(t3); - c.moveToNextRow(); - c.deleteCurrentRow(); - fail("IOException should have been thrown"); - } catch(IOException ignored) { - // success - assertTrue(ignored.getMessage().contains("Table3[id]")); - } - - Cursor c = Cursor.createCursor(t3); - Column col = t3.getColumn("id"); - for(Map row : c) { - int id = (Integer)row.get("id"); - id += 20; - c.setCurrentRowValue(col, id); - } - - List> expectedRows = - createExpectedTable( - createT1Row(0, 0, 30, "baz0", 0), - createT1Row(1, 1, 31, "baz11", 0), - createT1Row(2, 1, 31, "baz11-2", 0), - createT1Row(3, 2, 33, "baz13", 0)); - - assertTable(expectedRows, t1); - - c = Cursor.createCursor(t2); - for(Iterator iter = c.iterator(); iter.hasNext(); ) { - iter.next(); - iter.remove(); - } - - assertEquals(0, t1.getRowCount()); - - db.close(); - } - - } - - private static Map createT1Row( - int id1, int fk1, int fk2, String data, int fk3) - { - return createExpectedRow("id", id1, "otherfk1", fk1, "otherfk2", fk2, - "data", data, "otherfk3", fk3); - } -} diff --git a/test/src/java/com/healthmarketscience/jackcess/ImportTest.java b/test/src/java/com/healthmarketscience/jackcess/ImportTest.java deleted file mode 100644 index 0be36e1..0000000 --- a/test/src/java/com/healthmarketscience/jackcess/ImportTest.java +++ /dev/null @@ -1,327 +0,0 @@ -/* -Copyright (c) 2007 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.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.Types; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import junit.framework.TestCase; - -import static com.healthmarketscience.jackcess.Database.*; -import static com.healthmarketscience.jackcess.DatabaseTest.*; - -/** - * @author Rob Di Marco - */ -public class ImportTest extends TestCase -{ - - public ImportTest(String name) { - super(name); - } - - public void testImportFromFile() throws Exception - { - for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) { - Database db = create(fileFormat); - String tableName = new ImportUtil.Builder(db, "test") - .setDelimiter("\\t") - .importFile(new File("test/data/sample-input.tab")); - Table t = db.getTable(tableName); - - List colNames = new ArrayList(); - for(Column c : t.getColumns()) { - colNames.add(c.getName()); - } - assertEquals(Arrays.asList("Test1", "Test2", "Test3"), colNames); - - List> expectedRows = - createExpectedTable( - createExpectedRow( - "Test1", "Foo", - "Test2", "Bar", - "Test3", "Ralph"), - createExpectedRow( - "Test1", "S", - "Test2", "Mouse", - "Test3", "Rocks"), - createExpectedRow( - "Test1", "", - "Test2", "Partial line", - "Test3", null), - createExpectedRow( - "Test1", " Quoted Value", - "Test2", " bazz ", - "Test3", " Really \"Crazy" + ImportUtil.LINE_SEPARATOR - + "value\""), - createExpectedRow( - "Test1", "buzz", - "Test2", "embedded\tseparator", - "Test3", "long") - ); - assertTable(expectedRows, t); - - t = new TableBuilder("test2") - .addColumn(new ColumnBuilder("T1", DataType.TEXT)) - .addColumn(new ColumnBuilder("T2", DataType.TEXT)) - .addColumn(new ColumnBuilder("T3", DataType.TEXT)) - .toTable(db); - - new ImportUtil.Builder(db, "test2") - .setDelimiter("\\t") - .setUseExistingTable(true) - .setHeader(false) - .importFile(new File("test/data/sample-input.tab")); - - expectedRows = - createExpectedTable( - createExpectedRow( - "T1", "Test1", - "T2", "Test2", - "T3", "Test3"), - createExpectedRow( - "T1", "Foo", - "T2", "Bar", - "T3", "Ralph"), - createExpectedRow( - "T1", "S", - "T2", "Mouse", - "T3", "Rocks"), - createExpectedRow( - "T1", "", - "T2", "Partial line", - "T3", null), - createExpectedRow( - "T1", " Quoted Value", - "T2", " bazz ", - "T3", " Really \"Crazy" + ImportUtil.LINE_SEPARATOR - + "value\""), - createExpectedRow( - "T1", "buzz", - "T2", "embedded\tseparator", - "T3", "long") - ); - assertTable(expectedRows, t); - - - ImportFilter oddFilter = new SimpleImportFilter() { - private int _num; - @Override - public Object[] filterRow(Object[] row) { - if((_num++ % 2) == 1) { - return null; - } - return row; - } - }; - - tableName = new ImportUtil.Builder(db, "test3") - .setDelimiter("\\t") - .setFilter(oddFilter) - .importFile(new File("test/data/sample-input.tab")); - t = db.getTable(tableName); - - colNames = new ArrayList(); - for(Column c : t.getColumns()) { - colNames.add(c.getName()); - } - assertEquals(Arrays.asList("Test1", "Test2", "Test3"), colNames); - - expectedRows = - createExpectedTable( - createExpectedRow( - "Test1", "Foo", - "Test2", "Bar", - "Test3", "Ralph"), - createExpectedRow( - "Test1", "", - "Test2", "Partial line", - "Test3", null), - createExpectedRow( - "Test1", "buzz", - "Test2", "embedded\tseparator", - "Test3", "long") - ); - assertTable(expectedRows, t); - - db.close(); - } - } - - public void testImportFromFileWithOnlyHeaders() throws Exception - { - for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) { - Database db = create(fileFormat); - String tableName = new ImportUtil.Builder(db, "test") - .setDelimiter("\\t") - .importFile(new File("test/data/sample-input-only-headers.tab")); - - Table t = db.getTable(tableName); - - List colNames = new ArrayList(); - for(Column c : t.getColumns()) { - colNames.add(c.getName()); - } - assertEquals(Arrays.asList( - "RESULT_PHYS_ID", "FIRST", "MIDDLE", "LAST", "OUTLIER", - "RANK", "CLAIM_COUNT", "PROCEDURE_COUNT", - "WEIGHTED_CLAIM_COUNT", "WEIGHTED_PROCEDURE_COUNT"), - colNames); - - db.close(); - } - } - - public void testCopySqlHeaders() throws Exception - { - for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) { - - TestResultSet rs = new TestResultSet(); - - rs.addColumn(Types.INTEGER, "col1"); - rs.addColumn(Types.VARCHAR, "col2", 60, 0, 0); - rs.addColumn(Types.VARCHAR, "col3", 500, 0, 0); - rs.addColumn(Types.BINARY, "col4", 128, 0, 0); - rs.addColumn(Types.BINARY, "col5", 512, 0, 0); - rs.addColumn(Types.NUMERIC, "col6", 0, 7, 15); - rs.addColumn(Types.VARCHAR, "col7", Integer.MAX_VALUE, 0, 0); - - Database db = create(fileFormat); - db.copyTable("Test1", (ResultSet)Proxy.newProxyInstance( - Thread.currentThread().getContextClassLoader(), - new Class[]{ResultSet.class}, - rs)); - - Table t = db.getTable("Test1"); - List columns = t.getColumns(); - assertEquals(7, columns.size()); - - Column c = columns.get(0); - assertEquals("col1", c.getName()); - assertEquals(DataType.LONG, c.getType()); - - c = columns.get(1); - assertEquals("col2", c.getName()); - assertEquals(DataType.TEXT, c.getType()); - assertEquals(120, c.getLength()); - - c = columns.get(2); - assertEquals("col3", c.getName()); - assertEquals(DataType.MEMO, c.getType()); - assertEquals(0, c.getLength()); - - c = columns.get(3); - assertEquals("col4", c.getName()); - assertEquals(DataType.BINARY, c.getType()); - assertEquals(128, c.getLength()); - - c = columns.get(4); - assertEquals("col5", c.getName()); - assertEquals(DataType.OLE, c.getType()); - assertEquals(0, c.getLength()); - - c = columns.get(5); - assertEquals("col6", c.getName()); - assertEquals(DataType.NUMERIC, c.getType()); - assertEquals(17, c.getLength()); - assertEquals(7, c.getScale()); - assertEquals(15, c.getPrecision()); - - c = columns.get(6); - assertEquals("col7", c.getName()); - assertEquals(DataType.MEMO, c.getType()); - assertEquals(0, c.getLength()); - } - } - - - private static class TestResultSet implements InvocationHandler - { - private List _types = new ArrayList(); - private List _names = new ArrayList(); - private List _displaySizes = new ArrayList(); - private List _scales = new ArrayList(); - private List _precisions = new ArrayList(); - - public Object invoke(Object proxy, Method method, Object[] args) - { - String methodName = method.getName(); - if(methodName.equals("getMetaData")) { - return Proxy.newProxyInstance( - Thread.currentThread().getContextClassLoader(), - new Class[]{ResultSetMetaData.class}, - this); - } else if(methodName.equals("next")) { - return Boolean.FALSE; - } else if(methodName.equals("getColumnCount")) { - return _types.size(); - } else if(methodName.equals("getColumnName")) { - return getValue(_names, args[0]); - } else if(methodName.equals("getColumnDisplaySize")) { - return getValue(_displaySizes, args[0]); - } else if(methodName.equals("getColumnType")) { - return getValue(_types, args[0]); - } else if(methodName.equals("getScale")) { - return getValue(_scales, args[0]); - } else if(methodName.equals("getPrecision")) { - return getValue(_precisions, args[0]); - } else { - throw new UnsupportedOperationException(methodName); - } - } - - public void addColumn(int type, String name) - { - addColumn(type, name, 0, 0, 0); - } - - public void addColumn(int type, String name, int displaySize, - int scale, int precision) - { - _types.add(type); - _names.add(name); - _displaySizes.add(displaySize); - _scales.add(scale); - _precisions.add(precision); - } - - private static T getValue(List values, Object index) { - return values.get((Integer)index - 1); - } - } - -} diff --git a/test/src/java/com/healthmarketscience/jackcess/IndexCodesTest.java b/test/src/java/com/healthmarketscience/jackcess/IndexCodesTest.java deleted file mode 100644 index ed71ebe..0000000 --- a/test/src/java/com/healthmarketscience/jackcess/IndexCodesTest.java +++ /dev/null @@ -1,792 +0,0 @@ -/* -Copyright (c) 2008 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.lang.reflect.Field; -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.TreeMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import junit.framework.TestCase; - -import static com.healthmarketscience.jackcess.DatabaseTest.*; -import static com.healthmarketscience.jackcess.JetFormatTest.*; - - -/** - * @author James Ahlborn - */ -public class IndexCodesTest extends TestCase { - - private static final Map SPECIAL_CHARS = - new HashMap(); - static { - SPECIAL_CHARS.put('\b', "\\b"); - SPECIAL_CHARS.put('\t', "\\t"); - SPECIAL_CHARS.put('\n', "\\n"); - SPECIAL_CHARS.put('\f', "\\f"); - SPECIAL_CHARS.put('\r', "\\r"); - SPECIAL_CHARS.put('\"', "\\\""); - SPECIAL_CHARS.put('\'', "\\'"); - SPECIAL_CHARS.put('\\', "\\\\"); - } - - public IndexCodesTest(String name) throws Exception { - super(name); - } - - public void testIndexCodes() throws Exception - { - for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.INDEX_CODES)) { - Database db = openMem(testDB); - - for(Table t : db) { - for(Index index : t.getIndexes()) { - // System.out.println("Checking " + t.getName() + "." + index.getName()); - checkIndexEntries(testDB, t, index); - } - } - - db.close(); - } - } - - private static void checkIndexEntries(final TestDB testDB, Table t, Index index) throws Exception - { -// index.initialize(); -// System.out.println("Ind " + index); - - Cursor cursor = Cursor.createIndexCursor(t, index); - while(cursor.moveToNextRow()) { - - Map row = cursor.getCurrentRow(); - Cursor.Position curPos = cursor.getSavepoint().getCurrentPosition(); - boolean success = false; - try { - findRow(testDB, t, index, row, curPos); - success = true; - } finally { - if(!success) { - System.out.println("CurPos: " + curPos); - System.out.println("Value: " + row + ": " + - toUnicodeStr(row.get("data"))); - } - } - } - - } - - private static void findRow(final TestDB testDB, Table t, Index index, - Map expectedRow, - Cursor.Position expectedPos) - throws Exception - { - Object[] idxRow = index.constructIndexRow(expectedRow); - Cursor cursor = Cursor.createIndexCursor(t, index, idxRow, idxRow); - - Cursor.Position startPos = cursor.getSavepoint().getCurrentPosition(); - - cursor.beforeFirst(); - while(cursor.moveToNextRow()) { - Map row = cursor.getCurrentRow(); - if(expectedRow.equals(row)) { - // verify that the entries are indeed equal - Cursor.Position curPos = cursor.getSavepoint().getCurrentPosition(); - assertEquals(entryToString(expectedPos), entryToString(curPos)); - return; - } - } - - // TODO long rows not handled completely yet in V2010 - // seems to truncate entry at 508 bytes with some trailing 2 byte seq - if(testDB.getExpectedFileFormat() == Database.FileFormat.V2010) { - String rowId = (String)expectedRow.get("name"); - String tName = t.getName(); - if(("Table11".equals(tName) || "Table11_desc".equals(tName)) && - ("row10".equals(rowId) || "row11".equals(rowId) || - "row12".equals(rowId))) { - System.out.println( - "TODO long rows not handled completely yet in V2010: " + tName + - ", " + rowId); - return; - } - } - - fail("testDB: " + testDB + ";\nCould not find expected row " + expectedRow + " starting at " + - entryToString(startPos)); - } - - - ////// - // - // The code below is for use in reverse engineering index entries. - // - ////// - - public void testNothing() throws Exception { - // keep this so build doesn't fail if other tests are disabled - } - - public void x_testCreateIsoFile() throws Exception - { - Database db = create(Database.FileFormat.V2000, true); - - Table t = new TableBuilder("test") - .addColumn(new ColumnBuilder("row", DataType.TEXT)) - .addColumn(new ColumnBuilder("data", DataType.TEXT)) - .toTable(db); - - for(int i = 0; i < 256; ++i) { - String str = "AA" + ((char)i) + "AA"; - t.addRow("row" + i, str); - } - - db.close(); - } - - public void x_testCreateAltIsoFile() throws Exception - { - Database db = openCopy(Database.FileFormat.V2000, new File("/tmp/test_ind.mdb"), true); - - Table t = db.getTable("Table1"); - - for(int i = 0; i < 256; ++i) { - String str = "AA" + ((char)i) + "AA"; - t.addRow("row" + i, str, - (byte)42 + i, (short)53 + i, 13 * i, - (6.7d / i), null, null, true); - } - - db.close(); - } - - public void x_testWriteAllCodesMdb() throws Exception - { - Database db = create(Database.FileFormat.V2000, true); - -// Table t = new TableBuilder("Table1") -// .addColumn(new ColumnBuilder("key", DataType.TEXT)) -// .addColumn(new ColumnBuilder("data", DataType.TEXT)) -// .toTable(db); - -// for(int i = 0; i <= 0xFFFF; ++i) { -// // skip non-char chars -// char c = (char)i; -// if(Character.isHighSurrogate(c) || Character.isLowSurrogate(c)) { -// continue; -// } -// String key = toUnicodeStr(c); -// String str = "AA" + c + "AA"; -// t.addRow(key, str); -// } - - Table t = new TableBuilder("Table5") - .addColumn(new ColumnBuilder("name", DataType.TEXT)) - .addColumn(new ColumnBuilder("data", DataType.TEXT)) - .toTable(db); - - char c = (char)0x3041; // crazy 7F 02 ... A0 - char c2 = (char)0x30A2; // crazy 7F 02 ... - char c3 = (char)0x2045; // inat 27 ... 1C - char c4 = (char)0x3043; // crazy 7F 03 ... A0 - char c5 = (char)0x3046; // crazy 7F 04 ... - char c6 = (char)0x30F6; // crazy 7F 0D ... A0 - char c7 = (char)0x3099; // unprint 03 - char c8 = (char)0x0041; // A - char c9 = (char)0x002D; // - (unprint) - char c10 = (char)0x20E1; // unprint F2 - char c11 = (char)0x309A; // unprint 04 - char c12 = (char)0x01C4; // (long extra) - char c13 = (char)0x005F; // _ (long inline) - char c14 = (char)0xFFFE; // removed - - char[] cs = new char[]{c7, c8, c3, c12, c13, c14, c, c2, c9}; - addCombos(t, 0, "", cs, 5); - -// t = new TableBuilder("Table2") -// .addColumn(new ColumnBuilder("data", DataType.TEXT)) -// .toTable(db); - -// writeChars(0x0000, t); - -// t = new TableBuilder("Table3") -// .addColumn(new ColumnBuilder("data", DataType.TEXT)) -// .toTable(db); - -// writeChars(0x0400, t); - - - db.close(); - } - - public void x_testReadAllCodesMdb() throws Exception - { -// Database db = openCopy(new File("/data2/jackcess_test/testAllIndexCodes.mdb")); -// Database db = openCopy(new File("/data2/jackcess_test/testAllIndexCodes_orig.mdb")); -// Database db = openCopy(new File("/data2/jackcess_test/testSomeMoreCodes.mdb")); - Database db = openCopy(Database.FileFormat.V2000, new File("/data2/jackcess_test/testStillMoreCodes.mdb")); - Table t = db.getTable("Table5"); - - Index ind = t.getIndexes().iterator().next(); - ind.initialize(); - - System.out.println("Ind " + ind); - - Cursor cursor = Cursor.createIndexCursor(t, ind); - while(cursor.moveToNextRow()) { - System.out.println("======="); - String entryStr = - entryToString(cursor.getSavepoint().getCurrentPosition()); - System.out.println("Entry Bytes: " + entryStr); - System.out.println("Value: " + cursor.getCurrentRow() + "; " + - toUnicodeStr(cursor.getCurrentRow().get("data"))); - } - - db.close(); - } - - private int addCombos(Table t, int rowNum, String s, char[] cs, int len) - throws Exception - { - if(s.length() >= len) { - return rowNum; - } - - for(int i = 0; i < cs.length; ++i) { - String name = "row" + (rowNum++); - String ss = s + cs[i]; - t.addRow(name, ss); - rowNum = addCombos(t, rowNum, ss, cs, len); - } - - return rowNum; - } - - private void writeChars(int hibyte, Table t) throws Exception - { - char other = (char)(hibyte | 0x41); - for(int i = 0; i < 0xFF; ++i) { - char c = (char)(hibyte | i); - String str = "" + other + c + other; - t.addRow(str); - } - } - - public void x_testReadIsoMdb() throws Exception - { -// Database db = open(new File("/tmp/test_ind.mdb")); -// Database db = open(new File("/tmp/test_ind2.mdb")); - Database db = open(Database.FileFormat.V2000, new File("/tmp/test_ind3.mdb")); -// Database db = open(new File("/tmp/test_ind4.mdb")); - - Table t = db.getTable("Table1"); - Index index = t.getIndex("B"); - index.initialize(); - System.out.println("Ind " + index); - - Cursor cursor = Cursor.createIndexCursor(t, index); - while(cursor.moveToNextRow()) { - System.out.println("======="); - System.out.println("Savepoint: " + cursor.getSavepoint()); - System.out.println("Value: " + cursor.getCurrentRow()); - } - - db.close(); - } - - public void x_testReverseIsoMdb2010() throws Exception - { - Database db = open(Database.FileFormat.V2010, new File("/data2/jackcess_test/testAllIndexCodes3_2010.accdb")); - - Table t = db.getTable("Table1"); - Index index = t.getIndexes().iterator().next(); - index.initialize(); - System.out.println("Ind " + index); - - Pattern inlinePat = Pattern.compile("7F 0E 02 0E 02 (.*)0E 02 0E 02 01 00"); - Pattern unprintPat = Pattern.compile("01 01 01 80 (.+) 06 (.+) 00"); - Pattern unprint2Pat = Pattern.compile("0E 02 0E 02 0E 02 0E 02 01 02 (.+) 00"); - Pattern inatPat = Pattern.compile("7F 0E 02 0E 02 (.*)0E 02 0E 02 01 02 02 (.+) 00"); - Pattern inat2Pat = Pattern.compile("7F 0E 02 0E 02 (.*)0E 02 0E 02 01 (02 02 (.+))?01 01 (.*)FF 02 80 FF 80 00"); - - Map inlineCodes = new TreeMap(); - Map unprintCodes = new TreeMap(); - Map unprint2Codes = new TreeMap(); - Map inatInlineCodes = new TreeMap(); - Map inatExtraCodes = new TreeMap(); - Map inat2Codes = new TreeMap(); - Map inat2ExtraCodes = new TreeMap(); - Map inat2CrazyCodes = new TreeMap(); - - - Cursor cursor = Cursor.createIndexCursor(t, index); - while(cursor.moveToNextRow()) { -// System.out.println("======="); -// System.out.println("Savepoint: " + cursor.getSavepoint()); -// System.out.println("Value: " + cursor.getCurrentRow()); - Cursor.Savepoint savepoint = cursor.getSavepoint(); - String entryStr = entryToString(savepoint.getCurrentPosition()); - - Map row = cursor.getCurrentRow(); - String value = (String)row.get("data"); - String key = (String)row.get("key"); - char c = value.charAt(2); - - System.out.println("======="); - System.out.println("RowId: " + - savepoint.getCurrentPosition().getRowId()); - System.out.println("Entry: " + entryStr); -// System.out.println("Row: " + row); - System.out.println("Value: (" + key + ")" + value); - System.out.println("Char: " + c + ", " + (int)c + ", " + - toUnicodeStr(c)); - - String type = null; - if(entryStr.endsWith("01 00")) { - - // handle inline codes - type = "INLINE"; - Matcher m = inlinePat.matcher(entryStr); - m.find(); - handleInlineEntry(m.group(1), c, inlineCodes); - - } else if(entryStr.contains("01 01 01 80")) { - - // handle most unprintable codes - type = "UNPRINTABLE"; - Matcher m = unprintPat.matcher(entryStr); - m.find(); - handleUnprintableEntry(m.group(2), c, unprintCodes); - - } else if(entryStr.contains("01 02 02") && - !entryStr.contains("FF 02 80 FF 80")) { - - // handle chars w/ symbols - type = "CHAR_WITH_SYMBOL"; - Matcher m = inatPat.matcher(entryStr); - m.find(); - handleInternationalEntry(m.group(1), m.group(2), c, - inatInlineCodes, inatExtraCodes); - - } else if(entryStr.contains("0E 02 0E 02 0E 02 0E 02 01 02")) { - - // handle chars w/ symbols - type = "UNPRINTABLE_2"; - Matcher m = unprint2Pat.matcher(entryStr); - m.find(); - handleUnprintable2Entry(m.group(1), c, unprint2Codes); - - } else if(entryStr.contains("FF 02 80 FF 80")) { - - type = "CRAZY_INAT"; - Matcher m = inat2Pat.matcher(entryStr); - m.find(); - handleInternational2Entry(m.group(1), m.group(3), m.group(4), c, - inat2Codes, inat2ExtraCodes, - inat2CrazyCodes); - - } else { - - // throw new RuntimeException("unhandled " + entryStr); - System.out.println("unhandled " + entryStr); - } - - System.out.println("Type: " + type); - } - - System.out.println("\n***CODES"); - for(int i = 0; i <= 0xFFFF; ++i) { - - if(i == 256) { - System.out.println("\n***EXTENDED CODES"); - } - - // skip non-char chars - char c = (char)i; - if(Character.isHighSurrogate(c) || Character.isLowSurrogate(c)) { - continue; - } - - if(c == (char)0xFFFE) { - // this gets replaced with FFFD, treat it the same - c = (char)0xFFFD; - } - - Character cc = c; - String[] chars = inlineCodes.get(cc); - if(chars != null) { - if((chars.length == 1) && (chars[0].length() == 0)) { - System.out.println("X"); - } else { - System.out.println("S" + toByteString(chars)); - } - continue; - } - - chars = inatInlineCodes.get(cc); - if(chars != null) { - String[] extra = inatExtraCodes.get(cc); - System.out.println("I" + toByteString(chars) + "," + - toByteString(extra)); - continue; - } - - chars = unprintCodes.get(cc); - if(chars != null) { - System.out.println("U" + toByteString(chars)); - continue; - } - - chars = unprint2Codes.get(cc); - if(chars != null) { - if(chars.length > 1) { - throw new RuntimeException("long unprint codes"); - } - int val = Integer.parseInt(chars[0], 16) - 2; - String valStr = ByteUtil.toHexString(new byte[]{(byte)val}).trim(); - System.out.println("P" + valStr); - continue; - } - - chars = inat2Codes.get(cc); - if(chars != null) { - String [] crazyCodes = inat2CrazyCodes.get(cc); - String crazyCode = ""; - if(crazyCodes != null) { - if((crazyCodes.length != 1) || !"A0".equals(crazyCodes[0])) { - throw new RuntimeException("CC " + Arrays.asList(crazyCodes)); - } - crazyCode = "1"; - } - - String[] extra = inat2ExtraCodes.get(cc); - System.out.println("Z" + toByteString(chars) + "," + - toByteString(extra) + "," + - crazyCode); - continue; - } - - throw new RuntimeException("Unhandled char " + toUnicodeStr(c)); - } - System.out.println("\n***END CODES"); - - db.close(); - } - - public void x_testReverseIsoMdb() throws Exception - { - Database db = open(Database.FileFormat.V2000, new File("/data2/jackcess_test/testAllIndexCodes3.mdb")); - - Table t = db.getTable("Table1"); - Index index = t.getIndexes().iterator().next(); - index.initialize(); - System.out.println("Ind " + index); - - Pattern inlinePat = Pattern.compile("7F 4A 4A (.*)4A 4A 01 00"); - Pattern unprintPat = Pattern.compile("01 01 01 80 (.+) 06 (.+) 00"); - Pattern unprint2Pat = Pattern.compile("4A 4A 4A 4A 01 02 (.+) 00"); - Pattern inatPat = Pattern.compile("7F 4A 4A (.*)4A 4A 01 02 02 (.+) 00"); - Pattern inat2Pat = Pattern.compile("7F 4A 4A (.*)4A 4A 01 (02 02 (.+))?01 01 (.*)FF 02 80 FF 80 00"); - - Map inlineCodes = new TreeMap(); - Map unprintCodes = new TreeMap(); - Map unprint2Codes = new TreeMap(); - Map inatInlineCodes = new TreeMap(); - Map inatExtraCodes = new TreeMap(); - Map inat2Codes = new TreeMap(); - Map inat2ExtraCodes = new TreeMap(); - Map inat2CrazyCodes = new TreeMap(); - - - Cursor cursor = Cursor.createIndexCursor(t, index); - while(cursor.moveToNextRow()) { -// System.out.println("======="); -// System.out.println("Savepoint: " + cursor.getSavepoint()); -// System.out.println("Value: " + cursor.getCurrentRow()); - Cursor.Savepoint savepoint = cursor.getSavepoint(); - String entryStr = entryToString(savepoint.getCurrentPosition()); - - Map row = cursor.getCurrentRow(); - String value = (String)row.get("data"); - String key = (String)row.get("key"); - char c = value.charAt(2); - System.out.println("======="); - System.out.println("RowId: " + - savepoint.getCurrentPosition().getRowId()); - System.out.println("Entry: " + entryStr); -// System.out.println("Row: " + row); - System.out.println("Value: (" + key + ")" + value); - System.out.println("Char: " + c + ", " + (int)c + ", " + - toUnicodeStr(c)); - - String type = null; - if(entryStr.endsWith("01 00")) { - - // handle inline codes - type = "INLINE"; - Matcher m = inlinePat.matcher(entryStr); - m.find(); - handleInlineEntry(m.group(1), c, inlineCodes); - - } else if(entryStr.contains("01 01 01 80")) { - - // handle most unprintable codes - type = "UNPRINTABLE"; - Matcher m = unprintPat.matcher(entryStr); - m.find(); - handleUnprintableEntry(m.group(2), c, unprintCodes); - - } else if(entryStr.contains("01 02 02") && - !entryStr.contains("FF 02 80 FF 80")) { - - // handle chars w/ symbols - type = "CHAR_WITH_SYMBOL"; - Matcher m = inatPat.matcher(entryStr); - m.find(); - handleInternationalEntry(m.group(1), m.group(2), c, - inatInlineCodes, inatExtraCodes); - - } else if(entryStr.contains("4A 4A 4A 4A 01 02")) { - - // handle chars w/ symbols - type = "UNPRINTABLE_2"; - Matcher m = unprint2Pat.matcher(entryStr); - m.find(); - handleUnprintable2Entry(m.group(1), c, unprint2Codes); - - } else if(entryStr.contains("FF 02 80 FF 80")) { - - type = "CRAZY_INAT"; - Matcher m = inat2Pat.matcher(entryStr); - m.find(); - handleInternational2Entry(m.group(1), m.group(3), m.group(4), c, - inat2Codes, inat2ExtraCodes, - inat2CrazyCodes); - - } else { - - throw new RuntimeException("unhandled " + entryStr); - } - - System.out.println("Type: " + type); - } - - System.out.println("\n***CODES"); - for(int i = 0; i <= 0xFFFF; ++i) { - - if(i == 256) { - System.out.println("\n***EXTENDED CODES"); - } - - // skip non-char chars - char c = (char)i; - if(Character.isHighSurrogate(c) || Character.isLowSurrogate(c)) { - continue; - } - - if(c == (char)0xFFFE) { - // this gets replaced with FFFD, treat it the same - c = (char)0xFFFD; - } - - Character cc = c; - String[] chars = inlineCodes.get(cc); - if(chars != null) { - if((chars.length == 1) && (chars[0].length() == 0)) { - System.out.println("X"); - } else { - System.out.println("S" + toByteString(chars)); - } - continue; - } - - chars = inatInlineCodes.get(cc); - if(chars != null) { - String[] extra = inatExtraCodes.get(cc); - System.out.println("I" + toByteString(chars) + "," + - toByteString(extra)); - continue; - } - - chars = unprintCodes.get(cc); - if(chars != null) { - System.out.println("U" + toByteString(chars)); - continue; - } - - chars = unprint2Codes.get(cc); - if(chars != null) { - if(chars.length > 1) { - throw new RuntimeException("long unprint codes"); - } - int val = Integer.parseInt(chars[0], 16) - 2; - String valStr = ByteUtil.toHexString(new byte[]{(byte)val}).trim(); - System.out.println("P" + valStr); - continue; - } - - chars = inat2Codes.get(cc); - if(chars != null) { - String [] crazyCodes = inat2CrazyCodes.get(cc); - String crazyCode = ""; - if(crazyCodes != null) { - if((crazyCodes.length != 1) || !"A0".equals(crazyCodes[0])) { - throw new RuntimeException("CC " + Arrays.asList(crazyCodes)); - } - crazyCode = "1"; - } - - String[] extra = inat2ExtraCodes.get(cc); - System.out.println("Z" + toByteString(chars) + "," + - toByteString(extra) + "," + - crazyCode); - continue; - } - - throw new RuntimeException("Unhandled char " + toUnicodeStr(c)); - } - System.out.println("\n***END CODES"); - - db.close(); - } - - private static String toByteString(String[] chars) - { - String str = join(chars, "", ""); - if(str.length() > 0 && str.charAt(0) == '0') { - str = str.substring(1); - } - return str; - } - - private static void handleInlineEntry( - String entryCodes, char c, Map inlineCodes) - throws Exception - { - inlineCodes.put(c, entryCodes.trim().split(" ")); - } - - private static void handleUnprintableEntry( - String entryCodes, char c, Map unprintCodes) - throws Exception - { - unprintCodes.put(c, entryCodes.trim().split(" ")); - } - - private static void handleUnprintable2Entry( - String entryCodes, char c, Map unprintCodes) - throws Exception - { - unprintCodes.put(c, entryCodes.trim().split(" ")); - } - - private static void handleInternationalEntry( - String inlineCodes, String entryCodes, char c, - Map inatInlineCodes, - Map inatExtraCodes) - throws Exception - { - inatInlineCodes.put(c, inlineCodes.trim().split(" ")); - inatExtraCodes.put(c, entryCodes.trim().split(" ")); - } - - private static void handleInternational2Entry( - String inlineCodes, String entryCodes, String crazyCodes, char c, - Map inatInlineCodes, - Map inatExtraCodes, - Map inatCrazyCodes) - throws Exception - { - inatInlineCodes.put(c, inlineCodes.trim().split(" ")); - if(entryCodes != null) { - inatExtraCodes.put(c, entryCodes.trim().split(" ")); - } - if((crazyCodes != null) && (crazyCodes.length() > 0)) { - inatCrazyCodes.put(c, crazyCodes.trim().split(" ")); - } - } - - private static String toUnicodeStr(Object obj) throws Exception { - StringBuilder sb = new StringBuilder(); - for(char c : obj.toString().toCharArray()) { - sb.append(toUnicodeStr(c)).append(" "); - } - return sb.toString(); - } - - private static String toUnicodeStr(char c) throws Exception { - String specialStr = SPECIAL_CHARS.get(c); - if(specialStr != null) { - return specialStr; - } - - String digits = Integer.toHexString(c).toUpperCase(); - while(digits.length() < 4) { - digits = "0" + digits; - } - return "\\u" + digits; - } - - private static String join(String[] strs, String joinStr, String prefixStr) { - if(strs == null) { - return ""; - } - StringBuilder builder = new StringBuilder(); - for(int i = 0; i < strs.length; ++i) { - if(strs[i].length() == 0) { - continue; - } - builder.append(prefixStr).append(strs[i]); - if(i < (strs.length - 1)) { - builder.append(joinStr); - } - } - return builder.toString(); - } - - static String entryToString(Cursor.Position curPos) - throws Exception - { - Field eField = curPos.getClass().getDeclaredField("_entry"); - eField.setAccessible(true); - IndexData.Entry entry = (IndexData.Entry)eField.get(curPos); - Field ebField = entry.getClass().getDeclaredField("_entryBytes"); - ebField.setAccessible(true); - byte[] entryBytes = (byte[])ebField.get(entry); - - return ByteUtil.toHexString(ByteBuffer.wrap(entryBytes), - entryBytes.length) - .trim().replaceAll("\\p{Space}+", " "); - } - -} diff --git a/test/src/java/com/healthmarketscience/jackcess/IndexTest.java b/test/src/java/com/healthmarketscience/jackcess/IndexTest.java index 8f078f6..8c6284a 100644 --- a/test/src/java/com/healthmarketscience/jackcess/IndexTest.java +++ b/test/src/java/com/healthmarketscience/jackcess/IndexTest.java @@ -36,11 +36,16 @@ import java.util.Map; import java.util.SortedSet; import java.util.TreeSet; -import junit.framework.TestCase; - import static com.healthmarketscience.jackcess.Database.*; import static com.healthmarketscience.jackcess.DatabaseTest.*; -import static com.healthmarketscience.jackcess.JetFormatTest.*; +import com.healthmarketscience.jackcess.impl.ByteUtil; +import com.healthmarketscience.jackcess.impl.IndexCodesTest; +import com.healthmarketscience.jackcess.impl.IndexData; +import com.healthmarketscience.jackcess.impl.IndexImpl; +import static com.healthmarketscience.jackcess.impl.JetFormatTest.*; +import com.healthmarketscience.jackcess.impl.RowIdImpl; +import com.healthmarketscience.jackcess.impl.TableImpl; +import junit.framework.TestCase; /** * @author James Ahlborn @@ -110,8 +115,8 @@ public class IndexTest extends TestCase { for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.INDEX, true)) { Database mdb = open(testDB); - Table table = mdb.getTable("Table1"); - for(Index idx : table.getIndexes()) { + TableImpl table = (TableImpl)mdb.getTable("Table1"); + for(IndexImpl idx : table.getIndexes()) { idx.initialize(); } assertEquals(4, table.getIndexes().size()); @@ -122,8 +127,8 @@ public class IndexTest extends TestCase { "Table2Table1", "otherfk1", "Table3Table1", "otherfk2"); - table = mdb.getTable("Table2"); - for(Index idx : table.getIndexes()) { + table = (TableImpl)mdb.getTable("Table2"); + for(IndexImpl idx : table.getIndexes()) { idx.initialize(); } assertEquals(3, table.getIndexes().size()); @@ -134,8 +139,8 @@ public class IndexTest extends TestCase { "PrimaryKey", "id", ".rC", "id"); - Index pkIdx = table.getIndex("PrimaryKey"); - Index fkIdx = table.getIndex(".rC"); + IndexImpl pkIdx = table.getIndex("PrimaryKey"); + IndexImpl fkIdx = table.getIndex(".rC"); assertNotSame(pkIdx, fkIdx); assertTrue(fkIdx.isForeignKey()); assertSame(pkIdx.getIndexData(), fkIdx.getIndexData()); @@ -143,8 +148,8 @@ public class IndexTest extends TestCase { assertEquals(Arrays.asList(pkIdx, fkIdx), indexData.getIndexes()); assertSame(pkIdx, indexData.getPrimaryIndex()); - table = mdb.getTable("Table3"); - for(Index idx : table.getIndexes()) { + table = (TableImpl)mdb.getTable("Table3"); + for(IndexImpl idx : table.getIndexes()) { idx.initialize(); } assertEquals(3, table.getIndexes().size()); @@ -171,8 +176,8 @@ public class IndexTest extends TestCase { for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.COMP_INDEX)) { // this file has an index with "compressed" entries and node pages Database db = open(testDB); - Table t = db.getTable("Table1"); - Index index = t.getIndexes().get(0); + TableImpl t = (TableImpl)db.getTable("Table1"); + IndexImpl index = t.getIndexes().get(0); assertFalse(index.isInitialized()); assertEquals(512, countRows(t)); assertEquals(512, index.getIndexData().getEntryCount()); @@ -180,23 +185,12 @@ public class IndexTest extends TestCase { // copy to temp file and attempt to edit db = openCopy(testDB); - t = db.getTable("Table1"); + t = (TableImpl)db.getTable("Table1"); index = t.getIndexes().get(0); System.out.println("IndexTest: Index type: " + index.getIndexData().getClass()); - try { - t.addRow(99, "abc", "def"); - if(index.getIndexData() instanceof SimpleIndexData) { - // SimpleIndex doesn't support writing these indexes - fail("Should have thrown UnsupportedOperationException"); - } - } catch(UnsupportedOperationException e) { - // success - if(index.getIndexData() instanceof BigIndexData) { - throw e; - } - } + t.addRow(99, "abc", "def"); } } @@ -212,28 +206,28 @@ public class IndexTest extends TestCase { assertRowCount(12, table); for(Index index : table.getIndexes()) { - assertEquals(12, index.getIndexData().getEntryCount()); + assertEquals(12, ((IndexImpl)index).getIndexData().getEntryCount()); } table.reset(); table.getNextRow(); table.getNextRow(); - table.deleteCurrentRow(); + table.getDefaultCursor().deleteCurrentRow(); table.getNextRow(); - table.deleteCurrentRow(); + table.getDefaultCursor().deleteCurrentRow(); table.getNextRow(); table.getNextRow(); - table.deleteCurrentRow(); + table.getDefaultCursor().deleteCurrentRow(); table.getNextRow(); table.getNextRow(); table.getNextRow(); - table.deleteCurrentRow(); + table.getDefaultCursor().deleteCurrentRow(); table.reset(); assertRowCount(8, table); for(Index index : table.getIndexes()) { - assertEquals(8, index.getIndexData().getEntryCount()); + assertEquals(8, ((IndexImpl)index).getIndexData().getEntryCount()); } } } @@ -254,9 +248,9 @@ public class IndexTest extends TestCase { throws Exception { Table orig = db.getTable(tableName); - Index origI = orig.getIndex("DataIndex"); + IndexImpl origI = (IndexImpl)orig.getIndex("DataIndex"); Table temp = db.getTable(tableName + "_temp"); - Index tempI = temp.getIndex("DataIndex"); + IndexImpl tempI = (IndexImpl)temp.getIndex("DataIndex"); // copy from orig table to temp table for(Map row : orig) { @@ -266,8 +260,8 @@ public class IndexTest extends TestCase { assertEquals(origI.getIndexData().getEntryCount(), tempI.getIndexData().getEntryCount()); - Cursor origC = Cursor.createIndexCursor(orig, origI); - Cursor tempC = Cursor.createIndexCursor(temp, tempI); + Cursor origC = CursorBuilder.createCursor(orig, origI); + Cursor tempC = CursorBuilder.createCursor(temp, tempI); while(true) { boolean origHasNext = origC.moveToNextRow(); @@ -340,7 +334,7 @@ public class IndexTest extends TestCase { IOException failure = null; try { - index.addRow(row, new RowId(400 + i, 0)); + ((IndexImpl)index).addRow(row, new RowIdImpl(400 + i, 0)); } catch(IOException e) { failure = e; } @@ -357,8 +351,8 @@ public class IndexTest extends TestCase { for (final TestDB testDB : SUPPORTED_DBS_TEST) { Database db = openCopy(testDB); Table table = db.getTable("Table1"); - Index indA = table.getIndex("PrimaryKey"); - Index indB = table.getIndex("B"); + IndexImpl indA = (IndexImpl)table.getIndex("PrimaryKey"); + IndexImpl indB = (IndexImpl)table.getIndex("B"); assertEquals(2, indA.getUniqueEntryCount()); assertEquals(2, indB.getUniqueEntryCount()); @@ -382,8 +376,8 @@ public class IndexTest extends TestCase { indB = null; table = db.getTable("Table1"); - indA = table.getIndex("PrimaryKey"); - indB = table.getIndex("B"); + indA = (IndexImpl)table.getIndex("PrimaryKey"); + indB = (IndexImpl)table.getIndex("B"); assertEquals(12, indA.getIndexData().getEntryCount()); assertEquals(12, indB.getIndexData().getEntryCount()); @@ -391,7 +385,7 @@ public class IndexTest extends TestCase { assertEquals(12, indA.getUniqueEntryCount()); assertEquals(8, indB.getUniqueEntryCount()); - Cursor c = Cursor.createCursor(table); + Cursor c = CursorBuilder.createCursor(table); assertTrue(c.moveToNextRow()); final Map row = c.getCurrentRow(); @@ -443,7 +437,7 @@ public class IndexTest extends TestCase { .toTable(db); assertEquals(1, t.getIndexes().size()); - Index idx = t.getIndexes().get(0); + IndexImpl idx = (IndexImpl)t.getIndexes().get(0); assertEquals(IndexBuilder.PRIMARY_KEY_NAME, idx.getName()); assertEquals(1, idx.getColumns().size()); @@ -458,7 +452,7 @@ public class IndexTest extends TestCase { t.addRow(1, "row1"); t.addRow(3, "row3"); - Cursor c = new CursorBuilder(t) + Cursor c = t.newCursor() .setIndexByName(IndexBuilder.PRIMARY_KEY_NAME).toCursor(); for(int i = 1; i <= 3; ++i) { @@ -478,8 +472,8 @@ public class IndexTest extends TestCase { Table t2 = db.getTable("Table2"); Table t3 = db.getTable("Table3"); - Index t2t1 = t1.getIndex("Table2Table1"); - Index t3t1 = t1.getIndex("Table3Table1"); + IndexImpl t2t1 = (IndexImpl)t1.getIndex("Table2Table1"); + IndexImpl t3t1 = (IndexImpl)t1.getIndex("Table3Table1"); assertTrue(t2t1.isForeignKey()); @@ -498,7 +492,7 @@ public class IndexTest extends TestCase { Index t1pk = t1.getIndex(IndexBuilder.PRIMARY_KEY_NAME); assertNotNull(t1pk); - assertNull(t1pk.getReference()); + assertNull(((IndexImpl)t1pk).getReference()); assertNull(t1pk.getReferencedIndex()); } } @@ -506,7 +500,7 @@ public class IndexTest extends TestCase { private void doCheckForeignKeyIndex(Table ta, Index ia, Table tb) throws Exception { - Index ib = ia.getReferencedIndex(); + IndexImpl ib = (IndexImpl)ia.getReferencedIndex(); assertNotNull(ib); assertSame(tb, ib.getTable()); diff --git a/test/src/java/com/healthmarketscience/jackcess/JetFormatTest.java b/test/src/java/com/healthmarketscience/jackcess/JetFormatTest.java deleted file mode 100644 index 9c75b6d..0000000 --- a/test/src/java/com/healthmarketscience/jackcess/JetFormatTest.java +++ /dev/null @@ -1,240 +0,0 @@ -package com.healthmarketscience.jackcess; - -import java.io.File; -import java.io.IOException; -import java.nio.channels.FileChannel; -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.List; -import java.util.Set; - -import junit.framework.TestCase; - -import static com.healthmarketscience.jackcess.Database.*; -import static com.healthmarketscience.jackcess.DatabaseTest.*; - -/** - * @author Dan Rollo - * Date: Mar 5, 2010 - * Time: 12:44:21 PM - */ -public class JetFormatTest extends TestCase { - - static final File DIR_TEST_DATA = new File("test/data"); - - /** - * Defines known valid db test file base names. - */ - public static enum Basename { - - BIG_INDEX("bigIndexTest"), - COMP_INDEX("compIndexTest"), - DEL_COL("delColTest"), - DEL("delTest"), - FIXED_NUMERIC("fixedNumericTest"), - FIXED_TEXT("fixedTextTest"), - INDEX_CURSOR("indexCursorTest"), - INDEX("indexTest"), - OVERFLOW("overflowTest"), - QUERY("queryTest"), - TEST("test"), - TEST2("test2"), - INDEX_CODES("testIndexCodes"), - INDEX_PROPERTIES("testIndexProperties"), - PROMOTION("testPromotion"), - COMPLEX("complexDataTest"), - UNSUPPORTED("unsupportedFieldsTest"), - LINKED("linkerTest"); - - private final String _basename; - - Basename(String fileBasename) { - _basename = fileBasename; - } - - @Override - public String toString() { return _basename; } - } - - /** Defines currently supported db file formats. (can be modified at - runtime via the system property - "com.healthmarketscience.jackcess.testFormats") */ - final static FileFormat[] SUPPORTED_FILEFORMATS; - final static FileFormat[] SUPPORTED_FILEFORMATS_FOR_READ; - - static { - String testFormatStr = System.getProperty("com.healthmarketscience.jackcess.testFormats"); - Set testFormats = EnumSet.allOf(FileFormat.class); - if((testFormatStr != null) && (testFormatStr.length() > 0)) { - testFormats.clear(); - for(String tmp : testFormatStr.split(",")) { - testFormats.add(FileFormat.valueOf(tmp.toUpperCase())); - } - } - - List supported = new ArrayList(); - List supportedForRead = new ArrayList(); - for(FileFormat ff : FileFormat.values()) { - if(!testFormats.contains(ff)) { - continue; - } - supportedForRead.add(ff); - if(ff.getJetFormat().READ_ONLY || (ff == FileFormat.MSISAM)) { - continue; - } - supported.add(ff); - } - - SUPPORTED_FILEFORMATS = supported.toArray(new FileFormat[0]); - SUPPORTED_FILEFORMATS_FOR_READ = - supportedForRead.toArray(new FileFormat[0]); - } - - /** - * Defines known valid test database files, and their jet format version. - */ - public static final class TestDB { - - private final File dbFile; - private final FileFormat expectedFileFormat; - - private TestDB(File databaseFile, - FileFormat expectedDBFileFormat) { - - dbFile = databaseFile; - expectedFileFormat = expectedDBFileFormat; - } - - public final File getFile() { return dbFile; } - - public final FileFormat getExpectedFileFormat() { - return expectedFileFormat; - } - - public final JetFormat getExpectedFormat() { - return expectedFileFormat.getJetFormat(); - } - - @Override - public final String toString() { - return "dbFile: " + dbFile.getAbsolutePath() - + "; expectedFileFormat: " + expectedFileFormat; - } - - public static List getSupportedForBasename(Basename basename) { - return getSupportedForBasename(basename, false); - } - - public static List getSupportedForBasename(Basename basename, - boolean readOnly) { - - List supportedTestDBs = new ArrayList(); - for (FileFormat fileFormat : - (readOnly ? SUPPORTED_FILEFORMATS_FOR_READ : - SUPPORTED_FILEFORMATS)) { - File testFile = getFileForBasename(basename, fileFormat); - if(!testFile.exists()) { - continue; - } - - // verify that the db is the file format expected - try { - Database db = Database.open(testFile, true); - FileFormat dbFileFormat = db.getFileFormat(); - db.close(); - if(dbFileFormat != fileFormat) { - throw new IllegalStateException("Expected " + fileFormat + - " was " + dbFileFormat); - } - } catch(Exception e) { - throw new RuntimeException(e); - } - - supportedTestDBs.add(new TestDB(testFile, fileFormat)); - } - return supportedTestDBs; - } - - private static File getFileForBasename( - Basename basename, FileFormat fileFormat) { - - return new File(DIR_TEST_DATA, - fileFormat.name() + File.separator + - basename + fileFormat.name() + - fileFormat.getFileExtension()); - } - } - - static final List SUPPORTED_DBS_TEST = - TestDB.getSupportedForBasename(Basename.TEST); - static final List SUPPORTED_DBS_TEST_FOR_READ = - TestDB.getSupportedForBasename(Basename.TEST, true); - - - public void testGetFormat() throws Exception { - try { - JetFormat.getFormat(null); - fail("npe"); - } catch (NullPointerException e) { - // success - } - - for (final TestDB testDB : SUPPORTED_DBS_TEST_FOR_READ) { - - final FileChannel channel = Database.openChannel(testDB.dbFile, false); - try { - - JetFormat fmtActual = JetFormat.getFormat(channel); - assertEquals("Unexpected JetFormat for dbFile: " + - testDB.dbFile.getAbsolutePath(), - testDB.expectedFileFormat.getJetFormat(), fmtActual); - - } finally { - channel.close(); - } - - } - } - - public void testReadOnlyFormat() throws Exception { - - for (final TestDB testDB : SUPPORTED_DBS_TEST_FOR_READ) { - - Database db = null; - IOException failure = null; - try { - db = openCopy(testDB); - } catch(IOException e) { - failure = e; - } finally { - if(db != null) { - db.close(); - } - } - - if(!testDB.getExpectedFormat().READ_ONLY) { - assertNull(failure); - } else { - assertTrue(failure.getMessage().contains("does not support writing")); - } - - } - } - - public void testFileFormat() throws Exception { - - for (final TestDB testDB : SUPPORTED_DBS_TEST_FOR_READ) { - - Database db = null; - try { - db = open(testDB); - assertEquals(testDB.getExpectedFileFormat(), db.getFileFormat()); - } finally { - if(db != null) { - db.close(); - } - } - } - } - -} diff --git a/test/src/java/com/healthmarketscience/jackcess/JoinerTest.java b/test/src/java/com/healthmarketscience/jackcess/JoinerTest.java deleted file mode 100644 index d2049c3..0000000 --- a/test/src/java/com/healthmarketscience/jackcess/JoinerTest.java +++ /dev/null @@ -1,206 +0,0 @@ -/* -Copyright (c) 2011 James Ahlborn - -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 -*/ - -package com.healthmarketscience.jackcess; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import static com.healthmarketscience.jackcess.DatabaseTest.*; -import static com.healthmarketscience.jackcess.JetFormatTest.*; -import junit.framework.TestCase; - -/** - * - * @author James Ahlborn - */ -public class JoinerTest extends TestCase { - - public JoinerTest(String name) { - super(name); - } - - public void testJoiner() throws Exception - { - for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.INDEX)) { - - Database db = openCopy(testDB); - Table t1 = db.getTable("Table1"); - Table t2 = db.getTable("Table2"); - Table t3 = db.getTable("Table3"); - - Index t1t2 = t1.getIndex("Table2Table1"); - Index t1t3 = t1.getIndex("Table3Table1"); - - Index t2t1 = t1t2.getReferencedIndex(); - assertSame(t2, t2t1.getTable()); - Joiner t2t1Join = Joiner.create(t2t1); - - assertSame(t2, t2t1Join.getFromTable()); - assertSame(t2t1, t2t1Join.getFromIndex()); - assertSame(t1, t2t1Join.getToTable()); - assertSame(t1t2, t2t1Join.getToIndex()); - - doTestJoiner(t2t1Join, createT2T1Data()); - - Index t3t1 = t1t3.getReferencedIndex(); - assertSame(t3, t3t1.getTable()); - Joiner t3t1Join = Joiner.create(t3t1); - - assertSame(t3, t3t1Join.getFromTable()); - assertSame(t3t1, t3t1Join.getFromIndex()); - assertSame(t1, t3t1Join.getToTable()); - assertSame(t1t3, t3t1Join.getToIndex()); - - doTestJoiner(t3t1Join, createT3T1Data()); - - doTestJoinerDelete(t2t1Join); - } - } - - private static void doTestJoiner( - Joiner join, Map>> expectedData) - throws Exception - { - final Set colNames = new HashSet( - Arrays.asList("id", "data")); - - Joiner revJoin = join.createReverse(); - for(Map row : join.getFromTable()) { - Integer id = (Integer)row.get("id"); - - List> joinedRows = - new ArrayList>(); - for(Map t1Row : join.findRowsIterable(row)) { - joinedRows.add(t1Row); - } - - List> expectedRows = expectedData.get(id); - assertEquals(expectedData.get(id), joinedRows); - - if(!expectedRows.isEmpty()) { - assertTrue(join.hasRows(row)); - assertEquals(expectedRows.get(0), join.findFirstRow(row)); - - assertEquals(row, revJoin.findFirstRow(expectedRows.get(0))); - } else { - assertFalse(join.hasRows(row)); - assertNull(join.findFirstRow(row)); - } - - List> expectedRows2 = new - ArrayList>(); - for(Map tmpRow : expectedRows) { - Map tmpRow2 = new HashMap(tmpRow); - tmpRow2.keySet().retainAll(colNames); - expectedRows2.add(tmpRow2); - } - - joinedRows = new ArrayList>(); - for(Map t1Row : join.findRowsIterable(row, colNames)) { - joinedRows.add(t1Row); - } - - assertEquals(expectedRows2, joinedRows); - - if(!expectedRows2.isEmpty()) { - assertEquals(expectedRows2.get(0), join.findFirstRow(row, colNames)); - } else { - assertNull(join.findFirstRow(row, colNames)); - } - } - } - - private static void doTestJoinerDelete(Joiner t2t1Join) throws Exception - { - assertEquals(4, countRows(t2t1Join.getToTable())); - - Map row = createExpectedRow("id", 1); - assertTrue(t2t1Join.hasRows(row)); - - assertTrue(t2t1Join.deleteRows(row)); - - assertFalse(t2t1Join.hasRows(row)); - assertFalse(t2t1Join.deleteRows(row)); - - assertEquals(2, countRows(t2t1Join.getToTable())); - for(Map t1Row : t2t1Join.getToTable()) { - assertFalse(t1Row.get("otherfk1").equals(1)); - } - } - - private static Map>> createT2T1Data() - { - Map>> data = new - HashMap>>(); - - data.put(0, - createExpectedTable( - createExpectedRow("id", 0, "otherfk1", 0, "otherfk2", 10, - "data", "baz0", "otherfk3", 0))); - - data.put(1, - createExpectedTable( - createExpectedRow("id", 1, "otherfk1", 1, "otherfk2", 11, - "data", "baz11", "otherfk3", 0), - createExpectedRow("id", 2, "otherfk1", 1, "otherfk2", 11, - "data", "baz11-2", "otherfk3", 0))); - - data.put(2, - createExpectedTable( - createExpectedRow("id", 3, "otherfk1", 2, "otherfk2", 13, - "data", "baz13", "otherfk3", 0))); - - return data; - } - - private static Map>> createT3T1Data() - { - Map>> data = new - HashMap>>(); - - data.put(10, - createExpectedTable( - createExpectedRow("id", 0, "otherfk1", 0, "otherfk2", 10, - "data", "baz0", "otherfk3", 0))); - - data.put(11, - createExpectedTable( - createExpectedRow("id", 1, "otherfk1", 1, "otherfk2", 11, - "data", "baz11", "otherfk3", 0), - createExpectedRow("id", 2, "otherfk1", 1, "otherfk2", 11, - "data", "baz11-2", "otherfk3", 0))); - - data.put(12, - createExpectedTable()); - - data.put(13, - createExpectedTable( - createExpectedRow("id", 3, "otherfk1", 2, "otherfk2", 13, - "data", "baz13", "otherfk3", 0))); - - return data; - } - -} diff --git a/test/src/java/com/healthmarketscience/jackcess/MemFileChannelTest.java b/test/src/java/com/healthmarketscience/jackcess/MemFileChannelTest.java deleted file mode 100644 index f84f0ab..0000000 --- a/test/src/java/com/healthmarketscience/jackcess/MemFileChannelTest.java +++ /dev/null @@ -1,162 +0,0 @@ -/* -Copyright (c) 2012 James Ahlborn - -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 -*/ - -package com.healthmarketscience.jackcess; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.nio.channels.NonWritableChannelException; -import java.util.Arrays; - -import junit.framework.TestCase; - -/** - * - * @author James Ahlborn - */ -public class MemFileChannelTest extends TestCase -{ - - public MemFileChannelTest(String name) { - super(name); - } - - public void testReadOnlyChannel() throws Exception - { - File testFile = new File("test/data/V1997/compIndexTestV1997.mdb"); - MemFileChannel ch = MemFileChannel.newChannel(testFile, "r"); - assertEquals(testFile.length(), ch.size()); - assertEquals(0L, ch.position()); - - try { - ByteBuffer bb = ByteBuffer.allocate(1024); - ch.write(bb); - fail("NonWritableChannelException should have been thrown"); - } catch(NonWritableChannelException ignored) { - // success - } - - try { - ch.truncate(0L); - fail("NonWritableChannelException should have been thrown"); - } catch(NonWritableChannelException ignored) { - // success - } - - try { - ch.transferFrom(null, 0L, 10L); - fail("NonWritableChannelException should have been thrown"); - } catch(NonWritableChannelException ignored) { - // success - } - - assertEquals(testFile.length(), ch.size()); - assertEquals(0L, ch.position()); - - ch.close(); - } - - public void testChannel() throws Exception - { - ByteBuffer bb = ByteBuffer.allocate(1024); - - MemFileChannel ch = MemFileChannel.newChannel(); - assertTrue(ch.isOpen()); - assertEquals(0L, ch.size()); - assertEquals(0L, ch.position()); - assertEquals(-1, ch.read(bb)); - - ch.close(); - - assertFalse(ch.isOpen()); - - File testFile = new File("test/data/V1997/compIndexTestV1997.mdb"); - ch = MemFileChannel.newChannel(testFile, "r"); - assertEquals(testFile.length(), ch.size()); - assertEquals(0L, ch.position()); - - try { - ch.position(-1); - fail("IllegalArgumentException should have been thrown"); - } catch(IllegalArgumentException ignored) { - // success - } - - MemFileChannel ch2 = MemFileChannel.newChannel(); - ch.transferTo(ch2); - ch2.force(true); - assertEquals(testFile.length(), ch2.size()); - assertEquals(testFile.length(), ch2.position()); - - try { - ch2.truncate(-1L); - fail("IllegalArgumentException should have been thrown"); - } catch(IllegalArgumentException ignored) { - // success - } - - long trucSize = ch2.size()/3; - ch2.truncate(trucSize); - assertEquals(trucSize, ch2.size()); - assertEquals(trucSize, ch2.position()); - ch2.position(0L); - copy(ch, ch2, bb); - - File tmpFile = File.createTempFile("chtest_", ".dat"); - tmpFile.deleteOnExit(); - FileOutputStream fc = new FileOutputStream(tmpFile); - - ch2.transferTo(fc); - - fc.close(); - - assertEquals(testFile.length(), tmpFile.length()); - - assertTrue(Arrays.equals(DatabaseTest.toByteArray(testFile), - DatabaseTest.toByteArray(tmpFile))); - - ch2.truncate(0L); - assertTrue(ch2.isOpen()); - assertEquals(0L, ch2.size()); - assertEquals(0L, ch2.position()); - assertEquals(-1, ch2.read(bb)); - - ch2.close(); - assertFalse(ch2.isOpen()); - } - - private static void copy(FileChannel src, FileChannel dst, ByteBuffer bb) - throws IOException - { - src.position(0L); - while(true) { - bb.clear(); - if(src.read(bb) < 0) { - break; - } - bb.flip(); - dst.write(bb); - } - } - -} diff --git a/test/src/java/com/healthmarketscience/jackcess/PropertiesTest.java b/test/src/java/com/healthmarketscience/jackcess/PropertiesTest.java index fccbc67..8cd5a55 100644 --- a/test/src/java/com/healthmarketscience/jackcess/PropertiesTest.java +++ b/test/src/java/com/healthmarketscience/jackcess/PropertiesTest.java @@ -26,10 +26,13 @@ import java.util.List; import java.util.Map; import junit.framework.TestCase; - +import com.healthmarketscience.jackcess.impl.PropertyMapImpl; +import com.healthmarketscience.jackcess.impl.PropertyMaps; import static com.healthmarketscience.jackcess.Database.*; import static com.healthmarketscience.jackcess.DatabaseTest.*; -import static com.healthmarketscience.jackcess.JetFormatTest.*; +import static com.healthmarketscience.jackcess.impl.JetFormatTest.*; +import com.healthmarketscience.jackcess.impl.TableImpl; +import com.healthmarketscience.jackcess.impl.DatabaseImpl; /** * @author James Ahlborn @@ -49,12 +52,12 @@ public class PropertiesTest extends TestCase assertFalse(maps.iterator().hasNext()); assertEquals(10, maps.getObjectId()); - PropertyMap defMap = maps.getDefault(); + PropertyMapImpl defMap = maps.getDefault(); assertTrue(defMap.isEmpty()); assertEquals(0, defMap.getSize()); assertFalse(defMap.iterator().hasNext()); - PropertyMap colMap = maps.get("testcol"); + PropertyMapImpl colMap = maps.get("testcol"); assertTrue(colMap.isEmpty()); assertEquals(0, colMap.getSize()); assertFalse(colMap.iterator().hasNext()); @@ -105,7 +108,7 @@ public class PropertiesTest extends TestCase for(TestDB testDb : SUPPORTED_DBS_TEST_FOR_READ) { Database db = open(testDb); - Table t = db.getTable("Table1"); + TableImpl t = (TableImpl)db.getTable("Table1"); assertEquals(t.getTableDefPageNumber(), t.getPropertyMaps().getObjectId()); PropertyMap tProps = t.getProperties(); @@ -186,10 +189,10 @@ public class PropertiesTest extends TestCase assertTrue(((String)dbProps.getValue(PropertyMap.ACCESS_VERSION_PROP)) .matches("[0-9]{2}[.][0-9]{2}")); - for(Map row : db.getSystemCatalog()) { + for(Map row : ((DatabaseImpl)db).getSystemCatalog()) { int id = (Integer)row.get("Id"); byte[] propBytes = (byte[])row.get("LvProp"); - PropertyMaps propMaps = db.getPropertiesForObject(id); + PropertyMaps propMaps = ((DatabaseImpl)db).getPropertiesForObject(id); int byteLen = ((propBytes != null) ? propBytes.length : 0); if(byteLen == 0) { assertTrue(propMaps.isEmpty()); diff --git a/test/src/java/com/healthmarketscience/jackcess/RelationshipTest.java b/test/src/java/com/healthmarketscience/jackcess/RelationshipTest.java index e49b9bb..e2162c3 100644 --- a/test/src/java/com/healthmarketscience/jackcess/RelationshipTest.java +++ b/test/src/java/com/healthmarketscience/jackcess/RelationshipTest.java @@ -34,7 +34,8 @@ import java.util.Comparator; import java.util.List; import static com.healthmarketscience.jackcess.DatabaseTest.*; -import static com.healthmarketscience.jackcess.JetFormatTest.*; +import static com.healthmarketscience.jackcess.impl.JetFormatTest.*; +import com.healthmarketscience.jackcess.impl.RelationshipImpl; import junit.framework.TestCase; /** @@ -47,7 +48,7 @@ public class RelationshipTest extends TestCase { return String.CASE_INSENSITIVE_ORDER.compare(r1.getName(), r2.getName()); } }; - + public RelationshipTest(String name) throws Exception { super(name); } @@ -70,7 +71,7 @@ public class RelationshipTest extends TestCase { assertEquals(Arrays.asList(t1.getColumn("otherfk1")), rel.getToColumns()); assertTrue(rel.hasReferentialIntegrity()); - assertEquals(4096, rel.getFlags()); + assertEquals(4096, ((RelationshipImpl)rel).getFlags()); assertTrue(rel.cascadeDeletes()); assertSameRelationships(rels, db.getRelationships(t2, t1), true); @@ -89,7 +90,7 @@ public class RelationshipTest extends TestCase { assertEquals(Arrays.asList(t1.getColumn("otherfk2")), rel.getToColumns()); assertTrue(rel.hasReferentialIntegrity()); - assertEquals(256, rel.getFlags()); + assertEquals(256, ((RelationshipImpl)rel).getFlags()); assertTrue(rel.cascadeUpdates()); assertSameRelationships(rels, db.getRelationships(t3, t1), true); diff --git a/test/src/java/com/healthmarketscience/jackcess/RowFilterTest.java b/test/src/java/com/healthmarketscience/jackcess/RowFilterTest.java deleted file mode 100644 index 586ad9a..0000000 --- a/test/src/java/com/healthmarketscience/jackcess/RowFilterTest.java +++ /dev/null @@ -1,112 +0,0 @@ -/* -Copyright (c) 2008 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.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import junit.framework.TestCase; - -import static com.healthmarketscience.jackcess.DatabaseTest.*; - -/** - * @author James Ahlborn - */ -public class RowFilterTest extends TestCase -{ - private static final String ID_COL = "id"; - private static final String COL1 = "col1"; - private static final String COL2 = "col2"; - private static final String COL3 = "col3"; - - - public RowFilterTest(String name) { - super(name); - } - - @SuppressWarnings("unchecked") - public void testFilter() throws Exception - { - Map row0 = createExpectedRow(ID_COL, 0, COL1, "foo", COL2, 13, COL3, "bar"); - Map row1 = createExpectedRow(ID_COL, 1, COL1, "bar", COL2, 42, COL3, null); - Map row2 = createExpectedRow(ID_COL, 2, COL1, "foo", COL2, 55, COL3, "bar"); - Map row3 = createExpectedRow(ID_COL, 3, COL1, "baz", COL2, 42, COL3, "bar"); - Map row4 = createExpectedRow(ID_COL, 4, COL1, "foo", COL2, 13, COL3, null); - Map row5 = createExpectedRow(ID_COL, 5, COL1, "bla", COL2, 13, COL3, "bar"); - - - List> rows = Arrays.asList(row0, row1, row2, row3, row4, row5); - - assertEquals(Arrays.asList(row0, row2, row4), - toList(RowFilter.matchPattern( - new ColumnBuilder(COL1, DataType.TEXT).toColumn(), - "foo").apply(rows))); - assertEquals(Arrays.asList(row1, row3, row5), - toList(RowFilter.invert( - RowFilter.matchPattern( - new ColumnBuilder(COL1, DataType.TEXT).toColumn(), - "foo")).apply(rows))); - - assertEquals(Arrays.asList(row0, row2, row4), - toList(RowFilter.matchPattern( - createExpectedRow(COL1, "foo")) - .apply(rows))); - assertEquals(Arrays.asList(row0, row2), - toList(RowFilter.matchPattern( - createExpectedRow(COL1, "foo", COL3, "bar")) - .apply(rows))); - assertEquals(Arrays.asList(row4), - toList(RowFilter.matchPattern( - createExpectedRow(COL1, "foo", COL3, null)) - .apply(rows))); - assertEquals(Arrays.asList(row0, row4, row5), - toList(RowFilter.matchPattern( - createExpectedRow(COL2, 13)) - .apply(rows))); - assertEquals(Arrays.asList(row1), - toList(RowFilter.matchPattern(row1) - .apply(rows))); - - assertEquals(rows, toList(RowFilter.apply(null, rows))); - assertEquals(Arrays.asList(row1), - toList(RowFilter.apply(RowFilter.matchPattern(row1), - rows))); - } - - static List> toList(Iterable> rows) - { - List> rowList = new ArrayList>(); - for(Map row : rows) { - rowList.add(row); - } - return rowList; - } - -} diff --git a/test/src/java/com/healthmarketscience/jackcess/TableTest.java b/test/src/java/com/healthmarketscience/jackcess/TableTest.java index 146d42d..b70c045 100644 --- a/test/src/java/com/healthmarketscience/jackcess/TableTest.java +++ b/test/src/java/com/healthmarketscience/jackcess/TableTest.java @@ -36,6 +36,10 @@ import java.util.Calendar; import java.util.List; import java.util.TimeZone; +import com.healthmarketscience.jackcess.impl.ColumnImpl; +import com.healthmarketscience.jackcess.impl.JetFormat; +import com.healthmarketscience.jackcess.impl.PageChannel; +import com.healthmarketscience.jackcess.impl.TableImpl; import junit.framework.TestCase; /** @@ -43,24 +47,29 @@ import junit.framework.TestCase; */ public class TableTest extends TestCase { - private final PageChannel _pageChannel = new PageChannel(true); - private List _columns = new ArrayList(); - private Table _testTable; + private final PageChannel _pageChannel = new PageChannel(true) {}; + private List _columns = new ArrayList(); + private TableImpl _testTable; + private int _varLenIdx; + private int _fixedOffset; + public TableTest(String name) { super(name); } + + private void reset() { + _testTable = null; + _columns = new ArrayList(); + _varLenIdx = 0; + _fixedOffset = 0; + } public void testCreateRow() throws Exception { - Column col = newTestColumn(); - col.setType(DataType.INT); - _columns.add(col); - col = newTestColumn(); - col.setType(DataType.TEXT); - _columns.add(col); - col = newTestColumn(); - col.setType(DataType.TEXT); - _columns.add(col); + reset(); + newTestColumn(DataType.INT, false); + newTestColumn(DataType.TEXT, false); + newTestColumn(DataType.TEXT, false); newTestTable(); int colCount = _columns.size(); @@ -77,13 +86,9 @@ public class TableTest extends TestCase { } public void testUnicodeCompression() throws Exception { - Column col = newTestColumn(); - col = newTestColumn(); - col.setType(DataType.TEXT); - _columns.add(col); - col = newTestColumn(); - col.setType(DataType.MEMO); - _columns.add(col); + reset(); + newTestColumn(DataType.TEXT, false); + newTestColumn(DataType.MEMO, false); newTestTable(); String small = "this is a string"; @@ -94,9 +99,10 @@ public class TableTest extends TestCase { ByteBuffer[] buf1 = encodeColumns(small, large); ByteBuffer[] buf2 = encodeColumns(smallNotAscii, largeNotAscii); - for(Column tmp : _columns) { - tmp.setCompressedUnicode(true); - } + reset(); + newTestColumn(DataType.TEXT, true); + newTestColumn(DataType.MEMO, true); + newTestTable(); ByteBuffer[] bufCmp1 = encodeColumns(small, large); ByteBuffer[] bufCmp2 = encodeColumns(smallNotAscii, largeNotAscii); @@ -129,7 +135,7 @@ public class TableTest extends TestCase { { ByteBuffer[] result = new ByteBuffer[_columns.size()]; for(int i = 0; i < _columns.size(); ++i) { - Column col = _columns.get(i); + ColumnImpl col = _columns.get(i); result[i] = col.write(row[i], _testTable.getFormat().MAX_ROW_SIZE); } return result; @@ -140,7 +146,7 @@ public class TableTest extends TestCase { { Object[] result = new Object[_columns.size()]; for(int i = 0; i < _columns.size(); ++i) { - Column col = _columns.get(i); + ColumnImpl col = _columns.get(i); result[i] = col.read(toBytes(buffers[i])); } return result; @@ -153,10 +159,10 @@ public class TableTest extends TestCase { return b; } - private Table newTestTable() + private TableImpl newTestTable() throws Exception { - _testTable = new Table(true, _columns) { + _testTable = new TableImpl(true, _columns) { @Override public PageChannel getPageChannel() { return _pageChannel; @@ -169,10 +175,22 @@ public class TableTest extends TestCase { return _testTable; } - private Column newTestColumn() { - return new Column(true, null) { + private void newTestColumn(DataType type, final boolean compressedUnicode) { + + int nextColIdx = _columns.size(); + int nextVarLenIdx = 0; + int nextFixedOff = 0; + + if(type.isVariableLength()) { + nextVarLenIdx = _varLenIdx++; + } else { + nextFixedOff = _fixedOffset; + _fixedOffset += type.getFixedSize(); + } + + ColumnImpl col = new ColumnImpl(null, type, nextColIdx, nextFixedOff, nextVarLenIdx) { @Override - public Table getTable() { + public TableImpl getTable() { return _testTable; } @Override @@ -184,14 +202,20 @@ public class TableTest extends TestCase { return getTable().getPageChannel(); } @Override - Charset getCharset() { + protected Charset getCharset() { return getFormat().CHARSET; } @Override - Calendar getCalendar() { + protected Calendar getCalendar() { return Calendar.getInstance(); } + @Override + public boolean isCompressedUnicode() { + return compressedUnicode; + } }; + + _columns.add(col); } } diff --git a/test/src/java/com/healthmarketscience/jackcess/UsageMapTest.java b/test/src/java/com/healthmarketscience/jackcess/UsageMapTest.java deleted file mode 100644 index 87fa5c3..0000000 --- a/test/src/java/com/healthmarketscience/jackcess/UsageMapTest.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.healthmarketscience.jackcess; - -import junit.framework.TestCase; - -import java.io.File; -import java.io.IOException; - -import static com.healthmarketscience.jackcess.JetFormatTest.*; - -/** - * @author Dan Rollo - * Date: Mar 5, 2010 - * Time: 2:21:22 PM - */ -public final class UsageMapTest extends TestCase { - - public void testRead() throws Exception { - for (final TestDB testDB : SUPPORTED_DBS_TEST) { - final int expectedFirstPage; - final int expectedLastPage; - final Database.FileFormat expectedFileFormat = testDB.getExpectedFileFormat(); - if (Database.FileFormat.V2000.equals(expectedFileFormat)) { - expectedFirstPage = 743; - expectedLastPage = 767; - } else if (Database.FileFormat.V2003.equals(expectedFileFormat)) { - expectedFirstPage = 16; - expectedLastPage = 799; - } else if (Database.FileFormat.V2007.equals(expectedFileFormat)) { - expectedFirstPage = 94; - expectedLastPage = 511; - } else if (Database.FileFormat.V2010.equals(expectedFileFormat)) { - expectedFirstPage = 109; - expectedLastPage = 511; - } else { - throw new IllegalAccessException("Unknown file format: " + expectedFileFormat); - } - checkUsageMapRead(testDB.getFile(), expectedFirstPage, expectedLastPage); - } - } - - private static void checkUsageMapRead(final File dbFile, - final int expectedFirstPage, final int expectedLastPage) - throws IOException { - - final Database db = Database.open(dbFile); - final UsageMap usageMap = UsageMap.read(db, - PageChannel.PAGE_GLOBAL_USAGE_MAP, - PageChannel.ROW_GLOBAL_USAGE_MAP, - true); - assertEquals("Unexpected FirstPageNumber.", expectedFirstPage, usageMap.getFirstPageNumber()); - assertEquals("Unexpected LastPageNumber.", expectedLastPage, usageMap.getLastPageNumber()); - } -} diff --git a/test/src/java/com/healthmarketscience/jackcess/impl/CodecHandlerTest.java b/test/src/java/com/healthmarketscience/jackcess/impl/CodecHandlerTest.java new file mode 100644 index 0000000..47a832a --- /dev/null +++ b/test/src/java/com/healthmarketscience/jackcess/impl/CodecHandlerTest.java @@ -0,0 +1,304 @@ +/* +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.impl; + +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 com.healthmarketscience.jackcess.ColumnBuilder; +import com.healthmarketscience.jackcess.Cursor; +import com.healthmarketscience.jackcess.CursorBuilder; +import com.healthmarketscience.jackcess.DataType; +import com.healthmarketscience.jackcess.Database; +import com.healthmarketscience.jackcess.DatabaseBuilder; +import com.healthmarketscience.jackcess.DatabaseTest; +import com.healthmarketscience.jackcess.DatabaseTest; +import com.healthmarketscience.jackcess.IndexBuilder; +import com.healthmarketscience.jackcess.Table; +import com.healthmarketscience.jackcess.TableBuilder; +import static com.healthmarketscience.jackcess.impl.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 = ((DatabaseImpl)db).getFormat().PAGE_SIZE; + File dbFile = db.getFile(); + db.close(); + + // apply encoding to file + encodeFile(dbFile, pageSize, simple); + + db = new DatabaseBuilder(dbFile) + .setCodecProvider(simple ? SIMPLE_PROVIDER : FULL_PROVIDER) + .open(); + + 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 = t1.newCursor().setIndex(t1.getPrimaryKeyIndex()) + .toCursor(); + Cursor c2 = t2.newCursor().setIndex(t2.getPrimaryKeyIndex()) + .toCursor(); + + Iterator> i1 = c1.iterator(); + Iterator> i2 = c2.newIterable().reverse().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 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 boolean canDecodeInline() { + return true; + } + + public void decodePage(ByteBuffer inPage, ByteBuffer outPage, + int pageNumber) + throws IOException + { + byte[] arr = inPage.array(); + simpleDecode(arr, arr, pageNumber); + } + + public ByteBuffer encodePage(ByteBuffer page, int pageNumber, + int pageOffset) + throws IOException + { + ByteBuffer bb = _bufH.getPageBuffer(_channel); + bb.clear(); + 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 boolean canDecodeInline() { + return true; + } + + public void decodePage(ByteBuffer inPage, ByteBuffer outPage, + int pageNumber) + throws IOException + { + byte[] arr = inPage.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); + bb.clear(); + fullEncode(page.array(), bb.array(), pageNumber); + return bb; + } + } + +} diff --git a/test/src/java/com/healthmarketscience/jackcess/impl/FKEnforcerTest.java b/test/src/java/com/healthmarketscience/jackcess/impl/FKEnforcerTest.java new file mode 100644 index 0000000..7ea3123 --- /dev/null +++ b/test/src/java/com/healthmarketscience/jackcess/impl/FKEnforcerTest.java @@ -0,0 +1,144 @@ +/* +Copyright (c) 2012 James Ahlborn + +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 +*/ + +package com.healthmarketscience.jackcess.impl; + +import java.io.IOException; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import com.healthmarketscience.jackcess.Column; +import com.healthmarketscience.jackcess.Cursor; +import com.healthmarketscience.jackcess.CursorBuilder; +import com.healthmarketscience.jackcess.Database; +import static com.healthmarketscience.jackcess.DatabaseTest.*; +import com.healthmarketscience.jackcess.Row; +import com.healthmarketscience.jackcess.Table; +import static com.healthmarketscience.jackcess.impl.JetFormatTest.*; +import junit.framework.TestCase; + +/** + * + * @author James Ahlborn + */ +public class FKEnforcerTest extends TestCase +{ + + public FKEnforcerTest(String name) throws Exception { + super(name); + } + + public void testNoEnforceForeignKeys() throws Exception { + for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.INDEX)) { + + Database db = openCopy(testDB); + db.setEnforceForeignKeys(false); + Table t1 = db.getTable("Table1"); + Table t2 = db.getTable("Table2"); + Table t3 = db.getTable("Table3"); + + t1.addRow(20, 0, 20, "some data", 20); + + Cursor c = CursorBuilder.createCursor(t2); + c.moveToNextRow(); + c.updateCurrentRow(30, "foo30"); + + c = CursorBuilder.createCursor(t3); + c.moveToNextRow(); + c.deleteCurrentRow(); + + db.close(); + } + + } + + public void testEnforceForeignKeys() throws Exception { + for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.INDEX)) { + + Database db = openCopy(testDB); + Table t1 = db.getTable("Table1"); + Table t2 = db.getTable("Table2"); + Table t3 = db.getTable("Table3"); + + try { + t1.addRow(20, 0, 20, "some data", 20); + fail("IOException should have been thrown"); + } catch(IOException ignored) { + // success + assertTrue(ignored.getMessage().contains("Table1[otherfk2]")); + } + + try { + Cursor c = CursorBuilder.createCursor(t2); + c.moveToNextRow(); + c.updateCurrentRow(30, "foo30"); + fail("IOException should have been thrown"); + } catch(IOException ignored) { + // success + assertTrue(ignored.getMessage().contains("Table2[id]")); + } + + try { + Cursor c = CursorBuilder.createCursor(t3); + c.moveToNextRow(); + c.deleteCurrentRow(); + fail("IOException should have been thrown"); + } catch(IOException ignored) { + // success + assertTrue(ignored.getMessage().contains("Table3[id]")); + } + + Cursor c = CursorBuilder.createCursor(t3); + Column col = t3.getColumn("id"); + for(Map row : c) { + int id = (Integer)row.get("id"); + id += 20; + c.setCurrentRowValue(col, id); + } + + List> expectedRows = + createExpectedTable( + createT1Row(0, 0, 30, "baz0", 0), + createT1Row(1, 1, 31, "baz11", 0), + createT1Row(2, 1, 31, "baz11-2", 0), + createT1Row(3, 2, 33, "baz13", 0)); + + assertTable(expectedRows, t1); + + c = CursorBuilder.createCursor(t2); + for(Iterator iter = c.iterator(); iter.hasNext(); ) { + iter.next(); + iter.remove(); + } + + assertEquals(0, t1.getRowCount()); + + db.close(); + } + + } + + private static Row createT1Row( + int id1, int fk1, int fk2, String data, int fk3) + { + return createExpectedRow("id", id1, "otherfk1", fk1, "otherfk2", fk2, + "data", data, "otherfk3", fk3); + } +} diff --git a/test/src/java/com/healthmarketscience/jackcess/impl/IndexCodesTest.java b/test/src/java/com/healthmarketscience/jackcess/impl/IndexCodesTest.java new file mode 100644 index 0000000..56f9096 --- /dev/null +++ b/test/src/java/com/healthmarketscience/jackcess/impl/IndexCodesTest.java @@ -0,0 +1,798 @@ +/* +Copyright (c) 2008 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.impl; + +import java.io.File; +import java.lang.reflect.Field; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.healthmarketscience.jackcess.ColumnBuilder; +import com.healthmarketscience.jackcess.Cursor; +import com.healthmarketscience.jackcess.CursorBuilder; +import com.healthmarketscience.jackcess.DataType; +import com.healthmarketscience.jackcess.Database; +import static com.healthmarketscience.jackcess.DatabaseTest.*; +import com.healthmarketscience.jackcess.Index; +import com.healthmarketscience.jackcess.Table; +import com.healthmarketscience.jackcess.TableBuilder; +import static com.healthmarketscience.jackcess.impl.JetFormatTest.*; +import junit.framework.TestCase; + +/** + * @author James Ahlborn + */ +public class IndexCodesTest extends TestCase { + + private static final Map SPECIAL_CHARS = + new HashMap(); + static { + SPECIAL_CHARS.put('\b', "\\b"); + SPECIAL_CHARS.put('\t', "\\t"); + SPECIAL_CHARS.put('\n', "\\n"); + SPECIAL_CHARS.put('\f', "\\f"); + SPECIAL_CHARS.put('\r', "\\r"); + SPECIAL_CHARS.put('\"', "\\\""); + SPECIAL_CHARS.put('\'', "\\'"); + SPECIAL_CHARS.put('\\', "\\\\"); + } + + public IndexCodesTest(String name) throws Exception { + super(name); + } + + public void testIndexCodes() throws Exception + { + for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.INDEX_CODES)) { + Database db = openMem(testDB); + + for(Table t : db) { + for(Index index : t.getIndexes()) { + // System.out.println("Checking " + t.getName() + "." + index.getName()); + checkIndexEntries(testDB, t, index); + } + } + + db.close(); + } + } + + private static void checkIndexEntries(final TestDB testDB, Table t, Index index) throws Exception + { +// index.initialize(); +// System.out.println("Ind " + index); + + Cursor cursor = CursorBuilder.createCursor(t, index); + while(cursor.moveToNextRow()) { + + Map row = cursor.getCurrentRow(); + Cursor.Position curPos = cursor.getSavepoint().getCurrentPosition(); + boolean success = false; + try { + findRow(testDB, t, index, row, curPos); + success = true; + } finally { + if(!success) { + System.out.println("CurPos: " + curPos); + System.out.println("Value: " + row + ": " + + toUnicodeStr(row.get("data"))); + } + } + } + + } + + private static void findRow(final TestDB testDB, Table t, Index index, + Map expectedRow, + Cursor.Position expectedPos) + throws Exception + { + Object[] idxRow = ((IndexImpl)index).constructIndexRow(expectedRow); + Cursor cursor = CursorBuilder.createCursor(t, index, idxRow, idxRow); + + Cursor.Position startPos = cursor.getSavepoint().getCurrentPosition(); + + cursor.beforeFirst(); + while(cursor.moveToNextRow()) { + Map row = cursor.getCurrentRow(); + if(expectedRow.equals(row)) { + // verify that the entries are indeed equal + Cursor.Position curPos = cursor.getSavepoint().getCurrentPosition(); + assertEquals(entryToString(expectedPos), entryToString(curPos)); + return; + } + } + + // TODO long rows not handled completely yet in V2010 + // seems to truncate entry at 508 bytes with some trailing 2 byte seq + if(testDB.getExpectedFileFormat() == Database.FileFormat.V2010) { + String rowId = (String)expectedRow.get("name"); + String tName = t.getName(); + if(("Table11".equals(tName) || "Table11_desc".equals(tName)) && + ("row10".equals(rowId) || "row11".equals(rowId) || + "row12".equals(rowId))) { + System.out.println( + "TODO long rows not handled completely yet in V2010: " + tName + + ", " + rowId); + return; + } + } + + fail("testDB: " + testDB + ";\nCould not find expected row " + expectedRow + " starting at " + + entryToString(startPos)); + } + + + ////// + // + // The code below is for use in reverse engineering index entries. + // + ////// + + public void testNothing() throws Exception { + // keep this so build doesn't fail if other tests are disabled + } + + public void x_testCreateIsoFile() throws Exception + { + Database db = create(Database.FileFormat.V2000, true); + + Table t = new TableBuilder("test") + .addColumn(new ColumnBuilder("row", DataType.TEXT)) + .addColumn(new ColumnBuilder("data", DataType.TEXT)) + .toTable(db); + + for(int i = 0; i < 256; ++i) { + String str = "AA" + ((char)i) + "AA"; + t.addRow("row" + i, str); + } + + db.close(); + } + + public void x_testCreateAltIsoFile() throws Exception + { + Database db = openCopy(Database.FileFormat.V2000, new File("/tmp/test_ind.mdb"), true); + + Table t = db.getTable("Table1"); + + for(int i = 0; i < 256; ++i) { + String str = "AA" + ((char)i) + "AA"; + t.addRow("row" + i, str, + (byte)42 + i, (short)53 + i, 13 * i, + (6.7d / i), null, null, true); + } + + db.close(); + } + + public void x_testWriteAllCodesMdb() throws Exception + { + Database db = create(Database.FileFormat.V2000, true); + +// Table t = new TableBuilder("Table1") +// .addColumn(new ColumnBuilder("key", DataType.TEXT)) +// .addColumn(new ColumnBuilder("data", DataType.TEXT)) +// .toTable(db); + +// for(int i = 0; i <= 0xFFFF; ++i) { +// // skip non-char chars +// char c = (char)i; +// if(Character.isHighSurrogate(c) || Character.isLowSurrogate(c)) { +// continue; +// } +// String key = toUnicodeStr(c); +// String str = "AA" + c + "AA"; +// t.addRow(key, str); +// } + + Table t = new TableBuilder("Table5") + .addColumn(new ColumnBuilder("name", DataType.TEXT)) + .addColumn(new ColumnBuilder("data", DataType.TEXT)) + .toTable(db); + + char c = (char)0x3041; // crazy 7F 02 ... A0 + char c2 = (char)0x30A2; // crazy 7F 02 ... + char c3 = (char)0x2045; // inat 27 ... 1C + char c4 = (char)0x3043; // crazy 7F 03 ... A0 + char c5 = (char)0x3046; // crazy 7F 04 ... + char c6 = (char)0x30F6; // crazy 7F 0D ... A0 + char c7 = (char)0x3099; // unprint 03 + char c8 = (char)0x0041; // A + char c9 = (char)0x002D; // - (unprint) + char c10 = (char)0x20E1; // unprint F2 + char c11 = (char)0x309A; // unprint 04 + char c12 = (char)0x01C4; // (long extra) + char c13 = (char)0x005F; // _ (long inline) + char c14 = (char)0xFFFE; // removed + + char[] cs = new char[]{c7, c8, c3, c12, c13, c14, c, c2, c9}; + addCombos(t, 0, "", cs, 5); + +// t = new TableBuilder("Table2") +// .addColumn(new ColumnBuilder("data", DataType.TEXT)) +// .toTable(db); + +// writeChars(0x0000, t); + +// t = new TableBuilder("Table3") +// .addColumn(new ColumnBuilder("data", DataType.TEXT)) +// .toTable(db); + +// writeChars(0x0400, t); + + + db.close(); + } + + public void x_testReadAllCodesMdb() throws Exception + { +// Database db = openCopy(new File("/data2/jackcess_test/testAllIndexCodes.mdb")); +// Database db = openCopy(new File("/data2/jackcess_test/testAllIndexCodes_orig.mdb")); +// Database db = openCopy(new File("/data2/jackcess_test/testSomeMoreCodes.mdb")); + Database db = openCopy(Database.FileFormat.V2000, new File("/data2/jackcess_test/testStillMoreCodes.mdb")); + Table t = db.getTable("Table5"); + + Index ind = t.getIndexes().iterator().next(); + ((IndexImpl)ind).initialize(); + + System.out.println("Ind " + ind); + + Cursor cursor = CursorBuilder.createCursor(t, ind); + while(cursor.moveToNextRow()) { + System.out.println("======="); + String entryStr = + entryToString(cursor.getSavepoint().getCurrentPosition()); + System.out.println("Entry Bytes: " + entryStr); + System.out.println("Value: " + cursor.getCurrentRow() + "; " + + toUnicodeStr(cursor.getCurrentRow().get("data"))); + } + + db.close(); + } + + private int addCombos(Table t, int rowNum, String s, char[] cs, int len) + throws Exception + { + if(s.length() >= len) { + return rowNum; + } + + for(int i = 0; i < cs.length; ++i) { + String name = "row" + (rowNum++); + String ss = s + cs[i]; + t.addRow(name, ss); + rowNum = addCombos(t, rowNum, ss, cs, len); + } + + return rowNum; + } + + private void writeChars(int hibyte, Table t) throws Exception + { + char other = (char)(hibyte | 0x41); + for(int i = 0; i < 0xFF; ++i) { + char c = (char)(hibyte | i); + String str = "" + other + c + other; + t.addRow(str); + } + } + + public void x_testReadIsoMdb() throws Exception + { +// Database db = open(new File("/tmp/test_ind.mdb")); +// Database db = open(new File("/tmp/test_ind2.mdb")); + Database db = open(Database.FileFormat.V2000, new File("/tmp/test_ind3.mdb")); +// Database db = open(new File("/tmp/test_ind4.mdb")); + + Table t = db.getTable("Table1"); + Index index = t.getIndex("B"); + ((IndexImpl)index).initialize(); + System.out.println("Ind " + index); + + Cursor cursor = CursorBuilder.createCursor(t, index); + while(cursor.moveToNextRow()) { + System.out.println("======="); + System.out.println("Savepoint: " + cursor.getSavepoint()); + System.out.println("Value: " + cursor.getCurrentRow()); + } + + db.close(); + } + + public void x_testReverseIsoMdb2010() throws Exception + { + Database db = open(Database.FileFormat.V2010, new File("/data2/jackcess_test/testAllIndexCodes3_2010.accdb")); + + Table t = db.getTable("Table1"); + Index index = t.getIndexes().iterator().next(); + ((IndexImpl)index).initialize(); + System.out.println("Ind " + index); + + Pattern inlinePat = Pattern.compile("7F 0E 02 0E 02 (.*)0E 02 0E 02 01 00"); + Pattern unprintPat = Pattern.compile("01 01 01 80 (.+) 06 (.+) 00"); + Pattern unprint2Pat = Pattern.compile("0E 02 0E 02 0E 02 0E 02 01 02 (.+) 00"); + Pattern inatPat = Pattern.compile("7F 0E 02 0E 02 (.*)0E 02 0E 02 01 02 02 (.+) 00"); + Pattern inat2Pat = Pattern.compile("7F 0E 02 0E 02 (.*)0E 02 0E 02 01 (02 02 (.+))?01 01 (.*)FF 02 80 FF 80 00"); + + Map inlineCodes = new TreeMap(); + Map unprintCodes = new TreeMap(); + Map unprint2Codes = new TreeMap(); + Map inatInlineCodes = new TreeMap(); + Map inatExtraCodes = new TreeMap(); + Map inat2Codes = new TreeMap(); + Map inat2ExtraCodes = new TreeMap(); + Map inat2CrazyCodes = new TreeMap(); + + + Cursor cursor = CursorBuilder.createCursor(t, index); + while(cursor.moveToNextRow()) { +// System.out.println("======="); +// System.out.println("Savepoint: " + cursor.getSavepoint()); +// System.out.println("Value: " + cursor.getCurrentRow()); + Cursor.Savepoint savepoint = cursor.getSavepoint(); + String entryStr = entryToString(savepoint.getCurrentPosition()); + + Map row = cursor.getCurrentRow(); + String value = (String)row.get("data"); + String key = (String)row.get("key"); + char c = value.charAt(2); + + System.out.println("======="); + System.out.println("RowId: " + + savepoint.getCurrentPosition().getRowId()); + System.out.println("Entry: " + entryStr); +// System.out.println("Row: " + row); + System.out.println("Value: (" + key + ")" + value); + System.out.println("Char: " + c + ", " + (int)c + ", " + + toUnicodeStr(c)); + + String type = null; + if(entryStr.endsWith("01 00")) { + + // handle inline codes + type = "INLINE"; + Matcher m = inlinePat.matcher(entryStr); + m.find(); + handleInlineEntry(m.group(1), c, inlineCodes); + + } else if(entryStr.contains("01 01 01 80")) { + + // handle most unprintable codes + type = "UNPRINTABLE"; + Matcher m = unprintPat.matcher(entryStr); + m.find(); + handleUnprintableEntry(m.group(2), c, unprintCodes); + + } else if(entryStr.contains("01 02 02") && + !entryStr.contains("FF 02 80 FF 80")) { + + // handle chars w/ symbols + type = "CHAR_WITH_SYMBOL"; + Matcher m = inatPat.matcher(entryStr); + m.find(); + handleInternationalEntry(m.group(1), m.group(2), c, + inatInlineCodes, inatExtraCodes); + + } else if(entryStr.contains("0E 02 0E 02 0E 02 0E 02 01 02")) { + + // handle chars w/ symbols + type = "UNPRINTABLE_2"; + Matcher m = unprint2Pat.matcher(entryStr); + m.find(); + handleUnprintable2Entry(m.group(1), c, unprint2Codes); + + } else if(entryStr.contains("FF 02 80 FF 80")) { + + type = "CRAZY_INAT"; + Matcher m = inat2Pat.matcher(entryStr); + m.find(); + handleInternational2Entry(m.group(1), m.group(3), m.group(4), c, + inat2Codes, inat2ExtraCodes, + inat2CrazyCodes); + + } else { + + // throw new RuntimeException("unhandled " + entryStr); + System.out.println("unhandled " + entryStr); + } + + System.out.println("Type: " + type); + } + + System.out.println("\n***CODES"); + for(int i = 0; i <= 0xFFFF; ++i) { + + if(i == 256) { + System.out.println("\n***EXTENDED CODES"); + } + + // skip non-char chars + char c = (char)i; + if(Character.isHighSurrogate(c) || Character.isLowSurrogate(c)) { + continue; + } + + if(c == (char)0xFFFE) { + // this gets replaced with FFFD, treat it the same + c = (char)0xFFFD; + } + + Character cc = c; + String[] chars = inlineCodes.get(cc); + if(chars != null) { + if((chars.length == 1) && (chars[0].length() == 0)) { + System.out.println("X"); + } else { + System.out.println("S" + toByteString(chars)); + } + continue; + } + + chars = inatInlineCodes.get(cc); + if(chars != null) { + String[] extra = inatExtraCodes.get(cc); + System.out.println("I" + toByteString(chars) + "," + + toByteString(extra)); + continue; + } + + chars = unprintCodes.get(cc); + if(chars != null) { + System.out.println("U" + toByteString(chars)); + continue; + } + + chars = unprint2Codes.get(cc); + if(chars != null) { + if(chars.length > 1) { + throw new RuntimeException("long unprint codes"); + } + int val = Integer.parseInt(chars[0], 16) - 2; + String valStr = ByteUtil.toHexString(new byte[]{(byte)val}).trim(); + System.out.println("P" + valStr); + continue; + } + + chars = inat2Codes.get(cc); + if(chars != null) { + String [] crazyCodes = inat2CrazyCodes.get(cc); + String crazyCode = ""; + if(crazyCodes != null) { + if((crazyCodes.length != 1) || !"A0".equals(crazyCodes[0])) { + throw new RuntimeException("CC " + Arrays.asList(crazyCodes)); + } + crazyCode = "1"; + } + + String[] extra = inat2ExtraCodes.get(cc); + System.out.println("Z" + toByteString(chars) + "," + + toByteString(extra) + "," + + crazyCode); + continue; + } + + throw new RuntimeException("Unhandled char " + toUnicodeStr(c)); + } + System.out.println("\n***END CODES"); + + db.close(); + } + + public void x_testReverseIsoMdb() throws Exception + { + Database db = open(Database.FileFormat.V2000, new File("/data2/jackcess_test/testAllIndexCodes3.mdb")); + + Table t = db.getTable("Table1"); + Index index = t.getIndexes().iterator().next(); + ((IndexImpl)index).initialize(); + System.out.println("Ind " + index); + + Pattern inlinePat = Pattern.compile("7F 4A 4A (.*)4A 4A 01 00"); + Pattern unprintPat = Pattern.compile("01 01 01 80 (.+) 06 (.+) 00"); + Pattern unprint2Pat = Pattern.compile("4A 4A 4A 4A 01 02 (.+) 00"); + Pattern inatPat = Pattern.compile("7F 4A 4A (.*)4A 4A 01 02 02 (.+) 00"); + Pattern inat2Pat = Pattern.compile("7F 4A 4A (.*)4A 4A 01 (02 02 (.+))?01 01 (.*)FF 02 80 FF 80 00"); + + Map inlineCodes = new TreeMap(); + Map unprintCodes = new TreeMap(); + Map unprint2Codes = new TreeMap(); + Map inatInlineCodes = new TreeMap(); + Map inatExtraCodes = new TreeMap(); + Map inat2Codes = new TreeMap(); + Map inat2ExtraCodes = new TreeMap(); + Map inat2CrazyCodes = new TreeMap(); + + + Cursor cursor = CursorBuilder.createCursor(t, index); + while(cursor.moveToNextRow()) { +// System.out.println("======="); +// System.out.println("Savepoint: " + cursor.getSavepoint()); +// System.out.println("Value: " + cursor.getCurrentRow()); + Cursor.Savepoint savepoint = cursor.getSavepoint(); + String entryStr = entryToString(savepoint.getCurrentPosition()); + + Map row = cursor.getCurrentRow(); + String value = (String)row.get("data"); + String key = (String)row.get("key"); + char c = value.charAt(2); + System.out.println("======="); + System.out.println("RowId: " + + savepoint.getCurrentPosition().getRowId()); + System.out.println("Entry: " + entryStr); +// System.out.println("Row: " + row); + System.out.println("Value: (" + key + ")" + value); + System.out.println("Char: " + c + ", " + (int)c + ", " + + toUnicodeStr(c)); + + String type = null; + if(entryStr.endsWith("01 00")) { + + // handle inline codes + type = "INLINE"; + Matcher m = inlinePat.matcher(entryStr); + m.find(); + handleInlineEntry(m.group(1), c, inlineCodes); + + } else if(entryStr.contains("01 01 01 80")) { + + // handle most unprintable codes + type = "UNPRINTABLE"; + Matcher m = unprintPat.matcher(entryStr); + m.find(); + handleUnprintableEntry(m.group(2), c, unprintCodes); + + } else if(entryStr.contains("01 02 02") && + !entryStr.contains("FF 02 80 FF 80")) { + + // handle chars w/ symbols + type = "CHAR_WITH_SYMBOL"; + Matcher m = inatPat.matcher(entryStr); + m.find(); + handleInternationalEntry(m.group(1), m.group(2), c, + inatInlineCodes, inatExtraCodes); + + } else if(entryStr.contains("4A 4A 4A 4A 01 02")) { + + // handle chars w/ symbols + type = "UNPRINTABLE_2"; + Matcher m = unprint2Pat.matcher(entryStr); + m.find(); + handleUnprintable2Entry(m.group(1), c, unprint2Codes); + + } else if(entryStr.contains("FF 02 80 FF 80")) { + + type = "CRAZY_INAT"; + Matcher m = inat2Pat.matcher(entryStr); + m.find(); + handleInternational2Entry(m.group(1), m.group(3), m.group(4), c, + inat2Codes, inat2ExtraCodes, + inat2CrazyCodes); + + } else { + + throw new RuntimeException("unhandled " + entryStr); + } + + System.out.println("Type: " + type); + } + + System.out.println("\n***CODES"); + for(int i = 0; i <= 0xFFFF; ++i) { + + if(i == 256) { + System.out.println("\n***EXTENDED CODES"); + } + + // skip non-char chars + char c = (char)i; + if(Character.isHighSurrogate(c) || Character.isLowSurrogate(c)) { + continue; + } + + if(c == (char)0xFFFE) { + // this gets replaced with FFFD, treat it the same + c = (char)0xFFFD; + } + + Character cc = c; + String[] chars = inlineCodes.get(cc); + if(chars != null) { + if((chars.length == 1) && (chars[0].length() == 0)) { + System.out.println("X"); + } else { + System.out.println("S" + toByteString(chars)); + } + continue; + } + + chars = inatInlineCodes.get(cc); + if(chars != null) { + String[] extra = inatExtraCodes.get(cc); + System.out.println("I" + toByteString(chars) + "," + + toByteString(extra)); + continue; + } + + chars = unprintCodes.get(cc); + if(chars != null) { + System.out.println("U" + toByteString(chars)); + continue; + } + + chars = unprint2Codes.get(cc); + if(chars != null) { + if(chars.length > 1) { + throw new RuntimeException("long unprint codes"); + } + int val = Integer.parseInt(chars[0], 16) - 2; + String valStr = ByteUtil.toHexString(new byte[]{(byte)val}).trim(); + System.out.println("P" + valStr); + continue; + } + + chars = inat2Codes.get(cc); + if(chars != null) { + String [] crazyCodes = inat2CrazyCodes.get(cc); + String crazyCode = ""; + if(crazyCodes != null) { + if((crazyCodes.length != 1) || !"A0".equals(crazyCodes[0])) { + throw new RuntimeException("CC " + Arrays.asList(crazyCodes)); + } + crazyCode = "1"; + } + + String[] extra = inat2ExtraCodes.get(cc); + System.out.println("Z" + toByteString(chars) + "," + + toByteString(extra) + "," + + crazyCode); + continue; + } + + throw new RuntimeException("Unhandled char " + toUnicodeStr(c)); + } + System.out.println("\n***END CODES"); + + db.close(); + } + + private static String toByteString(String[] chars) + { + String str = join(chars, "", ""); + if(str.length() > 0 && str.charAt(0) == '0') { + str = str.substring(1); + } + return str; + } + + private static void handleInlineEntry( + String entryCodes, char c, Map inlineCodes) + throws Exception + { + inlineCodes.put(c, entryCodes.trim().split(" ")); + } + + private static void handleUnprintableEntry( + String entryCodes, char c, Map unprintCodes) + throws Exception + { + unprintCodes.put(c, entryCodes.trim().split(" ")); + } + + private static void handleUnprintable2Entry( + String entryCodes, char c, Map unprintCodes) + throws Exception + { + unprintCodes.put(c, entryCodes.trim().split(" ")); + } + + private static void handleInternationalEntry( + String inlineCodes, String entryCodes, char c, + Map inatInlineCodes, + Map inatExtraCodes) + throws Exception + { + inatInlineCodes.put(c, inlineCodes.trim().split(" ")); + inatExtraCodes.put(c, entryCodes.trim().split(" ")); + } + + private static void handleInternational2Entry( + String inlineCodes, String entryCodes, String crazyCodes, char c, + Map inatInlineCodes, + Map inatExtraCodes, + Map inatCrazyCodes) + throws Exception + { + inatInlineCodes.put(c, inlineCodes.trim().split(" ")); + if(entryCodes != null) { + inatExtraCodes.put(c, entryCodes.trim().split(" ")); + } + if((crazyCodes != null) && (crazyCodes.length() > 0)) { + inatCrazyCodes.put(c, crazyCodes.trim().split(" ")); + } + } + + private static String toUnicodeStr(Object obj) throws Exception { + StringBuilder sb = new StringBuilder(); + for(char c : obj.toString().toCharArray()) { + sb.append(toUnicodeStr(c)).append(" "); + } + return sb.toString(); + } + + private static String toUnicodeStr(char c) throws Exception { + String specialStr = SPECIAL_CHARS.get(c); + if(specialStr != null) { + return specialStr; + } + + String digits = Integer.toHexString(c).toUpperCase(); + while(digits.length() < 4) { + digits = "0" + digits; + } + return "\\u" + digits; + } + + private static String join(String[] strs, String joinStr, String prefixStr) { + if(strs == null) { + return ""; + } + StringBuilder builder = new StringBuilder(); + for(int i = 0; i < strs.length; ++i) { + if(strs[i].length() == 0) { + continue; + } + builder.append(prefixStr).append(strs[i]); + if(i < (strs.length - 1)) { + builder.append(joinStr); + } + } + return builder.toString(); + } + + public static String entryToString(Cursor.Position curPos) + throws Exception + { + Field eField = curPos.getClass().getDeclaredField("_entry"); + eField.setAccessible(true); + IndexData.Entry entry = (IndexData.Entry)eField.get(curPos); + Field ebField = entry.getClass().getDeclaredField("_entryBytes"); + ebField.setAccessible(true); + byte[] entryBytes = (byte[])ebField.get(entry); + + return ByteUtil.toHexString(ByteBuffer.wrap(entryBytes), + entryBytes.length) + .trim().replaceAll("\\p{Space}+", " "); + } + +} diff --git a/test/src/java/com/healthmarketscience/jackcess/impl/JetFormatTest.java b/test/src/java/com/healthmarketscience/jackcess/impl/JetFormatTest.java new file mode 100644 index 0000000..962a6f0 --- /dev/null +++ b/test/src/java/com/healthmarketscience/jackcess/impl/JetFormatTest.java @@ -0,0 +1,243 @@ +package com.healthmarketscience.jackcess.impl; + +import java.io.File; +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; +import java.util.Set; + +import com.healthmarketscience.jackcess.Database; +import static com.healthmarketscience.jackcess.Database.*; +import com.healthmarketscience.jackcess.DatabaseBuilder; +import static com.healthmarketscience.jackcess.DatabaseTest.*; +import junit.framework.TestCase; + + +/** + * @author Dan Rollo + * Date: Mar 5, 2010 + * Time: 12:44:21 PM + */ +public class JetFormatTest extends TestCase { + + public static final File DIR_TEST_DATA = new File("test/data"); + + /** + * Defines known valid db test file base names. + */ + public static enum Basename { + + BIG_INDEX("bigIndexTest"), + COMP_INDEX("compIndexTest"), + DEL_COL("delColTest"), + DEL("delTest"), + FIXED_NUMERIC("fixedNumericTest"), + FIXED_TEXT("fixedTextTest"), + INDEX_CURSOR("indexCursorTest"), + INDEX("indexTest"), + OVERFLOW("overflowTest"), + QUERY("queryTest"), + TEST("test"), + TEST2("test2"), + INDEX_CODES("testIndexCodes"), + INDEX_PROPERTIES("testIndexProperties"), + PROMOTION("testPromotion"), + COMPLEX("complexDataTest"), + UNSUPPORTED("unsupportedFieldsTest"), + LINKED("linkerTest"); + + private final String _basename; + + Basename(String fileBasename) { + _basename = fileBasename; + } + + @Override + public String toString() { return _basename; } + } + + /** Defines currently supported db file formats. (can be modified at + runtime via the system property + "com.healthmarketscience.jackcess.testFormats") */ + public final static FileFormat[] SUPPORTED_FILEFORMATS; + public final static FileFormat[] SUPPORTED_FILEFORMATS_FOR_READ; + + static { + String testFormatStr = System.getProperty("com.healthmarketscience.jackcess.testFormats"); + Set testFormats = EnumSet.allOf(FileFormat.class); + if((testFormatStr != null) && (testFormatStr.length() > 0)) { + testFormats.clear(); + for(String tmp : testFormatStr.split(",")) { + testFormats.add(FileFormat.valueOf(tmp.toUpperCase())); + } + } + + List supported = new ArrayList(); + List supportedForRead = new ArrayList(); + for(FileFormat ff : FileFormat.values()) { + if(!testFormats.contains(ff)) { + continue; + } + supportedForRead.add(ff); + if(DatabaseImpl.getFileFormatDetails(ff).getFormat().READ_ONLY || + (ff == FileFormat.MSISAM)) { + continue; + } + supported.add(ff); + } + + SUPPORTED_FILEFORMATS = supported.toArray(new FileFormat[0]); + SUPPORTED_FILEFORMATS_FOR_READ = + supportedForRead.toArray(new FileFormat[0]); + } + + /** + * Defines known valid test database files, and their jet format version. + */ + public static final class TestDB { + + private final File dbFile; + private final FileFormat expectedFileFormat; + + private TestDB(File databaseFile, + FileFormat expectedDBFileFormat) { + + dbFile = databaseFile; + expectedFileFormat = expectedDBFileFormat; + } + + public final File getFile() { return dbFile; } + + public final FileFormat getExpectedFileFormat() { + return expectedFileFormat; + } + + public final JetFormat getExpectedFormat() { + return DatabaseImpl.getFileFormatDetails(expectedFileFormat).getFormat(); + } + + @Override + public final String toString() { + return "dbFile: " + dbFile.getAbsolutePath() + + "; expectedFileFormat: " + expectedFileFormat; + } + + public static List getSupportedForBasename(Basename basename) { + return getSupportedForBasename(basename, false); + } + + public static List getSupportedForBasename(Basename basename, + boolean readOnly) { + + List supportedTestDBs = new ArrayList(); + for (FileFormat fileFormat : + (readOnly ? SUPPORTED_FILEFORMATS_FOR_READ : + SUPPORTED_FILEFORMATS)) { + File testFile = getFileForBasename(basename, fileFormat); + if(!testFile.exists()) { + continue; + } + + // verify that the db is the file format expected + try { + Database db = new DatabaseBuilder(testFile).setReadOnly(true).open(); + FileFormat dbFileFormat = db.getFileFormat(); + db.close(); + if(dbFileFormat != fileFormat) { + throw new IllegalStateException("Expected " + fileFormat + + " was " + dbFileFormat); + } + } catch(Exception e) { + throw new RuntimeException(e); + } + + supportedTestDBs.add(new TestDB(testFile, fileFormat)); + } + return supportedTestDBs; + } + + private static File getFileForBasename( + Basename basename, FileFormat fileFormat) { + + return new File(DIR_TEST_DATA, + fileFormat.name() + File.separator + + basename + fileFormat.name() + + fileFormat.getFileExtension()); + } + } + + public static final List SUPPORTED_DBS_TEST = + TestDB.getSupportedForBasename(Basename.TEST); + public static final List SUPPORTED_DBS_TEST_FOR_READ = + TestDB.getSupportedForBasename(Basename.TEST, true); + + + public void testGetFormat() throws Exception { + try { + JetFormat.getFormat(null); + fail("npe"); + } catch (NullPointerException e) { + // success + } + + for (final TestDB testDB : SUPPORTED_DBS_TEST_FOR_READ) { + + final FileChannel channel = DatabaseImpl.openChannel(testDB.dbFile, false); + try { + + JetFormat fmtActual = JetFormat.getFormat(channel); + assertEquals("Unexpected JetFormat for dbFile: " + + testDB.dbFile.getAbsolutePath(), + testDB.getExpectedFormat(), fmtActual); + + } finally { + channel.close(); + } + + } + } + + public void testReadOnlyFormat() throws Exception { + + for (final TestDB testDB : SUPPORTED_DBS_TEST_FOR_READ) { + + Database db = null; + IOException failure = null; + try { + db = openCopy(testDB); + } catch(IOException e) { + failure = e; + } finally { + if(db != null) { + db.close(); + } + } + + if(!testDB.getExpectedFormat().READ_ONLY) { + assertNull(failure); + } else { + assertTrue(failure.getMessage().contains("does not support writing")); + } + + } + } + + public void testFileFormat() throws Exception { + + for (final TestDB testDB : SUPPORTED_DBS_TEST_FOR_READ) { + + Database db = null; + try { + db = open(testDB); + assertEquals(testDB.getExpectedFileFormat(), db.getFileFormat()); + } finally { + if(db != null) { + db.close(); + } + } + } + } + +} diff --git a/test/src/java/com/healthmarketscience/jackcess/impl/UsageMapTest.java b/test/src/java/com/healthmarketscience/jackcess/impl/UsageMapTest.java new file mode 100644 index 0000000..aad1ddf --- /dev/null +++ b/test/src/java/com/healthmarketscience/jackcess/impl/UsageMapTest.java @@ -0,0 +1,54 @@ +package com.healthmarketscience.jackcess.impl; + +import java.io.File; +import java.io.IOException; + +import com.healthmarketscience.jackcess.Database; +import com.healthmarketscience.jackcess.DatabaseBuilder; +import static com.healthmarketscience.jackcess.impl.JetFormatTest.*; +import junit.framework.TestCase; + +/** + * @author Dan Rollo + * Date: Mar 5, 2010 + * Time: 2:21:22 PM + */ +public final class UsageMapTest extends TestCase { + + public void testRead() throws Exception { + for (final TestDB testDB : SUPPORTED_DBS_TEST) { + final int expectedFirstPage; + final int expectedLastPage; + final Database.FileFormat expectedFileFormat = testDB.getExpectedFileFormat(); + if (Database.FileFormat.V2000.equals(expectedFileFormat)) { + expectedFirstPage = 743; + expectedLastPage = 767; + } else if (Database.FileFormat.V2003.equals(expectedFileFormat)) { + expectedFirstPage = 16; + expectedLastPage = 799; + } else if (Database.FileFormat.V2007.equals(expectedFileFormat)) { + expectedFirstPage = 94; + expectedLastPage = 511; + } else if (Database.FileFormat.V2010.equals(expectedFileFormat)) { + expectedFirstPage = 109; + expectedLastPage = 511; + } else { + throw new IllegalAccessException("Unknown file format: " + expectedFileFormat); + } + checkUsageMapRead(testDB.getFile(), expectedFirstPage, expectedLastPage); + } + } + + private static void checkUsageMapRead(final File dbFile, + final int expectedFirstPage, final int expectedLastPage) + throws IOException { + + final Database db = DatabaseBuilder.open(dbFile); + final UsageMap usageMap = UsageMap.read((DatabaseImpl)db, + PageChannel.PAGE_GLOBAL_USAGE_MAP, + PageChannel.ROW_GLOBAL_USAGE_MAP, + true); + assertEquals("Unexpected FirstPageNumber.", expectedFirstPage, usageMap.getFirstPageNumber()); + assertEquals("Unexpected LastPageNumber.", expectedLastPage, usageMap.getLastPageNumber()); + } +} diff --git a/test/src/java/com/healthmarketscience/jackcess/impl/scsu/CompressMain.java b/test/src/java/com/healthmarketscience/jackcess/impl/scsu/CompressMain.java new file mode 100644 index 0000000..52b9e86 --- /dev/null +++ b/test/src/java/com/healthmarketscience/jackcess/impl/scsu/CompressMain.java @@ -0,0 +1,574 @@ +package com.healthmarketscience.jackcess.impl.scsu; + +import java.io.*; +import java.util.*; + +/** + * This sample software accompanies Unicode Technical Report #6 and + * distributed as is by Unicode, Inc., subject to the following: + * + * Copyright 1996-1998 Unicode, Inc.. All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software + * without fee is hereby granted provided that this copyright notice + * appears in all copies. + * + * UNICODE, INC. MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE + * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. + * UNICODE, INC., SHALL NOT BE LIABLE FOR ANY ERRORS OR OMISSIONS, AND + * SHALL NOT BE LIABLE FOR ANY DAMAGES, INCLUDING CONSEQUENTIAL AND + * INCIDENTAL DAMAGES, SUFFERED BY YOU AS A RESULT OF USING, MODIFYING + * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + * + * @author Asmus Freytag + * + * @version 001 Dec 25 1996 + * @version 002 Jun 25 1997 + * @version 003 Jul 25 1997 + * @version 004 Aug 25 1997 + * @version 005 Sep 30 1998 + * + * Unicode and the Unicode logo are trademarks of Unicode, Inc., + * and are registered in some jurisdictions. + **/ + +/** + Class CompressMain + + A small commandline driver interface for the compression routines + Use the /? to get usage +*/ +public class CompressMain +{ + static void usage() + { + System.err.println("java CompressMain /? : this usage information\n"); + System.err.println("java CompressMain /random : random test\n"); + System.err.println("java CompressMain /suite : suite test\n"); + System.err.println("java CompressMain /suite : file test (file data may include \\uXXXX)\n"); + System.err.println("java CompressMain : string test (string may include \\uXXXX)\n"); + System.err.println("java CompressMain /roundtrip : check Unicode file for roundtrip\n"); + System.err.println("java CompressMain /compress : compresses Unicode files (no \\uXXXX)\n"); + System.err.println("java CompressMain /expand : expands into Unicode files\n"); + System.err.println("java CompressMain /byteswap : swaps byte order of Unicode files\n"); + System.err.println("java CompressMain /display : like expand, but creates a dump instead\n"); + System.err.println("java CompressMain /parse : parses \\uXXXX into binary Unicode\n"); + } + + static void analyze(String text, int inlength, String result, int outlength) + { + boolean fSuccess = text.equals(result); + Debug.out(fSuccess ? "Round trip OK" : "Round trip FAILED"); + if (!fSuccess && result != null) + { + int iLim = Math.min(text.length(), result.length()); + for (int i = 0; i < iLim; i++) + { + if (text.charAt(i) != result.charAt(i)) + { + Debug.out("First Mismatch at "+ i +"=", result.charAt(i) ); + Debug.out("Original character "+ i +"=", text.charAt(i) ); + break; + } + } + } + else + { + Debug.out("Compressed: "+inlength+" chars to "+outlength+" bytes."); + Debug.out(" Ratio: "+(outlength == 0 ? 0 :(outlength * 50 / inlength))+"%."); + } + } + + static void test2(String text) + { + byte bytes[] = null; + String result = null; + Debug.out("SCSU:\n"); + Compress compressor = new Compress(); + try + { + bytes = compressor.compress(text); + Expand display = new Expand(); + result = display.expand(bytes); + Debug.out("Input: ", text.toCharArray()); + Debug.out("Result: ", result.toCharArray()); + Debug.out(""); + Expand expander = new Expand(); + result = expander.expand(bytes); + } + catch (Exception e) + { + System.out.println(e); + } + int inlength = compressor.charsRead(); + int outlength = compressor.bytesWritten(); + analyze(text, inlength, result, outlength); + } + + static void test(String text) throws Exception + { + test(text, false); + } + + static void test(String text, boolean shouldFail) + throws Exception + { + // Create an instance of the compressor + Compress compressor = new Compress(); + + byte [] bytes = null; + String result = null; + Exception failure = null; + try { + // perform compression + bytes = compressor.compress(text); + } + catch(Exception e) + { + failure = e; + } + + if(shouldFail) { + if(failure == null) { + throw new RuntimeException("Did not fail"); + } + return; + } + + if(failure != null) { + throw failure; + } + + Expand expander = new Expand(); + // perform expansion + result = expander.expand(bytes); + + // analyze the results + int inlength = compressor.charsRead(); + int outlength = compressor.bytesWritten(); + analyze(text, inlength, result, outlength); + + } + + public static void display(byte [] input) + { + try + { + Expand expand = new Expand(); + String text = expand.expand(input); + Debug.out(text.toCharArray()); + } + catch (Exception e) + { + System.out.println(e); + } + } + + public static String parse(String input) + { + StringTokenizer st = new StringTokenizer(input, "\\", true); + Debug.out("Input: ", input); + + StringBuffer sb = new StringBuffer(); + + while(st.hasMoreTokens()) + { + String token = st.nextToken(); + Debug.out("Token: ", token); + if (token.charAt(0) == '\\' && token.length() == 1) + { + if(st.hasMoreTokens()) + { + token = st.nextToken(); + } + if(token.charAt(0) == 'u') + { + Debug.out("Token: "+ token+ " ", sb.toString()); + String hexnum; + if (token.length() > 5) + { + hexnum = token.substring(1,5); + token = token.substring(5); + } + else + { + hexnum = token.substring(1); + token = ""; + } + sb.append((char)Integer.parseInt(hexnum, 16)); + } + } + sb.append(token); + } + return sb.toString(); + } + + public static void randomTest(int nTest) + throws Exception + { + Random random = new Random(); + + for(int n=0; n < nTest; n++) + { + int iLen = (int) (20 * random.nextFloat()); + StringBuffer sb = new StringBuffer(iLen); + + for(int i = 0; i < iLen; i++) + { + sb.append((char) (0xFFFF * random.nextFloat())); + } + + test(sb.toString()); + } + } + + @SuppressWarnings("deprecation") + public static void fileTest(String name) + throws Exception + { + DataInputStream dis = new DataInputStream(new FileInputStream(name)); + + int iLine = 0; + + while(dis.available() != 0) + { + String line = dis.readLine(); + Debug.out("Line "+ iLine++ +" "+line); + test(parse(line), false ); //false);// initially no debug info + } + } + + public static void displayFile(String name) + throws IOException + { + DataInputStream dis = new DataInputStream(new FileInputStream(name)); + + byte bytes[] = new byte[dis.available()]; + dis.read(bytes); + display(bytes); + } + + public static void decodeTest(String name) + throws IOException + { + DataInputStream dis = new DataInputStream(new FileInputStream(name)); + + byte bytes[] = new byte[dis.available()]; + dis.read(bytes); + + Expand expand = new Expand(); + + char [] chars = null; + try + { + String text = expand.expand(bytes); + chars = text.toCharArray(); + } + catch (Exception e) + { + System.out.println(e); + } + int inlength = expand.bytesRead(); + int iDot = name.lastIndexOf('.'); + StringBuffer sb = new StringBuffer(name); + sb.setLength(iDot + 1); + sb.append("txt"); + String outName = sb.toString(); + + int outlength = expand.charsWritten(); + + Debug.out("Expanded "+name+": "+inlength+" bytes to "+outName+" " +outlength+" chars." + " Ratio: "+(outlength == 0 ? 0 :(outlength * 200 / inlength))+"%."); + + if (chars == null) + return; + + writeUnicodeFile(outName, chars); + } + + /** most of the next 3 functions should not be needed by JDK11 and later */ + private static int iMSB = 1; + + public static String readUnicodeFile(String name) + { + try + { + FileInputStream dis = new FileInputStream(name); + + byte b[] = new byte[2]; + StringBuffer sb = new StringBuffer(); + char ch = 0; + + iMSB = 1; + int i = 0; + for(i = 0; (dis.available() != 0); i++) + { + b[i%2] = (byte) dis.read(); + + if ((i & 1) == 1) + { + ch = Expand.charFromTwoBytes(b[(i + iMSB)%2], b[(i + iMSB + 1) % 2]); + } + else + { + continue; + } + if (i == 1 && ch == '\uFEFF') + continue; // throw away byte order mark + + if (i == 1 && ch == '\uFFFE') + { + iMSB ++; // flip byte order + continue; // throw away byte order mark + } + sb.append(ch); + } + + return sb.toString(); + } + catch (IOException e) + { + System.err.println(e); + return ""; + } + } + + public static void writeUnicodeFile(String outName, char [] chars) + throws IOException + { + DataOutputStream dos = new DataOutputStream(new FileOutputStream(outName)); + if ((iMSB & 1) == 1) + { + dos.writeByte(0xFF); + dos.writeByte(0xFE); + } + else + { + dos.writeByte(0xFE); + dos.writeByte(0xFF); + } + byte b[] = new byte[2]; + for (int ich = 0; ich < chars.length; ich++) + { + b[(iMSB + 0)%2] = (byte) (chars[ich] >>> 8); + b[(iMSB + 1)%2] = (byte) (chars[ich] & 0xFF); + dos.write(b, 0, 2); + } + } + + static void byteswap(String name) + throws IOException + { + String text = readUnicodeFile(name); + char chars[] = text.toCharArray(); + writeUnicodeFile(name, chars); + } + + @SuppressWarnings("deprecation") + public static void parseFile(String name) + throws IOException + { + DataInputStream dis = new DataInputStream(new FileInputStream(name)); + + byte bytes[] = new byte[dis.available()]; + dis.read(bytes); + + // simplistic test + int bom = (char) bytes[0] + (char) bytes[1]; + if (bom == 131069) + { + // FEFF or FFFE detected (either one sums to 131069) + Debug.out(name + " is already in Unicode!"); + return; + } + + // definitely assumes an ASCII file at this point + String text = new String(bytes, 0); + + char chars[] = parse(text).toCharArray(); + writeUnicodeFile(name, chars); + return; + } + + public static void encodeTest(String name) + throws Exception + { + String text = readUnicodeFile(name); + + // Create an instance of the compressor + Compress compressor = new Compress(); + + byte [] bytes = null; + + // perform compression + bytes = compressor.compress(text); + + int inlength = compressor.charsRead(); + int iDot = name.lastIndexOf('.'); + StringBuffer sb = new StringBuffer(name); + sb.setLength(iDot + 1); + sb.append("csu"); + String outName = sb.toString(); + + DataOutputStream dos = new DataOutputStream(new FileOutputStream(outName)); + dos.write(bytes, 0, bytes.length); + + int outlength = compressor.bytesWritten(); + + Debug.out("Compressed "+name+": "+inlength+" chars to "+outName+" " +outlength+" bytes." + " Ratio: "+(outlength == 0 ? 0 :(outlength * 50 / inlength))+"%."); + } + + public static void roundtripTest(String name) + throws Exception + { + test(readUnicodeFile(name), false);// no debug info + } + + /** The Main function */ + public static void main(String args[]) + throws Exception + { + int iArg = args.length; + + try + { + if (iArg != 0) + { + if (args[0].equalsIgnoreCase("/compress")) + { + while (--iArg > 0) + { + encodeTest(args[args.length - iArg]); + } + } + else if (args[0].equalsIgnoreCase("/parse")) + { + while (--iArg > 0) + { + parseFile(args[args.length - iArg]); + } + } + else if (args[0].equalsIgnoreCase("/expand")) + { + while (--iArg > 0) + { + decodeTest(args[args.length - iArg]); + } + } + else if (args[0].equalsIgnoreCase("/display")) + { + while (--iArg > 0) + { + displayFile(args[args.length - iArg]); + } + } + else if (args[0].equalsIgnoreCase("/roundtrip")) + { + while (--iArg > 0) + { + roundtripTest(args[args.length - iArg]); + } + } + else if (args[0].equalsIgnoreCase("/byteswap")) + { + while (--iArg > 0) + { + byteswap(args[args.length - iArg]); + } + }else if (args[0].equalsIgnoreCase("/random")) + { + randomTest(8); + } + else if (args[0].equalsIgnoreCase("/suite")) + { + if (iArg == 1) + { + suiteTest(); + } + else + { + while (--iArg > 0) + { + fileTest(args[args.length - iArg]); + } + } + } + else if (args[0].equalsIgnoreCase("/?")) + { + usage(); + } + else + { + while (iArg > 0) + { + test2(parse(args[--iArg])); + } + } + } + else + { + usage(); + } + } + catch (IOException e) + { + System.err.println(e); + } + try + { + System.err.println("Done. Press enter to exit"); + System.in.read(); + } + catch (IOException e) + { + + } + } + + static void suiteTest() + throws Exception + { + Debug.out("Standard Compression test suite:"); + test("Hello \u9292 \u9192 World!"); + test("Hell\u0429o \u9292 \u9192 W\u00e4rld!"); + test("Hell\u0429o \u9292 \u9292W\u00e4rld!"); + + test("\u0648\u06c8"); // catch missing reset + test("\u0648\u06c8"); + + test("\u4444\uE001"); // lowest quotable + test("\u4444\uf2FF"); // highest quotable + test("\u4444\uf188\u4444"); + test("\u4444\uf188\uf288"); + test("\u4444\uf188abc\0429\uf288"); + test("\u9292\u2222"); + test("Hell\u0429\u04230o \u9292 \u9292W\u00e4\u0192rld!"); + test("Hell\u0429o \u9292 \u9292W\u00e4rld!"); + test("Hello World!123456"); + test("Hello W\u0081\u011f\u0082!"); // Latin 1 run + + test("abc\u0301\u0302"); // uses SQn for u301 u302 + test("abc\u4411d"); // uses SQU + test("abc\u4411\u4412d");// uses SCU + test("abc\u0401\u0402\u047f\u00a5\u0405"); // uses SQn for ua5 + test("\u9191\u9191\u3041\u9191\u3041\u3041\u3000"); // SJIS like data + test("\u9292\u2222"); + test("\u9191\u9191\u3041\u9191\u3041\u3041\u3000"); + test("\u9999\u3051\u300c\u9999\u9999\u3060\u9999\u3065\u3065\u3065\u300c"); + test("\u3000\u266a\u30ea\u30f3\u30b4\u53ef\u611b\u3044\u3084\u53ef\u611b\u3044\u3084\u30ea\u30f3\u30b4\u3002"); + + test(""); // empty input + test("\u0000"); // smallest BMP character + test("\uFFFF"); // largest BMP character + + test("\ud800\udc00"); // smallest surrogate + test("\ud8ff\udcff"); // largest surrogate pair + + + Debug.out("\nTHESE TESTS ARE SUPPOSED TO FAIL:"); + test("\ud800 \udc00", true); // unpaired surrogate (1) + test("\udc00", true); // unpaired surrogate (2) + test("\ud800", true); // unpaired surrogate (3) + } +} diff --git a/test/src/java/com/healthmarketscience/jackcess/impl/scsu/CompressTest.java b/test/src/java/com/healthmarketscience/jackcess/impl/scsu/CompressTest.java new file mode 100644 index 0000000..b9dc13a --- /dev/null +++ b/test/src/java/com/healthmarketscience/jackcess/impl/scsu/CompressTest.java @@ -0,0 +1,47 @@ +/* +Copyright (c) 2007 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.impl.scsu; + +import junit.framework.TestCase; + +/** + * @author James Ahlborn + */ +public class CompressTest extends TestCase +{ + + public CompressTest(String name) throws Exception { + super(name); + } + + public void testCompression() throws Exception + { + CompressMain.suiteTest(); + } + +} diff --git a/test/src/java/com/healthmarketscience/jackcess/query/QueryTest.java b/test/src/java/com/healthmarketscience/jackcess/query/QueryTest.java index 73d91b7..015f2fc 100644 --- a/test/src/java/com/healthmarketscience/jackcess/query/QueryTest.java +++ b/test/src/java/com/healthmarketscience/jackcess/query/QueryTest.java @@ -37,14 +37,15 @@ import java.util.Map; import com.healthmarketscience.jackcess.DataType; import com.healthmarketscience.jackcess.Database; import com.healthmarketscience.jackcess.DatabaseTest; -import com.healthmarketscience.jackcess.query.Query.Row; +import com.healthmarketscience.jackcess.impl.query.QueryImpl; +import com.healthmarketscience.jackcess.impl.query.QueryImpl.Row; import junit.framework.TestCase; import org.apache.commons.lang.StringUtils; import static org.apache.commons.lang.SystemUtils.LINE_SEPARATOR; -import static com.healthmarketscience.jackcess.query.QueryFormat.*; +import static com.healthmarketscience.jackcess.impl.query.QueryFormat.*; -import static com.healthmarketscience.jackcess.JetFormatTest.*; +import static com.healthmarketscience.jackcess.impl.JetFormatTest.*; /** @@ -169,7 +170,7 @@ public class QueryTest extends TestCase { List rowList = new ArrayList(); rowList.add(newRow(TYPE_ATTRIBUTE, null, -1, null, null)); - Query query = Query.create(-1, "TestQuery", rowList, 13); + QueryImpl query = QueryImpl.create(-1, "TestQuery", rowList, 13); try { query.toSQLString(); fail("UnsupportedOperationException should have been thrown"); @@ -187,7 +188,7 @@ public class QueryTest extends TestCase } try { - new Query("TestQuery", rowList, 13, Query.Type.UNION) { + new QueryImpl("TestQuery", rowList, 13, Query.Type.UNION) { @Override protected void toSQLString(StringBuilder builder) { throw new UnsupportedOperationException(); }}; @@ -468,7 +469,7 @@ public class QueryTest extends TestCase rowList.add(newRow(TYPE_ATTRIBUTE, typeExpr, type.getValue(), null, typeName1, null)); rowList.addAll(Arrays.asList(rows)); - return Query.create(type.getObjectFlag(), "TestQuery", rowList, 13); + return QueryImpl.create(type.getObjectFlag(), "TestQuery", rowList, 13); } private static Row newRow(Byte attr, String expr, String name1, String name2) @@ -487,7 +488,7 @@ public class QueryTest extends TestCase { Short flag = ((flagNum != null) ? flagNum.shortValue() : null); Integer extra = ((extraNum != null) ? extraNum.intValue() : null); - return new Row(attr, expr, flag, extra, name1, name2, null, null); + return new Row(null, attr, expr, flag, extra, name1, name2, null, null); } private static void setFlag(Query query, Number newFlagNum) @@ -498,7 +499,7 @@ public class QueryTest extends TestCase private static void addRows(Query query, Row... rows) { - query.getRows().addAll(Arrays.asList(rows)); + ((QueryImpl)query).getRows().addAll(Arrays.asList(rows)); } private static void replaceRows(Query query, Row... rows) @@ -509,7 +510,7 @@ public class QueryTest extends TestCase private static void removeRows(Query query, Byte attr) { - for(Iterator iter = query.getRows().iterator(); iter.hasNext(); ) { + for(Iterator iter = ((QueryImpl)query).getRows().iterator(); iter.hasNext(); ) { if(attr.equals(iter.next().attribute)) { iter.remove(); } @@ -518,7 +519,7 @@ public class QueryTest extends TestCase private static void removeLastRows(Query query, int num) { - List rows = query.getRows(); + List rows = ((QueryImpl)query).getRows(); int size = rows.size(); rows.subList(size - num, size).clear(); } diff --git a/test/src/java/com/healthmarketscience/jackcess/scsu/CompressMain.java b/test/src/java/com/healthmarketscience/jackcess/scsu/CompressMain.java deleted file mode 100644 index af3063d..0000000 --- a/test/src/java/com/healthmarketscience/jackcess/scsu/CompressMain.java +++ /dev/null @@ -1,574 +0,0 @@ -package com.healthmarketscience.jackcess.scsu; - -import java.io.*; -import java.util.*; - -/** - * This sample software accompanies Unicode Technical Report #6 and - * distributed as is by Unicode, Inc., subject to the following: - * - * Copyright 1996-1998 Unicode, Inc.. All Rights Reserved. - * - * Permission to use, copy, modify, and distribute this software - * without fee is hereby granted provided that this copyright notice - * appears in all copies. - * - * UNICODE, INC. MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE - * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING - * BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. - * UNICODE, INC., SHALL NOT BE LIABLE FOR ANY ERRORS OR OMISSIONS, AND - * SHALL NOT BE LIABLE FOR ANY DAMAGES, INCLUDING CONSEQUENTIAL AND - * INCIDENTAL DAMAGES, SUFFERED BY YOU AS A RESULT OF USING, MODIFYING - * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. - * - * @author Asmus Freytag - * - * @version 001 Dec 25 1996 - * @version 002 Jun 25 1997 - * @version 003 Jul 25 1997 - * @version 004 Aug 25 1997 - * @version 005 Sep 30 1998 - * - * Unicode and the Unicode logo are trademarks of Unicode, Inc., - * and are registered in some jurisdictions. - **/ - -/** - Class CompressMain - - A small commandline driver interface for the compression routines - Use the /? to get usage -*/ -public class CompressMain -{ - static void usage() - { - System.err.println("java CompressMain /? : this usage information\n"); - System.err.println("java CompressMain /random : random test\n"); - System.err.println("java CompressMain /suite : suite test\n"); - System.err.println("java CompressMain /suite : file test (file data may include \\uXXXX)\n"); - System.err.println("java CompressMain : string test (string may include \\uXXXX)\n"); - System.err.println("java CompressMain /roundtrip : check Unicode file for roundtrip\n"); - System.err.println("java CompressMain /compress : compresses Unicode files (no \\uXXXX)\n"); - System.err.println("java CompressMain /expand : expands into Unicode files\n"); - System.err.println("java CompressMain /byteswap : swaps byte order of Unicode files\n"); - System.err.println("java CompressMain /display : like expand, but creates a dump instead\n"); - System.err.println("java CompressMain /parse : parses \\uXXXX into binary Unicode\n"); - } - - static void analyze(String text, int inlength, String result, int outlength) - { - boolean fSuccess = text.equals(result); - Debug.out(fSuccess ? "Round trip OK" : "Round trip FAILED"); - if (!fSuccess && result != null) - { - int iLim = Math.min(text.length(), result.length()); - for (int i = 0; i < iLim; i++) - { - if (text.charAt(i) != result.charAt(i)) - { - Debug.out("First Mismatch at "+ i +"=", result.charAt(i) ); - Debug.out("Original character "+ i +"=", text.charAt(i) ); - break; - } - } - } - else - { - Debug.out("Compressed: "+inlength+" chars to "+outlength+" bytes."); - Debug.out(" Ratio: "+(outlength == 0 ? 0 :(outlength * 50 / inlength))+"%."); - } - } - - static void test2(String text) - { - byte bytes[] = null; - String result = null; - Debug.out("SCSU:\n"); - Compress compressor = new Compress(); - try - { - bytes = compressor.compress(text); - Expand display = new Expand(); - result = display.expand(bytes); - Debug.out("Input: ", text.toCharArray()); - Debug.out("Result: ", result.toCharArray()); - Debug.out(""); - Expand expander = new Expand(); - result = expander.expand(bytes); - } - catch (Exception e) - { - System.out.println(e); - } - int inlength = compressor.charsRead(); - int outlength = compressor.bytesWritten(); - analyze(text, inlength, result, outlength); - } - - static void test(String text) throws Exception - { - test(text, false); - } - - static void test(String text, boolean shouldFail) - throws Exception - { - // Create an instance of the compressor - Compress compressor = new Compress(); - - byte [] bytes = null; - String result = null; - Exception failure = null; - try { - // perform compression - bytes = compressor.compress(text); - } - catch(Exception e) - { - failure = e; - } - - if(shouldFail) { - if(failure == null) { - throw new RuntimeException("Did not fail"); - } - return; - } - - if(failure != null) { - throw failure; - } - - Expand expander = new Expand(); - // perform expansion - result = expander.expand(bytes); - - // analyze the results - int inlength = compressor.charsRead(); - int outlength = compressor.bytesWritten(); - analyze(text, inlength, result, outlength); - - } - - public static void display(byte [] input) - { - try - { - Expand expand = new Expand(); - String text = expand.expand(input); - Debug.out(text.toCharArray()); - } - catch (Exception e) - { - System.out.println(e); - } - } - - public static String parse(String input) - { - StringTokenizer st = new StringTokenizer(input, "\\", true); - Debug.out("Input: ", input); - - StringBuffer sb = new StringBuffer(); - - while(st.hasMoreTokens()) - { - String token = st.nextToken(); - Debug.out("Token: ", token); - if (token.charAt(0) == '\\' && token.length() == 1) - { - if(st.hasMoreTokens()) - { - token = st.nextToken(); - } - if(token.charAt(0) == 'u') - { - Debug.out("Token: "+ token+ " ", sb.toString()); - String hexnum; - if (token.length() > 5) - { - hexnum = token.substring(1,5); - token = token.substring(5); - } - else - { - hexnum = token.substring(1); - token = ""; - } - sb.append((char)Integer.parseInt(hexnum, 16)); - } - } - sb.append(token); - } - return sb.toString(); - } - - public static void randomTest(int nTest) - throws Exception - { - Random random = new Random(); - - for(int n=0; n < nTest; n++) - { - int iLen = (int) (20 * random.nextFloat()); - StringBuffer sb = new StringBuffer(iLen); - - for(int i = 0; i < iLen; i++) - { - sb.append((char) (0xFFFF * random.nextFloat())); - } - - test(sb.toString()); - } - } - - @SuppressWarnings("deprecation") - public static void fileTest(String name) - throws Exception - { - DataInputStream dis = new DataInputStream(new FileInputStream(name)); - - int iLine = 0; - - while(dis.available() != 0) - { - String line = dis.readLine(); - Debug.out("Line "+ iLine++ +" "+line); - test(parse(line), false ); //false);// initially no debug info - } - } - - public static void displayFile(String name) - throws IOException - { - DataInputStream dis = new DataInputStream(new FileInputStream(name)); - - byte bytes[] = new byte[dis.available()]; - dis.read(bytes); - display(bytes); - } - - public static void decodeTest(String name) - throws IOException - { - DataInputStream dis = new DataInputStream(new FileInputStream(name)); - - byte bytes[] = new byte[dis.available()]; - dis.read(bytes); - - Expand expand = new Expand(); - - char [] chars = null; - try - { - String text = expand.expand(bytes); - chars = text.toCharArray(); - } - catch (Exception e) - { - System.out.println(e); - } - int inlength = expand.bytesRead(); - int iDot = name.lastIndexOf('.'); - StringBuffer sb = new StringBuffer(name); - sb.setLength(iDot + 1); - sb.append("txt"); - String outName = sb.toString(); - - int outlength = expand.charsWritten(); - - Debug.out("Expanded "+name+": "+inlength+" bytes to "+outName+" " +outlength+" chars." + " Ratio: "+(outlength == 0 ? 0 :(outlength * 200 / inlength))+"%."); - - if (chars == null) - return; - - writeUnicodeFile(outName, chars); - } - - /** most of the next 3 functions should not be needed by JDK11 and later */ - private static int iMSB = 1; - - public static String readUnicodeFile(String name) - { - try - { - FileInputStream dis = new FileInputStream(name); - - byte b[] = new byte[2]; - StringBuffer sb = new StringBuffer(); - char ch = 0; - - iMSB = 1; - int i = 0; - for(i = 0; (dis.available() != 0); i++) - { - b[i%2] = (byte) dis.read(); - - if ((i & 1) == 1) - { - ch = Expand.charFromTwoBytes(b[(i + iMSB)%2], b[(i + iMSB + 1) % 2]); - } - else - { - continue; - } - if (i == 1 && ch == '\uFEFF') - continue; // throw away byte order mark - - if (i == 1 && ch == '\uFFFE') - { - iMSB ++; // flip byte order - continue; // throw away byte order mark - } - sb.append(ch); - } - - return sb.toString(); - } - catch (IOException e) - { - System.err.println(e); - return ""; - } - } - - public static void writeUnicodeFile(String outName, char [] chars) - throws IOException - { - DataOutputStream dos = new DataOutputStream(new FileOutputStream(outName)); - if ((iMSB & 1) == 1) - { - dos.writeByte(0xFF); - dos.writeByte(0xFE); - } - else - { - dos.writeByte(0xFE); - dos.writeByte(0xFF); - } - byte b[] = new byte[2]; - for (int ich = 0; ich < chars.length; ich++) - { - b[(iMSB + 0)%2] = (byte) (chars[ich] >>> 8); - b[(iMSB + 1)%2] = (byte) (chars[ich] & 0xFF); - dos.write(b, 0, 2); - } - } - - static void byteswap(String name) - throws IOException - { - String text = readUnicodeFile(name); - char chars[] = text.toCharArray(); - writeUnicodeFile(name, chars); - } - - @SuppressWarnings("deprecation") - public static void parseFile(String name) - throws IOException - { - DataInputStream dis = new DataInputStream(new FileInputStream(name)); - - byte bytes[] = new byte[dis.available()]; - dis.read(bytes); - - // simplistic test - int bom = (char) bytes[0] + (char) bytes[1]; - if (bom == 131069) - { - // FEFF or FFFE detected (either one sums to 131069) - Debug.out(name + " is already in Unicode!"); - return; - } - - // definitely assumes an ASCII file at this point - String text = new String(bytes, 0); - - char chars[] = parse(text).toCharArray(); - writeUnicodeFile(name, chars); - return; - } - - public static void encodeTest(String name) - throws Exception - { - String text = readUnicodeFile(name); - - // Create an instance of the compressor - Compress compressor = new Compress(); - - byte [] bytes = null; - - // perform compression - bytes = compressor.compress(text); - - int inlength = compressor.charsRead(); - int iDot = name.lastIndexOf('.'); - StringBuffer sb = new StringBuffer(name); - sb.setLength(iDot + 1); - sb.append("csu"); - String outName = sb.toString(); - - DataOutputStream dos = new DataOutputStream(new FileOutputStream(outName)); - dos.write(bytes, 0, bytes.length); - - int outlength = compressor.bytesWritten(); - - Debug.out("Compressed "+name+": "+inlength+" chars to "+outName+" " +outlength+" bytes." + " Ratio: "+(outlength == 0 ? 0 :(outlength * 50 / inlength))+"%."); - } - - public static void roundtripTest(String name) - throws Exception - { - test(readUnicodeFile(name), false);// no debug info - } - - /** The Main function */ - public static void main(String args[]) - throws Exception - { - int iArg = args.length; - - try - { - if (iArg != 0) - { - if (args[0].equalsIgnoreCase("/compress")) - { - while (--iArg > 0) - { - encodeTest(args[args.length - iArg]); - } - } - else if (args[0].equalsIgnoreCase("/parse")) - { - while (--iArg > 0) - { - parseFile(args[args.length - iArg]); - } - } - else if (args[0].equalsIgnoreCase("/expand")) - { - while (--iArg > 0) - { - decodeTest(args[args.length - iArg]); - } - } - else if (args[0].equalsIgnoreCase("/display")) - { - while (--iArg > 0) - { - displayFile(args[args.length - iArg]); - } - } - else if (args[0].equalsIgnoreCase("/roundtrip")) - { - while (--iArg > 0) - { - roundtripTest(args[args.length - iArg]); - } - } - else if (args[0].equalsIgnoreCase("/byteswap")) - { - while (--iArg > 0) - { - byteswap(args[args.length - iArg]); - } - }else if (args[0].equalsIgnoreCase("/random")) - { - randomTest(8); - } - else if (args[0].equalsIgnoreCase("/suite")) - { - if (iArg == 1) - { - suiteTest(); - } - else - { - while (--iArg > 0) - { - fileTest(args[args.length - iArg]); - } - } - } - else if (args[0].equalsIgnoreCase("/?")) - { - usage(); - } - else - { - while (iArg > 0) - { - test2(parse(args[--iArg])); - } - } - } - else - { - usage(); - } - } - catch (IOException e) - { - System.err.println(e); - } - try - { - System.err.println("Done. Press enter to exit"); - System.in.read(); - } - catch (IOException e) - { - - } - } - - static void suiteTest() - throws Exception - { - Debug.out("Standard Compression test suite:"); - test("Hello \u9292 \u9192 World!"); - test("Hell\u0429o \u9292 \u9192 W\u00e4rld!"); - test("Hell\u0429o \u9292 \u9292W\u00e4rld!"); - - test("\u0648\u06c8"); // catch missing reset - test("\u0648\u06c8"); - - test("\u4444\uE001"); // lowest quotable - test("\u4444\uf2FF"); // highest quotable - test("\u4444\uf188\u4444"); - test("\u4444\uf188\uf288"); - test("\u4444\uf188abc\0429\uf288"); - test("\u9292\u2222"); - test("Hell\u0429\u04230o \u9292 \u9292W\u00e4\u0192rld!"); - test("Hell\u0429o \u9292 \u9292W\u00e4rld!"); - test("Hello World!123456"); - test("Hello W\u0081\u011f\u0082!"); // Latin 1 run - - test("abc\u0301\u0302"); // uses SQn for u301 u302 - test("abc\u4411d"); // uses SQU - test("abc\u4411\u4412d");// uses SCU - test("abc\u0401\u0402\u047f\u00a5\u0405"); // uses SQn for ua5 - test("\u9191\u9191\u3041\u9191\u3041\u3041\u3000"); // SJIS like data - test("\u9292\u2222"); - test("\u9191\u9191\u3041\u9191\u3041\u3041\u3000"); - test("\u9999\u3051\u300c\u9999\u9999\u3060\u9999\u3065\u3065\u3065\u300c"); - test("\u3000\u266a\u30ea\u30f3\u30b4\u53ef\u611b\u3044\u3084\u53ef\u611b\u3044\u3084\u30ea\u30f3\u30b4\u3002"); - - test(""); // empty input - test("\u0000"); // smallest BMP character - test("\uFFFF"); // largest BMP character - - test("\ud800\udc00"); // smallest surrogate - test("\ud8ff\udcff"); // largest surrogate pair - - - Debug.out("\nTHESE TESTS ARE SUPPOSED TO FAIL:"); - test("\ud800 \udc00", true); // unpaired surrogate (1) - test("\udc00", true); // unpaired surrogate (2) - test("\ud800", true); // unpaired surrogate (3) - } -} diff --git a/test/src/java/com/healthmarketscience/jackcess/scsu/CompressTest.java b/test/src/java/com/healthmarketscience/jackcess/scsu/CompressTest.java deleted file mode 100644 index 0f17e6c..0000000 --- a/test/src/java/com/healthmarketscience/jackcess/scsu/CompressTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* -Copyright (c) 2007 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.scsu; - -import junit.framework.TestCase; - -/** - * @author James Ahlborn - */ -public class CompressTest extends TestCase -{ - - public CompressTest(String name) throws Exception { - super(name); - } - - public void testCompression() throws Exception - { - CompressMain.suiteTest(); - } - -} diff --git a/test/src/java/com/healthmarketscience/jackcess/util/ErrorHandlerTest.java b/test/src/java/com/healthmarketscience/jackcess/util/ErrorHandlerTest.java new file mode 100644 index 0000000..6431ad8 --- /dev/null +++ b/test/src/java/com/healthmarketscience/jackcess/util/ErrorHandlerTest.java @@ -0,0 +1,195 @@ +/* +Copyright (c) 2007 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.util; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.nio.ByteOrder; +import java.util.List; + +import com.healthmarketscience.jackcess.Column; +import com.healthmarketscience.jackcess.ColumnBuilder; +import com.healthmarketscience.jackcess.Cursor; +import com.healthmarketscience.jackcess.CursorBuilder; +import com.healthmarketscience.jackcess.DataType; +import com.healthmarketscience.jackcess.Database; +import static com.healthmarketscience.jackcess.Database.*; +import static com.healthmarketscience.jackcess.DatabaseTest.*; +import com.healthmarketscience.jackcess.Table; +import com.healthmarketscience.jackcess.TableBuilder; +import com.healthmarketscience.jackcess.impl.ColumnImpl; +import com.healthmarketscience.jackcess.impl.JetFormatTest; +import com.healthmarketscience.jackcess.impl.TableImpl; +import junit.framework.TestCase; + +/** + * @author James Ahlborn + */ +public class ErrorHandlerTest extends TestCase +{ + + public ErrorHandlerTest(String name) { + super(name); + } + + public void testErrorHandler() throws Exception + { + for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) { + Database db = create(fileFormat); + + Table table = + new TableBuilder("test") + .addColumn(new ColumnBuilder("col", DataType.TEXT)) + .addColumn(new ColumnBuilder("val", DataType.LONG)) + .toTable(db); + + table.addRow("row1", 1); + table.addRow("row2", 2); + table.addRow("row3", 3); + + assertTable(createExpectedTable( + createExpectedRow("col", "row1", + "val", 1), + createExpectedRow("col", "row2", + "val", 2), + createExpectedRow("col", "row3", + "val", 3)), + table); + + + replaceColumn(table, "val"); + + table.reset(); + try { + table.getNextRow(); + fail("IOException should have been thrown"); + } catch(IOException e) { + // success + } + + table.reset(); + table.setErrorHandler(new ReplacementErrorHandler()); + + assertTable(createExpectedTable( + createExpectedRow("col", "row1", + "val", null), + createExpectedRow("col", "row2", + "val", null), + createExpectedRow("col", "row3", + "val", null)), + table); + + Cursor c1 = CursorBuilder.createCursor(table); + Cursor c2 = CursorBuilder.createCursor(table); + Cursor c3 = CursorBuilder.createCursor(table); + + c2.setErrorHandler(new DebugErrorHandler("#error")); + c3.setErrorHandler(ErrorHandler.DEFAULT); + + assertCursor(createExpectedTable( + createExpectedRow("col", "row1", + "val", null), + createExpectedRow("col", "row2", + "val", null), + createExpectedRow("col", "row3", + "val", null)), + c1); + + assertCursor(createExpectedTable( + createExpectedRow("col", "row1", + "val", "#error"), + createExpectedRow("col", "row2", + "val", "#error"), + createExpectedRow("col", "row3", + "val", "#error")), + c2); + + try { + c3.getNextRow(); + fail("IOException should have been thrown"); + } catch(IOException e) { + // success + } + + table.setErrorHandler(null); + c1.setErrorHandler(null); + c1.reset(); + try { + c1.getNextRow(); + fail("IOException should have been thrown"); + } catch(IOException e) { + // success + } + + + db.close(); + } + } + + @SuppressWarnings("unchecked") + private static void replaceColumn(Table t, String colName) throws Exception + { + Field colsField = TableImpl.class.getDeclaredField("_columns"); + colsField.setAccessible(true); + List cols = (List)colsField.get(t); + + Column srcCol = null; + ColumnImpl destCol = new BogusColumn(t); + destCol.setName(colName); + for(int i = 0; i < cols.size(); ++i) { + srcCol = cols.get(i); + if(srcCol.getName().equals(colName)) { + cols.set(i, destCol); + break; + } + } + + // copy fields from source to dest + for(Field f : Column.class.getDeclaredFields()) { + if(!Modifier.isFinal(f.getModifiers())) { + f.setAccessible(true); + f.set(destCol, f.get(srcCol)); + } + } + + } + + private static class BogusColumn extends ColumnImpl + { + private BogusColumn(Table table) { + super((TableImpl)table, DataType.LONG, 1, 0, 0); + } + + @Override + public Object read(byte[] data, ByteOrder order) throws IOException { + throw new IOException("bogus column"); + } + } + +} diff --git a/test/src/java/com/healthmarketscience/jackcess/util/ExportTest.java b/test/src/java/com/healthmarketscience/jackcess/util/ExportTest.java new file mode 100644 index 0000000..a271771 --- /dev/null +++ b/test/src/java/com/healthmarketscience/jackcess/util/ExportTest.java @@ -0,0 +1,139 @@ +/* +Copyright (c) 2007 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.util; + +import java.io.BufferedWriter; +import java.io.StringWriter; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +import com.healthmarketscience.jackcess.ColumnBuilder; +import com.healthmarketscience.jackcess.DataType; +import com.healthmarketscience.jackcess.Database; +import static com.healthmarketscience.jackcess.Database.*; +import static com.healthmarketscience.jackcess.DatabaseTest.*; +import com.healthmarketscience.jackcess.Table; +import com.healthmarketscience.jackcess.TableBuilder; +import com.healthmarketscience.jackcess.impl.JetFormatTest; +import junit.framework.TestCase; +import org.apache.commons.lang.SystemUtils; + +/** + * + * @author James Ahlborn + */ +public class ExportTest extends TestCase +{ + private static final String NL = SystemUtils.LINE_SEPARATOR; + + + public ExportTest(String name) { + super(name); + } + + public void testExportToFile() throws Exception + { + DateFormat df = new SimpleDateFormat("yyyyMMdd HH:mm:ss"); + df.setTimeZone(TEST_TZ); + + for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) { + Database db = create(fileFormat); + db.setTimeZone(TEST_TZ); + + Table t = new TableBuilder("test") + .addColumn(new ColumnBuilder("col1", DataType.TEXT)) + .addColumn(new ColumnBuilder("col2", DataType.LONG)) + .addColumn(new ColumnBuilder("col3", DataType.DOUBLE)) + .addColumn(new ColumnBuilder("col4", DataType.OLE)) + .addColumn(new ColumnBuilder("col5", DataType.BOOLEAN)) + .addColumn(new ColumnBuilder("col6", DataType.SHORT_DATE_TIME)) + .toTable(db); + + Date testDate = df.parse("19801231 00:00:00"); + t.addRow("some text||some more", 13, 13.25, createString(30).getBytes(), + true, testDate); + + t.addRow("crazy'data\"here", -345, -0.000345, createString(7).getBytes(), + true, null); + + t.addRow("C:\\temp\\some_file.txt", 25, 0.0, null, false, null); + + StringWriter out = new StringWriter(); + + new ExportUtil.Builder(db, "test") + .exportWriter(new BufferedWriter(out)); + + String expected = + "some text||some more,13,13.25,\"61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78\n79 7A 61 62 63 64\",true," + testDate + NL + + "\"crazy'data\"\"here\",-345,-3.45E-4,61 62 63 64 65 66 67,true," + NL + + "C:\\temp\\some_file.txt,25,0.0,,false," + NL; + + assertEquals(expected, out.toString()); + + out = new StringWriter(); + + new ExportUtil.Builder(db, "test") + .setHeader(true) + .setDelimiter("||") + .setQuote('\'') + .exportWriter(new BufferedWriter(out)); + + expected = + "col1||col2||col3||col4||col5||col6" + NL + + "'some text||some more'||13||13.25||'61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78\n79 7A 61 62 63 64'||true||" + testDate + NL + + "'crazy''data\"here'||-345||-3.45E-4||61 62 63 64 65 66 67||true||" + NL + + "C:\\temp\\some_file.txt||25||0.0||||false||" + NL; + assertEquals(expected, out.toString()); + + ExportFilter oddFilter = new SimpleExportFilter() { + private int _num; + @Override + public Object[] filterRow(Object[] row) { + if((_num++ % 2) == 1) { + return null; + } + return row; + } + }; + + out = new StringWriter(); + + new ExportUtil.Builder(db, "test") + .setFilter(oddFilter) + .exportWriter(new BufferedWriter(out)); + + expected = + "some text||some more,13,13.25,\"61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78\n79 7A 61 62 63 64\",true," + testDate + NL + + "C:\\temp\\some_file.txt,25,0.0,,false," + NL; + + assertEquals(expected, out.toString()); + } + } + +} diff --git a/test/src/java/com/healthmarketscience/jackcess/util/ImportTest.java b/test/src/java/com/healthmarketscience/jackcess/util/ImportTest.java new file mode 100644 index 0000000..49be97c --- /dev/null +++ b/test/src/java/com/healthmarketscience/jackcess/util/ImportTest.java @@ -0,0 +1,333 @@ +/* +Copyright (c) 2007 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.util; + +import java.io.File; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.Types; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import com.healthmarketscience.jackcess.Column; +import com.healthmarketscience.jackcess.ColumnBuilder; +import com.healthmarketscience.jackcess.DataType; +import com.healthmarketscience.jackcess.Database; +import static com.healthmarketscience.jackcess.Database.*; +import static com.healthmarketscience.jackcess.DatabaseTest.*; +import com.healthmarketscience.jackcess.Table; +import com.healthmarketscience.jackcess.TableBuilder; +import com.healthmarketscience.jackcess.impl.JetFormatTest; +import junit.framework.TestCase; + +/** + * @author Rob Di Marco + */ +public class ImportTest extends TestCase +{ + + public ImportTest(String name) { + super(name); + } + + public void testImportFromFile() throws Exception + { + for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) { + Database db = create(fileFormat); + String tableName = new ImportUtil.Builder(db, "test") + .setDelimiter("\\t") + .importFile(new File("test/data/sample-input.tab")); + Table t = db.getTable(tableName); + + List colNames = new ArrayList(); + for(Column c : t.getColumns()) { + colNames.add(c.getName()); + } + assertEquals(Arrays.asList("Test1", "Test2", "Test3"), colNames); + + List> expectedRows = + createExpectedTable( + createExpectedRow( + "Test1", "Foo", + "Test2", "Bar", + "Test3", "Ralph"), + createExpectedRow( + "Test1", "S", + "Test2", "Mouse", + "Test3", "Rocks"), + createExpectedRow( + "Test1", "", + "Test2", "Partial line", + "Test3", null), + createExpectedRow( + "Test1", " Quoted Value", + "Test2", " bazz ", + "Test3", " Really \"Crazy" + ImportUtil.LINE_SEPARATOR + + "value\""), + createExpectedRow( + "Test1", "buzz", + "Test2", "embedded\tseparator", + "Test3", "long") + ); + assertTable(expectedRows, t); + + t = new TableBuilder("test2") + .addColumn(new ColumnBuilder("T1", DataType.TEXT)) + .addColumn(new ColumnBuilder("T2", DataType.TEXT)) + .addColumn(new ColumnBuilder("T3", DataType.TEXT)) + .toTable(db); + + new ImportUtil.Builder(db, "test2") + .setDelimiter("\\t") + .setUseExistingTable(true) + .setHeader(false) + .importFile(new File("test/data/sample-input.tab")); + + expectedRows = + createExpectedTable( + createExpectedRow( + "T1", "Test1", + "T2", "Test2", + "T3", "Test3"), + createExpectedRow( + "T1", "Foo", + "T2", "Bar", + "T3", "Ralph"), + createExpectedRow( + "T1", "S", + "T2", "Mouse", + "T3", "Rocks"), + createExpectedRow( + "T1", "", + "T2", "Partial line", + "T3", null), + createExpectedRow( + "T1", " Quoted Value", + "T2", " bazz ", + "T3", " Really \"Crazy" + ImportUtil.LINE_SEPARATOR + + "value\""), + createExpectedRow( + "T1", "buzz", + "T2", "embedded\tseparator", + "T3", "long") + ); + assertTable(expectedRows, t); + + + ImportFilter oddFilter = new SimpleImportFilter() { + private int _num; + @Override + public Object[] filterRow(Object[] row) { + if((_num++ % 2) == 1) { + return null; + } + return row; + } + }; + + tableName = new ImportUtil.Builder(db, "test3") + .setDelimiter("\\t") + .setFilter(oddFilter) + .importFile(new File("test/data/sample-input.tab")); + t = db.getTable(tableName); + + colNames = new ArrayList(); + for(Column c : t.getColumns()) { + colNames.add(c.getName()); + } + assertEquals(Arrays.asList("Test1", "Test2", "Test3"), colNames); + + expectedRows = + createExpectedTable( + createExpectedRow( + "Test1", "Foo", + "Test2", "Bar", + "Test3", "Ralph"), + createExpectedRow( + "Test1", "", + "Test2", "Partial line", + "Test3", null), + createExpectedRow( + "Test1", "buzz", + "Test2", "embedded\tseparator", + "Test3", "long") + ); + assertTable(expectedRows, t); + + db.close(); + } + } + + public void testImportFromFileWithOnlyHeaders() throws Exception + { + for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) { + Database db = create(fileFormat); + String tableName = new ImportUtil.Builder(db, "test") + .setDelimiter("\\t") + .importFile(new File("test/data/sample-input-only-headers.tab")); + + Table t = db.getTable(tableName); + + List colNames = new ArrayList(); + for(Column c : t.getColumns()) { + colNames.add(c.getName()); + } + assertEquals(Arrays.asList( + "RESULT_PHYS_ID", "FIRST", "MIDDLE", "LAST", "OUTLIER", + "RANK", "CLAIM_COUNT", "PROCEDURE_COUNT", + "WEIGHTED_CLAIM_COUNT", "WEIGHTED_PROCEDURE_COUNT"), + colNames); + + db.close(); + } + } + + public void testCopySqlHeaders() throws Exception + { + for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) { + + TestResultSet rs = new TestResultSet(); + + rs.addColumn(Types.INTEGER, "col1"); + rs.addColumn(Types.VARCHAR, "col2", 60, 0, 0); + rs.addColumn(Types.VARCHAR, "col3", 500, 0, 0); + rs.addColumn(Types.BINARY, "col4", 128, 0, 0); + rs.addColumn(Types.BINARY, "col5", 512, 0, 0); + rs.addColumn(Types.NUMERIC, "col6", 0, 7, 15); + rs.addColumn(Types.VARCHAR, "col7", Integer.MAX_VALUE, 0, 0); + + Database db = create(fileFormat); + ImportUtil.importResultSet((ResultSet)Proxy.newProxyInstance( + Thread.currentThread().getContextClassLoader(), + new Class[]{ResultSet.class}, + rs), db, "Test1"); + + Table t = db.getTable("Test1"); + List columns = t.getColumns(); + assertEquals(7, columns.size()); + + Column c = columns.get(0); + assertEquals("col1", c.getName()); + assertEquals(DataType.LONG, c.getType()); + + c = columns.get(1); + assertEquals("col2", c.getName()); + assertEquals(DataType.TEXT, c.getType()); + assertEquals(120, c.getLength()); + + c = columns.get(2); + assertEquals("col3", c.getName()); + assertEquals(DataType.MEMO, c.getType()); + assertEquals(0, c.getLength()); + + c = columns.get(3); + assertEquals("col4", c.getName()); + assertEquals(DataType.BINARY, c.getType()); + assertEquals(128, c.getLength()); + + c = columns.get(4); + assertEquals("col5", c.getName()); + assertEquals(DataType.OLE, c.getType()); + assertEquals(0, c.getLength()); + + c = columns.get(5); + assertEquals("col6", c.getName()); + assertEquals(DataType.NUMERIC, c.getType()); + assertEquals(17, c.getLength()); + assertEquals(7, c.getScale()); + assertEquals(15, c.getPrecision()); + + c = columns.get(6); + assertEquals("col7", c.getName()); + assertEquals(DataType.MEMO, c.getType()); + assertEquals(0, c.getLength()); + } + } + + + private static class TestResultSet implements InvocationHandler + { + private List _types = new ArrayList(); + private List _names = new ArrayList(); + private List _displaySizes = new ArrayList(); + private List _scales = new ArrayList(); + private List _precisions = new ArrayList(); + + public Object invoke(Object proxy, Method method, Object[] args) + { + String methodName = method.getName(); + if(methodName.equals("getMetaData")) { + return Proxy.newProxyInstance( + Thread.currentThread().getContextClassLoader(), + new Class[]{ResultSetMetaData.class}, + this); + } else if(methodName.equals("next")) { + return Boolean.FALSE; + } else if(methodName.equals("getColumnCount")) { + return _types.size(); + } else if(methodName.equals("getColumnName")) { + return getValue(_names, args[0]); + } else if(methodName.equals("getColumnDisplaySize")) { + return getValue(_displaySizes, args[0]); + } else if(methodName.equals("getColumnType")) { + return getValue(_types, args[0]); + } else if(methodName.equals("getScale")) { + return getValue(_scales, args[0]); + } else if(methodName.equals("getPrecision")) { + return getValue(_precisions, args[0]); + } else { + throw new UnsupportedOperationException(methodName); + } + } + + public void addColumn(int type, String name) + { + addColumn(type, name, 0, 0, 0); + } + + public void addColumn(int type, String name, int displaySize, + int scale, int precision) + { + _types.add(type); + _names.add(name); + _displaySizes.add(displaySize); + _scales.add(scale); + _precisions.add(precision); + } + + private static T getValue(List values, Object index) { + return values.get((Integer)index - 1); + } + } + +} diff --git a/test/src/java/com/healthmarketscience/jackcess/util/JoinerTest.java b/test/src/java/com/healthmarketscience/jackcess/util/JoinerTest.java new file mode 100644 index 0000000..975b4fb --- /dev/null +++ b/test/src/java/com/healthmarketscience/jackcess/util/JoinerTest.java @@ -0,0 +1,209 @@ +/* +Copyright (c) 2011 James Ahlborn + +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 +*/ + +package com.healthmarketscience.jackcess.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.healthmarketscience.jackcess.Database; +import static com.healthmarketscience.jackcess.DatabaseTest.*; +import com.healthmarketscience.jackcess.Index; +import com.healthmarketscience.jackcess.Row; +import com.healthmarketscience.jackcess.Table; +import com.healthmarketscience.jackcess.impl.RowImpl; +import static com.healthmarketscience.jackcess.impl.JetFormatTest.*; +import junit.framework.TestCase; + +/** + * + * @author James Ahlborn + */ +public class JoinerTest extends TestCase { + + public JoinerTest(String name) { + super(name); + } + + public void testJoiner() throws Exception + { + for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.INDEX)) { + + Database db = openCopy(testDB); + Table t1 = db.getTable("Table1"); + Table t2 = db.getTable("Table2"); + Table t3 = db.getTable("Table3"); + + Index t1t2 = t1.getIndex("Table2Table1"); + Index t1t3 = t1.getIndex("Table3Table1"); + + Index t2t1 = t1t2.getReferencedIndex(); + assertSame(t2, t2t1.getTable()); + Joiner t2t1Join = Joiner.create(t2t1); + + assertSame(t2, t2t1Join.getFromTable()); + assertSame(t2t1, t2t1Join.getFromIndex()); + assertSame(t1, t2t1Join.getToTable()); + assertSame(t1t2, t2t1Join.getToIndex()); + + doTestJoiner(t2t1Join, createT2T1Data()); + + Index t3t1 = t1t3.getReferencedIndex(); + assertSame(t3, t3t1.getTable()); + Joiner t3t1Join = Joiner.create(t3t1); + + assertSame(t3, t3t1Join.getFromTable()); + assertSame(t3t1, t3t1Join.getFromIndex()); + assertSame(t1, t3t1Join.getToTable()); + assertSame(t1t3, t3t1Join.getToIndex()); + + doTestJoiner(t3t1Join, createT3T1Data()); + + doTestJoinerDelete(t2t1Join); + } + } + + private static void doTestJoiner( + Joiner join, Map> expectedData) + throws Exception + { + final Set colNames = new HashSet( + Arrays.asList("id", "data")); + + Joiner revJoin = join.createReverse(); + for(Row row : join.getFromTable()) { + Integer id = (Integer)row.get("id"); + + List joinedRows = + new ArrayList(); + for(Row t1Row : join.findRowsIterable(row)) { + joinedRows.add(t1Row); + } + + List expectedRows = expectedData.get(id); + assertEquals(expectedData.get(id), joinedRows); + + if(!expectedRows.isEmpty()) { + assertTrue(join.hasRows(row)); + assertEquals(expectedRows.get(0), join.findFirstRow(row)); + + assertEquals(row, revJoin.findFirstRow(expectedRows.get(0))); + } else { + assertFalse(join.hasRows(row)); + assertNull(join.findFirstRow(row)); + } + + List expectedRows2 = new ArrayList(); + for(Row tmpRow : expectedRows) { + Row tmpRow2 = new RowImpl(tmpRow); + tmpRow2.keySet().retainAll(colNames); + expectedRows2.add(tmpRow2); + } + + joinedRows = new ArrayList(); + for(Row t1Row : join.findRowsIterable(row, colNames)) { + joinedRows.add(t1Row); + } + + assertEquals(expectedRows2, joinedRows); + + if(!expectedRows2.isEmpty()) { + assertEquals(expectedRows2.get(0), join.findFirstRow(row, colNames)); + } else { + assertNull(join.findFirstRow(row, colNames)); + } + } + } + + private static void doTestJoinerDelete(Joiner t2t1Join) throws Exception + { + assertEquals(4, countRows(t2t1Join.getToTable())); + + Row row = createExpectedRow("id", 1); + assertTrue(t2t1Join.hasRows(row)); + + assertTrue(t2t1Join.deleteRows(row)); + + assertFalse(t2t1Join.hasRows(row)); + assertFalse(t2t1Join.deleteRows(row)); + + assertEquals(2, countRows(t2t1Join.getToTable())); + for(Row t1Row : t2t1Join.getToTable()) { + assertFalse(t1Row.get("otherfk1").equals(1)); + } + } + + private static Map> createT2T1Data() + { + Map> data = new + HashMap>(); + + data.put(0, + createExpectedTable( + createExpectedRow("id", 0, "otherfk1", 0, "otherfk2", 10, + "data", "baz0", "otherfk3", 0))); + + data.put(1, + createExpectedTable( + createExpectedRow("id", 1, "otherfk1", 1, "otherfk2", 11, + "data", "baz11", "otherfk3", 0), + createExpectedRow("id", 2, "otherfk1", 1, "otherfk2", 11, + "data", "baz11-2", "otherfk3", 0))); + + data.put(2, + createExpectedTable( + createExpectedRow("id", 3, "otherfk1", 2, "otherfk2", 13, + "data", "baz13", "otherfk3", 0))); + + return data; + } + + private static Map> createT3T1Data() + { + Map> data = new HashMap>(); + + data.put(10, + createExpectedTable( + createExpectedRow("id", 0, "otherfk1", 0, "otherfk2", 10, + "data", "baz0", "otherfk3", 0))); + + data.put(11, + createExpectedTable( + createExpectedRow("id", 1, "otherfk1", 1, "otherfk2", 11, + "data", "baz11", "otherfk3", 0), + createExpectedRow("id", 2, "otherfk1", 1, "otherfk2", 11, + "data", "baz11-2", "otherfk3", 0))); + + data.put(12, + createExpectedTable()); + + data.put(13, + createExpectedTable( + createExpectedRow("id", 3, "otherfk1", 2, "otherfk2", 13, + "data", "baz13", "otherfk3", 0))); + + return data; + } + +} diff --git a/test/src/java/com/healthmarketscience/jackcess/util/MemFileChannelTest.java b/test/src/java/com/healthmarketscience/jackcess/util/MemFileChannelTest.java new file mode 100644 index 0000000..3e78a2c --- /dev/null +++ b/test/src/java/com/healthmarketscience/jackcess/util/MemFileChannelTest.java @@ -0,0 +1,164 @@ +/* +Copyright (c) 2012 James Ahlborn + +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 +*/ + +package com.healthmarketscience.jackcess.util; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.NonWritableChannelException; +import java.util.Arrays; + +import junit.framework.TestCase; + +import com.healthmarketscience.jackcess.DatabaseTest; + +/** + * + * @author James Ahlborn + */ +public class MemFileChannelTest extends TestCase +{ + + public MemFileChannelTest(String name) { + super(name); + } + + public void testReadOnlyChannel() throws Exception + { + File testFile = new File("test/data/V1997/compIndexTestV1997.mdb"); + MemFileChannel ch = MemFileChannel.newChannel(testFile, "r"); + assertEquals(testFile.length(), ch.size()); + assertEquals(0L, ch.position()); + + try { + ByteBuffer bb = ByteBuffer.allocate(1024); + ch.write(bb); + fail("NonWritableChannelException should have been thrown"); + } catch(NonWritableChannelException ignored) { + // success + } + + try { + ch.truncate(0L); + fail("NonWritableChannelException should have been thrown"); + } catch(NonWritableChannelException ignored) { + // success + } + + try { + ch.transferFrom(null, 0L, 10L); + fail("NonWritableChannelException should have been thrown"); + } catch(NonWritableChannelException ignored) { + // success + } + + assertEquals(testFile.length(), ch.size()); + assertEquals(0L, ch.position()); + + ch.close(); + } + + public void testChannel() throws Exception + { + ByteBuffer bb = ByteBuffer.allocate(1024); + + MemFileChannel ch = MemFileChannel.newChannel(); + assertTrue(ch.isOpen()); + assertEquals(0L, ch.size()); + assertEquals(0L, ch.position()); + assertEquals(-1, ch.read(bb)); + + ch.close(); + + assertFalse(ch.isOpen()); + + File testFile = new File("test/data/V1997/compIndexTestV1997.mdb"); + ch = MemFileChannel.newChannel(testFile, "r"); + assertEquals(testFile.length(), ch.size()); + assertEquals(0L, ch.position()); + + try { + ch.position(-1); + fail("IllegalArgumentException should have been thrown"); + } catch(IllegalArgumentException ignored) { + // success + } + + MemFileChannel ch2 = MemFileChannel.newChannel(); + ch.transferTo(ch2); + ch2.force(true); + assertEquals(testFile.length(), ch2.size()); + assertEquals(testFile.length(), ch2.position()); + + try { + ch2.truncate(-1L); + fail("IllegalArgumentException should have been thrown"); + } catch(IllegalArgumentException ignored) { + // success + } + + long trucSize = ch2.size()/3; + ch2.truncate(trucSize); + assertEquals(trucSize, ch2.size()); + assertEquals(trucSize, ch2.position()); + ch2.position(0L); + copy(ch, ch2, bb); + + File tmpFile = File.createTempFile("chtest_", ".dat"); + tmpFile.deleteOnExit(); + FileOutputStream fc = new FileOutputStream(tmpFile); + + ch2.transferTo(fc); + + fc.close(); + + assertEquals(testFile.length(), tmpFile.length()); + + assertTrue(Arrays.equals(DatabaseTest.toByteArray(testFile), + DatabaseTest.toByteArray(tmpFile))); + + ch2.truncate(0L); + assertTrue(ch2.isOpen()); + assertEquals(0L, ch2.size()); + assertEquals(0L, ch2.position()); + assertEquals(-1, ch2.read(bb)); + + ch2.close(); + assertFalse(ch2.isOpen()); + } + + private static void copy(FileChannel src, FileChannel dst, ByteBuffer bb) + throws IOException + { + src.position(0L); + while(true) { + bb.clear(); + if(src.read(bb) < 0) { + break; + } + bb.flip(); + dst.write(bb); + } + } + +} diff --git a/test/src/java/com/healthmarketscience/jackcess/util/RowFilterTest.java b/test/src/java/com/healthmarketscience/jackcess/util/RowFilterTest.java new file mode 100644 index 0000000..7808a08 --- /dev/null +++ b/test/src/java/com/healthmarketscience/jackcess/util/RowFilterTest.java @@ -0,0 +1,114 @@ +/* +Copyright (c) 2008 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.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.healthmarketscience.jackcess.DataType; +import static com.healthmarketscience.jackcess.DatabaseTest.*; +import com.healthmarketscience.jackcess.Row; +import com.healthmarketscience.jackcess.impl.ColumnImpl; +import junit.framework.TestCase; + +/** + * @author James Ahlborn + */ +public class RowFilterTest extends TestCase +{ + private static final String ID_COL = "id"; + private static final String COL1 = "col1"; + private static final String COL2 = "col2"; + private static final String COL3 = "col3"; + + + public RowFilterTest(String name) { + super(name); + } + + @SuppressWarnings("unchecked") + public void testFilter() throws Exception + { + Row row0 = createExpectedRow(ID_COL, 0, COL1, "foo", COL2, 13, COL3, "bar"); + Row row1 = createExpectedRow(ID_COL, 1, COL1, "bar", COL2, 42, COL3, null); + Row row2 = createExpectedRow(ID_COL, 2, COL1, "foo", COL2, 55, COL3, "bar"); + Row row3 = createExpectedRow(ID_COL, 3, COL1, "baz", COL2, 42, COL3, "bar"); + Row row4 = createExpectedRow(ID_COL, 4, COL1, "foo", COL2, 13, COL3, null); + Row row5 = createExpectedRow(ID_COL, 5, COL1, "bla", COL2, 13, COL3, "bar"); + + + List rows = Arrays.asList(row0, row1, row2, row3, row4, row5); + + ColumnImpl testCol = new ColumnImpl(null, DataType.TEXT, 0, 0, 0) {}; + testCol.setName(COL1); + assertEquals(Arrays.asList(row0, row2, row4), + toList(RowFilter.matchPattern(testCol, + "foo").apply(rows))); + assertEquals(Arrays.asList(row1, row3, row5), + toList(RowFilter.invert( + RowFilter.matchPattern( + testCol, + "foo")).apply(rows))); + + assertEquals(Arrays.asList(row0, row2, row4), + toList(RowFilter.matchPattern( + createExpectedRow(COL1, "foo")) + .apply(rows))); + assertEquals(Arrays.asList(row0, row2), + toList(RowFilter.matchPattern( + createExpectedRow(COL1, "foo", COL3, "bar")) + .apply(rows))); + assertEquals(Arrays.asList(row4), + toList(RowFilter.matchPattern( + createExpectedRow(COL1, "foo", COL3, null)) + .apply(rows))); + assertEquals(Arrays.asList(row0, row4, row5), + toList(RowFilter.matchPattern( + createExpectedRow(COL2, 13)) + .apply(rows))); + assertEquals(Arrays.asList(row1), + toList(RowFilter.matchPattern(row1) + .apply(rows))); + + assertEquals(rows, toList(RowFilter.apply(null, rows))); + assertEquals(Arrays.asList(row1), + toList(RowFilter.apply(RowFilter.matchPattern(row1), + rows))); + } + + public static List toList(Iterable rows) + { + List rowList = new ArrayList(); + for(Row row : rows) { + rowList.add(row); + } + return rowList; + } + +} -- cgit v1.2.3