1   /*
2    *
3    * The DbUnit Database Testing Framework
4    * Copyright (C)2002-2004, DbUnit.org
5    *
6    * This library is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU Lesser General Public
8    * License as published by the Free Software Foundation; either
9    * version 2.1 of the License, or (at your option) any later version.
10   *
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Lesser General Public License for more details.
15   *
16   * You should have received a copy of the GNU Lesser General Public
17   * License along with this library; if not, write to the Free Software
18   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19   *
20   */
21  
22  package org.dbunit.ant;
23  
24  import java.io.File;
25  import java.sql.SQLException;
26  import java.util.Hashtable;
27  import java.util.Iterator;
28  import java.util.List;
29  
30  import junit.framework.Test;
31  import junit.framework.TestSuite;
32  import junitx.framework.ArrayAssert;
33  
34  import org.apache.tools.ant.BuildException;
35  import org.apache.tools.ant.BuildFileTest;
36  import org.apache.tools.ant.Target;
37  import org.dbunit.DatabaseEnvironment;
38  import org.dbunit.DatabaseUnitException;
39  import org.dbunit.IDatabaseTester;
40  import org.dbunit.database.DatabaseConfig;
41  import org.dbunit.database.IDatabaseConnection;
42  import org.dbunit.dataset.FilteredDataSet;
43  import org.dbunit.dataset.IDataSet;
44  import org.dbunit.dataset.NoSuchTableException;
45  import org.dbunit.dataset.ITable;
46  import org.dbunit.dataset.datatype.IDataTypeFactory;
47  import org.dbunit.ext.mssql.InsertIdentityOperation;
48  import org.dbunit.ext.oracle.OracleDataTypeFactory;
49  import org.dbunit.operation.DatabaseOperation;
50  import org.dbunit.testutil.TestUtils;
51  import org.dbunit.util.FileHelper;
52  
53  /**
54   * Ant-based test class for the Dbunit ant task definition.
55   *
56   * @author Timothy Ruppert
57   * @author Ben Cox
58   * @author Last changed by: $Author: jbhurst $
59   * @version $Revision: 1162 $ $Date: 2010-02-12 00:29:37 +0100 (ven, 12 feb 2010) $
60   * @since Jun 10, 2002
61   * @see org.dbunit.ant.AntTest
62   */
63  public class DbUnitTaskIT extends BuildFileTest
64  {
65      static protected Class classUnderTest = DbUnitTaskIT.class;
66  
67      private static final String BUILD_FILE_DIR = "xml";
68      private static final String OUTPUT_DIR = "target/xml";
69  
70      private File outputDir;
71  
72      public DbUnitTaskIT(String name)
73      {
74          super(name);
75      }
76  
77      public void setUp() throws Exception
78      {
79          // This line ensure test database is initialized
80          DatabaseEnvironment.getInstance();
81  
82          String filePath = BUILD_FILE_DIR + "/antTestBuildFile.xml";
83          assertTrue("Buildfile not found", TestUtils.getFile(filePath).isFile());
84          configureProject(TestUtils.getFileName(filePath));
85  
86          outputDir = new File(getProjectDir(), OUTPUT_DIR);
87          outputDir.mkdirs();
88      }
89  
90      protected void tearDown() throws Exception
91      {
92          super.tearDown();
93  
94          outputDir = new File(getProjectDir(), OUTPUT_DIR);
95          FileHelper.deleteDirectory(outputDir);
96      }
97  
98      public void testNoDriver()
99      {
100         expectBuildException("no-driver", "Should have required a driver attribute.");
101     }
102 
103     public void testNoDbUrl()
104     {
105         expectBuildException("no-db-url", "Should have required a url attribute.");
106     }
107 
108     public void testNoUserid()
109     {
110         expectBuildException("no-userid", "Should have required a userid attribute.");
111     }
112 
113     public void testNoPassword()
114     {
115         expectBuildException("no-password", "Should have required a password attribute.");
116     }
117 
118     public void testInvalidDatabaseInformation()
119     {
120         Throwable sql = null;
121         try
122         {
123             executeTarget("invalid-db-info");
124         }
125         catch (BuildException e)
126         {
127             sql = e.getException();
128         }
129         finally
130         {
131             assertNotNull("Should have thrown a SQLException.", sql);
132             assertTrue("Should have thrown a SQLException.", (sql instanceof SQLException));
133         }
134     }
135 
136     public void testInvalidOperationType()
137     {
138         Throwable iae = null;
139         try
140         {
141             executeTarget("invalid-type");
142         }
143         catch (BuildException e)
144         {
145             iae = e.getException();
146         }
147         finally
148         {
149             assertNotNull("Should have thrown an IllegalArgumentException.", iae);
150             assertTrue("Should have thrown an IllegalArgumentException.",
151                     (iae instanceof IllegalArgumentException));
152         }
153     }
154 
155     public void testSetFlatFalse()
156     {
157         String targetName = "set-format-xml";
158         Operation operation = (Operation)getFirstStepFromTarget(targetName);
159         assertTrue("Operation attribute format should have been 'xml', but was: "
160                 + operation.getFormat(), operation.getFormat().equalsIgnoreCase("xml"));
161     }
162 
163     public void testResolveOperationTypes()
164     {
165         assertOperationType("Should have been a NONE operation",
166                 "test-type-none", DatabaseOperation.NONE);
167         assertOperationType("Should have been an DELETE_ALL operation",
168                 "test-type-delete-all", DatabaseOperation.DELETE_ALL);
169         assertOperationType("Should have been an INSERT operation",
170                 "test-type-insert", DatabaseOperation.INSERT);
171         assertOperationType("Should have been an UPDATE operation",
172                 "test-type-update", DatabaseOperation.UPDATE);
173         assertOperationType("Should have been an REFRESH operation",
174                 "test-type-refresh", DatabaseOperation.REFRESH);
175         assertOperationType("Should have been an CLEAN_INSERT operation",
176                 "test-type-clean-insert", DatabaseOperation.CLEAN_INSERT);
177         assertOperationType("Should have been an DELETE operation",
178                 "test-type-delete", DatabaseOperation.DELETE);
179         assertOperationType("Should have been an MSSQL_INSERT operation",
180                 "test-type-mssql-insert", InsertIdentityOperation.INSERT);
181         assertOperationType("Should have been an MSSQL_REFRESH operation",
182                 "test-type-mssql-refresh", InsertIdentityOperation.REFRESH);
183         assertOperationType("Should have been an MSSQL_CLEAN_INSERT operation",
184                 "test-type-mssql-clean-insert", InsertIdentityOperation.CLEAN_INSERT);
185     }
186 
187     public void testInvalidCompositeOperationSrc()
188     {
189         expectBuildException("invalid-composite-operation-src",
190                 "Should have objected to nested operation src attribute "
191                 + "being set.");
192     }
193 
194     public void testInvalidCompositeOperationFlat()
195     {
196         expectBuildException("invalid-composite-operation-format-flat",
197                 "Should have objected to nested operation format attribute "
198                 + "being set.");
199     }
200 
201     public void testExportFull()
202     {
203         String targetName = "test-export-full";
204         Export export = (Export)getFirstStepFromTarget(targetName);
205         assertTrue("Should have been a flat format, "
206                 + "but was: " + export.getFormat(),
207                 export.getFormat().equalsIgnoreCase("flat"));
208         List tables = export.getTables();
209         assertTrue("Should have been an empty table list "
210                 + "(indicating a full dataset), but was: "
211                 + tables, tables.size() == 0);
212     }
213 
214     public void testExportPartial()
215     {
216         String targetName = "test-export-partial";
217         Export export = (Export)getFirstStepFromTarget(targetName);
218         List tables = export.getTables();
219         assertEquals("table count", 2, tables.size());
220         Table testTable = (Table)tables.get(0);
221         Table pkTable = (Table)tables.get(1);
222         assertTrue("Should have been been TABLE TEST_TABLE, but was: "
223                 + testTable.getName(), testTable.getName().equals("TEST_TABLE"));
224         assertTrue("Should have been been TABLE PK_TABLE, but was: "
225                 + pkTable.getName(), pkTable.getName().equals("PK_TABLE"));
226     }
227 
228     public void testExportFlat()
229     {
230         String targetName = "test-export-format-flat";
231         Export export = (Export)getFirstStepFromTarget(targetName);
232         assertEquals("format", "flat", export.getFormat());
233     }
234 
235     public void testExportFlatWithDocytpe()
236     {
237         String targetName = "test-export-format-flat-with-doctype";
238         Export export = (Export)getFirstStepFromTarget(targetName);
239         assertEquals("format", "flat", export.getFormat());
240         assertEquals("doctype", "dataset.dtd", export.getDoctype());
241     }
242 
243     public void testExportFlatWithEncoding()
244     {
245         String targetName = "test-export-format-flat-with-encoding";
246         Export export = (Export)getFirstStepFromTarget(targetName);
247         assertEquals("format", "flat", export.getFormat());
248         assertEquals("encoding", "ISO-8859-1", export.getEncoding());
249     }
250 
251     public void testExportXml()
252     {
253         String targetName = "test-export-format-xml";
254         Export export = (Export)getFirstStepFromTarget(targetName);
255         assertTrue("Should have been an xml format, "
256                 + "but was: " + export.getFormat(),
257                 export.getFormat().equalsIgnoreCase("xml"));
258     }
259 
260 	public void testExportCsv() {
261 		String targetName = "test-export-format-csv";
262 		Export export = (Export)getFirstStepFromTarget(targetName);
263 		assertTrue("Should have been a csv format, "
264 				+ "but was: " + export.getFormat(),
265 				export.getFormat().equalsIgnoreCase("csv"));
266 	}
267 
268     public void testExportDtd()
269     {
270         String targetName = "test-export-format-dtd";
271         Export export = (Export)getFirstStepFromTarget(targetName);
272         assertTrue("Should have been a dtd format, "
273                 + "but was: " + export.getFormat(),
274                 export.getFormat().equalsIgnoreCase("dtd"));
275     }
276 
277     public void testInvalidExportFormat()
278     {
279         expectBuildException("invalid-export-format",
280                 "Should have objected to invalid format attribute.");
281     }
282 
283     public void testExportXmlOrdered() throws Exception
284     {
285         String targetName = "test-export-format-xml-ordered";
286         Export export = (Export)getFirstStepFromTarget(targetName);
287         assertEquals("Should be ordered", true, export.isOrdered());
288         assertTrue("Should have been an xml format, "
289                 + "but was: " + export.getFormat(),
290                 export.getFormat().equalsIgnoreCase("xml"));
291 
292         // Test if the correct dataset is created for ordered export
293         DbUnitTask task = getFirstTargetTask(targetName);
294         IDatabaseConnection connection = task.createConnection();
295         IDataSet dataSetToBeExported = export.getExportDataSet(connection);
296         // Ordered export should use the filtered dataset
297         assertEquals(dataSetToBeExported.getClass(), FilteredDataSet.class);
298     }
299 
300     public void testExportQuery()
301     {
302         String targetName = "test-export-query";
303         Export export = (Export)getFirstStepFromTarget(targetName);
304         assertEquals("format", "flat", export.getFormat());
305 
306         List queries = export.getTables();
307         assertEquals("query count", 2, getQueryCount(queries));
308 
309         Query testTable = (Query)queries.get(0);
310         assertEquals("name", "TEST_TABLE", testTable.getName());
311         assertEquals("sql", "SELECT * FROM TEST_TABLE ORDER BY column0 DESC", testTable.getSql());
312 
313         Query pkTable = (Query)queries.get(1);
314         assertEquals("name", "PK_TABLE", pkTable.getName());
315         assertEquals("sql", "SELECT * FROM PK_TABLE", pkTable.getSql());
316     }
317 
318 	public void testExportWithQuerySet() {
319 		String targetName = "test-export-with-queryset";
320 		Export export = (Export)getFirstStepFromTarget(targetName);
321 		assertEquals("format", "csv", export.getFormat());
322 
323 		List queries = export.getTables();
324 
325 		assertEquals("query count", 1, getQueryCount(queries));
326 		assertEquals("table count", 1, getTableCount(queries));
327 		assertEquals("queryset count", 2, getQuerySetCount(queries));
328 
329 		Query secondTable = (Query)queries.get(0);
330 		assertEquals("name", "SECOND_TABLE", secondTable.getName());
331 		assertEquals("sql", "SELECT * FROM SECOND_TABLE", secondTable.getSql());
332 
333 		QuerySet queryset1 = (QuerySet)queries.get(1);
334 
335 		Query testTable = (Query)queryset1.getQueries().get(0);
336 
337 		assertEquals("name", "TEST_TABLE", testTable.getName());
338 
339 		QuerySet queryset2 = (QuerySet)queries.get(2);
340 
341 		Query pkTable = (Query)queryset2.getQueries().get(0);
342 		Query testTable2 = (Query)queryset2.getQueries().get(1);
343 
344 		assertEquals("name", "PK_TABLE", pkTable.getName());
345 		assertEquals("name", "TEST_TABLE", testTable2.getName());
346 
347 		Table emptyTable = (Table)queries.get(3);
348 
349 		assertEquals("name", "EMPTY_TABLE", emptyTable.getName());
350 	}
351 
352 	public void testWithBadQuerySet() {
353 		expectBuildException("invalid-queryset",
354 			"Cannot specify 'id' and 'refid' attributes together in queryset.");
355 	}
356 
357 	public void testWithReferenceQuerySet() {
358 		String targetName = "test-queryset-reference";
359 
360 		Export export = (Export)getFirstStepFromTarget(targetName);
361 
362 		List tables = export.getTables();
363 
364 		assertEquals("total count", 1, tables.size());
365 
366 		QuerySet queryset = (QuerySet)tables.get(0);
367 		Query testTable = (Query)queryset.getQueries().get(0);
368 		Query secondTable = (Query)queryset.getQueries().get(1);
369 
370 		assertEquals("name", "TEST_TABLE", testTable.getName());
371 		assertEquals("sql", "SELECT * FROM TEST_TABLE WHERE COLUMN0 = 'row0 col0'",
372 					testTable.getSql());
373 
374 		assertEquals("name", "SECOND_TABLE", secondTable.getName());
375 		assertEquals("sql",
376 			"SELECT B.* FROM TEST_TABLE A, SECOND_TABLE B " +
377 			"WHERE A.COLUMN0 = 'row0 col0' AND B.COLUMN0 = A.COLUMN0",
378 			secondTable.getSql());
379 
380 	}
381 
382     public void testExportQueryMixed() {
383         String targetName = "test-export-query-mixed";
384         Export export = (Export)getFirstStepFromTarget(targetName);
385         assertEquals("format", "flat", export.getFormat());
386 
387         List tables = export.getTables();
388         assertEquals("total count", 2, tables.size());
389         assertEquals("table count", 1, getTableCount(tables));
390         assertEquals("query count", 1, getQueryCount(tables));
391 
392         Table testTable = (Table)tables.get(0);
393         assertEquals("name", "TEST_TABLE", testTable.getName());
394 
395         Query pkTable = (Query)tables.get(1);
396         assertEquals("name", "PK_TABLE", pkTable.getName());
397     }
398 
399     /**
400      * Tests the exception that is thrown when the compare fails because
401      * the source format was different from the previous "export" task's write format.
402      */
403     public void testExportAndCompareFormatMismatch() {
404         String targetName = "test-export-and-compare-format-mismatch";
405 
406         try {
407         	getFirstTargetTask(targetName);
408         	fail("Should not be able to invoke ant task where the expected table was not found because it was tried to read in the wrong format.");
409         }
410         catch(BuildException expected){
411         	Throwable cause = expected.getCause();
412         	assertTrue(cause instanceof DatabaseUnitException);
413         	DatabaseUnitException dbUnitException = (DatabaseUnitException)cause;
414         	String filename = new File(outputDir, "antExportDataSet.xml").toString();
415         	String expectedMsg = "Did not find table in source file '" + filename + "' using format 'xml'";
416         	assertEquals(expectedMsg, dbUnitException.getMessage());
417         	assertTrue(dbUnitException.getCause() instanceof NoSuchTableException);
418         	NoSuchTableException nstException = (NoSuchTableException)dbUnitException.getCause();
419         	assertEquals("TEST_TABLE", nstException.getMessage());
420         }
421     }
422 
423     public void testDataTypeFactory() throws Exception
424     {
425         String targetName = "test-datatypefactory";
426         DbUnitTask task = getFirstTargetTask(targetName);
427 
428         IDatabaseConnection connection = task.createConnection();
429         IDataTypeFactory factory = (IDataTypeFactory)connection.getConfig().getProperty(
430                         DatabaseConfig.PROPERTY_DATATYPE_FACTORY);
431 
432         Class expectedClass = OracleDataTypeFactory.class;
433         assertEquals("factory", expectedClass, factory.getClass());
434     }
435 
436     public void testEscapePattern() throws Exception
437     {
438         String targetName = "test-escapepattern";
439         DbUnitTask task = getFirstTargetTask(targetName);
440 
441         IDatabaseConnection connection = task.createConnection();
442         String actualPattern = (String)connection.getConfig().getProperty(
443                         DatabaseConfig.PROPERTY_ESCAPE_PATTERN);
444 
445         String expectedPattern = "[?]";
446         assertEquals("factory", expectedPattern, actualPattern);
447     }
448 
449     public void testDataTypeFactoryViaGenericConfig() throws Exception
450     {
451         String targetName = "test-datatypefactory-via-generic-config";
452         DbUnitTask task = getFirstTargetTask(targetName);
453 
454         IDatabaseConnection connection = task.createConnection();
455 
456         DatabaseConfig config =connection.getConfig();
457 
458         IDataTypeFactory factory = (IDataTypeFactory)config.getProperty(
459                         DatabaseConfig.PROPERTY_DATATYPE_FACTORY);
460         Class expectedClass = OracleDataTypeFactory.class;
461         assertEquals("factory", expectedClass, factory.getClass());
462 
463         String[] actualTableType = (String[])config.getProperty(DatabaseConfig.PROPERTY_TABLE_TYPE);
464         ArrayAssert.assertEquals("tableType", new String[]{"TABLE", "SYNONYM"}, actualTableType);
465         assertTrue("batched statements feature should be true",
466                 connection.getConfig().getFeature(DatabaseConfig.FEATURE_BATCHED_STATEMENTS));
467         assertTrue("qualified tablenames feature should be true",
468                 connection.getConfig().getFeature(DatabaseConfig.FEATURE_CASE_SENSITIVE_TABLE_NAMES));
469     }
470 
471 
472     public void testClasspath() throws Exception
473     {
474         String targetName = "test-classpath";
475 
476         try
477         {
478             executeTarget(targetName);
479             fail("Should not be able to connect with invalid url!");
480         }
481         catch (BuildException e)
482         {
483             // Verify exception type
484             assertTrue("nested exxception type", e.getException() instanceof SQLException);
485         }
486 
487     }
488 
489     public void testDriverNotInClasspath() throws Exception
490     {
491         String targetName = "test-drivernotinclasspath";
492 
493         try
494         {
495             executeTarget(targetName);
496             fail("Should not have found driver!");
497         }
498         catch (BuildException e)
499         {
500             // Verify exception type
501             assertEquals("nested exception type", ClassNotFoundException.class, e.getException().getClass());
502         }
503     }
504 
505     public void testReplaceOperation() throws Exception {
506         String targetName = "test-replace";
507         final IDatabaseTester dbTest = DatabaseEnvironment.getInstance().getDatabaseTester();
508         executeTarget(targetName);
509         final IDataSet ds = dbTest.getConnection().createDataSet();
510         final ITable table = ds.getTable("PK_TABLE");
511         assertNull(table.getValue(0,"NORMAL0"));
512         assertEquals("row 1",table.getValue(1,"NORMAL0"));
513     }
514 
515     public void testOrderedOperation() throws Exception {
516         String targetName = "test-ordered";
517         final IDatabaseTester dbTest = DatabaseEnvironment.getInstance().getDatabaseTester();
518         executeTarget(targetName);
519         final IDataSet ds = dbTest.getConnection().createDataSet();
520         final ITable table = ds.getTable("PK_TABLE");
521         assertEquals("row 0",table.getValue(0,"NORMAL0"));
522         assertEquals("row 1",table.getValue(1,"NORMAL0"));
523     }
524 
525     public void testReplaceOrderedOperation() throws Exception {
526         String targetName = "test-replace-ordered";
527         final IDatabaseTester dbTest = DatabaseEnvironment.getInstance().getDatabaseTester();
528         executeTarget(targetName);
529         final IDataSet ds = dbTest.getConnection().createDataSet();
530         final ITable table = ds.getTable("PK_TABLE");
531         assertNull(table.getValue(0,"NORMAL0"));
532         assertEquals("row 1",table.getValue(1,"NORMAL0"));
533     }
534 
535     protected void assertOperationType(String failMessage, String targetName, DatabaseOperation expected)
536     {
537         Operation oper = (Operation)getFirstStepFromTarget(targetName);
538         DatabaseOperation dbOper = oper.getDbOperation();
539         assertTrue(failMessage + ", but was: " + dbOper, expected.equals(dbOper));
540     }
541 
542     protected int getQueryCount(List tables)
543     {
544         int count = 0;
545         for (Iterator it = tables.iterator(); it.hasNext();)
546         {
547             if (it.next() instanceof Query)
548             {
549                 count++;
550             }
551         }
552 
553         return count;
554     }
555 
556     protected int getTableCount(List tables)
557     {
558         int count = 0;
559         for (Iterator it = tables.iterator(); it.hasNext();)
560         {
561             if (it.next() instanceof Table)
562             {
563                 count++;
564             }
565         }
566 
567         return count;
568     }
569 
570 	protected int getQuerySetCount(List tables) {
571 		int count = 0;
572 		for (Iterator it = tables.iterator(); it.hasNext();) {
573 			if (it.next() instanceof QuerySet) {
574 				count++;
575 			}
576 		}
577 
578 		return count;
579 	}
580 
581     protected DbUnitTaskStep getFirstStepFromTarget(String targetName)
582     {
583     	return getStepFromTarget(targetName, 0);
584     }
585 
586     protected DbUnitTaskStep getStepFromTarget(String targetName, int index)
587     {
588         DbUnitTask task = getFirstTargetTask(targetName);
589         List steps = task.getSteps();
590         if(steps == null || steps.size() == 0)
591         {
592         	fail("Can't get a dbunit <step> from the target: " + targetName + ". No steps available.");
593         }
594         return (DbUnitTaskStep)steps.get(index);
595     }
596 
597     private DbUnitTask getFirstTargetTask(String targetName)
598     {
599         Hashtable targets = project.getTargets();
600         executeTarget(targetName);
601         Target target = (Target)targets.get(targetName);
602 
603         DbUnitTask task = null;
604 
605         Object[] tasks = target.getTasks();
606         for(int i = 0; i < tasks.length; i++) {
607         	if(tasks[i] instanceof DbUnitTask) {
608         		task = (DbUnitTask)tasks[i];
609         	}
610         }
611 
612         return task;
613     }
614 
615     public static Test suite()
616     {
617         TestSuite suite = new TestSuite(classUnderTest);
618         return suite;
619     }
620 
621     public static void main(String args[])
622     {
623         if (args.length > 0 && args[0].equals("-gui"))
624         {
625             String[] testCaseName = {classUnderTest.getName()};
626             junit.swingui.TestRunner.main(testCaseName);
627         }
628         else
629         {
630             junit.textui.TestRunner.run(suite());
631         }
632     }
633 
634 }