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  
18  package org.apache.log4j.pattern;
19  
20  import junit.framework.Test;
21  import junit.framework.TestCase;
22  import junit.framework.TestSuite;
23  
24  import org.apache.log4j.pattern.CachedDateFormat;
25  
26  import java.text.DateFormat;
27  import java.util.TimeZone;
28  import java.util.Date;
29  import java.text.SimpleDateFormat;
30  import java.util.Locale;
31  import java.util.Calendar;
32  
33  /***
34     Unit test {@link AbsoluteTimeDateFormat}.
35     @author Curt Arnold
36     */
37  public final class CachedDateFormatTest
38      extends TestCase {
39  
40    /***
41     * Test constructor
42     * @param name String test name
43     */
44    public CachedDateFormatTest(String name) {
45      super(name);
46    }
47    
48    private static DateFormat createAbsoluteTimeDateFormat(TimeZone timeZone) {
49        DateFormat df = new SimpleDateFormat("HH:mm:ss,SSS");
50        df.setTimeZone(timeZone);
51        return df;
52    }
53  
54    /***
55     * Asserts that formatting the provided date results
56     * in the expected string.
57     *
58     * @param date Date date
59     * @param timeZone TimeZone timezone for conversion
60     * @param expected String expected string
61     */
62    private final void assertFormattedTime(Date date,
63                                           TimeZone timeZone,
64                                           String expected) {
65      DateFormat formatter = createAbsoluteTimeDateFormat(timeZone);
66      String actual = formatter.format(date);
67      assertEquals(expected, actual);
68    }
69  
70    /***
71     * Timezone representing GMT.
72     */
73    private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
74  
75    /***
76     * Timezone for Chicago, Ill. USA.
77     */
78    private static final TimeZone CHICAGO = TimeZone.getTimeZone(
79        "America/Chicago");
80  
81    /***
82     * Test multiple calls in close intervals.
83     */
84    public void test1() {
85      //   subsequent calls within one minute
86      //     are optimized to reuse previous formatted value
87      //     make a couple of nearly spaced calls
88      DateFormat gmtFormat = new CachedDateFormat(createAbsoluteTimeDateFormat(GMT), 1000);
89      long ticks = 12601L * 86400000L;
90      Date jul1 = new Date(ticks);
91      assertEquals("00:00:00,000", gmtFormat.format(jul1));
92      Date plus8ms = new Date(ticks + 8);
93      assertEquals("00:00:00,008", gmtFormat.format(plus8ms));
94      Date plus17ms = new Date(ticks + 17);
95      assertEquals("00:00:00,017", gmtFormat.format(plus17ms));
96      Date plus237ms = new Date(ticks + 237);
97      assertEquals("00:00:00,237", gmtFormat.format(plus237ms));
98      Date plus1415ms = new Date(ticks + 1415);
99      assertEquals("00:00:01,415", gmtFormat.format(plus1415ms));
100   }
101 
102   /***
103    *  Check for interaction between caches.
104    */
105   public void test2() {
106       Date jul2 = new Date(12602L * 86400000L);
107       DateFormat gmtFormat = new CachedDateFormat(createAbsoluteTimeDateFormat(GMT), 1000);
108       DateFormat chicagoFormat = new CachedDateFormat(createAbsoluteTimeDateFormat(CHICAGO), 1000);
109       assertEquals("00:00:00,000", gmtFormat.format(jul2));
110       assertEquals("19:00:00,000", chicagoFormat.format(jul2));
111       assertEquals("00:00:00,000", gmtFormat.format(jul2));
112   }
113 
114   /***
115    * Test multiple calls in close intervals prior to 1 Jan 1970.
116    */
117   public void test3() {
118     //   subsequent calls within one minute
119     //     are optimized to reuse previous formatted value
120     //     make a couple of nearly spaced calls
121     DateFormat gmtFormat = new CachedDateFormat(
122        createAbsoluteTimeDateFormat(GMT), 1000);
123     //
124     //  if the first call was exactly on an integral
125     //     second, it would not test the round toward zero compensation
126     long ticks = -7L * 86400000L;
127     Date jul1 = new Date(ticks + 8);
128     assertEquals("00:00:00,008", gmtFormat.format(jul1));
129     Date plus8ms = new Date(ticks + 16);
130     assertEquals("00:00:00,016", gmtFormat.format(plus8ms));
131     Date plus17ms = new Date(ticks + 23);
132     assertEquals("00:00:00,023", gmtFormat.format(plus17ms));
133     Date plus237ms = new Date(ticks + 245);
134     assertEquals("00:00:00,245", gmtFormat.format(plus237ms));
135     Date plus1415ms = new Date(ticks + 1423);
136     assertEquals("00:00:01,423", gmtFormat.format(plus1415ms));
137   }
138 
139   public void test4() {
140     //  subsequent calls within one minute are optimized to reuse previous 
141     //  formatted value. make a couple of nearly spaced calls
142     // (Note: 'Z' is JDK 1.4, using 'z' instead.)
143     SimpleDateFormat baseFormat =
144          new SimpleDateFormat("EEE, MMM dd, HH:mm:ss.SSS z", Locale.ENGLISH);
145     DateFormat cachedFormat = new CachedDateFormat(baseFormat, 1000);
146     //
147     //   use a date in 2000 to attempt to confuse the millisecond locator
148     long ticks = 11141L * 86400000L;
149     Date jul1 = new Date(ticks);
150     assertEquals(baseFormat.format(jul1), cachedFormat.format(jul1));
151     Date plus8ms = new Date(ticks + 8);
152     String base = baseFormat.format(plus8ms);
153     String cached = cachedFormat.format(plus8ms);
154     assertEquals(baseFormat.format(plus8ms), cachedFormat.format(plus8ms));
155     Date plus17ms = new Date(ticks + 17);
156     assertEquals(baseFormat.format(plus17ms), cachedFormat.format(plus17ms));
157     Date plus237ms = new Date(ticks + 237);
158     assertEquals(baseFormat.format(plus237ms), cachedFormat.format(plus237ms));
159     Date plus1415ms = new Date(ticks + 1415);
160     assertEquals(baseFormat.format(plus1415ms), cachedFormat.format(plus1415ms));
161   }
162 
163   public void test5() {
164     //   subsequent calls within one minute
165     //     are optimized to reuse previous formatted value
166     //     make a couple of nearly spaced calls
167     // (Note: 'Z' is JDK 1.4, using 'z' instead.)
168     Locale thai = new Locale("th", "TH");
169     SimpleDateFormat baseFormat =
170          new SimpleDateFormat("EEE, MMM dd, HH:mm:ss.SSS z", thai);
171     DateFormat cachedFormat = new CachedDateFormat(baseFormat, 1000);
172     //
173     // use a date in the year 2000 CE to attempt to confuse the millisecond locator
174     long ticks = 11141L * 86400000L;
175    
176     String sx;
177     Date jul1 = new Date(ticks);
178     sx = cachedFormat.format(jul1);
179     System.out.println(baseFormat.format(jul1));
180     System.out.println(sx);
181     assertEquals(baseFormat.format(jul1), sx);
182     
183     sx = cachedFormat.format(jul1);
184     System.out.println(baseFormat.format(jul1));
185     System.out.println(sx);
186     assertEquals(baseFormat.format(jul1), sx);
187     
188     
189     Date plus8ms = new Date(ticks + 8);
190     sx = cachedFormat.format(plus8ms);
191     System.out.println(baseFormat.format(plus8ms));
192     System.out.println(sx);
193     
194     assertEquals(baseFormat.format(plus8ms), sx);
195     
196     Date plus17ms = new Date(ticks + 17);
197     assertEquals(baseFormat.format(plus17ms), cachedFormat.format(plus17ms));
198     
199     Date plus237ms = new Date(ticks + 237);
200     assertEquals(baseFormat.format(plus237ms), cachedFormat.format(plus237ms));
201     
202     Date plus1415ms = new Date(ticks + 1415);
203     assertEquals(baseFormat.format(plus1415ms), cachedFormat.format(plus1415ms));
204   }
205 
206   /***
207    * Checks that getNumberFormat does not return null.
208    */
209   public void test6() {
210     assertNotNull(new CachedDateFormat(new SimpleDateFormat(), 1000).getNumberFormat());
211   }
212 
213   /***
214    * Set time zone on cached and check that it is effective.
215    */
216   public void test8() {
217     DateFormat baseFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS");
218     baseFormat.setTimeZone(GMT);
219     DateFormat cachedFormat = new CachedDateFormat(baseFormat, 1000);
220     Date jul4 = new Date(12603L * 86400000L);
221     assertEquals("2004-07-04 00:00:00,000", cachedFormat.format(jul4));
222     cachedFormat.setTimeZone(TimeZone.getTimeZone("GMT-6"));
223     assertEquals("2004-07-03 18:00:00,000", cachedFormat.format(jul4));
224   }
225 
226 
227   /***
228    * Test of caching when less than three millisecond digits are specified.
229    */
230   public void test9() {
231     // (Note: 'Z' is JDK 1.4, using 'z' instead.)
232     DateFormat baseFormat = new SimpleDateFormat("yyyy-MMMM-dd HH:mm:ss,SS z", Locale.US);
233     DateFormat cachedFormat = new CachedDateFormat(baseFormat, 1000);
234     TimeZone cet = TimeZone.getTimeZone("GMT+1");
235     cachedFormat.setTimeZone(cet);
236     
237     Calendar c = Calendar.getInstance();
238     c.set(2004, Calendar.DECEMBER, 12, 20, 0);
239     c.set(Calendar.SECOND, 37);
240     c.set(Calendar.MILLISECOND, 23);
241     c.setTimeZone(cet);
242 
243     String s = cachedFormat.format(c.getTime());
244     assertEquals("2004-December-12 20:00:37,23 GMT+01:00", s);
245 
246     c.set(2005, Calendar.JANUARY, 1, 0, 0);
247     c.set(Calendar.SECOND, 13);
248     c.set(Calendar.MILLISECOND, 905);
249 
250     s = cachedFormat.format(c.getTime());
251     assertEquals("2005-January-01 00:00:13,905 GMT+01:00", s);
252   }
253   
254 
255   /***
256    * Test when millisecond position moves but length remains constant.
257    */
258   public void test10() {
259     DateFormat baseFormat = new SimpleDateFormat("MMMM SSS EEEEEE", Locale.US);
260     DateFormat cachedFormat = new CachedDateFormat(baseFormat, 1000);
261     TimeZone cet = TimeZone.getTimeZone("GMT+1");
262     cachedFormat.setTimeZone(cet);
263     
264     Calendar c = Calendar.getInstance();
265     c.set(2004, Calendar.OCTOBER, 5, 20, 0);
266     c.set(Calendar.SECOND, 37);
267     c.set(Calendar.MILLISECOND, 23);
268     c.setTimeZone(cet);
269 
270     String s = cachedFormat.format(c.getTime());
271     assertEquals("October 023 Tuesday", s);
272 
273     c.set(2004, Calendar.NOVEMBER, 1, 0, 0);
274     c.set(Calendar.MILLISECOND, 23);
275     s = cachedFormat.format(c.getTime());
276     assertEquals("November 023 Monday", s);
277 
278 
279     c.set(Calendar.MILLISECOND, 984);
280     s = cachedFormat.format(c.getTime());
281     assertEquals("November 984 Monday", s);
282   }
283 
284   /***
285    * Test that tests if caching is skipped if only "SS"
286    *     is specified.
287    */
288   public void test11() {
289      //
290      //   Earlier versions could be tricked by "SS0" patterns.
291      //
292      String badPattern = "ss,SS0";
293      SimpleDateFormat simpleFormat = new SimpleDateFormat(badPattern);
294      DateFormat gmtFormat = new CachedDateFormat(simpleFormat, 1000);
295      gmtFormat.setTimeZone(GMT);
296 
297      //
298      // The first request has to 100 ms after an ordinal second
299      //    to push the literal zero out of the pattern check
300      long ticks = 11142L * 86400000L;
301      Date jul2 = new Date(ticks + 120);
302      assertEquals("00,1200", gmtFormat.format(jul2));
303      jul2.setTime(ticks + 87);
304      
305 
306      //
307      //   Cache gives 00,087
308      assertEquals("00,870", gmtFormat.format(jul2));
309 
310   }
311 
312   /***
313    * Check pattern location for ISO8601
314    */
315   public void test12() {
316      SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS");
317      long ticks = 11142L * 86400000L;
318      String formatted = df.format(new Date(ticks));
319      int millisecondStart = CachedDateFormat.findMillisecondStart(ticks, formatted, df);
320      assertEquals(20, millisecondStart);     
321   }
322 
323   /***
324    * Check pattern location for DATE
325    */
326   public void test13() {
327      SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
328      long ticks = 11142L * 86400000L;
329      String formatted = df.format(new Date(ticks));
330      int millisecondStart = CachedDateFormat.findMillisecondStart(ticks, formatted, df);
331      assertEquals(CachedDateFormat.NO_MILLISECONDS, millisecondStart);     
332   }
333 
334   /***
335    * Check pattern location for ABSOLUTE
336    */
337   public void test14() {
338      SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss,SSS");
339      long ticks = 11142L * 86400000L;
340      String formatted = df.format(new Date(ticks));
341      int millisecondStart = CachedDateFormat.findMillisecondStart(ticks, formatted, df);
342      assertEquals(9, millisecondStart);     
343   }
344 
345   /***
346    * Check pattern location for single S
347    */
348   public void test15() {
349      SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss,S");
350      long ticks = 11142L * 86400000L;
351      String formatted = df.format(new Date(ticks));
352      int millisecondStart = CachedDateFormat.findMillisecondStart(ticks, formatted, df);
353      assertEquals(CachedDateFormat.UNRECOGNIZED_MILLISECONDS, millisecondStart);     
354   }
355 
356   /***
357    * Check pattern location for single SS
358    */
359   public void test16() {
360      SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss,SS");
361      long ticks = 11142L * 86400000L;
362      String formatted = df.format(new Date(ticks));
363      int millisecondStart = CachedDateFormat.findMillisecondStart(ticks, formatted, df);
364      assertEquals(CachedDateFormat.UNRECOGNIZED_MILLISECONDS, millisecondStart);     
365   }
366 
367 
368   /***
369    * Check caching when multiple SSS appear in pattern
370    */
371   public void test17() {
372       Date jul2 = new Date(12602L * 86400000L);
373       String badPattern = "HH:mm:ss,SSS HH:mm:ss,SSS";
374       SimpleDateFormat simpleFormat = new SimpleDateFormat(badPattern);
375       simpleFormat.setTimeZone(GMT);
376       DateFormat cachedFormat = new CachedDateFormat(simpleFormat, 1000);
377       String s = cachedFormat.format(jul2);
378       assertEquals("00:00:00,000 00:00:00,000", s);
379       jul2.setTime(jul2.getTime() + 120);
380       assertEquals("00:00:00,120 00:00:00,120", simpleFormat.format(jul2));
381       s = cachedFormat.format(jul2);
382       //
383       //  TODO: why is this returning ,120 ... , 120
384       //
385       //assertEquals("00:00:00,120 00:00:00,000", s) ;
386       
387       int maxValid = CachedDateFormat.getMaximumCacheValidity(badPattern);
388       assertEquals(1, maxValid);
389   }
390 
391   
392   public static Test xsuite() {
393     TestSuite suite = new TestSuite();
394     suite.addTest(new CachedDateFormatTest("test5"));
395     //suite.addTest(new CachedDateFormatTest("testS2"));
396     return suite;
397   }
398 
399 }