001: /*
002: * $Id: TestIsValidDateTimeFunction.java,v 1.5 2005/06/18 18:04:38 ahimanikya Exp $
003: * =======================================================================
004: * Copyright (c) 2004 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.functions;
042:
043: import java.util.HashMap;
044:
045: import junit.framework.Test;
046: import junit.framework.TestSuite;
047:
048: import org.axiondb.AxionException;
049: import org.axiondb.ColumnIdentifier;
050: import org.axiondb.Literal;
051: import org.axiondb.RowDecorator;
052: import org.axiondb.engine.rows.SimpleRow;
053: import org.axiondb.types.TimestampType;
054:
055: /**
056: * Unit tests for IsValidDateTime function.
057: *
058: * @version $Revision: 1.5 $ $Date: 2005/06/18 18:04:38 $
059: * @author Jonathan Giron
060: */
061: public class TestIsValidDateTimeFunction extends BaseFunctionTest {
062:
063: public TestIsValidDateTimeFunction(String testName) {
064: super (testName);
065: }
066:
067: public static final void main(String[] args) {
068: junit.textui.TestRunner.run(suite());
069: }
070:
071: public static Test suite() {
072: return new TestSuite(TestIsValidDateTimeFunction.class);
073: }
074:
075: public void setUp() throws Exception {
076: super .setUp();
077: TimestampType.setTimeZone("GMT");
078: }
079:
080: /*
081: * @see org.axiondb.functions.BaseFunctionTest#makeFunction()
082: */
083: protected ConcreteFunction makeFunction() {
084: return new IsValidDateTimeFunction();
085: }
086:
087: public void testMakeNewInstance() {
088: assertNotNull((new IsValidDateTimeFunction()).makeNewInstance());
089: }
090:
091: public void testIsValid() {
092: ConcreteFunction function = makeFunction();
093: assertFalse(function.isValid());
094: function.addArgument(new ColumnIdentifier("column"));
095: assertFalse(function.isValid());
096: function.addArgument(new ColumnIdentifier("column2"));
097: assertTrue(function.isValid());
098: function.addArgument(new ColumnIdentifier("column3"));
099: assertFalse(function.isValid());
100: }
101:
102: public void testValidFormats() throws Exception {
103: //
104: // Test YYYY-MM-DD date only format, with various separators
105: //
106: String formatStr = "yyyy-mm-dd";
107: String testItem = "2004-04-01";
108: assertValidDateTime(testItem, formatStr);
109:
110: formatStr = "yyyy/mm/dd";
111: testItem = "2004/04/01";
112: assertValidDateTime(testItem, formatStr);
113:
114: formatStr = "yyyy.mm.dd";
115: testItem = "2005.01.01";
116: assertValidDateTime(testItem, formatStr);
117:
118: formatStr = "yyyy mm dd";
119: testItem = "2004 04 01";
120: assertValidDateTime(testItem, formatStr);
121:
122: formatStr = "yyyymmdd";
123: testItem = "20040401";
124: assertValidDateTime(testItem, formatStr);
125:
126: // Test US civilian time only format, with colon separators
127: formatStr = "hh:mi:ss am";
128: testItem = "00:00:00 AM";
129: assertValidDateTime(testItem, formatStr);
130:
131: formatStr = "hh:mi:ss";
132: assertValidDateTime("00:00:00", formatStr);
133: assertValidDateTime("11:45:36", formatStr);
134:
135: // Test NATO/military time only formats
136: formatStr = "hh24:mi:ss";
137: testItem = "19:45:00";
138: assertValidDateTime(testItem, formatStr);
139:
140: formatStr = "hh24:mi:ss.ff";
141: testItem = "16:30:00.00";
142: assertValidDateTime(testItem, formatStr);
143:
144: //Test date/time combinations
145: formatStr = "MON DD YYYY HH:MIAM";
146: testItem = "APR 01 2004 01:45AM";
147: assertValidDateTime(testItem, formatStr);
148:
149: formatStr = "DD MON YYYY HH24:MI:SS";
150: testItem = "01 APR 2004 13:24:36";
151: assertValidDateTime(testItem, formatStr);
152:
153: formatStr = "YYYY-MM-DD HH24:MI:SS.FF";
154: testItem = "2004-04-01 18:45:22.5";
155: assertValidDateTime(testItem, formatStr);
156:
157: formatStr = "DD MON YYYY HH:MI:SS.FFAM";
158: testItem = "01 APR 2004 06:30:45.5pm";
159: assertValidDateTime(testItem, formatStr);
160:
161: formatStr = "DD/MM/YYYY HH:MI:SS.FFAM";
162: testItem = "01/04/2004 10:15:30.45AM";
163: assertValidDateTime(testItem, formatStr);
164:
165: // Test compact ISO 8601 format
166: formatStr = "yyyymmddThh24miss";
167: testItem = "20040401T000000";
168: assertValidDateTime(testItem, formatStr);
169:
170: // Test three-letter month abbreviation
171: formatStr = "dd mon yyyy hh24:mi:ss.ff";
172: testItem = "01 APR 2004 00:00:00.00";
173: assertValidDateTime(testItem, formatStr);
174:
175: formatStr = "dd mon yyyy";
176: testItem = "01 AUG 2004";
177: assertValidDateTime(testItem, formatStr);
178:
179: formatStr = "mon dd, yyyy";
180: testItem = "FEB 29, 2004";
181: assertValidDateTime(testItem, formatStr);
182:
183: // Test German-style date format with various separators
184: formatStr = "dd.mm.yyyy";
185: testItem = "01.04.2004";
186: assertValidDateTime(testItem, formatStr);
187:
188: formatStr = "dd/mm/yyyy";
189: testItem = "13/01/2004";
190: assertValidDateTime(testItem, formatStr);
191:
192: formatStr = "dd-mm-yyyy";
193: testItem = "30-04-2004";
194: assertValidDateTime(testItem, formatStr);
195:
196: // Test US-style date format with various separators
197: formatStr = "mm/dd/yyyy";
198: testItem = "04/01/2004";
199: assertValidDateTime(testItem, formatStr);
200:
201: formatStr = "mm-dd-yyyy";
202: testItem = "04-01-2004";
203: assertValidDateTime(testItem, formatStr);
204:
205: formatStr = "mm.dd.yyyy";
206: testItem = "04.01.2004";
207: assertValidDateTime(testItem, formatStr);
208:
209: // Test pattern with all capital letters
210: formatStr = "YYYYMMDDTHH24MISS";
211: testItem = "20040401T000000";
212: assertValidDateTime(testItem, formatStr);
213:
214: // Test patterns with 2-digit year
215: formatStr = "YYMMDD";
216: testItem = "080229";
217: assertValidDateTime(testItem, formatStr);
218:
219: formatStr = "mm/dd/yy";
220: testItem = "02/29/04";
221: assertValidDateTime(testItem, formatStr);
222:
223: formatStr = "DD/MM/YY";
224: testItem = "29/02/04";
225: assertValidDateTime(testItem, formatStr);
226:
227: formatStr = "YY/MM/DD";
228: testItem = "04/02/29";
229: assertValidDateTime(testItem, formatStr);
230:
231: formatStr = "mm-dd-yy";
232: testItem = "02-29-00";
233: assertValidDateTime(testItem, formatStr);
234:
235: formatStr = "DD-MM-YY";
236: testItem = "29-02-00";
237: assertValidDateTime(testItem, formatStr);
238:
239: formatStr = "YY-MM-DD";
240: testItem = "04-02-29";
241: assertValidDateTime(testItem, formatStr);
242:
243: formatStr = "MM.DD.YY";
244: testItem = "02.29.96";
245: assertValidDateTime(testItem, formatStr);
246:
247: formatStr = "DD.MM.YY";
248: testItem = "29.02.96";
249: assertValidDateTime(testItem, formatStr);
250:
251: formatStr = "YY.MM.DD";
252: testItem = "96.02.29";
253: assertValidDateTime(testItem, formatStr);
254:
255: formatStr = "MON DD, YY";
256: testItem = "FEB 29, 92";
257: assertValidDateTime(testItem, formatStr);
258:
259: formatStr = "DD MON YY";
260: testItem = "29 FEB 92";
261: assertValidDateTime(testItem, formatStr);
262:
263: formatStr = "YY MON DD";
264: testItem = "92 FEB 29";
265: assertValidDateTime(testItem, formatStr);
266: }
267:
268: public void testNullDateStrYieldsNull() throws Exception {
269: IsValidDateTimeFunction function = new IsValidDateTimeFunction();
270: ColumnIdentifier timestampLbl = new ColumnIdentifier("dateStr");
271: ColumnIdentifier formatLbl = new ColumnIdentifier("format");
272:
273: function.addArgument(timestampLbl);
274: function.addArgument(formatLbl);
275:
276: HashMap map = new HashMap();
277: map.put(timestampLbl, new Integer(0));
278: map.put(formatLbl, new Integer(1));
279:
280: RowDecorator dec = new RowDecorator(map);
281: Literal format = new Literal("yyyy.mm.dd");
282: dec.setRow(new SimpleRow(new Object[] { null, format }));
283:
284: Object returnVal = function.evaluate(dec);
285: assertNull(
286: "Null value for date-str input should have returned null",
287: returnVal);
288: }
289:
290: public void testInvalidDateStrReturnsFalse() throws Exception {
291: String formatStr = "yyyy-mm-dd";
292: assertInvalidDateTime("abcdef", formatStr);
293: }
294:
295: public void testOutOfRangeYearInDateStrReturnsFalse()
296: throws Exception {
297: String formatStr = "yyyy-mm-dd";
298: assertInvalidDateTime("testItem", formatStr);
299: }
300:
301: public void testOutOfRangeMonthInDateStrReturnsFalse()
302: throws Exception {
303: String formatStr = "yyyy-mm-dd";
304: assertInvalidDateTime("2004-13-02", formatStr);
305: assertInvalidDateTime("2004-00-01", formatStr);
306: }
307:
308: public void testOutOfRangeDayInDateStrReturnsFalse()
309: throws Exception {
310: String formatStr = "yyyymmdd";
311: assertInvalidDateTime("20050229", formatStr);
312: assertInvalidDateTime("200502-1", formatStr);
313: assertInvalidDateTime("20052903", formatStr);
314: }
315:
316: public void testOutOfRangeHourInTimeStrReturnsFalse()
317: throws Exception {
318: // Test 24-hour format range
319: String formatStr = "hh24:mi:ss";
320: assertInvalidDateTime("24:00:00", formatStr);
321: assertInvalidDateTime("-1:00:00", formatStr);
322:
323: // Test 12-hour format range (1-12) [hh12]
324: formatStr = "hh12:mi:ss";
325: assertInvalidDateTime("13:00:00", formatStr);
326: assertInvalidDateTime("-1:00:00", formatStr);
327:
328: // Test 12-hour format range (1-12) [hh - identical to hh12]
329: formatStr = "hh:mi:ss";
330: assertInvalidDateTime("13:00:00", formatStr);
331: assertInvalidDateTime("-1:00:00", formatStr);
332: }
333:
334: public void testOutOfRangeMinuteInTimeStrReturnsFalse()
335: throws Exception {
336: // Test minute range (00-59)
337: String formatStr = "hh24:mi:ss";
338: assertInvalidDateTime("10:61:00", formatStr);
339: assertInvalidDateTime("10:-1:00", formatStr);
340: }
341:
342: public void testOutOfRangeSecondInTimeStrReturnsFalse()
343: throws Exception {
344: // Test second range (00-59)
345: String formatStr = "hh24:mi:ss";
346: assertInvalidDateTime("10:00:61", formatStr);
347: assertInvalidDateTime("10:00:-1", formatStr);
348: }
349:
350: public void testMalformedAMPMReturnsFalse() throws Exception {
351: String formatStr = "hh24:mi:ss am";
352: assertInvalidDateTime("10:00:00 DM", formatStr);
353: }
354:
355: public void testInvalidFormatThrowsException() throws Exception {
356: ColumnIdentifier timestampLbl = new ColumnIdentifier("dateStr");
357: ColumnIdentifier formatLbl = new ColumnIdentifier(
358: "formatLiteral");
359:
360: IsValidDateTimeFunction function = new IsValidDateTimeFunction();
361: function.addArgument(timestampLbl);
362: function.addArgument(formatLbl);
363:
364: HashMap map = new HashMap();
365: map.put(timestampLbl, new Integer(0));
366: map.put(formatLbl, new Integer(1));
367:
368: RowDecorator dec = new RowDecorator(map);
369: dec
370: .setRow(new SimpleRow(new Object[] { "2004-04-15",
371: "bcdef" }));
372: try {
373: function.evaluate(dec);
374: fail("Expected AxionException(22007) for invalid format string");
375: } catch (AxionException e) {
376: if (!"22007".equals(e.getSQLState())) {
377: fail("Expected AxionException(22007) for invalid format string");
378: }
379: // expected
380: }
381:
382: // mmm is not a valid date/time part mnemonic
383: dec.setRow(new SimpleRow(new Object[] { "2004-04-15",
384: "yyyy-mmm-dd" }));
385: try {
386: function.evaluate(dec);
387: fail("Expected AxionException(22007) for invalid format string: yyyy-mmm-dd");
388: } catch (AxionException e) {
389: if (!"22007".equals(e.getSQLState())) {
390: fail("Expected AxionException(22007) for invalid format string: yyyy-mmm-dd");
391: }
392: // expected
393: }
394: }
395:
396: public void testNullFormatThrowsException() throws Exception {
397: ColumnIdentifier timestampLbl = new ColumnIdentifier("dateStr");
398: ColumnIdentifier formatLbl = new ColumnIdentifier(
399: "formatLiteral");
400:
401: IsValidDateTimeFunction function = new IsValidDateTimeFunction();
402: function.addArgument(timestampLbl);
403: function.addArgument(formatLbl);
404:
405: HashMap map = new HashMap();
406: map.put(timestampLbl, new Integer(0));
407: map.put(formatLbl, new Integer(1));
408:
409: RowDecorator dec = new RowDecorator(map);
410: dec.setRow(new SimpleRow(new Object[] { "2004-04-15", null }));
411: try {
412: function.evaluate(dec);
413: fail("Expected AxionException(22004) for null format string");
414: } catch (AxionException e) {
415: if (!"22004".equals(e.getSQLState())) {
416: fail("Expected AxionException(22004) for null format string");
417: }
418: // expected
419: }
420: }
421:
422: public void testMismatchedFormatsAndValues() throws Exception {
423: String formatStr = "dd/mm/yy";
424: assertInvalidDateTime("03/24/2002", formatStr);
425: assertInvalidDateTime("11/29/1999 12:37:09.18PM", formatStr);
426:
427: formatStr = "hh:mi:ss";
428: assertInvalidDateTime("03/24/2002", formatStr);
429: }
430:
431: public void testPartialMatchesReturnFalse() throws Exception {
432: String formatStr = "dd/mm/yyyy";
433: assertInvalidDateTime("23 03 2002 15:23:45", formatStr);
434:
435: formatStr = "hh24:mi:ss am";
436: assertInvalidDateTime("15:23:45", formatStr);
437: }
438:
439: public void testTwoDigitYearPatternRejectsFourYearString()
440: throws Exception {
441: assertInvalidDateTime("1971-03-31", "yy-mm-dd");
442: assertInvalidDateTime("03-31-1971 15:45", "mm-dd-yy hh24:mi");
443: assertInvalidDateTime("03-31-1971", "mm-dd-yy");
444:
445: assertInvalidDateTime("1971 03 31", "yy mm dd");
446: assertInvalidDateTime("03 31 1971 15:45", "mm dd yy hh24:mi");
447: assertInvalidDateTime("03 31 1971", "mm dd yy");
448:
449: assertInvalidDateTime("1971/03/31", "yy/mm/dd");
450: assertInvalidDateTime("03/31/1971 15:45", "mm/dd/yy hh24:mi");
451: assertInvalidDateTime("03/31/1971", "mm/dd/yy");
452:
453: assertInvalidDateTime("1971.03.31", "yy.mm.dd");
454: assertInvalidDateTime("03.31.1971 15:45", "mm.dd.yy hh24:mi");
455: assertInvalidDateTime("03.31.1971", "mm.dd.yy");
456:
457: assertInvalidDateTime("19710331", "yymmdd");
458: assertInvalidDateTime("03311971 15:45", "mmddyy hh24:mi");
459: assertInvalidDateTime("03311971", "mmddyy");
460:
461: assertInvalidDateTime("19710331 125900", "yymmdd hhmiss");
462: assertInvalidDateTime("01312005123456", "mmddyyThhmiss");
463: }
464:
465: public void testFourDigitYearPatternRejectsTwoYearString()
466: throws Exception {
467: assertInvalidDateTime("71-03-31", "yyyy-mm-dd");
468: assertInvalidDateTime("03-31-71 15:45", "mm-dd-yyyy hh24:mi");
469: assertInvalidDateTime("03-31-71", "mm-dd-yyyy");
470:
471: assertInvalidDateTime("71 03 31", "yyyy mm dd");
472: assertInvalidDateTime("03 31 71 15:45", "mm dd yyyy hh24:mi");
473: assertInvalidDateTime("03 31 71", "mm dd yyyy");
474:
475: assertInvalidDateTime("71/03/31", "yyyy/mm/dd");
476: assertInvalidDateTime("03/31/71 15:45", "mm/dd/yyyy hh24:mi");
477: assertInvalidDateTime("03/31/71", "mm/dd/yyyy");
478:
479: assertInvalidDateTime("71.03.31", "yyyy.mm.dd");
480: assertInvalidDateTime("03.31.71 15:45", "mm.dd.yyyy hh24:mi");
481: assertInvalidDateTime("03.31.71", "mm.dd.yyyy");
482:
483: assertInvalidDateTime("710331", "yyyymmdd");
484: assertInvalidDateTime("033171 15:45", "mmddyyyy hh24:mi");
485: assertInvalidDateTime("033171", "mmddyyyy");
486:
487: assertInvalidDateTime("710331 125900", "yyyymmdd hhmiss");
488: assertInvalidDateTime("013105123456", "mmddyyyyhhmiss");
489:
490: assertInvalidDateTime("013105T123456", "mmddyyyyThhmiss");
491: }
492:
493: public void testDuplicatedMnemonicInPatternRejected()
494: throws AxionException {
495: ColumnIdentifier timestampLbl = new ColumnIdentifier("dateStr");
496: ColumnIdentifier formatLbl = new ColumnIdentifier(
497: "formatLiteral");
498:
499: IsValidDateTimeFunction function = new IsValidDateTimeFunction();
500: function.addArgument(timestampLbl);
501: function.addArgument(formatLbl);
502:
503: HashMap map = new HashMap();
504: map.put(timestampLbl, new Integer(0));
505: map.put(formatLbl, new Integer(1));
506:
507: RowDecorator dec = new RowDecorator(map);
508: dec.setRow(new SimpleRow(
509: new Object[] { "20042004", "yyyyyyyy" }));
510: try {
511: function.evaluate(dec);
512: fail("Expected AxionException(22007) for bad format string");
513: } catch (AxionException e) {
514: if (!"22007".equals(e.getSQLState())) {
515: fail("Expected AxionException(22007) for bad format string");
516: }
517: // expected
518: }
519:
520: dec.setRow(new SimpleRow(new Object[] { "1212", "mmmm" }));
521: try {
522: function.evaluate(dec);
523: fail("Expected AxionException(22007) for bad format string");
524: } catch (AxionException e) {
525: if (!"22007".equals(e.getSQLState())) {
526: fail("Expected AxionException(22007) for bad format string");
527: }
528: // expected
529: }
530: }
531:
532: private void assertValidDateTime(String testItem, String formatStr)
533: throws AxionException {
534: Literal format = new Literal(formatStr);
535:
536: ColumnIdentifier timestampLbl = new ColumnIdentifier("dateStr");
537: ColumnIdentifier formatLbl = new ColumnIdentifier(
538: "formatLiteral");
539:
540: IsValidDateTimeFunction function = new IsValidDateTimeFunction();
541: function.addArgument(timestampLbl);
542: function.addArgument(formatLbl);
543:
544: HashMap map = new HashMap();
545: map.put(timestampLbl, new Integer(0));
546: map.put(formatLbl, new Integer(1));
547:
548: RowDecorator dec = new RowDecorator(map);
549: dec.setRow(new SimpleRow(new Object[] { testItem, format }));
550: Object returnVal = function.evaluate(dec);
551:
552: assertEquals("Expected true for valid string " + testItem
553: + "; ", Boolean.TRUE, returnVal);
554: }
555:
556: private void assertInvalidDateTime(String testItem, String formatStr)
557: throws AxionException {
558: Literal format = new Literal(formatStr);
559:
560: ColumnIdentifier timestampLbl = new ColumnIdentifier("dateStr");
561: ColumnIdentifier formatLbl = new ColumnIdentifier(
562: "formatLiteral");
563:
564: IsValidDateTimeFunction function = new IsValidDateTimeFunction();
565: function.addArgument(timestampLbl);
566: function.addArgument(formatLbl);
567:
568: HashMap map = new HashMap();
569: map.put(timestampLbl, new Integer(0));
570: map.put(formatLbl, new Integer(1));
571:
572: RowDecorator dec = new RowDecorator(map);
573: dec.setRow(new SimpleRow(new Object[] { testItem, format }));
574:
575: Object returnVal = function.evaluate(dec);
576: assertEquals("Expected false for invalid string " + testItem
577: + "; ", Boolean.FALSE, returnVal);
578: }
579: }
|