1 /*
2  *******************************************************************************
3  * Copyright (C) 1996-2010, International Business Machines Corporation and    *
4  * others. All Rights Reserved.                                                *
5  *******************************************************************************
6  */
7 package com.ibm.icu.dev.test.calendar;
8 
9 import java.util.Date;
10 import java.util.Locale;
11 
12 import com.ibm.icu.dev.test.TestLog;
13 import com.ibm.icu.util.Calendar;
14 import com.ibm.icu.util.GregorianCalendar;
15 import com.ibm.icu.util.SimpleTimeZone;
16 
17 /**
18  * A pseudo <code>Calendar</code> that is useful for testing
19  * new calendars.  A <code>TestCase</code> object is used to hold the
20  * field and millisecond values that the calendar should have at one
21  * particular instant in time.  The applyFields and applyTime
22  * methods are used to apply these settings to the calendar object being
23  * tested, and the equals and fieldsEqual methods are used to ensure
24  * that the calendar has ended up in the right state.
25  */
26 public class TestCase {
27 
28     //------------------------------------------------------------------
29     // Pseudo-Calendar fields and methods
30     //------------------------------------------------------------------
31 
32     protected int[] fields = new int[32];
33     protected boolean[] isSet = new boolean[32];
34     protected long time;
35 
set(int field, int value)36     protected void set(int field, int value) {
37         fields[field] = value;
38         isSet[field] = true;
39     }
40 
get(int field)41     protected int get(int field) {
42         return fields[field];
43     }
44 
isSet(int field)45     protected boolean isSet(int field) {
46         return isSet[field];
47     }
48 
setTime(Date d)49     protected void setTime(Date d) {
50         time = d.getTime();
51     }
52 
getTime()53     public Date getTime() {
54         return new Date(time);
55     }
56 
57     /**
58      * Return a String representation of this test case's time.
59      */
toString()60     public String toString() {
61         return dowToString(get(Calendar.DAY_OF_WEEK)) + " " +
62             get(Calendar.YEAR) + "/" + (get(Calendar.MONTH)+1) + "/" +
63             get(Calendar.DATE);
64     }
65 
66     private static final String[] DOW_NAMES = {
67         "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
68     };
69 
dowToString(int dow)70     public static String dowToString(int dow) {
71         --dow;
72         return (dow < 0 || dow > 6) ?
73             ("<DOW " + dow + ">") : DOW_NAMES[dow];
74     }
75 
76     /**
77      * Initialize a TestCase object using a julian day number and
78      * the corresponding fields for the calendar being tested.
79      *
80      * @param era       The ERA field of tested calendar on the given julian day
81      * @param year      The YEAR field of tested calendar on the given julian day
82      * @param month     The MONTH (1-based) field of tested calendar on the given julian day
83      * @param day       The DAY_OF_MONTH field of tested calendar on the given julian day
84      * @param dayOfWeek The DAY_OF_WEEK field of tested calendar on the given julian day
85      * @param hour      The HOUR field of tested calendar on the given julian day
86      * @param min       The MINUTE field of tested calendar on the given julian day
87      * @param sec       The SECOND field of tested calendar on the given julian day
88      */
TestCase(double julian, int era, int year, int month, int day, int dayOfWeek, int hour, int min, int sec)89     public TestCase(double julian,
90                     int era, int year, int month, int day,
91                     int dayOfWeek,
92                     int hour, int min, int sec)
93     {
94         setTime(new Date(JULIAN_EPOCH + (long)(ONE_DAY * julian)));
95 
96         set(Calendar.ERA, era);
97         set(Calendar.YEAR, year);
98         set(Calendar.MONTH, month - 1);
99         set(Calendar.DATE, day);
100         set(Calendar.DAY_OF_WEEK, dayOfWeek);
101         set(Calendar.HOUR, hour);
102         set(Calendar.MINUTE, min);
103         set(Calendar.SECOND, sec);
104     }
105 
106     /**
107      * Initialize a TestCase object using a Gregorian year/month/day and
108      * the corresponding fields for the calendar being tested.
109      *
110      * @param gregYear  The Gregorian year of the date to be tested
111      * @param gregMonth The Gregorian month of the date to be tested
112      * @param gregDay   The Gregorian day of the month of the date to be tested
113      *
114      * @param era       The ERA field of tested calendar on the given gregorian date
115      * @param year      The YEAR field of tested calendar on the given gregorian date
116      * @param month     The MONTH (0-based) field of tested calendar on the given gregorian date
117      * @param day       The DAY_OF_MONTH field of tested calendar on the given gregorian date
118      * @param dayOfWeek The DAY_OF_WEEK field of tested calendar on the given gregorian date
119      * @param hour      The HOUR field of tested calendar on the given gregorian date
120      * @param min       The MINUTE field of tested calendar on the given gregorian date
121      * @param sec       The SECOND field of tested calendar on the given gregorian date
122      */
TestCase(int gregYear, int gregMonth, int gregDay, int era, int year, int month, int day, int dayOfWeek, int hour, int min, int sec)123     public TestCase(int gregYear, int gregMonth, int gregDay,
124                     int era, int year, int month, int day,
125                     int dayOfWeek,
126                     int hour, int min, int sec)
127     {
128         GregorianCalendar greg = new GregorianCalendar(UTC, Locale.getDefault());
129         greg.clear();
130         greg.set(gregYear, gregMonth-1, gregDay);
131         setTime(greg.getTime());
132 
133         set(Calendar.ERA, era);
134         set(Calendar.YEAR, year);
135         set(Calendar.MONTH, month - 1);
136         set(Calendar.DATE, day);
137         set(Calendar.DAY_OF_WEEK, dayOfWeek);
138         set(Calendar.HOUR, hour);
139         set(Calendar.MINUTE, min);
140         set(Calendar.SECOND, sec);
141     }
142 
143     /**
144      * For subclasses.
145      */
TestCase()146     protected TestCase() {}
147 
148     /**
149      * Apply this test case's field values to another calendar
150      * by calling its set method for each field.  This is useful in combination
151      * with the equal method.
152      *
153      * @see com.ibm.icu.util.Calendar#equals
154      */
applyFields(Calendar c)155     public void applyFields(Calendar c) {
156         for (int i=0; i < c.getFieldCount(); i++) {
157             if (isSet(i)) {
158                 c.set(i, get(i));
159             }
160         }
161     }
162 
163     /**
164      * Apply this test case's time in milliseconds to another calendar
165      * by calling its setTime method.  This is useful in combination
166      * with fieldsEqual
167      *
168      * @see #fieldsEqual
169      */
applyTime(Calendar c)170     public void applyTime(Calendar c) {
171         c.setTime(new Date(time));
172     }
173 
174     /**
175      * Determine whether the fields of this calendar
176      * are the same as that of the other calendar.  This method is useful
177      * for determining whether the other calendar's computeFields method
178      * works properly.  For example:
179      * <pre>
180      *    Calendar testCalendar = ...
181      *    TestCase case = ...
182      *    case.applyTime(testCalendar);
183      *    if (!case.fieldsEqual(testCalendar)) {
184      *        // Error!
185      *    }
186      * </pre>
187      *
188      * @see #applyTime
189      */
fieldsEqual(Calendar c, TestLog log)190     public boolean fieldsEqual(Calendar c, TestLog log) {
191         for (int i=0; i < c.getFieldCount(); i++) {
192             if (isSet(i) && get(i) != c.get(i)) {
193                 StringBuffer buf = new StringBuffer();
194                 buf.append("Fail: " + CalendarTest.fieldName(i) + " = " + c.get(i) +
195                           ", expected " + get(i));
196                 for (int j=0; j<c.getFieldCount(); ++j) {
197                     if (isSet(j)) {
198                         if (get(j) == c.get(j)) {
199                             buf.append("\n  ok: " + CalendarTest.fieldName(j) + " = " +
200                                       c.get(j));
201                         } else {
202                             buf.append("\n  fail: " + CalendarTest.fieldName(j) + " = " +
203                                       c.get(j) + ", expected " + get(j));
204                         }
205                     }
206                 }
207                 log.errln(buf.toString());
208                 return false;
209             }
210         }
211 
212         return true;
213     }
214 
215     /**
216      * Determine whether time in milliseconds of this calendar
217      * is the same as that of the other calendar.  This method is useful
218      * for determining whether the other calendar's computeTime method
219      * works properly.  For example:
220      * <pre>
221      *    Calendar testCalendar = ...
222      *    TestCase case = ...
223      *    case.applyFields(testCalendar);
224      *    if (!case.equals(testCalendar)) {
225      *        // Error!
226      *    }
227      * </pre>
228      *
229      * @see #applyFields
230      */
equals(Object obj)231     public boolean equals(Object obj) {
232         return time == ((Calendar)obj).getTime().getTime();
233     }
234 
235     protected static final int  ONE_SECOND = 1000;
236     protected static final int  ONE_MINUTE = 60*ONE_SECOND;
237     protected static final int  ONE_HOUR   = 60*ONE_MINUTE;
238     protected static final long ONE_DAY    = 24*ONE_HOUR;
239     protected static final long JULIAN_EPOCH = -210866760000000L;   // 1/1/4713 BC 12:00
240 
241     public final static SimpleTimeZone UTC = new SimpleTimeZone(0, "GMT");
242 }
243