1 /*
  2  * Copyright (c) 2003, 2023, 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 4817812 4847186 4956227 4956479
 27  * @summary Confirm that BuddhistCalendar's add(), roll(), set(), and toString()
 28  *          work correctly with Buddhist Era years.
 29  * @run junit BuddhistCalendarTest
 30  */
 31 
 32 import java.util.Calendar;
 33 import java.util.GregorianCalendar;
 34 import java.util.Locale;
 35 import java.util.stream.Stream;
 36 
 37 import static java.util.Calendar.APRIL;
 38 import static java.util.Calendar.DATE;
 39 import static java.util.Calendar.DECEMBER;
 40 import static java.util.Calendar.ERA;
 41 import static java.util.Calendar.FEBRUARY;
 42 import static java.util.Calendar.JANUARY;
 43 import static java.util.Calendar.MAY;
 44 import static java.util.Calendar.MONTH;
 45 import static java.util.Calendar.WEEK_OF_YEAR;
 46 import static java.util.Calendar.YEAR;
 47 
 48 
 49 import org.junit.jupiter.api.Test;
 50 import org.junit.jupiter.params.ParameterizedTest;
 51 import org.junit.jupiter.params.provider.Arguments;
 52 import org.junit.jupiter.params.provider.MethodSource;
 53 
 54 import static org.junit.jupiter.api.Assertions.assertEquals;
 55 import static org.junit.jupiter.api.Assertions.assertThrows;
 56 
 57 public class BuddhistCalendarTest {
 58 
 59     private static final Locale THAI_LOCALE = Locale.of("th", "TH");
 60 
 61     /*
 62      * Test some add values for the BuddhistCalendar. This test compares the same field
 63      * as the one added.
 64      */
 65     @ParameterizedTest
 66     @MethodSource("addDataProvider")
 67     public void buddhistAddTest(Calendar cal, int amount, int fieldToAdd) {
 68         int base = cal.get(YEAR);
 69         cal.add(fieldToAdd, amount);
 70         int yearAfterRoll = cal.get(YEAR);
 71         assertEquals(yearAfterRoll, base+amount, String.format(
 72                 "Added: %s to field: %s", amount, fieldToAdd));
 73     }
 74 
 75     /*
 76      * Given in the format: Calendar, amount to add, and field to add.
 77      * Test adding of positive and negative year values.
 78      */
 79     private static Stream<Arguments> addDataProvider() {
 80         return Stream.of(
 81                 Arguments.of(getBuddhistCalendar(), 1, YEAR),
 82                 Arguments.of(getBuddhistCalendar(), -3, YEAR)
 83         );
 84     }
 85 
 86     /*
 87      * Test some add values for the BuddhistCalendar. Compare a bigger field
 88      * (year) than the one added (month). Larger field should roll over.
 89      */
 90     @ParameterizedTest
 91     @MethodSource("alternateAddDataProvider")
 92     public void buddhistAlternateAddTest(Calendar cal, int amount, int fieldToAdd) {
 93         int base = cal.get(YEAR);
 94         cal.add(fieldToAdd, amount);
 95         int yearAfterRoll = cal.get(YEAR);
 96         assertEquals(yearAfterRoll, (amount>0) ? (base+1): (base-1), String.format(
 97                 "Added: %s to field: %s", amount, fieldToAdd));
 98     }
 99 
100     /*
101      * Given in the format: Calendar, amount to add, and field to add.
102      * Test adding of positive and negative month values.
103      */
104     private static Stream<Arguments> alternateAddDataProvider() {
105         return Stream.of(
106                 Arguments.of(getBuddhistCalendarBuilder().set(MONTH, DECEMBER).build(), 2, MONTH),
107                 Arguments.of(getBuddhistCalendarBuilder().set(MONTH, FEBRUARY).build(), -4, MONTH)
108                 );
109     }
110 
111     /*
112      * Test some roll values for the BuddhistCalendar. Compare same field
113      * that was rolled, value should change.
114      */
115     @ParameterizedTest
116     @MethodSource("rollProvider")
117     public void buddhistRollTest(Calendar cal, int amount, int fieldToRoll) {
118         int base = cal.get(YEAR);
119         cal.roll(fieldToRoll, amount);
120         int year = cal.get(YEAR);
121         assertEquals(year, base+amount, "Rolling field should change value");
122     }
123 
124     /*
125      * Given in the format: Calendar, amount to roll, and field to roll.
126      * Test rolling of positive and negative year values.
127      */
128     private static Stream<Arguments> rollProvider() {
129         return Stream.of(
130                 Arguments.of(getBuddhistCalendar(), 2, YEAR),
131                 Arguments.of(getBuddhistCalendar(), -4, YEAR)
132         );
133     }
134 
135     /*
136      * Set some calendar values and roll, however, measure a different
137      * field than the field that was rolled. Rolling should not change the
138      * larger field.
139      */
140     @ParameterizedTest
141     @MethodSource("alternateRollProvider")
142     public void buddhistAlternateRollTest(Calendar cal, int amount, int fieldToRoll) {
143         int base = cal.get(YEAR);
144         cal.roll(fieldToRoll, amount);
145         int year = cal.get(YEAR);
146         assertEquals(year, base, "Rolling smaller field should not change bigger field");
147     }
148 
149     /*
150      * Given in the format: Calendar, amount to roll, and field to roll.
151      * Test rolling of positive and negative week_of_year values.
152      */
153     private static Stream<Arguments> alternateRollProvider() {
154         return Stream.of(
155                 Arguments.of(getBuddhistCalendarBuilder().set(YEAR, 2543)
156                         .set(MONTH, DECEMBER).set(DATE, 31).build(), 10, WEEK_OF_YEAR),
157                 Arguments.of(getBuddhistCalendarBuilder().set(YEAR, 2543)
158                         .set(MONTH, JANUARY).set(DATE, 1).build(), -10, WEEK_OF_YEAR)
159         );
160     }
161 
162     // Test the overloaded set() methods. Check year value.
163     @Test
164     public void buddhistSetTest() {
165         Calendar cal = getBuddhistCalendar();
166         cal.set(3001, APRIL, 10);
167         assertEquals(cal.get(YEAR), 3001);
168         cal.set(3020, MAY, 20, 9, 10);
169         assertEquals(cal.get(YEAR), 3020);
170         cal.set(3120, MAY, 20, 9, 10, 52 );
171         assertEquals(cal.get(YEAR), 3120);
172     }
173 
174     /*
175      * Test BuddhistCalendar.getActualMaximum(YEAR);
176      * set(YEAR)/get(YEAR) in this method doesn't affect the real
177      * YEAR value because a clone is used with set() and get().
178      */
179     @Test
180     public void buddhistActualMaximumTest() {
181         Calendar cal = getBuddhistCalendar();
182         int base = cal.get(YEAR);
183         int ignored = cal.getActualMaximum(YEAR);
184         int year = cal.get(YEAR);
185         assertEquals(year, base, "BuddhistCalendar.getActualMaximum(YEAR)");
186     }
187 
188     // Test BuddhistCalendar.getActualMinimum(YEAR), doesn't call set(YEAR) nor get(YEAR).
189     @Test
190     public void buddhistActualMinimumTest() {
191         Calendar cal = getBuddhistCalendar();
192         int base = cal.get(YEAR);
193         int ignored = cal.getActualMinimum(YEAR);
194         int year = cal.get(YEAR);
195         assertEquals(year, base, "BuddhistCalendar.getActualMinimum(YEAR)");
196     }
197 
198     // 4847186: BuddhistCalendar: toString() returns Gregorian year
199     @Test
200     public void buddhistToStringTest() {
201         Calendar cal = getBuddhistCalendar();
202         int year = cal.get(YEAR);
203         String s = cal.toString();
204         String y = s.replaceAll(".+,YEAR=(\\d+),.+", "$1");
205         assertEquals(year, Integer.parseInt(y), "Wrong year value");
206     }
207 
208     // 4956479: BuddhistCalendar methods may return wrong values after exception
209     @Test
210     public void buddhistValuesAfterExceptionTest() {
211         Calendar cal = getBuddhistCalendar();
212         int year = cal.get(YEAR);
213         assertThrows(IllegalArgumentException.class, ()-> cal.add(100, +1));
214         int year2 = cal.get(YEAR);
215         assertEquals(year2, year, "Wrong year value after exception thrown");
216     }
217 
218     // 4956227: getLeastMaximum(WEEK_OF_MONTH) return diff. val. for Greg. and Buddhist Calendar
219     @Test
220     public void buddhistLeastMaximumTest() {
221         Calendar bc = getBuddhistCalendar();
222         // Specify THAI_LOCALE to get the same params for WEEK
223         // calculations (6904680).
224         Calendar gc = new GregorianCalendar(THAI_LOCALE);
225         for (int f = 0; f < Calendar.FIELD_COUNT; f++) {
226             if (f == ERA || f == YEAR) {
227                 continue;
228             }
229             int bn = bc.getLeastMaximum(f);
230             int gn = gc.getLeastMaximum(f);
231             assertEquals(bn, gn, "Inconsistent Least Max value for " + Koyomi.getFieldName(f));
232         }
233     }
234 
235     // Utility to get a new Buddhist Calendar Builder (to allow setting of other values)
236     private static Calendar.Builder getBuddhistCalendarBuilder() {
237         return new Calendar.Builder().setLocale(THAI_LOCALE);
238     }
239 
240     // Utility to get a new Buddhist calendar
241     private static Calendar getBuddhistCalendar() {
242         return Calendar.getInstance(THAI_LOCALE);
243     }
244 }