001: /*
002: * $Id: TestFixedWidthFlatfileTable.java,v 1.13 2005/12/20 19:08:58 ahimanikya Exp $
003: * =======================================================================
004: * Copyright (c) 2002 Axion Development Team. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above
011: * copyright notice, this list of conditions and the following
012: * disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * 3. The names "Tigris", "Axion", nor the names of its contributors may
020: * not be used to endorse or promote products derived from this
021: * software without specific prior written permission.
022: *
023: * 4. Products derived from this software may not be called "Axion", nor
024: * may "Tigris" or "Axion" appear in their names without specific prior
025: * written permission.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
028: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
029: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
030: * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
031: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
032: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
033: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
034: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
035: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
036: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
037: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
038: * =======================================================================
039: */
040:
041: package org.axiondb.engine.tables;
042:
043: import java.io.File;
044: import java.io.FileWriter;
045: import java.util.ArrayList;
046: import java.util.List;
047: import java.util.Properties;
048: import java.util.Random;
049:
050: import junit.framework.Test;
051: import junit.framework.TestSuite;
052:
053: import org.axiondb.AxionException;
054: import org.axiondb.Column;
055: import org.axiondb.ColumnIdentifier;
056: import org.axiondb.Database;
057: import org.axiondb.ExternalTable;
058: import org.axiondb.ExternalTableLoader;
059: import org.axiondb.Row;
060: import org.axiondb.RowIterator;
061: import org.axiondb.Table;
062: import org.axiondb.TableIdentifier;
063: import org.axiondb.engine.DiskDatabase;
064: import org.axiondb.engine.commands.AxionQueryContext;
065: import org.axiondb.engine.commands.CreateTableCommand;
066: import org.axiondb.engine.commands.SubSelectCommand;
067: import org.axiondb.engine.rows.SimpleRow;
068: import org.axiondb.types.BooleanType;
069: import org.axiondb.types.CharacterVaryingType;
070: import org.axiondb.types.IntegerType;
071:
072: /**
073: * @version $Revision: 1.13 $ $Date: 2005/12/20 19:08:58 $
074: * @author Ahimanikya Satapathy
075: */
076: public class TestFixedWidthFlatfileTable extends AbstractTableTest {
077:
078: //------------------------------------------------------------ Conventional
079:
080: public TestFixedWidthFlatfileTable(String testName) {
081: super (testName);
082: }
083:
084: public static Test suite() {
085: TestSuite suite = new TestSuite(
086: TestFixedWidthFlatfileTable.class);
087: return suite;
088: }
089:
090: //--------------------------------------------------------------- Lifecycle
091:
092: //--------------------------------------------------------------- Lifecycle
093:
094: protected DiskDatabase _db = null;
095: protected String tableName = null;
096: protected String dataFileName = null;
097:
098: protected Table createTable(String name) throws Exception {
099: tableName = name;
100: ExternalTableLoader loader = new FixedWidthFlatfileTableLoader();
101: ExternalTable t = (ExternalTable) loader.createTable(_db, name);
102: t.loadExternalTable(setProperties(name));
103: return t;
104: }
105:
106: protected Database getDatabase() throws Exception {
107: return _db;
108: }
109:
110: protected File getDataFile() throws Exception {
111: return new File(getDbdir(), dataFileName);
112: }
113:
114: protected Properties setProperties(String name) {
115: Properties props = new Properties();
116:
117: props.setProperty(ExternalTable.PROP_LOADTYPE, "fixedwidth");
118: String eol = System.getProperty("line.separator");
119: props.setProperty(BaseFlatfileTable.PROP_RECORDDELIMITER, eol);
120: props.setProperty(BaseFlatfileTable.PROP_ISFIRSTLINEHEADER,
121: "false");
122:
123: dataFileName = name + ".txt";
124: props
125: .setProperty(BaseFlatfileTable.PROP_FILENAME,
126: dataFileName);
127:
128: return props;
129: }
130:
131: protected String getTableName() {
132: return tableName != null ? tableName : "FWTXT";
133: }
134:
135: public void setUp() throws Exception {
136: getDbdir().mkdirs();
137: _db = new DiskDatabase(getDbdir());
138: super .setUp();
139: }
140:
141: public void tearDown() throws Exception {
142: super .tearDown();
143: _db.shutdown();
144: File data = new File(getDbdir(), tableName + ".txt");
145: data.delete();
146: }
147:
148: //------------------------------------------------------------------- Tests
149:
150: public void testObjectTable() throws Exception {
151: // TODO: Make this test pass, define a interface MarshallableObject for method
152: // toString and toObject, or or MarshallableXMLObject toXMLString , toObject , If
153: // the Object implement this then we can use them in flat file.
154: }
155:
156: public void testInvalidPropertyKey() throws Exception {
157: try {
158: Properties badProps = new Properties();
159: badProps.put(ExternalTable.PROP_LOADTYPE, "fixedwidth");
160: badProps.put("UNKNOWN_PROPERTY", Boolean.TRUE);
161: ExternalTableFactory factory = new ExternalTableFactory();
162: factory.createTable(_db, "BADTABLE", badProps,
163: buildColumns());
164: fail("Expected AxionException due to unrecognized property name 'UNKNOWN_PROPERTY'");
165: } catch (AxionException expected) {
166: // Expected AxionException due to unrecognized property name.
167: }
168: }
169:
170: public void testDataTypes() throws Exception {
171: Table typeTable = createTable("TYPETABLE");
172:
173: ((ExternalTable) typeTable)
174: .loadExternalTable(setProperties("TYPETABLE"));
175:
176: typeTable.addColumn(new Column("STRCOL",
177: new CharacterVaryingType(255)));
178: typeTable.addColumn(new Column("INTCOL", new IntegerType()));
179: Column bolCol = new Column("BOOLCOL", new BooleanType());
180: typeTable.addColumn(bolCol);
181:
182: // This will allow us to test truncating value
183: // note: unless user mentioned a size for string its default to 255
184: String name = "";
185: for (int i = 0; i < 10; i++) {
186: name += "cccddvvffvv";
187: }
188:
189: Object[][] values = new Object[][] {
190: new Object[] { "", "A String", name, null },
191: new Object[] { new Integer(17), new Integer(0),
192: new Integer(5575), null },
193: new Object[] { Boolean.TRUE, Boolean.TRUE,
194: Boolean.FALSE, null } };
195:
196: Random random = new Random();
197: int numRows = 7;
198:
199: for (int i = 0; i < numRows; i++) {
200: Row row = new SimpleRow(typeTable.getColumnCount());
201: for (int j = 0; j < typeTable.getColumnCount(); j++) {
202: row.set(j, values[j][random.nextInt(values[j].length)]);
203: }
204: typeTable.addRow(row);
205: }
206:
207: RowIterator iter = typeTable.getRowIterator(true);
208: assertNotNull(iter);
209: for (int i = 0; i < numRows; i++) {
210: assertTrue(iter.hasNext());
211: assertNotNull(iter.next());
212: }
213: assertTrue(!iter.hasNext());
214: typeTable.shutdown();
215: }
216:
217: public void testDiskInsert() throws Exception {
218: testAddRow();
219: table.shutdown();
220: File data = new File(getDbdir(), "FWTXT.txt");
221: assertTrue("Should have data file", data.exists());
222: assertTrue("Should have some data in data file",
223: data.length() > 43);
224: }
225:
226: public void testDiskDrop() throws Exception {
227: testAddRow();
228: File tabledir = new File(getDbdir(), "FWTXT");
229: File meta = new File(tabledir, "FWTXT.META");
230: assertTrue("Table directory should exist", tabledir.exists());
231: assertTrue("Meta file should exist", meta.exists());
232: table.drop();
233: assertTrue("Meta file should not exist", !meta.exists());
234: assertTrue("Table directory should not exist", !tabledir
235: .exists());
236: }
237:
238: public void testRemount() throws Exception {
239: testAddRow();
240: ((ExternalTable) table).remount();
241:
242: RowIterator iter = table.getRowIterator(true);
243: assertNotNull(iter);
244: assertTrue(iter.hasNext());
245: assertNotNull(iter.next());
246: assertTrue(iter.hasNext());
247: assertNotNull(iter.next());
248: assertTrue(!iter.hasNext());
249: }
250:
251: public void testFileRead() throws Exception {
252: File data = new File(getDbdir(), "FFTest.txt");
253: FileWriter out = new FileWriter(data);
254:
255: String eol = System.getProperty("line.separator");
256:
257: out.write("ID NAME " + eol); // Header
258: out.write("1 aa " + eol); // 1
259: out.write("2.00 bbb " + eol); // 2
260: out.write("3.00 ccc " + eol); // 3
261: out.write("4.00 ddd " + eol); // 4
262: out.write("" + eol); // skip
263: out.write("we " + eol); // bad 1
264: out.write("7 dfdf " + eol); // 5
265: out.write("7.0f ccc " + eol); // 6
266: out.write("xx xx " + eol); // bad 2
267: out.write("5 test " + eol); // 7
268: out.write("10-1 hhhh " + eol); // bad 3
269: out.write(" " + eol); // bad 4
270: out.close();
271:
272: ExternalTableFactory factory = new ExternalTableFactory();
273: Properties prop = setProperties("FFTest");
274: prop.put(BaseFlatfileTable.PROP_ISFIRSTLINEHEADER, "true");
275: prop.put(BaseFlatfileTable.PROP_ROWSTOSKIP, "1");
276:
277: try {
278: Table table2 = factory.createTable(_db, "FFTEST", prop,
279: buildColumns());
280: RowIterator itr = table2.getRowIterator(false);
281:
282: int rowCount = 0;
283: while (itr.hasNext()) {
284: itr.next();
285: rowCount++;
286: }
287:
288: assertEquals("Valid row count should have correct value",
289: 7, rowCount);
290: table2.drop();
291:
292: prop.put(BaseFlatfileTable.PROP_MAXFAULTS, "2");
293:
294: try {
295: table2 = factory.createTable(_db, "FFTEST", prop,
296: buildColumns());
297: itr = table2.getRowIterator(false);
298: while (itr.hasNext()) {
299: itr.next();
300: }
301: fail("Expected Exception");
302: } catch (Exception e) {
303: // expected
304: }
305: table2.drop();
306:
307: // bad property value, should use default value
308: prop.put(BaseFlatfileTable.PROP_MAXFAULTS, "-10");
309: prop.put(BaseFlatfileTable.PROP_ROWSTOSKIP, "-10");
310:
311: table2 = factory.createTable(_db, "FFTEST", prop,
312: buildColumns());
313: itr = table2.getRowIterator(false);
314:
315: rowCount = 0;
316: while (itr.hasNext()) {
317: itr.next();
318: rowCount++;
319: }
320:
321: assertEquals("Valid row count should have correct value",
322: 7, rowCount);
323: table2.drop();
324:
325: // bad property value, should use default value
326: prop.put(BaseFlatfileTable.PROP_MAXFAULTS, "ABC");
327: prop.put(BaseFlatfileTable.PROP_ROWSTOSKIP, "ABC");
328:
329: table2 = factory.createTable(_db, "FFTEST", prop,
330: buildColumns());
331: itr = table2.getRowIterator(false);
332:
333: rowCount = 0;
334: while (itr.hasNext()) {
335: itr.next();
336: rowCount++;
337: }
338:
339: assertEquals("Valid row count should have correct value",
340: 7, rowCount);
341: table2.drop();
342:
343: prop.put(BaseFlatfileTable.PROP_MAXFAULTS, "5");
344: prop.put(BaseFlatfileTable.PROP_ROWSTOSKIP, "0");
345: table2 = factory.createTable(_db, "FFTEST", prop,
346: buildColumns());
347: itr = table2.getRowIterator(false);
348:
349: rowCount = 0;
350: while (itr.hasNext()) {
351: itr.next();
352: rowCount++;
353: }
354:
355: assertEquals("Valid row count should have correct value",
356: 7, rowCount);
357:
358: _db.addTable(table2);
359: CreateTableCommand cmd = new CreateTableCommand();
360: cmd.setObjectName("FFTEST2");
361: cmd.setType("external");
362: prop.put(BaseFlatfileTable.PROP_FILENAME, "FFTest2.txt");
363: prop.put(BaseFlatfileTable.PROP_ISFIRSTLINEHEADER, "true");
364: cmd.setProperties(prop);
365: AxionQueryContext ctx = new AxionQueryContext();
366: ctx.addSelect(new ColumnIdentifier("*"));
367: ctx.addFrom(new TableIdentifier("FFTEST"));
368: SubSelectCommand subSelect = new SubSelectCommand(ctx);
369: cmd.setSubQuery(subSelect);
370: cmd.execute(_db);
371:
372: Table table3 = _db.getTable("FFTEST2");
373: itr = table3.getRowIterator(false);
374:
375: assertEquals("Valid row count should have correct value",
376: 7, table3.getRowCount());
377:
378: rowCount = 0;
379: while (itr.hasNext()) {
380: itr.next();
381: rowCount++;
382: }
383:
384: assertEquals("Valid row count should have correct value",
385: 7, rowCount);
386: } finally {
387: try {
388: _db.dropTable("FFTEST");
389: } catch (AxionException ignore) {
390: // ignore
391: }
392:
393: try {
394: _db.dropTable("FFTEST2");
395: } catch (AxionException ignore) {
396: // ignore
397: }
398:
399: data.delete();
400: }
401:
402: }
403:
404: public void testFileReadForPackedRecord() throws Exception {
405: File data = new File(getDbdir(), "FFTEST.txt");
406: FileWriter out = new FileWriter(data);
407:
408: out.write("ID NAME "); // Header
409: out.write("1 aa "); // 1
410: out.write("2 bbb "); // 2
411: out.write("3.00 ccc "); // 3
412: out.write("4.00 ddd "); // 4
413: out.write(""); // skip
414: out.write("we "); // bad 1
415: out.write("7 dfdf "); // 5
416: out.write("7.0f ccc "); // 6
417: out.write("xx xx "); // bad 2
418: out.write("10-1 hhhh "); // bad 3
419: out.write(" "); // bad 4
420: out.write("5 test"); // 7 EOF before end of record
421: out.close();
422:
423: ExternalTableFactory factory = new ExternalTableFactory();
424: Properties prop = setProperties("FFTEST");
425: prop.put(BaseFlatfileTable.PROP_RECORDDELIMITER, "");
426: prop.put(BaseFlatfileTable.PROP_ISFIRSTLINEHEADER, "true");
427: prop.put(BaseFlatfileTable.PROP_ROWSTOSKIP, "1");
428:
429: Table table2 = factory.createTable(_db, "FFTEST", prop,
430: buildColumns());
431: RowIterator itr = table2.getRowIterator(false);
432:
433: int rowCount = 0;
434: while (itr.hasNext()) {
435: itr.next();
436: rowCount++;
437: }
438:
439: assertEquals("Valid row count should have correct value", 7,
440: rowCount);
441: table2.drop();
442:
443: prop.put(BaseFlatfileTable.PROP_MAXFAULTS, "2");
444:
445: try {
446: table2 = factory.createTable(_db, "FFTEST", prop,
447: buildColumns());
448: itr = table2.getRowIterator(false);
449: while (itr.hasNext()) {
450: itr.next();
451: }
452: fail("Expected Exception");
453: } catch (Exception e) {
454: // expected
455: }
456: table2.drop();
457:
458: // bad property value, should use default value
459: prop.put(BaseFlatfileTable.PROP_MAXFAULTS, "-10");
460: prop.put(BaseFlatfileTable.PROP_ROWSTOSKIP, "-10");
461:
462: table2 = factory.createTable(_db, "FFTEST", prop,
463: buildColumns());
464: itr = table2.getRowIterator(false);
465:
466: rowCount = 0;
467: while (itr.hasNext()) {
468: itr.next();
469: rowCount++;
470: }
471:
472: assertEquals("Valid row count should have correct value", 7,
473: rowCount);
474: table2.drop();
475:
476: // test headerBytesOffset
477: prop.put(BaseFlatfileTable.PROP_ISFIRSTLINEHEADER, "false");
478: prop.put(FixedWidthFlatfileTable.PROP_HEADERBYTESOFFSET, "16");
479: prop.put(BaseFlatfileTable.PROP_ROWSTOSKIP, "0");
480:
481: table2 = factory.createTable(_db, "FFTEST", prop,
482: buildColumns());
483: itr = table2.getRowIterator(false);
484:
485: rowCount = 0;
486: while (itr.hasNext()) {
487: itr.next();
488: rowCount++;
489: }
490:
491: assertEquals("Valid row count should have correct value", 7,
492: rowCount);
493: table2.drop();
494:
495: // bad property value, should use default value
496: prop.put(BaseFlatfileTable.PROP_ISFIRSTLINEHEADER, "true");
497: prop.put(BaseFlatfileTable.PROP_MAXFAULTS, "ABC");
498: prop.put(BaseFlatfileTable.PROP_ROWSTOSKIP, "ABC");
499:
500: table2 = factory.createTable(_db, "FFTEST", prop,
501: buildColumns());
502: itr = table2.getRowIterator(false);
503:
504: rowCount = 0;
505: while (itr.hasNext()) {
506: itr.next();
507: rowCount++;
508: }
509:
510: assertEquals("Valid row count should have correct value", 7,
511: rowCount);
512: table2.drop();
513:
514: prop.put(BaseFlatfileTable.PROP_MAXFAULTS, "5");
515: prop.put(BaseFlatfileTable.PROP_ROWSTOSKIP, "0");
516: table2 = factory.createTable(_db, "FFTEST", prop,
517: buildColumns());
518: itr = table2.getRowIterator(false);
519:
520: rowCount = 0;
521: while (itr.hasNext()) {
522: itr.next();
523: rowCount++;
524: }
525:
526: assertEquals("Valid row count should have correct value", 7,
527: rowCount);
528:
529: _db.addTable(table2);
530: CreateTableCommand cmd = new CreateTableCommand();
531: cmd.setObjectName("FFTEST2");
532: cmd.setType("external");
533: prop.put(BaseFlatfileTable.PROP_FILENAME, "FFTest2.txt");
534: prop.put(BaseFlatfileTable.PROP_ISFIRSTLINEHEADER, "true");
535: cmd.setProperties(prop);
536: AxionQueryContext ctx = new AxionQueryContext();
537: ctx.addSelect(new ColumnIdentifier("*"));
538: ctx.addFrom(new TableIdentifier("FFTEST"));
539: SubSelectCommand subSelect = new SubSelectCommand(ctx);
540: cmd.setSubQuery(subSelect);
541: cmd.execute(_db);
542:
543: Table table3 = _db.getTable("FFTEST2");
544: itr = table3.getRowIterator(false);
545:
546: assertEquals("Valid row count should have correct value", 7,
547: table3.getRowCount());
548:
549: rowCount = 0;
550: while (itr.hasNext()) {
551: itr.next();
552: rowCount++;
553: }
554:
555: assertEquals("Valid row count should have correct value", 7,
556: rowCount);
557: _db.dropTable("FFTEST");
558: _db.dropTable("FFTEST2");
559:
560: data.delete();
561:
562: }
563:
564: public void testRestartDB() throws Exception {
565: testAddRow();
566: table.shutdown();
567: table = null;
568: _db.shutdown();
569:
570: _db = new DiskDatabase(getDbdir());
571: assertTrue(_db.hasTable(getTableName()));
572: table = _db.getTable(getTableName());
573: testGetName();
574: RowIterator iter = table.getRowIterator(true);
575: assertNotNull(iter);
576: assertTrue(iter.hasNext());
577: assertNotNull(iter.next());
578: assertTrue(iter.hasNext());
579: assertNotNull(iter.next());
580: assertTrue(!iter.hasNext());
581: }
582:
583: private List buildColumns() {
584: List list = new ArrayList(2);
585: Column id = new Column("ID", new IntegerType());
586: list.add(id);
587:
588: Column name = new Column("NAME", new CharacterVaryingType(5));
589: list.add(name);
590: return list;
591: }
592: }
|