1 /***
2 * Redistribution and use of this software and associated documentation
3 * ("Software"), with or without modification, are permitted provided
4 * that the following conditions are met:
5 *
6 * 1. Redistributions of source code must retain copyright
7 * statements and notices. Redistributions must also contain a
8 * copy of this document.
9 *
10 * 2. Redistributions in binary form must reproduce the
11 * above copyright notice, this list of conditions and the
12 * following disclaimer in the documentation and/or other
13 * materials provided with the distribution.
14 *
15 * 3. The name "Exolab" must not be used to endorse or promote
16 * products derived from this Software without prior written
17 * permission of Exoffice Technologies. For written permission,
18 * please contact info@exolab.org.
19 *
20 * 4. Products derived from this Software may not be called "Exolab"
21 * nor may "Exolab" appear in their names without prior written
22 * permission of Exoffice Technologies. Exolab is a registered
23 * trademark of Exoffice Technologies.
24 *
25 * 5. Due credit should be given to the Exolab Project
26 * (http://www.exolab.org/).
27 *
28 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32 * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 * OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Copyright 2005 (C) Exoffice Technologies Inc. All Rights Reserved.
42 *
43 * $Id: ExportImportTest.java,v 1.2 2005/11/12 12:52:06 tanderson Exp $
44 */
45 package org.exolab.jms.tools.migration;
46
47 import java.io.InputStream;
48 import java.sql.Connection;
49 import java.sql.DriverManager;
50 import java.sql.SQLException;
51
52 import org.apache.derby.jdbc.EmbeddedDataSource;
53
54 import junit.framework.TestCase;
55 import org.dbunit.Assertion;
56 import org.dbunit.database.DatabaseConnection;
57 import org.dbunit.database.IDatabaseConnection;
58 import org.dbunit.database.QueryDataSet;
59 import org.dbunit.dataset.IDataSet;
60 import org.dbunit.dataset.ITable;
61 import org.exolab.jms.config.Configuration;
62 import org.exolab.jms.config.ConfigurationReader;
63 import org.exolab.jms.config.DatabaseConfiguration;
64 import org.exolab.jms.config.RdbmsDatabaseConfiguration;
65 import org.exolab.jms.persistence.PersistenceException;
66 import org.exolab.jms.tools.db.Database;
67 import org.exolab.jms.tools.db.RDBMSTool;
68 import org.exolab.jms.tools.db.SchemaHelper;
69
70
71 /***
72 * Tests the {@link Exporter} and {@link Importer}.
73 *
74 * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a>
75 * @version $Revision: 1.2 $ $Date: 2005/11/12 12:52:06 $
76 */
77 public class ExportImportTest extends TestCase {
78
79 /***
80 * Migration database name.
81 */
82 private static final String DB_NAME = "openjms_migdb";
83
84 /***
85 * Destinations table query. Ignores destination identifiers as these
86 * may be different between databases.
87 */
88 private static final String DESTINATIONS_QUERY
89 = "select name, isQueue from destinations order by name";
90 /***
91 * Message handles table query. Translates destination and consumer
92 * identifiers to their corresponding names, as these may be different
93 * between databases.
94 */
95 private static final String MESSAGE_HANDLES_QUERY
96 = "select messageId, d.name destination, c.name consumer, "
97 + " priority, acceptedTime, sequenceNumber, expiryTime, "
98 + " delivered "
99 + "from message_handles m, destinations d, consumers c "
100 + "where m.destinationId = d.destinationId and "
101 + " m.consumerId = c.consumerId "
102 + "order by messageId, destination, consumer";
103
104 /***
105 * Consumers table query. Ignores the 'created' column which is no longer
106 * used.
107 */
108 private static final String CONSUMERS_QUERY
109 = "select c.name name, d.name destination "
110 + "from consumers c, destinations d "
111 + "where c.destinationId = d.destinationId "
112 + "order by name, destination";
113
114 /***
115 * Verifies that the exporter creates the tables in the target proxy,
116 * if they don't exist.
117 *
118 * @throws Exception for any error
119 */
120 public void testExporterCreateTables() throws Exception {
121
122 Configuration config = read("/openjmstest.xml");
123
124
125 EmbeddedDataSource ds = MigrationHelper.getDataSource(DB_NAME);
126 RDBMSTool tool = new RDBMSTool(ds.getConnection());
127 Database schema = MigrationHelper.getSchema();
128 tool.drop(schema);
129 assertFalse(tool.hasTables(schema.getTable()));
130
131
132 new Exporter(config, DB_NAME, false);
133 assertTrue(tool.hasTables(schema.getTable()));
134 }
135
136 /***
137 * Verifies that the exporter will only export data if the delete flag
138 * is true when the tables exists.
139 *
140 * @throws Exception for any error
141 */
142 public void testExporterDelete() throws Exception {
143
144 Configuration config = read("/openjmstest.xml");
145
146
147 EmbeddedDataSource ds = MigrationHelper.getDataSource(DB_NAME);
148 RDBMSTool tool = new RDBMSTool(ds.getConnection());
149 Database schema = MigrationHelper.getSchema();
150 tool.drop(schema);
151 tool.create(schema);
152
153
154 try {
155 new Exporter(config, DB_NAME, false);
156 fail("Expected Exporter construction to fail, as tables exist");
157 } catch (PersistenceException expected) {
158
159 }
160
161 try {
162 new Exporter(config, DB_NAME, true);
163 } catch (PersistenceException unexpected) {
164 fail("Expected Exporter construction to succeed");
165 }
166 }
167
168 /***
169 * Verifies that the importer creates the tables in the target master,
170 * if they don't exist.
171 *
172 * @throws Exception for any error
173 */
174 public void testImporterCreateTables() throws Exception {
175
176 Configuration config = read("/openjmstest_migrated.xml");
177
178
179 RDBMSTool tool = new RDBMSTool(config);
180 Database schema = SchemaHelper.getSchema();
181 tool.drop(schema);
182 assertFalse(tool.hasTables(schema.getTable()));
183
184
185 new Importer(config, DB_NAME, false);
186 assertTrue(tool.hasTables(schema.getTable()));
187 }
188
189 /***
190 * Verifies that the importer will only import data if the delete flag
191 * is true when the tables exists.
192 *
193 * @throws Exception for any error
194 */
195 public void testImporterDelete() throws Exception {
196
197 Configuration config = read("/openjmstest_migrated.xml");
198
199
200 RDBMSTool tool = new RDBMSTool(config);
201 Database schema = SchemaHelper.getSchema();
202 tool.drop(schema);
203 tool.create(schema);
204 tool.close();
205
206
207 try {
208 new Importer(config, DB_NAME, false);
209 fail("Expected Importer construction to fail, as tables exist");
210 } catch (PersistenceException expected) {
211
212 }
213
214 try {
215 new Importer(config, DB_NAME, true);
216 } catch (PersistenceException unexpected) {
217 fail("Expected Importer construction to succeed");
218 }
219 }
220
221 /***
222 * Exports data from a database and imports it to another, verifying the
223 * contents are the same between each.
224 *
225 * @throws Exception for any error
226 */
227 public void testRoundtrip() throws Exception {
228
229 Configuration master = read("/openjmstest.xml");
230
231
232 Exporter exporter = new Exporter(master, DB_NAME, true);
233 exporter.apply();
234
235
236 Configuration migrated = read("/openjmstest_migrated.xml");
237
238
239 Importer importer = new Importer(migrated, DB_NAME, true);
240 importer.apply();
241
242
243 IDatabaseConnection masterConn = getConnection(master);
244 IDatabaseConnection migratedConn = getConnection(migrated);
245 IDataSet expectedDataSet = masterConn.createDataSet();
246 IDataSet actualDataSet = migratedConn.createDataSet();
247
248
249
250
251 checkQuery("destinations", DESTINATIONS_QUERY, masterConn,
252 migratedConn);
253 checkTable("messages", expectedDataSet, actualDataSet);
254 checkQuery("message_handles", MESSAGE_HANDLES_QUERY, masterConn,
255 migratedConn);
256 checkQuery("consumers", CONSUMERS_QUERY, masterConn, migratedConn);
257 checkTable("users", expectedDataSet, actualDataSet);
258 }
259
260 /***
261 * Reads a configuration from a resource.
262 *
263 * @param path the path to the resource
264 * @throws Exception for any error
265 */
266 private Configuration read(String path) throws Exception {
267 InputStream stream = ExportImportTest.class.getResourceAsStream(path);
268 return ConfigurationReader.read(stream);
269 }
270
271 /***
272 * Returns a dbunit connection for a database.
273 *
274 * @param config the configuration to use
275 * @return the connection
276 * @throws SQLException for any error
277 */
278 private IDatabaseConnection getConnection(Configuration config)
279 throws SQLException {
280 DatabaseConfiguration db = config.getDatabaseConfiguration();
281 Connection connection
282 = getConnection(db.getRdbmsDatabaseConfiguration());
283 return new DatabaseConnection(connection);
284 }
285
286 /***
287 * Returns a connection given the configuration.
288 *
289 * @param config the config to use
290 * @throws SQLException for any error
291 */
292 private Connection getConnection(RdbmsDatabaseConfiguration config)
293 throws SQLException {
294 return DriverManager.getConnection(config.getUrl(), config.getUser(),
295 config.getPassword());
296 }
297
298 /***
299 * Verifies that the contents of the named table is the same in 2 datasets.
300 *
301 * @param table the table name
302 * @param expectedDataSet the data set containing the expected results
303 * @param actualDataSet the data st containing the actual results
304 * @throws Exception for any error
305 */
306 private void checkTable(String table, IDataSet expectedDataSet,
307 IDataSet actualDataSet) throws Exception {
308 ITable expected = expectedDataSet.getTable(table);
309 ITable actual = actualDataSet.getTable(table);
310
311
312 assertTrue(expected.getRowCount() != 0);
313
314 Assertion.assertEquals(expected, actual);
315 }
316
317 /***
318 * Verifies that the results returned by a query are the same from two
319 * different connections.
320 *
321 * @param table the table name
322 * @param query the query to execute
323 * @param expectedConnection the connection containing the expected results
324 * @param actualConnection the connection containing the actual results
325 * @throws Exception for any error
326 */
327 private void checkQuery(String table, String query,
328 IDatabaseConnection expectedConnection,
329 IDatabaseConnection actualConnection)
330 throws Exception {
331 QueryDataSet expectedDataSet = new QueryDataSet(expectedConnection);
332 expectedDataSet.addTable(table, query);
333
334 QueryDataSet actualDataSet = new QueryDataSet(actualConnection);
335 actualDataSet.addTable(table, query);
336
337
338
339
340
341 assertTrue(expectedDataSet.getTable(table).getRowCount() != 0);
342
343 Assertion.assertEquals(expectedDataSet, actualDataSet);
344 }
345
346 }