diff options
author | James Ahlborn <jtahlborn@yahoo.com> | 2008-03-10 15:22:09 +0000 |
---|---|---|
committer | James Ahlborn <jtahlborn@yahoo.com> | 2008-03-10 15:22:09 +0000 |
commit | f2bc4572f4b2a6ccf62153c8fd513cb7a1a591ad (patch) | |
tree | d418f52ad9803afbb9013de54f76106ba330c4b0 | |
parent | 022d94d13c1263386049b8ddf2eb9fd5b8de43b1 (diff) | |
download | jackcess-f2bc4572f4b2a6ccf62153c8fd513cb7a1a591ad.tar.gz jackcess-f2bc4572f4b2a6ccf62153c8fd513cb7a1a591ad.zip |
add tests for the various supported index types
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@259 f203690c-595d-4dc9-a70b-905162fa7fd2
-rwxr-xr-x | test/data/testIndexCodes.mdb | bin | 0 -> 3833856 bytes | |||
-rw-r--r-- | test/src/java/com/healthmarketscience/jackcess/IndexCodesTest.java | 394 |
2 files changed, 394 insertions, 0 deletions
diff --git a/test/data/testIndexCodes.mdb b/test/data/testIndexCodes.mdb Binary files differnew file mode 100755 index 0000000..957f99b --- /dev/null +++ b/test/data/testIndexCodes.mdb diff --git a/test/src/java/com/healthmarketscience/jackcess/IndexCodesTest.java b/test/src/java/com/healthmarketscience/jackcess/IndexCodesTest.java new file mode 100644 index 0000000..8e3ee2b --- /dev/null +++ b/test/src/java/com/healthmarketscience/jackcess/IndexCodesTest.java @@ -0,0 +1,394 @@ +/* +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.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +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.*; + + +/** + * @author James Ahlborn + */ +public class IndexCodesTest extends TestCase { + + private static final Map<Character,String> SPECIAL_CHARS = + new HashMap<Character,String>(); + 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 + { + Database db = Database.open(new File("test/data/testIndexCodes.mdb")); + + for(Table t : db) { + for(Index index : t.getIndexes()) { +// System.out.println("Checking " + t.getName() + "." + index.getName()); + checkIndexEntries(t, index); + } + } + + db.close(); + } + + private static void checkIndexEntries(Table t, Index index) throws Exception + { +// index.initialize(); +// System.out.println("Ind " + index); + + Cursor cursor = Cursor.createIndexCursor(t, index); + while(cursor.moveToNextRow()) { + + Map<String,Object> row = cursor.getCurrentRow(); + Cursor.Position curPos = cursor.getSavepoint().getCurrentPosition(); + boolean success = false; + try { + findRow(t, index, row, curPos); + success = true; + } finally { + if(!success) { + System.out.println("CurPos: " + curPos); + System.out.println("Value: " + row); + } + } + } + + } + + private static void findRow(Table t, Index index, + Map<String,Object> 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<String,Object> 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; + } + } + fail("Could 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(true); + + List<Column> columns = new ArrayList<Column>(); + Column col = new Column(); + col.setName("row"); + col.setType(DataType.TEXT); + columns.add(col); + col = new Column(); + col.setName("data"); + col.setType(DataType.TEXT); + columns.add(col); + + db.createTable("test", columns); + + Table t = db.getTable("test"); + + 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(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_testReadIsoMdb() throws Exception + { +// Database db = Database.open(new File("/tmp/test_ind.mdb")); +// Database db = Database.open(new File("/tmp/test_ind2.mdb")); + Database db = Database.open(new File("/tmp/test_ind3.mdb")); +// Database db = Database.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_testReverseIsoMdb() throws Exception + { +// Database db = Database.open(new File("/tmp/test_ind.mdb")); + Database db = Database.open(new File("/tmp/test_ind2.mdb")); +// Database db = Database.open(new File("/tmp/databaseTest14366_ind.mdb")); +// Database db = Database.open(new File("/tmp/databaseTest56165_ind.mdb")); +// Database db = Database.open(new File("/tmp/databaseTest53970_ind.mdb")); + + Table t = db.getTable("Table1"); + Index index = t.getIndex("B"); + 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 inatPat = Pattern.compile("7F 4A 4A (.*)4A 4A 01 02 02 (.+) 00"); + + Map<Character,String[]> inlineCodes = new TreeMap<Character,String[]>(); + Map<Character,String[]> unprintCodes = new TreeMap<Character,String[]>(); + Map<Character,String[]> inatInlineCodes = new TreeMap<Character,String[]>(); + Map<Character,String[]> inatExtraCodes = new TreeMap<Character,String[]>(); + + 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<String,Object> row = cursor.getCurrentRow(); + String value = (String)row.get("B"); + 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: " + 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")) { + + // 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")) { + + // 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 { + + throw new RuntimeException("unhandled " + entryStr); + } + + System.out.println("Type: " + type); + } + +// System.out.println("Normal " + inlineCodes); +// System.out.println("Unprintable " + unprintCodes); +// System.out.println("International " + inatCodes); + System.out.println("\n***INLINE"); + for(Map.Entry<Character,String[]> e : inlineCodes.entrySet()) { + System.out.println( + generateCodeString("registerCodes", e.getKey(), e.getValue(), + null)); + } + System.out.println("\n***UNPRINTABLE"); + for(Map.Entry<Character,String[]> e : unprintCodes.entrySet()) { + System.out.println( + generateCodeString("registerUnprintableCodes", + e.getKey(), e.getValue(), null)); + } + System.out.println("\n***INTERNATIONAL"); + for(Map.Entry<Character,String[]> e : inatInlineCodes.entrySet()) { + + System.out.println( + generateCodeString("registerInternationalCodes", + e.getKey(), e.getValue(), + inatExtraCodes.get(e.getKey()))); + } + + db.close(); + } + + private static String generateCodeString(String methodName, + char c, + String[] charStrs1, + String[] charStrs2) + { + StringBuilder builder = new StringBuilder() + .append(methodName).append("('").append(toUnicodeStr(c)) + .append("', new byte[]{") + .append(join(charStrs1, ", ", "(byte)0x")) + .append("}"); + if(charStrs2 != null) { + builder.append(",\nnew byte[]{") + .append(join(charStrs2, ", ", "(byte)0x")) + .append("}"); + } + builder.append(");"); + return builder.toString(); + } + + private static void handleInlineEntry( + String entryCodes, char c, Map<Character,String[]> inlineCodes) + throws Exception + { + inlineCodes.put(c, entryCodes.trim().split(" ")); + } + + private static void handleUnprintableEntry( + String entryCodes, char c, Map<Character,String[]> unprintCodes) + throws Exception + { + unprintCodes.put(c, entryCodes.trim().split(" ")); + } + + private static void handleInternationalEntry( + String inlineCodes, String entryCodes, char c, + Map<Character,String[]> inatInlineCodes, + Map<Character,String[]> inatExtraCodes) + throws Exception + { + inatInlineCodes.put(c, inlineCodes.trim().split(" ")); + inatExtraCodes.put(c, entryCodes.trim().split(" ")); + } + + private static String toUnicodeStr(char c) { + 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) { + 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(); + } + + private static String entryToString(Cursor.Position curPos) + throws Exception + { + Field eField = curPos.getClass().getDeclaredField("_entry"); + eField.setAccessible(true); + Index.Entry entry = (Index.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}+", " "); + } + +} |