View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.validator.routines;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertFalse;
21  import static org.junit.jupiter.api.Assertions.assertNotNull;
22  import static org.junit.jupiter.api.Assertions.assertNull;
23  import static org.junit.jupiter.api.Assertions.assertTrue;
24  import static org.junit.jupiter.api.Assertions.fail;
25  
26  import java.io.ByteArrayInputStream;
27  import java.io.ByteArrayOutputStream;
28  import java.io.ObjectInputStream;
29  import java.io.ObjectOutputStream;
30  import java.util.Calendar;
31  import java.util.Date;
32  import java.util.Locale;
33  import java.util.TimeZone;
34  
35  import org.junit.jupiter.api.AfterEach;
36  import org.junit.jupiter.api.Test;
37  
38  /**
39   * Base Calendar Test Case.
40   */
41  public abstract class AbstractCalendarValidatorTest {
42  
43      protected static final TimeZone GMT = TimeZone.getTimeZone("GMT"); // 0 offset
44  
45      protected static final TimeZone EST = TimeZone.getTimeZone("EST"); // - 5 hours
46      protected static final TimeZone EET = TimeZone.getTimeZone("EET"); // + 2 hours
47      protected static final TimeZone UTC = TimeZone.getTimeZone("UTC"); // + 2 hours
48  
49      /**
50       * Create a calendar instance for a specified time zone, date and time.
51       *
52       * @param zone The time zone
53       * @param date The date in yyyyMMdd format
54       * @param time the time in HH:mm:ss format
55       * @return the new Calendar instance.
56       */
57      protected static Calendar createCalendar(final TimeZone zone, final int date, final int time) {
58          final Calendar calendar = zone == null ? Calendar.getInstance() : Calendar.getInstance(zone);
59          final int year = date / 10000 * 10000;
60          final int mth = date / 100 * 100 - year;
61          final int day = date - (year + mth);
62          final int hour = time / 10000 * 10000;
63          final int min = time / 100 * 100 - hour;
64          final int sec = time - (hour + min);
65          calendar.set(Calendar.YEAR, year / 10000);
66          calendar.set(Calendar.MONTH, mth / 100 - 1);
67          calendar.set(Calendar.DATE, day);
68          calendar.set(Calendar.HOUR_OF_DAY, hour / 10000);
69          calendar.set(Calendar.MINUTE, min / 100);
70          calendar.set(Calendar.SECOND, sec);
71          calendar.set(Calendar.MILLISECOND, 0);
72          return calendar;
73      }
74  
75      /**
76       * Create a date instance for a specified time zone, date and time.
77       *
78       * @param zone The time zone
79       * @param date The date in yyyyMMdd format
80       * @param time the time in HH:mm:ss format
81       * @return the new Date instance.
82       */
83      protected static Date createDate(final TimeZone zone, final int date, final int time) {
84          final Calendar calendar = createCalendar(zone, date, time);
85          return calendar.getTime();
86      }
87  
88      protected AbstractCalendarValidator validator;
89      protected String[] patternValid = { "2005-01-01", "2005-12-31", "2004-02-29" // valid leap
90              , "2005-04-30", "05-12-31", "2005-1-1", "05-1-1" };
91      protected String[] localeValid = { "01/01/2005", "12/31/2005", "02/29/2004" // valid leap
92              , "04/30/2005", "12/31/05", "1/1/2005", "1/1/05" };
93      protected Date[] patternExpect = { createDate(null, 20050101, 0), createDate(null, 20051231, 0), createDate(null, 20040229, 0),
94              createDate(null, 20050430, 0), createDate(null, 20051231, 0), createDate(null, 20050101, 0), createDate(null, 20050101, 0) };
95  
96      protected String[] patternInvalid = { "2005-00-01" // zero month
97              , "2005-01-00" // zero day
98              , "2005-13-03" // month invalid
99              , "2005-04-31" // invalid day
100             , "2005-03-32" // invalid day
101             , "2005-02-29" // invalid leap
102             , "200X-01-01" // invalid char
103             , "2005-0X-01" // invalid char
104             , "2005-01-0X" // invalid char
105             , "01/01/2005" // invalid pattern
106             , "2005-01" // invalid pattern
107             , "2005--01" // invalid pattern
108             , "2005-01-" }; // invalid pattern
109 
110     protected String[] localeInvalid = { "01/00/2005" // zero month
111             , "00/01/2005" // zero day
112             , "13/01/2005" // month invalid
113             , "04/31/2005" // invalid day
114             , "03/32/2005" // invalid day
115             , "02/29/2005" // invalid leap
116             , "01/01/200X" // invalid char
117             , "01/0X/2005" // invalid char
118             , "0X/01/2005" // invalid char
119             , "01-01-2005" // invalid pattern
120             , "01/2005" // invalid pattern
121             // -------- ,"/01/2005" ---- passes on some JDK
122             , "01//2005" }; // invalid pattern
123 
124     /**
125      * Tear down
126      */
127     @AfterEach
128     protected void tearDown() {
129         validator = null;
130     }
131 
132     /**
133      * Test Invalid Dates with "locale" validation
134      */
135     @Test
136     public void testFormat() {
137 
138         // Create a Date or Calendar
139         final Object test = validator.parse("2005-11-28", "yyyy-MM-dd", null, null);
140         assertNotNull(test, "Test Date");
141         assertEquals("28.11.05", validator.format(test, "dd.MM.yy"), "Format pattern");
142         assertEquals("11/28/05", validator.format(test, Locale.US), "Format locale");
143     }
144 
145     /**
146      * Test Invalid Dates with "locale" validation
147      */
148     @Test
149     public void testLocaleInvalid() {
150         for (int i = 0; i < localeInvalid.length; i++) {
151             final String text = i + " value=[" + localeInvalid[i] + "] passed ";
152             final Object date = validator.parse(localeInvalid[i], null, Locale.US, null);
153             assertNull(date, "validateObj() " + text + date);
154             assertFalse(validator.isValid(localeInvalid[i], Locale.US), "isValid() " + text);
155         }
156     }
157 
158     /**
159      * Test Valid Dates with "locale" validation
160      */
161     @Test
162     public void testLocaleValid() {
163         for (int i = 0; i < localeValid.length; i++) {
164             final String text = i + " value=[" + localeValid[i] + "] failed ";
165             Object date = validator.parse(localeValid[i], null, Locale.US, null);
166             assertNotNull(date, "validateObj() " + text + date);
167             assertTrue(validator.isValid(localeValid[i], Locale.US), "isValid() " + text);
168             if (date instanceof Calendar) {
169                 date = ((Calendar) date).getTime();
170             }
171             assertEquals(patternExpect[i], date, "compare " + text);
172         }
173     }
174 
175     /**
176      * Test Invalid Dates with "pattern" validation
177      */
178     @Test
179     public void testPatternInvalid() {
180         for (int i = 0; i < patternInvalid.length; i++) {
181             final String text = i + " value=[" + patternInvalid[i] + "] passed ";
182             final Object date = validator.parse(patternInvalid[i], "yy-MM-dd", null, null);
183             assertNull(date, "validateObj() " + text + date);
184             assertFalse(validator.isValid(patternInvalid[i], "yy-MM-dd"), "isValid() " + text);
185         }
186     }
187 
188     /**
189      * Test Valid Dates with "pattern" validation
190      */
191     @Test
192     public void testPatternValid() {
193         for (int i = 0; i < patternValid.length; i++) {
194             final String text = i + " value=[" + patternValid[i] + "] failed ";
195             Object date = validator.parse(patternValid[i], "yy-MM-dd", null, null);
196             assertNotNull(date, "validateObj() " + text + date);
197             assertTrue(validator.isValid(patternValid[i], "yy-MM-dd"), "isValid() " + text);
198             if (date instanceof Calendar) {
199                 date = ((Calendar) date).getTime();
200             }
201             assertEquals(patternExpect[i], date, "compare " + text);
202         }
203     }
204 
205     /**
206      * Test validator serialization.
207      */
208     @Test
209     public void testSerialization() {
210         // Serialize the check digit routine
211         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
212         try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
213             oos.writeObject(validator);
214             oos.flush();
215         } catch (final Exception e) {
216             fail(validator.getClass().getName() + " error during serialization: " + e);
217         }
218 
219         // Deserialize the test object
220         Object result = null;
221         try (ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray())) {
222             final ObjectInputStream ois = new ObjectInputStream(bais);
223             result = ois.readObject();
224         } catch (final Exception e) {
225             fail(validator.getClass().getName() + " error during deserialization: " + e);
226         }
227         assertNotNull(result);
228     }
229 
230 }