1 /*------------------------------------------------------------------------------
2 Name: TestTimestamp.java
3 Project: org.xmlBlasterProject: xmlBlaster.org
4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
5 ------------------------------------------------------------------------------*/
6 package org.xmlBlaster.test.contrib.dbwatcher;
7
8 import java.text.SimpleDateFormat;
9 import java.util.prefs.Preferences;
10
11
12 import junit.framework.TestCase;
13 import org.custommonkey.xmlunit.XMLTestCase;
14 import org.xmlBlaster.contrib.I_Info;
15 import org.xmlBlaster.contrib.db.I_DbPool;
16 import org.xmlBlaster.contrib.dbwatcher.DbWatcher;
17 import org.xmlBlaster.contrib.dbwatcher.Info;
18 import org.xmlBlaster.contrib.dbwatcher.detector.I_ChangeDetector;
19 import org.xmlBlaster.contrib.dbwatcher.detector.TimestampChangeDetector;
20
21 import java.util.logging.Logger;
22
23 import java.util.Map;
24 import java.util.HashMap;
25
26
27 /**
28 * Test basic functionality.
29 * <p>
30 * To run most of the tests you need to have a databse (for example Oracle)
31 * and XmlBlaster up and running.
32 * </p>
33 * <p>
34 * The connection configuration (url, password etc.) is configured
35 * as JVM property or in
36 * {@link org.xmlBlaster.test.contrib.dbwatcher.TestResultSetToXmlConverter#createTest(I_Info, Map)}
37 * and
38 * {@link org.xmlBlaster.test.contrib.dbwatcher.TestResultSetToXmlConverter#setUpDbPool(I_Info)}
39 * </p>
40 *
41 * @see DbWatcher
42 * @author Marcel Ruff
43 */
44 public class TestTimestamp extends XMLTestCase {
45 private static Logger log = Logger.getLogger(TestTimestamp.class.getName());
46 private Preferences prefs;
47 private I_Info info;
48 private I_DbPool dbPool;
49 private Map updateMap = new HashMap(); // collects received update messages
50 private DbWatcher processor;
51
52 /**
53 * Start the test.
54 * <pre>
55 * java -Ddb.password=secret junit.swingui.TestRunner -noloading org.xmlBlaster.test.contrib.dbwatcher.TestTimestamp
56 * </pre>
57 * @param args Command line settings
58 */
59 public static void main(String[] args) {
60 // junit.swingui.TestRunner.run(TestResultSetToXmlConverter.class);
61
62 TestTimestamp test = new TestTimestamp();
63 try {
64 // test.setUp();
65 test.testReplaceDate();
66 // test.tearDown();
67
68 }
69 catch (Exception ex) {
70 ex.printStackTrace();
71 fail("An exception occured: '" + ex.getMessage() + "-");
72 }
73 }
74
75 /**
76 * Default ctor.
77 */
78 public TestTimestamp() {
79 }
80
81 /**
82 * Constructor for TestResultSetToXmlConverter.
83 * @param arg0
84 */
85 public TestTimestamp(String arg0) {
86 super(arg0);
87 }
88
89 /**
90 * Configure database access.
91 * @see TestCase#setUp()
92 */
93 protected void setUp() throws Exception {
94 super.setUp();
95 this.prefs = Preferences.userRoot();
96 this.prefs.clear();
97 this.info = new Info(this.prefs);
98 this.dbPool = org.xmlBlaster.test.contrib.dbwatcher.TestResultSetToXmlConverter.setUpDbPool(info);
99 this.processor = null;
100 try {
101 this.dbPool.update("DROP TABLE TEST_TS");
102 } catch(Exception e) {
103 log.warning(e.toString());
104 }
105 }
106
107 /**
108 * Creates a DbWatcher instance and listens on MoM messages.
109 * @see org.xmlBlaster.test.contrib.dbwatcher.TestResultSetToXmlConverter#createTest(I_Info, Map)
110 */
111 private DbWatcher createTest(I_Info info, final Map updateMap) throws Exception {
112 return org.xmlBlaster.test.contrib.dbwatcher.TestResultSetToXmlConverter.createTest(info, updateMap);
113 }
114
115 /*
116 * @see TestCase#tearDown()
117 */
118 protected void tearDown() throws Exception {
119 super.tearDown();
120
121 if (this.processor != null) {
122 this.processor.shutdown();
123 this.processor = null;
124 }
125
126 if (this.dbPool != null) {
127 try {
128 this.dbPool.update("DROP TABLE TEST_TS");
129 } catch(Exception e) {
130 log.warning(e.toString());
131 }
132 this.dbPool.shutdown();
133 }
134 }
135
136 private void sleep(long millis) {
137 try { Thread.sleep(millis); } catch(Exception e) { /* Ignore */ }
138 }
139
140 /**
141 * Check detection of changes on a table and deliver the change as
142 * pure event without XML dump.
143 * @throws Exception Any type is possible
144 */
145 public final void testEmptyTableStates() throws Exception {
146
147 this.prefs.put("changeDetector.class", "org.xmlBlaster.contrib.dbwatcher.detector.TimestampChangeDetector");
148 this.prefs.put("converter.class", "");
149 this.prefs.put("changeDetector.detectStatement", "SELECT MAX(TO_CHAR(ts, 'YYYY-MM-DD HH24:MI:SSXFF')) FROM TEST_TS");
150 this.prefs.put("changeDetector.timestampColName", "ts");
151 this.prefs.put("alertScheduler.pollInterval", "0"); // switch off
152 this.prefs.put("changeDetector.groupColName", "ICAO_ID");
153 this.prefs.put("converter.rootName", "myRootTag");
154 this.prefs.put("converter.addMeta", ""+true);
155 this.prefs.put("db.queryMeatStatement", "SELECT * FROM TEST_TS WHERE TO_CHAR(ts, 'YYYY-MM-DD HH24:MI:SSXFF') > '${oldTimestamp}' ORDER BY ICAO_ID");
156 this.prefs.put("mom.topicName", "db.change.event.${groupColValue}");
157
158 this.processor = createTest(new Info(prefs), this.updateMap);
159 I_ChangeDetector changeDetector = processor.getChangeDetector();
160
161 for (int i=0; i<2; i++) {
162 log.info("Testing no table ...");
163 changeDetector.checkAgain(null);
164 sleep(500);
165 assertEquals("Number of message is wrong", 0, this.updateMap.size());
166 }
167
168 {
169 log.info("Now testing an empty table ...");
170 this.dbPool.update("CREATE TABLE TEST_TS (ts TIMESTAMP(9), colKey NUMBER(10,3), col1 VARCHAR(20), col2 NUMBER(12), ICAO_ID VARCHAR(10))");
171 changeDetector.checkAgain(null);
172 sleep(500);
173 assertEquals("Number of message is wrong", 1, this.updateMap.size());
174 String xml = (String)this.updateMap.get("db.change.event.${groupColValue}");
175 assertNotNull("No db.change.event.${groupColValue} message has arrived", xml);
176 assertEquals("", xml);
177 this.updateMap.clear();
178
179 changeDetector.checkAgain(null);
180 sleep(500);
181 assertEquals("Number of message is wrong", 0, this.updateMap.size());
182 }
183
184 {
185 log.info("Insert one row");
186 this.dbPool.update("INSERT INTO TEST_TS VALUES (CURRENT_TIMESTAMP, '1.1', '<Bla', '9000', 'EDDI')");
187 changeDetector.checkAgain(null);
188 sleep(500);
189 assertEquals("Number of message is wrong", 1, this.updateMap.size());
190 String xml = (String)this.updateMap.get("db.change.event.EDDI");
191 assertEquals("", xml);
192 this.updateMap.clear();
193
194 changeDetector.checkAgain(null);
195 sleep(500);
196 assertEquals("Number of message is wrong", 0, this.updateMap.size());
197 }
198
199 {
200 log.info("Update one row");
201 this.dbPool.update("UPDATE TEST_TS SET ts=CURRENT_TIMESTAMP, colKey='4.44' WHERE ICAO_ID='EDDI'");
202 changeDetector.checkAgain(null);
203 Thread.sleep(500);
204 assertEquals("Number of message is wrong", 1, this.updateMap.size());
205 String xml = (String)this.updateMap.get("db.change.event.EDDI");
206 assertNotNull("xml returned is null", xml);
207 assertEquals("", xml);
208 this.updateMap.clear();
209
210 changeDetector.checkAgain(null);
211 sleep(500);
212 assertEquals("Number of message is wrong", 0, this.updateMap.size());
213 }
214
215 // Is not detected by Timestamp poller!
216 {
217 log.info("Delete one row");
218 this.dbPool.update("DELETE FROM TEST_TS WHERE ICAO_ID='EDDI'");
219 changeDetector.checkAgain(null);
220 sleep(500);
221 assertEquals("Number of message is wrong", 0, this.updateMap.size());
222 // TODO: We don't know that EDDI was deleted
223 //String xml = (String)this.updateMap.get("db.change.event.${groupColValue}");
224 //assertNotNull("xml returned is null", xml);
225 //assertEquals("", xml);
226 this.updateMap.clear();
227
228 changeDetector.checkAgain(null);
229 sleep(500);
230 assertEquals("Number of message is wrong", 0, this.updateMap.size());
231 }
232
233 {
234 log.info("Drop a table");
235 this.dbPool.update("DROP TABLE TEST_TS");
236 changeDetector.checkAgain(null);
237 sleep(500);
238 assertEquals("Number of message is wrong", 1, this.updateMap.size());
239 String xml = (String)this.updateMap.get("db.change.event.${groupColValue}");
240 assertNotNull("xml returned is null", xml);
241 assertEquals("", xml);
242 this.updateMap.clear();
243
244 changeDetector.checkAgain(null);
245 sleep(500);
246 assertEquals("Number of message is wrong", 0, this.updateMap.size());
247 }
248
249 log.info("SUCCESS");
250 }
251
252
253 /**
254 * Checks if the conversion of the special token ${currentDate} is correct
255 */
256 public final void testReplaceDate() throws Exception {
257 // time='1157049798000' gives '2006-08-31 20:43:18.0'
258 // String // '2005-11-25 12:48:00.0' "yyyy-MM-dd HH:mm:ss.0"
259
260 long refTime = 1157049798000L;
261 String format = "yyyy-MM-dd HH:mm:ss.0";
262
263 String txt = "${currentDate}=" + format;
264 SimpleDateFormat dateFormatter = new SimpleDateFormat(format);
265 txt = "${currentDate}=yyyy-MM-dd HH:mm:ss.0";
266 String res = TimestampChangeDetector.modifyMinStrIfDate(txt, refTime);
267 assertEquals("date conversion is wrong", "2006-08-31 20:43:18.0", res);
268
269 txt = "${currentDate}= " + format;
270 res = TimestampChangeDetector.modifyMinStrIfDate(txt, refTime);
271 assertEquals("date conversion is wrong", " 2006-08-31 20:43:18.0", res);
272
273 txt = "${currentDate}";
274 res = TimestampChangeDetector.modifyMinStrIfDate(txt, refTime);
275 assertEquals("date conversion is wrong", "1157049798000", res);
276
277 txt = "${currentDate}=";
278 res = TimestampChangeDetector.modifyMinStrIfDate(txt, refTime);
279 assertEquals("date conversion is wrong", "", res);
280
281 txt = "currentDate";
282 res = TimestampChangeDetector.modifyMinStrIfDate(txt, refTime);
283 assertEquals("date conversion is wrong", "currentDate", res);
284
285 txt = null;
286 res = TimestampChangeDetector.modifyMinStrIfDate(txt, refTime);
287 assertNull("must be null", res);
288
289 txt = "${currentDate}=" + format;
290 res = TimestampChangeDetector.modifyMinStrIfDate(txt, 0L);
291 long currentTime = dateFormatter.parse(res).getTime();
292 String res2 = TimestampChangeDetector.modifyMinStrIfDate(txt, currentTime);
293 assertEquals("Wrong data conversion", res, res2);
294 log.info("SUCCESS");
295 }
296
297 /**
298 * Check detection of changes on a table and deliver the change as XML.
299 * @throws Exception Any type is possible
300 */
301 public final void testQueryMeatTableStates() throws Exception {
302 log.info("Start testQueryMeatTableStates()");
303
304 this.prefs.put("changeDetector.class", "org.xmlBlaster.contrib.dbwatcher.detector.TimestampChangeDetector");
305 this.prefs.put("changeDetector.detectStatement", "SELECT MAX(TO_CHAR(ts, 'YYYY-MM-DD HH24:MI:SSXFF')) FROM TEST_TS");
306 this.prefs.put("changeDetector.timestampColName", "ts");
307 this.prefs.put("alertScheduler.pollInterval", "0"); // switch off
308 this.prefs.put("changeDetector.groupColName", "ICAO_ID");
309 this.prefs.put("converter.rootName", "myRootTag");
310 this.prefs.put("converter.addMeta", ""+true);
311 this.prefs.put("db.queryMeatStatement", "SELECT * FROM TEST_TS WHERE TO_CHAR(ts, 'YYYY-MM-DD HH24:MI:SSXFF') > '${oldTimestamp}' ORDER BY ICAO_ID");
312 this.prefs.put("mom.topicName", "db.change.event.${groupColValue}");
313
314 this.processor = createTest(new Info(prefs), this.updateMap);
315 I_ChangeDetector changeDetector = processor.getChangeDetector();
316
317 for (int i=0; i<2; i++) {
318 log.info("Testing no table ...");
319 changeDetector.checkAgain(null);
320 sleep(500);
321 assertEquals("Number of message is wrong", 0, this.updateMap.size());
322 }
323
324 {
325 log.info("Now testing an empty table ...");
326 this.dbPool.update("CREATE TABLE TEST_TS (ts TIMESTAMP(9), colKey NUMBER(10,3), col1 VARCHAR(20), col2 NUMBER(12), ICAO_ID VARCHAR(10))");
327 changeDetector.checkAgain(null);
328 sleep(500);
329 assertEquals("Number of message is wrong", 1, this.updateMap.size());
330 String xml = (String)this.updateMap.get("db.change.event.${groupColValue}");
331 assertNotNull("No db.change.event.${groupColValue} message has arrived", xml);
332 assertXpathNotExists("/myRootTag/row[@num='0']", xml);
333 assertXpathEvaluatesTo("CREATE", "/myRootTag/desc/command/text()", xml);
334 this.updateMap.clear();
335
336 changeDetector.checkAgain(null);
337 sleep(500);
338 assertEquals("Number of message is wrong", 0, this.updateMap.size());
339 }
340
341 {
342 log.info("Insert one row");
343 this.dbPool.update("INSERT INTO TEST_TS VALUES (CURRENT_TIMESTAMP, '1.1', '<Bla', '9000', 'EDDI')");
344 changeDetector.checkAgain(null);
345 sleep(500);
346 assertEquals("Number of message is wrong", 1, this.updateMap.size());
347 String xml = (String)this.updateMap.get("db.change.event.EDDI");
348 assertNotNull("xml returned is null", xml);
349 assertXpathEvaluatesTo("UPDATE", "/myRootTag/desc/command/text()", xml);
350 assertXpathEvaluatesTo("<Bla", "/myRootTag/row[@num='0']/col[@name='COL1']/text()", xml);
351 //assertTrue(xml.indexOf("Bla-1.1") != -1);
352 this.updateMap.clear();
353
354 writeToFile("db.change.event.INSERT", xml);
355
356 changeDetector.checkAgain(null);
357 sleep(500);
358 assertEquals("Number of message is wrong", 0, this.updateMap.size());
359 }
360
361 {
362 log.info("Update one row");
363 this.dbPool.update("UPDATE TEST_TS SET ts=CURRENT_TIMESTAMP, colKey='4.44' WHERE ICAO_ID='EDDI'");
364 changeDetector.checkAgain(null);
365 Thread.sleep(500);
366 assertEquals("Number of message is wrong", 1, this.updateMap.size());
367 String xml = (String)this.updateMap.get("db.change.event.EDDI");
368 assertNotNull("xml returned is null", xml);
369 assertXpathEvaluatesTo("UPDATE", "/myRootTag/desc/command/text()", xml);
370 assertXpathEvaluatesTo("4.44", "/myRootTag/row[@num='0']/col[@name='COLKEY']/text()", xml);
371 this.updateMap.clear();
372
373 writeToFile("db.change.event.UPDATE", xml);
374
375 changeDetector.checkAgain(null);
376 sleep(500);
377 assertEquals("Number of message is wrong", 0, this.updateMap.size());
378 }
379
380 // Is not detected by Timestamp poller!
381 {
382 log.info("Delete one row");
383 this.dbPool.update("DELETE FROM TEST_TS WHERE ICAO_ID='EDDI'");
384 changeDetector.checkAgain(null);
385 sleep(500);
386 assertEquals("Number of message is wrong", 0, this.updateMap.size());
387 // TODO: We don't know that EDDI was deleted
388 //String xml = (String)this.updateMap.get("db.change.event.${groupColValue}");
389 //assertNotNull("xml returned is null", xml);
390 this.updateMap.clear();
391
392 changeDetector.checkAgain(null);
393 sleep(500);
394 assertEquals("Number of message is wrong", 0, this.updateMap.size());
395 }
396
397 {
398 log.info("Drop a table");
399 this.dbPool.update("DROP TABLE TEST_TS");
400 changeDetector.checkAgain(null);
401 sleep(500);
402 assertEquals("Number of message is wrong", 1, this.updateMap.size());
403 String xml = (String)this.updateMap.get("db.change.event.${groupColValue}");
404 assertNotNull("xml returned is null", xml);
405 assertXpathEvaluatesTo("DROP", "/myRootTag/desc/command/text()", xml);
406 assertXpathNotExists("/myRootTag/row[@num='0']", xml);
407 this.updateMap.clear();
408
409 writeToFile("db.change.event.DROP", xml);
410
411 changeDetector.checkAgain(null);
412 sleep(500);
413 assertEquals("Number of message is wrong", 0, this.updateMap.size());
414 }
415
416 log.info("SUCCESS");
417 }
418
419 /**
420 * Dump to file.
421 * @param topic The file name body
422 * @param xml The file content
423 * @throws Exception IOException
424 */
425 public static void writeToFile(String topic, String xml) throws Exception {
426 java.io.File f = new java.io.File(System.getProperty("java.io.tmpdir")+System.getProperty("file.separator")+topic+".xml");
427 java.io.FileOutputStream to = new java.io.FileOutputStream(f);
428 to.write(xml.getBytes());
429 to.close();
430 }
431 }
syntax highlighted by Code2HTML, v. 0.9.1