View Javadoc
1   package com.healthmarketscience.jackcess.impl;
2   
3   import java.io.File;
4   import java.io.IOException;
5   import java.io.InputStream;
6   import java.nio.channels.FileChannel;
7   import java.nio.channels.NonWritableChannelException;
8   import java.util.ArrayList;
9   import java.util.EnumSet;
10  import java.util.List;
11  import java.util.Set;
12  
13  import com.healthmarketscience.jackcess.Database;
14  import static com.healthmarketscience.jackcess.Database.*;
15  import com.healthmarketscience.jackcess.DatabaseBuilder;
16  import com.healthmarketscience.jackcess.PropertyMap;
17  import junit.framework.TestCase;
18  import static com.healthmarketscience.jackcess.TestUtil.*;
19  
20  
21  /**
22   * @author Dan Rollo
23   *         Date: Mar 5, 2010
24   *         Time: 12:44:21 PM
25   */
26  public class JetFormatTest extends TestCase {
27  
28    public static final File DIR_TEST_DATA = new File("src/test/data");
29  
30    /**
31     * Defines known valid db test file base names.
32     */
33    public static enum Basename {
34  
35      BIG_INDEX("bigIndexTest"),
36      COMP_INDEX("compIndexTest"),
37      DEL_COL("delColTest"),
38      DEL("delTest"),
39      FIXED_NUMERIC("fixedNumericTest"),
40      FIXED_TEXT("fixedTextTest"),
41      INDEX_CURSOR("indexCursorTest"),
42      INDEX("indexTest"),
43      OVERFLOW("overflowTest"),
44      QUERY("queryTest"),
45      TEST("test"),
46      TEST2("test2"),
47      INDEX_CODES("testIndexCodes"),
48      INDEX_PROPERTIES("testIndexProperties"),
49      PROMOTION("testPromotion"),
50      COMPLEX("complexDataTest"),
51      UNSUPPORTED("unsupportedFieldsTest"),
52      LINKED("linkerTest"),
53      BLOB("testOle"),
54      CALC_FIELD("calcFieldTest"),
55      BINARY_INDEX("binIdxTest"),
56      OLD_DATES("oldDates");
57  
58      private final String _basename;
59  
60      Basename(String fileBasename) {
61        _basename = fileBasename;
62      }
63  
64      @Override
65      public String toString() { return _basename; }
66    }
67  
68    /** Defines currently supported db file formats.  (can be modified at
69        runtime via the system property
70        "com.healthmarketscience.jackcess.testFormats") */
71    public final static FileFormat[] SUPPORTED_FILEFORMATS;
72    public final static FileFormat[] SUPPORTED_FILEFORMATS_FOR_READ;
73  
74    static {
75      String testFormatStr = System.getProperty("com.healthmarketscience.jackcess.testFormats");
76      Set<FileFormat> testFormats = EnumSet.allOf(FileFormat.class);
77      if((testFormatStr != null) && (testFormatStr.length() > 0)) {
78        testFormats.clear();
79        for(String tmp : testFormatStr.split(",")) {
80          testFormats.add(FileFormat.valueOf(tmp.toUpperCase()));
81        }
82      }
83  
84      List<FileFormat> supported = new ArrayList<FileFormat>();
85      List<FileFormat> supportedForRead = new ArrayList<FileFormat>();
86      for(FileFormat ff : FileFormat.values()) {
87        if(!testFormats.contains(ff)) {
88          continue;
89        }
90        supportedForRead.add(ff);
91        if(DatabaseImpl.getFileFormatDetails(ff).getFormat().READ_ONLY ||
92           (ff == FileFormat.MSISAM)) {
93          continue;
94        }
95        supported.add(ff);
96      }
97  
98      SUPPORTED_FILEFORMATS = supported.toArray(new FileFormat[0]);
99      SUPPORTED_FILEFORMATS_FOR_READ = 
100       supportedForRead.toArray(new FileFormat[0]);
101   }
102 
103   /**
104    * Defines known valid test database files, and their jet format version.
105    */
106   public static final class TestDB {
107 
108     private final File dbFile;
109     private final FileFormat expectedFileFormat;
110 
111     private TestDB(File databaseFile, 
112                    FileFormat expectedDBFileFormat) {
113 
114       dbFile = databaseFile;
115       expectedFileFormat = expectedDBFileFormat;
116     }
117 
118     public final File getFile() { return dbFile; }
119 
120     public final FileFormat  getExpectedFileFormat() { 
121       return expectedFileFormat; 
122     }
123 
124     public final JetFormat getExpectedFormat() { 
125       return DatabaseImpl.getFileFormatDetails(expectedFileFormat).getFormat(); 
126     }
127 
128     @Override
129     public final String toString() {
130       return "dbFile: " + dbFile.getAbsolutePath()
131         + "; expectedFileFormat: " + expectedFileFormat;
132     }
133 
134     public static List<TestDB> getSupportedForBasename(Basename basename) {
135       return getSupportedForBasename(basename, false);
136     }
137 
138     public static List<TestDB> getSupportedForBasename(Basename basename,
139                                                        boolean readOnly) {
140 
141       List<TestDB> supportedTestDBs = new ArrayList<TestDB>();
142       for (FileFormat fileFormat : 
143              (readOnly ? SUPPORTED_FILEFORMATS_FOR_READ :
144               SUPPORTED_FILEFORMATS)) {
145         File testFile = getFileForBasename(basename, fileFormat);
146         if(!testFile.exists()) {
147           continue;
148         }
149         
150         // verify that the db is the file format expected
151         try {
152           Database db = new DatabaseBuilder(testFile).setReadOnly(true).open();
153           FileFormat dbFileFormat = db.getFileFormat();
154           db.close();
155           if(dbFileFormat != fileFormat) {
156             throw new IllegalStateException("Expected " + fileFormat +
157                                             " was " + dbFileFormat);
158           }
159         } catch(Exception e) {
160           throw new RuntimeException(e);
161         }
162 
163         supportedTestDBs.add(new TestDB(testFile, fileFormat));
164       }
165       return supportedTestDBs;
166     }
167 
168     private static File getFileForBasename(
169         Basename basename, FileFormat fileFormat) {
170 
171       return new File(DIR_TEST_DATA, 
172                       fileFormat.name() + File.separator +
173                       basename + fileFormat.name() + 
174                       fileFormat.getFileExtension());
175     }
176   }
177 
178   public static final List<TestDB> SUPPORTED_DBS_TEST = 
179     TestDB.getSupportedForBasename(Basename.TEST);
180   public static final List<TestDB> SUPPORTED_DBS_TEST_FOR_READ = 
181     TestDB.getSupportedForBasename(Basename.TEST, true);
182 
183 
184   public void testGetFormat() throws Exception {
185     try {
186       JetFormat.getFormat(null);
187       fail("npe");
188     } catch (NullPointerException e) {
189       // success
190     }
191 
192     for (final TestDB testDB : SUPPORTED_DBS_TEST_FOR_READ) {
193 
194       final FileChannel channel = DatabaseImpl.openChannel(testDB.dbFile, false);
195       try {
196 
197         JetFormat fmtActual = JetFormat.getFormat(channel);
198         assertEquals("Unexpected JetFormat for dbFile: " + 
199                      testDB.dbFile.getAbsolutePath(),
200                      testDB.getExpectedFormat(), fmtActual);
201 
202       } finally {
203         channel.close();
204       }
205 
206     }
207   }
208 
209   public void testReadOnlyFormat() throws Exception {
210 
211     for (final TestDB testDB : SUPPORTED_DBS_TEST_FOR_READ) {
212 
213       Database db = null;
214       Exception failure = null;
215       try {
216         db = openCopy(testDB);
217 
218         if(testDB.getExpectedFormat().READ_ONLY) {
219           PropertyMap props = db.getUserDefinedProperties();
220           props.put("foo", "bar");
221           props.save();
222         } 
223 
224       } catch(Exception e) {
225         failure = e;
226       } finally {
227         if(db != null) {
228           db.close();
229         }
230       }
231 
232       if(!testDB.getExpectedFormat().READ_ONLY) {
233         assertNull(failure);
234       } else {
235         assertTrue(failure instanceof NonWritableChannelException);
236       }
237 
238     }
239   }
240 
241   public void testFileFormat() throws Exception {
242 
243     for (final TestDB testDB : SUPPORTED_DBS_TEST_FOR_READ) {
244 
245       Database db = null;
246       try {
247         db = open(testDB);
248         assertEquals(testDB.getExpectedFileFormat(), db.getFileFormat());
249       } finally {
250         if(db != null) {
251           db.close();
252         }
253       }
254     }
255 
256     Database db = null;
257     try {
258       db = open(Database.FileFormat.GENERIC_JET4,
259                 new File(DIR_TEST_DATA, "adox_jet4.mdb"));
260       assertEquals(Database.FileFormat.GENERIC_JET4, db.getFileFormat());
261     } finally {
262       if(db != null) {
263         db.close();
264       }
265     }
266   }
267 
268   public static void transferDbFrom(FileChannel channel, InputStream in)
269     throws IOException
270   {
271     DatabaseImpl.transferDbFrom(channel, in);
272   }
273 }