View Javadoc
1   /*
2    *
3    * The DbUnit Database Testing Framework
4    * Copyright (C)2002-2008, 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  package org.dbunit;
22  
23  import java.util.ArrayList;
24  import java.util.Arrays;
25  import java.util.List;
26  import java.util.Map;
27  
28  import org.dbunit.assertion.comparer.value.ValueComparer;
29  import org.dbunit.assertion.comparer.value.verifier.DefaultValueComparerAndVerifyTableDefinitionVerifier;
30  import org.dbunit.assertion.comparer.value.verifier.ValueComparerAndVerifyTableDefinitionVerifier;
31  import org.dbunit.database.IDatabaseConnection;
32  import org.dbunit.dataset.Column;
33  import org.dbunit.dataset.CompositeDataSet;
34  import org.dbunit.dataset.DataSetException;
35  import org.dbunit.dataset.DefaultDataSet;
36  import org.dbunit.dataset.IDataSet;
37  import org.dbunit.dataset.ITable;
38  import org.dbunit.dataset.SortedTable;
39  import org.dbunit.dataset.filter.DefaultColumnFilter;
40  import org.dbunit.operation.DatabaseOperation;
41  import org.dbunit.util.fileloader.DataFileLoader;
42  import org.slf4j.Logger;
43  import org.slf4j.LoggerFactory;
44  
45  //TODO update JavaDoc
46  /**
47   * Test case base class supporting prep data and expected data. Prep data is the
48   * data needed for the test to run. Expected data is the data needed to compare
49   * if the test ran successfully.
50   *
51   * Use this class in two ways:
52   * <ol>
53   * <li>Dependency inject it as its interface into a test class.</li>
54   * <p>
55   * Configure a bean of its interface, injecting a IDatabaseTester and a
56   * DataFileLoader using the databaseTester and a dataFileLoader properties.
57   * </p>
58   *
59   * <li>Extend it in a test class.</li>
60   * <p>
61   * Obtain IDatabaseTester and DataFileLoader instances (possibly dependency
62   * injecting them into the test class) and set them accordingly, probably in a
63   * setup type of method, such as:
64   *
65   * <pre>
66   * &#064;Before
67   * public void setDbunitTestDependencies()
68   * {
69   *     setDatabaseTester(databaseTester);
70   *     setDataFileLoader(dataFileLoader);
71   * }
72   * </pre>
73   *
74   * </p>
75   * </ol>
76   *
77   * To setup, execute, and clean up tests, call the configureTest(), preTest(),
78   * and postTest() methods. Note there is a preTest() convenience method that
79   * takes the same parameters as the configureTest() method; use it instead of
80   * using both configureTest() and preTest().
81   *
82   * Where the test case calls them depends on data needs:
83   * <ul>
84   * <li>For the whole test case, i.e. in setUp() and tearDown() or &#064;Before
85   * and &#064;After.</li>
86   * <li>In each test method.</li>
87   * <li>Or some combination of both test case setup/teardown and test methods.
88   * </li>
89   * </ul>
90   *
91   * <h4>When each test method requires different prep and expected data</h4>
92   *
93   * If each test method requires its own prep and expected data, then the test
94   * methods will look something like the following:
95   *
96   * <pre>
97   * &#064;Autowired
98   * private PrepAndExpectedTestCase tc;
99   *
100  * &#064;Test
101  * public void testExample() throws Exception
102  * {
103  *     try
104  *     {
105  *         final String[] prepDataFiles = {}; // define prep files
106  *         final String[] expectedDataFiles = {}; // define expected files
107  *         final VerifyTableDefinition[] tables = {}; // define tables to verify
108  *
109  *         tc.preTest(tables, prepDataFiles, expectedDataFiles);
110  *
111  *         // execute test steps
112  *     } catch (Exception e)
113  *     {
114  *         log.error(&quot;Test error&quot;, e);
115  *         throw e;
116  *     } finally
117  *     {
118  *         tc.postTest();
119  *     }
120  * }
121  * </pre>
122  *
123  * <h4>When all test methods share the same prep and/or expected data</h4>
124  *
125  * If each test method can share all of the prep and/or expected data, then use
126  * setUp() for the configureTest() and preTest() calls and tearDown() for the
127  * postTest() call. The methods will look something like the following:
128  *
129  * <pre>
130  * &#064;Override
131  * protected void setUp() throws Exception
132  * {
133  *     setDatabaseTester(databaseTester);
134  *     setDataFileLoader(dataFileLoader);
135  *
136  *     String[] prepDataFiles = {}; // define prep files
137  *     String[] expectedDataFiles = {}; // define expected files
138  *     VerifyTableDefinition[] tables = {}; // define tables to verify
139  *
140  *     preTest(tables, prepDataFiles, expectedDataFiles);
141  *
142  *     // call this if overriding setUp() and databaseTester &amp; dataFileLoader
143  *     // are already set.
144  *     super.setUp();
145  * }
146  *
147  * &#064;Override
148  * protected void tearDown() throws Exception
149  * {
150  *     postTest();
151  *     super.tearDown();
152  * }
153  *
154  * &#064;Test
155  * public void testExample() throws Exception
156  * {
157  *     // execute test steps
158  * }
159  * </pre>
160  *
161  * Note that it is unlikely that all test methods can share the same expected
162  * data.
163  *
164  * <h4>Sharing common (but not all) prep or expected data among test methods.
165  * </h4>
166  *
167  * Put common data in one or more files and pass the needed ones in the correct
168  * data file array.
169  *
170  * <h4>Java 8 and Anonymous Interfaces</h4>
171  * <p>
172  * Release 2.5.2 introduced interface {@link PrepAndExpectedTestCaseSteps} and
173  * the
174  * {@link #runTest(VerifyTableDefinition[], String[], String[], PrepAndExpectedTestCaseSteps)}
175  * method. This allows for encapsulating test steps into an anonymous inner
176  * class or a Java 8+ lambda and avoiding the try/catch/finally template in
177  * tests.
178  * </p>
179  *
180  * <pre>
181  * &#064;Autowired
182  * private PrepAndExpectedTestCase tc;
183  *
184  * &#064;Test
185  * public void testExample() throws Exception
186  * {
187  *     final String[] prepDataFiles = {}; // define prep files
188  *     final String[] expectedDataFiles = {}; // define expected files
189  *     final VerifyTableDefinition[] tables = {}; // define tables to verify
190  *     final PrepAndExpectedTestCaseSteps testSteps = () -> {
191  *         // execute test steps
192  *
193  *         return null; // or an object for use outside the Steps
194  *     };
195  *
196  *     tc.runTest(tables, prepDataFiles, expectedDataFiles, testSteps);
197  * }
198  * </pre>
199  *
200  * <h4>Notes</h4>
201  * <ol>
202  * <li>For additional examples, refer to the ITs (listed in the See Also
203  * section).</li>
204  * <li>To change the setup or teardown operation (e.g. change the teardown to
205  * org.dbunit.operation.DatabaseOperation.DELETE_ALL), set the setUpOperation or
206  * tearDownOperation property on the databaseTester.</li>
207  * <li>To set DatabaseConfig features/properties, one way is to extend this
208  * class and override the setUpDatabaseConfig(DatabaseConfig config) method from
209  * DatabaseTestCase.</li>
210  * </ol>
211  *
212  * @see org.dbunit.DefaultPrepAndExpectedTestCaseDiIT
213  * @see org.dbunit.DefaultPrepAndExpectedTestCaseExtIT
214  *
215  * @author Jeff Jensen jeffjensen AT users.sourceforge.net
216  * @since 2.6.0
217  */
218 // TODO extract common w/DefaultPrepAndExpectedTestCase to base or other classes
219 // TODO don't implement interface due to method pollution/incompatibility?
220 public class ComparerPrepAndExpectedTestCase extends DBTestCase
221         implements PrepAndExpectedTestCase
222 {
223     private final Logger log =
224             LoggerFactory.getLogger(ComparerPrepAndExpectedTestCase.class);
225 
226     private static final String DATABASE_TESTER_IS_NULL_MSG =
227             "databaseTester is null; must configure or set it first";
228 
229     public static final String TEST_ERROR_MSG = "DbUnit test error.";
230 
231     private IDatabaseTester databaseTester;
232     private DataFileLoader dataFileLoader;
233 
234     // per test data
235     private IDataSet prepDataSet = new DefaultDataSet();
236     private IDataSet expectedDataSet = new DefaultDataSet();
237     private VerifyTableDefinition[] verifyTableDefs = {};
238 
239     private ValueComparer defaultValueComparer;
240     private Map<String, Map<String, ValueComparer>> tableColumnValueComparers;
241 
242     private ValueComparerAndVerifyTableDefinitionVerifier valueComparerAndVerifyTableDefinitionVerifier =
243             new DefaultValueComparerAndVerifyTableDefinitionVerifier();
244 
245     /** Create new instance. */
246     public ComparerPrepAndExpectedTestCase()
247     {
248     }
249 
250     /**
251      * Create new instance with specified dataFileLoader and databaseTester.
252      *
253      * @param dataFileLoader
254      *            Load to use for loading the data files.
255      * @param databaseTester
256      *            Tester to use for database manipulation.
257      */
258     public ComparerPrepAndExpectedTestCase(final DataFileLoader dataFileLoader,
259             final IDatabaseTester databaseTester)
260     {
261         this.dataFileLoader = dataFileLoader;
262         this.databaseTester = databaseTester;
263     }
264 
265     /**
266      * Create new instance with specified test case name.
267      *
268      * @param name
269      *            The test case name.
270      */
271     public ComparerPrepAndExpectedTestCase(final String name)
272     {
273         super(name);
274     }
275 
276     /**
277      * {@inheritDoc} This implementation returns the databaseTester set by the
278      * test.
279      */
280     @Override
281     public IDatabaseTester newDatabaseTester() throws Exception
282     {
283         // questionable, but there is not a "setter" for any parent...
284         return databaseTester;
285     }
286 
287     /**
288      * {@inheritDoc} Returns the prep dataset.
289      */
290     @Override
291     public IDataSet getDataSet() throws Exception
292     {
293         return prepDataSet;
294     }
295 
296     /**
297      * {@inheritDoc}
298      */
299     public void configureTest(
300             final VerifyTableDefinition[] verifyTableDefinitions,
301             final String[] prepDataFiles, final String[] expectedDataFiles)
302             throws Exception
303     {
304         log.info("configureTest: saving instance variables");
305         this.prepDataSet = makeCompositeDataSet(prepDataFiles, "prep");
306         this.expectedDataSet =
307                 makeCompositeDataSet(expectedDataFiles, "expected");
308         this.verifyTableDefs = verifyTableDefinitions;
309     }
310 
311     public void configureTest(
312             final VerifyTableDefinition[] verifyTableDefinitions,
313             final String[] prepDataFiles, final String[] expectedDataFiles,
314             final ValueComparer defaultValueComparer,
315             final Map<String, Map<String, ValueComparer>> tableColumnValueComparers)
316             throws Exception
317     {
318         configureTest(verifyTableDefinitions, prepDataFiles, expectedDataFiles);
319         this.defaultValueComparer = defaultValueComparer;
320         this.tableColumnValueComparers = tableColumnValueComparers;
321     }
322 
323     /**
324      * {@inheritDoc}
325      */
326     public void preTest() throws Exception
327     {
328         setupData();
329     }
330 
331     /**
332      * {@inheritDoc}
333      */
334     public void preTest(final VerifyTableDefinition[] tables,
335             final String[] prepDataFiles, final String[] expectedDataFiles)
336             throws Exception
337     {
338         configureTest(tables, prepDataFiles, expectedDataFiles);
339         preTest();
340     }
341 
342     public void preTest(final VerifyTableDefinition[] tables,
343             final String[] prepDataFiles, final String[] expectedDataFiles,
344             final ValueComparer defaultValueComparer,
345             final Map<String, Map<String, ValueComparer>> tableColumnValueComparers)
346             throws Exception
347     {
348         configureTest(tables, prepDataFiles, expectedDataFiles,
349                 defaultValueComparer, tableColumnValueComparers);
350         preTest();
351     }
352 
353     /**
354      * {@inheritDoc}
355      */
356     public Object runTest(final VerifyTableDefinition[] verifyTables,
357             final String[] prepDataFiles, final String[] expectedDataFiles,
358             final PrepAndExpectedTestCaseSteps testSteps) throws Exception
359     {
360         return runTest(verifyTables, prepDataFiles, expectedDataFiles, null,
361                 null, testSteps);
362     }
363 
364     /**
365      * {@inheritDoc}
366      */
367     public Object runTest(final VerifyTableDefinition[] verifyTables,
368             final String[] prepDataFiles, final String[] expectedDataFiles,
369             final ValueComparer defaultValueComparer,
370             final Map<String, Map<String, ValueComparer>> tableColumnValueComparers,
371             final PrepAndExpectedTestCaseSteps testSteps) throws Exception
372     {
373         final Object result;
374 
375         try
376         {
377             preTest(verifyTables, prepDataFiles, expectedDataFiles,
378                     defaultValueComparer, tableColumnValueComparers);
379             log.info("runTest: running test steps");
380             result = testSteps.run();
381         } catch (final Exception e)
382         {
383             log.error(TEST_ERROR_MSG, e);
384             // don't verify table data when test execution has errors as:
385             // * a verify data failure masks the test error exception
386             // * tables in unknown state and therefore probably not accurate
387             postTest(false);
388             throw e;
389         }
390 
391         postTest();
392 
393         return result;
394     }
395 
396     /**
397      * {@inheritDoc}
398      */
399     public void postTest() throws Exception
400     {
401         postTest(true);
402     }
403 
404     /**
405      * {@inheritDoc}
406      */
407     public void postTest(final boolean verifyData) throws Exception
408     {
409         try
410         {
411             if (verifyData)
412             {
413                 verifyData();
414             }
415         } finally
416         {
417             // it is deliberate to have cleanup exceptions shadow verify
418             // failures so user knows db is probably in unknown state (for
419             // those not using an in-memory db or transaction rollback),
420             // otherwise would mask probable cause of subsequent test failures
421             cleanupData();
422         }
423     }
424 
425     /**
426      * {@inheritDoc}
427      */
428     public void cleanupData() throws Exception
429     {
430         try
431         {
432             final IDataSet dataset =
433                     new CompositeDataSet(prepDataSet, expectedDataSet);
434             final String[] tableNames = dataset.getTableNames();
435             final int count = tableNames.length;
436             log.info("cleanupData: about to clean up {} tables={}", count,
437                     tableNames);
438 
439             if (databaseTester == null)
440             {
441                 throw new IllegalStateException(DATABASE_TESTER_IS_NULL_MSG);
442             }
443 
444             databaseTester.setTearDownOperation(getTearDownOperation());
445             databaseTester.setDataSet(dataset);
446             databaseTester.setOperationListener(getOperationListener());
447             databaseTester.onTearDown();
448             log.debug("cleanupData: Clean up done");
449         } catch (final Exception e)
450         {
451             log.error("cleanupData: Exception:", e);
452             throw e;
453         }
454     }
455 
456     @Override
457     protected void tearDown() throws Exception
458     {
459         // parent tearDown() only cleans up prep data
460         cleanupData();
461         super.tearDown();
462     }
463 
464     /**
465      * Use the provided databaseTester to prep the database with the provided
466      * prep dataset. See {@link org.dbunit.IDatabaseTester#onSetup()}.
467      *
468      * @throws Exception
469      */
470     public void setupData() throws Exception
471     {
472         log.info("setupData: setting prep dataset and inserting rows");
473         if (databaseTester == null)
474         {
475             throw new IllegalStateException(DATABASE_TESTER_IS_NULL_MSG);
476         }
477 
478         try
479         {
480             super.setUp();
481         } catch (final Exception e)
482         {
483             log.error("setupData: Exception with setting up data:", e);
484             throw e;
485         }
486     }
487 
488     @Override
489     protected DatabaseOperation getSetUpOperation() throws Exception
490     {
491         assertNotNull(DATABASE_TESTER_IS_NULL_MSG, databaseTester);
492         return databaseTester.getSetUpOperation();
493     }
494 
495     @Override
496     protected DatabaseOperation getTearDownOperation() throws Exception
497     {
498         assertNotNull(DATABASE_TESTER_IS_NULL_MSG, databaseTester);
499         return databaseTester.getTearDownOperation();
500     }
501 
502     /**
503      * {@inheritDoc} Uses the connection from the provided databaseTester.
504      */
505     public void verifyData() throws Exception
506     {
507         if (databaseTester == null)
508         {
509             throw new IllegalStateException(DATABASE_TESTER_IS_NULL_MSG);
510         }
511 
512         valueComparerAndVerifyTableDefinitionVerifier
513                 .verify(tableColumnValueComparers, verifyTableDefs);
514 
515         final IDatabaseConnection connection = getConnection();
516 
517         try
518         {
519             final int tableDefsCount = verifyTableDefs.length;
520             log.info(
521                     "verifyData: about to verify {} tables"
522                             + " using verifyTableDefinitions={}",
523                     tableDefsCount, verifyTableDefs);
524             if (tableDefsCount == 0)
525             {
526                 log.warn("verifyData: No tables to verify as"
527                         + " no VerifyTableDefinitions specified");
528             }
529 
530             for (int i = 0; i < tableDefsCount; i++)
531             {
532                 final VerifyTableDefinition td = verifyTableDefs[i];
533                 verifyData(connection, td);
534             }
535         } catch (final Exception e)
536         {
537             log.error("verifyData: Exception:", e);
538             throw e;
539         } finally
540         {
541             log.debug("verifyData: Verification done, closing connection");
542             connection.close();
543         }
544     }
545 
546     protected void verifyData(final IDatabaseConnection connection,
547             final VerifyTableDefinition verifyTableDefinition) throws Exception
548     {
549         final String tableName = verifyTableDefinition.getTableName();
550         log.info("verifyData: Verifying table '{}'", tableName);
551 
552         final String[] excludeColumns =
553                 verifyTableDefinition.getColumnExclusionFilters();
554         final String[] includeColumns =
555                 verifyTableDefinition.getColumnInclusionFilters();
556 
557         final ITable expectedTable = loadTableDataFromDataSet(tableName);
558         final ITable actualTable =
559                 loadTableDataFromDatabase(tableName, connection);
560 
561         final Map<String, ValueComparer> columnValueComparers =
562                 findColumnValueComparer(tableName);
563 
564         verifyData(expectedTable, actualTable, excludeColumns, includeColumns,
565                 defaultValueComparer, columnValueComparers);
566     }
567 
568     public Map<String, ValueComparer> findColumnValueComparer(
569             final String tableName)
570     {
571         final Map<String, ValueComparer> columnValueComparers;
572 
573         if (tableColumnValueComparers == null)
574         {
575             columnValueComparers = null;
576         } else
577         {
578             columnValueComparers = tableColumnValueComparers.get(tableName);
579         }
580 
581         return columnValueComparers;
582     }
583 
584     public ITable loadTableDataFromDataSet(final String tableName)
585             throws DataSetException
586     {
587         ITable table = null;
588 
589         final String methodName = "loadTableDataFromDataSet";
590 
591         log.debug("{}: Loading table {} from expected dataset", methodName,
592                 tableName);
593         try
594         {
595             table = expectedDataSet.getTable(tableName);
596         } catch (final Exception e)
597         {
598             final String msg = methodName + ": Problem obtaining table '"
599                     + tableName + "' from expected dataset";
600             log.error(msg, e);
601             throw new DataSetException(msg, e);
602         }
603         return table;
604     }
605 
606     public ITable loadTableDataFromDatabase(final String tableName,
607             final IDatabaseConnection connection) throws Exception
608     {
609         ITable table = null;
610 
611         final String methodName = "loadTableDataFromDatabase";
612 
613         log.debug("{}: Loading table {} from database", methodName, tableName);
614         try
615         {
616             table = connection.createTable(tableName);
617         } catch (final Exception e)
618         {
619             final String msg = methodName + ": Problem obtaining table '"
620                     + tableName + "' from database";
621             log.error(msg, e);
622             throw new DataSetException(msg, e);
623         }
624         return table;
625     }
626 
627     /**
628      * For the specified expected and actual tables (and excluding and including
629      * the specified columns), verify the actual data is as expected.
630      *
631      * @param expectedTable
632      *            The expected table to compare the actual table to.
633      * @param actualTable
634      *            The actual table to compare to the expected table.
635      * @param excludeColumns
636      *            The column names to exclude from comparison. See
637      *            {@link org.dbunit.dataset.filter.DefaultColumnFilter#excludeColumn(String)}
638      *            .
639      * @param includeColumns
640      *            The column names to only include in comparison. See
641      *            {@link org.dbunit.dataset.filter.DefaultColumnFilter#includeColumn(String)}
642      *            .
643      * @param defaultValueComparer
644      *            TODO
645      * @param columnValueComparers
646      *            TODO
647      * @throws DatabaseUnitException
648      */
649     public void verifyData(final ITable expectedTable, final ITable actualTable,
650             final String[] excludeColumns, final String[] includeColumns,
651             final ValueComparer defaultValueComparer,
652             final Map<String, ValueComparer> columnValueComparers)
653             throws DatabaseUnitException
654     {
655         final String methodName = "verifyData";
656         // Filter out the columns from the expected and actual results
657         log.debug("{}: Applying filters to expected table", methodName);
658         final ITable expectedFilteredTable = applyColumnFilters(expectedTable,
659                 excludeColumns, includeColumns);
660         log.debug("{}: Applying filters to actual table", methodName);
661         final ITable actualFilteredTable =
662                 applyColumnFilters(actualTable, excludeColumns, includeColumns);
663 
664         log.debug("{}: Sorting expected table", methodName);
665         final SortedTable expectedSortedTable =
666                 new SortedTable(expectedFilteredTable);
667         log.debug("{}: Sorted expected table={}", methodName,
668                 expectedSortedTable);
669 
670         log.debug("{}: Sorting actual table", methodName);
671         final SortedTable actualSortedTable = new SortedTable(
672                 actualFilteredTable, expectedFilteredTable.getTableMetaData());
673         log.debug("{}: Sorted actual table={}", methodName, actualSortedTable);
674 
675         log.debug("{}: Creating additionalColumnInfo", methodName);
676         final Column[] additionalColumnInfo =
677                 makeAdditionalColumnInfo(expectedTable, excludeColumns);
678         log.debug("{}: additionalColumnInfo={}", methodName,
679                 additionalColumnInfo);
680 
681         log.debug("{}: Comparing expected table to actual table", methodName);
682         compareData(expectedSortedTable, actualSortedTable,
683                 additionalColumnInfo, defaultValueComparer,
684                 columnValueComparers);
685     }
686 
687     /** Compare the tables, enables easy overriding. */
688     public void compareData(final SortedTable expectedSortedTable,
689             final SortedTable actualSortedTable,
690             final Column[] additionalColumnInfo,
691             final ValueComparer defaultValueComparer,
692             final Map<String, ValueComparer> columnValueComparers)
693             throws DatabaseUnitException
694     {
695         Assertion.assertWithValueComparer(expectedSortedTable,
696                 actualSortedTable, additionalColumnInfo, defaultValueComparer,
697                 columnValueComparers);
698     }
699 
700     /**
701      * Don't add excluded columns to additionalColumnInfo as they are not found
702      * and generate a not found message in the fail message.
703      */
704     protected Column[] makeAdditionalColumnInfo(final ITable expectedTable,
705             final String[] excludeColumns) throws DataSetException
706     {
707         final List<Column> keepColumnsList = new ArrayList<Column>();
708         final List<String> excludeColumnsList = Arrays.asList(excludeColumns);
709 
710         final Column[] allColumns =
711                 expectedTable.getTableMetaData().getColumns();
712         for (final Column column : allColumns)
713         {
714             final String columnName = column.getColumnName();
715             if (!excludeColumnsList.contains(columnName))
716             {
717                 keepColumnsList.add(column);
718             }
719         }
720 
721         return keepColumnsList.toArray(new Column[keepColumnsList.size()]);
722     }
723 
724     /**
725      * Make a <code>IDataSet</code> from the specified files.
726      *
727      * @param dataFiles
728      *            Represents the array of dbUnit data files.
729      * @return The composite dataset.
730      * @throws DataSetException
731      *             On dbUnit errors.
732      */
733     public IDataSet makeCompositeDataSet(final String[] dataFiles,
734             final String dataFilesName) throws DataSetException
735     {
736         if (dataFileLoader == null)
737         {
738             throw new IllegalStateException(
739                     "dataFileLoader is null; must configure or set it first");
740         }
741 
742         final int count = dataFiles.length;
743         log.debug("makeCompositeDataSet: {} dataFiles count={}", dataFilesName,
744                 count);
745         if (count == 0)
746         {
747             log.info("makeCompositeDataSet: Specified zero {} data files",
748                     dataFilesName);
749         }
750 
751         final List list = new ArrayList();
752         for (int i = 0; i < count; i++)
753         {
754             final IDataSet ds = dataFileLoader.load(dataFiles[i]);
755             list.add(ds);
756         }
757 
758         final IDataSet[] dataSet = (IDataSet[]) list.toArray(new IDataSet[] {});
759         final IDataSet compositeDS = new CompositeDataSet(dataSet);
760         return compositeDS;
761     }
762 
763     /**
764      * Apply the specified exclude and include column filters to the specified
765      * table.
766      *
767      * @param table
768      *            The table to apply the filters to.
769      * @param excludeColumns
770      *            The exclude filters; use null or empty array to mean exclude
771      *            none.
772      * @param includeColumns
773      *            The include filters; use null to mean include all.
774      * @return The filtered table.
775      * @throws DataSetException
776      */
777     public ITable applyColumnFilters(final ITable table,
778             final String[] excludeColumns, final String[] includeColumns)
779             throws DataSetException
780     {
781         ITable filteredTable = table;
782 
783         if (table == null)
784         {
785             throw new IllegalArgumentException("table is null");
786         }
787 
788         // note: dbunit interprets an empty inclusion filter array as one
789         // not wanting to compare anything!
790         if (includeColumns == null)
791         {
792             log.debug("applyColumnFilters: including columns=(all)");
793         } else
794         {
795             log.debug("applyColumnFilters: including columns='{}'",
796                     new Object[] {includeColumns});
797             filteredTable = DefaultColumnFilter
798                     .includedColumnsTable(filteredTable, includeColumns);
799         }
800 
801         if (excludeColumns == null || excludeColumns.length == 0)
802         {
803             log.debug("applyColumnFilters: excluding columns=(none)");
804         } else
805         {
806             log.debug("applyColumnFilters: excluding columns='{}'",
807                     new Object[] {excludeColumns});
808             filteredTable = DefaultColumnFilter
809                     .excludedColumnsTable(filteredTable, excludeColumns);
810         }
811 
812         return filteredTable;
813     }
814 
815     /**
816      * {@inheritDoc}
817      */
818     public IDataSet getPrepDataset()
819     {
820         return prepDataSet;
821     }
822 
823     /**
824      * {@inheritDoc}
825      */
826     public IDataSet getExpectedDataset()
827     {
828         return expectedDataSet;
829     }
830 
831     /**
832      * Get the databaseTester.
833      *
834      * @see {@link #databaseTester}.
835      *
836      * @return The databaseTester.
837      */
838     @Override
839     public IDatabaseTester getDatabaseTester()
840     {
841         return databaseTester;
842     }
843 
844     /**
845      * Set the databaseTester.
846      *
847      * @see {@link #databaseTester}.
848      *
849      * @param databaseTester
850      *            The databaseTester to set.
851      */
852     public void setDatabaseTester(final IDatabaseTester databaseTester)
853     {
854         this.databaseTester = databaseTester;
855     }
856 
857     /**
858      * Get the dataFileLoader.
859      *
860      * @see {@link #dataFileLoader}.
861      *
862      * @return The dataFileLoader.
863      */
864     public DataFileLoader getDataFileLoader()
865     {
866         return dataFileLoader;
867     }
868 
869     /**
870      * Set the dataFileLoader.
871      *
872      * @see {@link #dataFileLoader}.
873      *
874      * @param dataFileLoader
875      *            The dataFileLoader to set.
876      */
877     public void setDataFileLoader(final DataFileLoader dataFileLoader)
878     {
879         this.dataFileLoader = dataFileLoader;
880     }
881 
882     /**
883      * Set the prepDs.
884      *
885      * @see {@link #prepDataSet}.
886      *
887      * @param prepDataSet
888      *            The prepDs to set.
889      */
890     public void setPrepDs(final IDataSet prepDataSet)
891     {
892         this.prepDataSet = prepDataSet;
893     }
894 
895     /**
896      * Set the expectedDs.
897      *
898      * @see {@link #expectedDataSet}.
899      *
900      * @param expectedDataSet
901      *            The expectedDs to set.
902      */
903     public void setExpectedDs(final IDataSet expectedDataSet)
904     {
905         this.expectedDataSet = expectedDataSet;
906     }
907 
908     /**
909      * Get the tableDefs.
910      *
911      * @see {@link #verifyTableDefs}.
912      *
913      * @return The tableDefs.
914      */
915     public VerifyTableDefinition[] getTableDefs()
916     {
917         return verifyTableDefs;
918     }
919 
920     /**
921      * Set the tableDefs.
922      *
923      * @see {@link #verifyTableDefs}.
924      *
925      * @param verifyTableDefs
926      *            The tableDefs to set.
927      */
928     public void setTableDefs(final VerifyTableDefinition[] verifyTableDefs)
929     {
930         this.verifyTableDefs = verifyTableDefs;
931     }
932 
933     public ValueComparerAndVerifyTableDefinitionVerifier getValueComparerAndVerifyTableDefinitionVerifier()
934     {
935         return valueComparerAndVerifyTableDefinitionVerifier;
936     }
937 
938     public void setValueComparerAndVerifyTableDefinitionVerifier(
939             final ValueComparerAndVerifyTableDefinitionVerifier valueComparerAndVerifyTableDefinitionVerifier)
940     {
941         this.valueComparerAndVerifyTableDefinitionVerifier =
942                 valueComparerAndVerifyTableDefinitionVerifier;
943     }
944 }