1 /*
   2  * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 4745761
  27  * @summary Unit test for Calendar.Builder.
  28  */
  29 
  30 import java.util.*;
  31 import static java.util.Calendar.*;
  32 
  33 public class BuilderTest {
  34     private static final Locale jaJPJP = new Locale("ja", "JP", "JP");
  35     private static final Locale thTH = new Locale("th", "TH");
  36     private static final TimeZone LA = TimeZone.getTimeZone("America/Los_Angeles");
  37     private static final TimeZone TOKYO = TimeZone.getTimeZone("Asia/Tokyo");
  38     private static int error;
  39 
  40     public static void main(String[] args) {
  41         TimeZone tz = TimeZone.getDefault();
  42         Locale loc = Locale.getDefault();
  43         try {
  44             TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
  45             Locale.setDefault(Locale.US);
  46             Calendar.Builder calb;
  47             Calendar cal, expected;
  48 
  49             // set instant
  50             calb = builder();
  51             long time = System.currentTimeMillis();
  52             cal = calb.setInstant(time).build();
  53             expected = new GregorianCalendar();
  54             expected.setTimeInMillis(time);
  55             check(cal, expected);
  56 
  57             calb = builder();
  58             cal = calb.setInstant(new Date(time)).build();
  59             check(cal, expected);
  60 
  61             // set time zone
  62             calb = builder();
  63             cal = calb.setTimeZone(LA).setInstant(time).build();
  64             expected = new GregorianCalendar(LA, Locale.US);
  65             expected.setTimeInMillis(time);
  66             check(cal, expected);
  67 
  68             calb = builder();
  69             cal = calb.setTimeZone(TOKYO).setInstant(time).build();
  70             expected = new GregorianCalendar(TOKYO, Locale.US);
  71             expected.setTimeInMillis(time);
  72             check(cal, expected);
  73 
  74             // set vs. setFields
  75             calb = builder();
  76             cal = calb.set(YEAR, 2013).set(MONTH, JANUARY).set(DAY_OF_MONTH, 31)
  77                       .set(HOUR_OF_DAY, 10).set(MINUTE, 20).set(SECOND, 30).set(MILLISECOND, 40).build();
  78             expected = new GregorianCalendar(2013, JANUARY, 31, 10, 20, 30);
  79             expected.set(MILLISECOND, 40);
  80             check(cal, expected);
  81 
  82             calb = builder();
  83             cal = calb.setFields(YEAR, 2013, MONTH, JANUARY, DAY_OF_MONTH, 31,
  84                                  HOUR_OF_DAY, 10, MINUTE, 20, SECOND, 30, MILLISECOND, 40).build();
  85             check(cal, expected);
  86 
  87             // field resolution
  88             calb = builder();
  89             cal = calb.setFields(YEAR, 2013, MONTH, DECEMBER, DAY_OF_MONTH, 31,
  90                                  HOUR_OF_DAY, 10, MINUTE, 20, SECOND, 30, MILLISECOND, 40)
  91                       .set(DAY_OF_YEAR, 31).build();  // DAY_OF_YEAR wins.
  92             check(cal, expected);
  93 
  94             // setDate/setTimeOfDay
  95             calb = builder();
  96             cal = calb.setDate(2013, JANUARY, 31).setTimeOfDay(10, 20, 30, 40).build();
  97             check(cal, expected);
  98 
  99             // week date (ISO 8601)
 100             calb = builder().setCalendarType("iso8601");
 101             cal = calb.setWeekDate(2013, 1, MONDAY).setTimeOfDay(10, 20, 30).build();
 102             expected = getISO8601();
 103             expected.set(2012, DECEMBER, 31, 10, 20, 30);
 104             check(cal, expected);
 105 
 106             // default YEAR == 1970
 107             cal = builder().setFields(MONTH, JANUARY,
 108                                                    DAY_OF_MONTH, 9).build();
 109             check(cal, new GregorianCalendar(1970, JANUARY, 9));
 110 
 111             // no parameters are given.
 112             calb = builder();
 113             cal = calb.build();
 114             expected = new GregorianCalendar();
 115             expected.clear();
 116             check(cal, expected);
 117 
 118             // Thai Buddhist calendar
 119             calb = builder();
 120             cal = calb.setCalendarType("buddhist").setDate(2556, JANUARY, 31).build();
 121             expected = Calendar.getInstance(thTH);
 122             expected.clear();
 123             expected.set(2556, JANUARY, 31);
 124             check(cal, expected);
 125             // setLocale
 126             calb = builder();
 127             cal = calb.setLocale(thTH).setDate(2556, JANUARY, 31).build();
 128             check(cal, expected);
 129 
 130             // Japanese Imperial calendar
 131             cal = builder().setCalendarType("japanese")
 132                 .setFields(YEAR, 1, DAY_OF_YEAR, 1).build();
 133             expected = Calendar.getInstance(jaJPJP);
 134             expected.clear();
 135             expected.set(1, JANUARY, 8);
 136             check(cal, expected);
 137             // setLocale
 138             calb = builder();
 139             cal = calb.setLocale(jaJPJP).setFields(YEAR, 1, DAY_OF_YEAR, 1).build();
 140             check(cal, expected);
 141 
 142             testExceptions();
 143         } finally {
 144             // Restore default Locale and TimeZone
 145             Locale.setDefault(loc);
 146             TimeZone.setDefault(tz);
 147         }
 148         if (error > 0) {
 149             throw new RuntimeException("Failed");
 150         }
 151     }
 152 
 153     private static void testExceptions() {
 154         Calendar.Builder calb;
 155         Calendar cal;
 156 
 157         // NPE
 158         try {
 159             calb = builder().setInstant((Date)null);
 160             noException("setInstant((Date)null)");
 161         } catch (NullPointerException npe) {
 162         }
 163         try {
 164             calb = builder().setCalendarType(null);
 165             noException("setCalendarType(null)");
 166         } catch (NullPointerException npe) {
 167         }
 168         try {
 169             calb = builder().setLocale(null);
 170             noException("setLocale(null)");
 171         } catch (NullPointerException npe) {
 172         }
 173         try {
 174             calb = builder().setTimeZone(null);
 175             noException("setTimeZone(null)");
 176         } catch (NullPointerException npe) {
 177         }
 178 
 179         // IllegalArgumentException
 180         try {
 181             // invalid field index in set
 182             calb = builder().set(100, 2013);
 183             noException("set(100, 2013)");
 184         } catch (IllegalArgumentException e) {
 185         }
 186         try {
 187             // invalid field index in setField
 188             calb = builder().setFields(100, 2013);
 189             noException("setFields(100, 2013)");
 190         } catch (IllegalArgumentException e) {
 191         }
 192         try {
 193             // odd number of arguments
 194             calb = builder().setFields(YEAR, 2013, MONTH);
 195             noException("setFields(YEAR, 2013, MONTH)");
 196         } catch (IllegalArgumentException e) {
 197         }
 198         try {
 199             // unknown calendar type
 200             calb = builder().setCalendarType("foo");
 201             noException("setCalendarType(\"foo\")");
 202         } catch (IllegalArgumentException e) {
 203         }
 204         try {
 205             // invalid week definition parameter
 206             calb = builder().setWeekDefinition(8, 1);
 207             noException("setWeekDefinition(8, 1)");
 208         } catch (IllegalArgumentException e) {
 209         }
 210         try {
 211             // invalid week definition parameter
 212             calb = builder().setWeekDefinition(SUNDAY, 0);
 213             noException("setWeekDefinition(8, 1)");
 214         } catch (IllegalArgumentException e) {
 215         }
 216 
 217         try {
 218             // sets both instant and field parameters
 219             calb = builder().setInstant(new Date()).setDate(2013, JANUARY, 1);
 220             noException("setInstant(new Date()).setDate(2013, JANUARY, 1)");
 221         } catch (IllegalStateException e) {
 222         }
 223         try {
 224             // sets both field parameters and instant
 225             calb = builder().setDate(2013, JANUARY, 1).setInstant(new Date());
 226             noException("setDate(2013, JANUARY, 1).setInstant(new Date())");
 227         } catch (IllegalStateException e) {
 228         }
 229         try {
 230             // sets inconsistent calendar types
 231             calb = builder().setCalendarType("iso8601").setCalendarType("japanese");
 232             noException("setCalendarType(\"iso8601\").setCalendarType(\"japanese\")");
 233         } catch (IllegalStateException e) {
 234         }
 235 
 236         // IllegalArgumentException in build()
 237         calb = nonLenientBuilder().set(MONTH, 100);
 238         checkException(calb, IllegalArgumentException.class);
 239         calb = nonLenientBuilder().setTimeOfDay(23, 59, 70);
 240         checkException(calb, IllegalArgumentException.class);
 241         calb = builder().setCalendarType("japanese").setWeekDate(2013, 1, MONDAY);
 242         checkException(calb, IllegalArgumentException.class);
 243     }
 244 
 245     private static Calendar.Builder builder() {
 246         return new Calendar.Builder();
 247     }
 248 
 249     private static Calendar.Builder nonLenientBuilder() {
 250         return builder().setLenient(false);
 251     }
 252 
 253     private static Calendar getISO8601() {
 254         GregorianCalendar cal = new GregorianCalendar();
 255         cal.setFirstDayOfWeek(MONDAY);
 256         cal.setMinimalDaysInFirstWeek(4);
 257         cal.setGregorianChange(new Date(Long.MIN_VALUE));
 258         cal.clear();
 259         return cal;
 260     }
 261 
 262     private static void check(Calendar cal, Calendar expected) {
 263         if (!cal.equals(expected)) {
 264             error++;
 265             System.err.println("FAILED:");
 266             System.err.println("\t     cal = "+cal.getTime());
 267             System.err.println("\texpected = "+expected.getTime());
 268             System.err.printf("\tcal = %s%n\texp = %s%n", cal, expected);
 269         }
 270     }
 271 
 272     private static void checkException(Calendar.Builder calb, Class<? extends Exception> exception) {
 273         try {
 274             Calendar cal = calb.build();
 275             error++;
 276             System.err.println("expected exception: " + exception);
 277         } catch (Exception e) {
 278             if (!e.getClass().equals(exception)) {
 279                 error++;
 280                 System.err.println("unexpected exception: " + e.getClass() + ", expected: " + exception);
 281             }
 282         }
 283     }
 284 
 285     private static void noException(String msg) {
 286         error++;
 287         System.err.println("no exception with "+msg);
 288     }
 289 }