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