1// © 2016 and later: Unicode, Inc. and others. 2// License & terms of use: http://www.unicode.org/copyright.html#License 3/* 4 ******************************************************************************* 5 * Copyright (C) 1996-2014, International Business Machines Corporation and 6 * others. All Rights Reserved. 7 ******************************************************************************* 8 * 9 */ 10 11package com.ibm.icu.dev.test.serializable; 12 13import java.io.ByteArrayInputStream; 14import java.io.ByteArrayOutputStream; 15import java.io.File; 16import java.io.FileInputStream; 17import java.io.FileOutputStream; 18import java.io.IOException; 19import java.io.InputStream; 20import java.io.ObjectInputStream; 21import java.io.ObjectOutputStream; 22import java.lang.reflect.Modifier; 23import java.net.URL; 24import java.util.ArrayList; 25import java.util.Date; 26import java.util.Enumeration; 27import java.util.HashMap; 28import java.util.List; 29import java.util.Locale; 30 31import com.ibm.icu.dev.test.format.MeasureUnitTest; 32import com.ibm.icu.dev.test.format.PluralRulesTest; 33import com.ibm.icu.impl.JavaTimeZone; 34import com.ibm.icu.impl.OlsonTimeZone; 35import com.ibm.icu.impl.TimeZoneAdapter; 36import com.ibm.icu.impl.URLHandler; 37import com.ibm.icu.impl.Utility; 38import com.ibm.icu.math.BigDecimal; 39import com.ibm.icu.math.MathContext; 40import com.ibm.icu.util.AnnualTimeZoneRule; 41import com.ibm.icu.util.Calendar; 42import com.ibm.icu.util.Currency; 43import com.ibm.icu.util.DateInterval; 44import com.ibm.icu.util.DateTimeRule; 45import com.ibm.icu.util.GregorianCalendar; 46import com.ibm.icu.util.ICUCloneNotSupportedException; 47import com.ibm.icu.util.ICUException; 48import com.ibm.icu.util.ICUUncheckedIOException; 49import com.ibm.icu.util.InitialTimeZoneRule; 50import com.ibm.icu.util.RuleBasedTimeZone; 51import com.ibm.icu.util.SimpleTimeZone; 52import com.ibm.icu.util.TimeArrayTimeZoneRule; 53import com.ibm.icu.util.TimeZone; 54import com.ibm.icu.util.TimeZoneRule; 55import com.ibm.icu.util.ULocale; 56import com.ibm.icu.util.VTimeZone; 57 58/** 59 * @author emader 60 * 61 * TODO To change the template for this generated type comment go to 62 * Window - Preferences - Java - Code Style - Code Templates 63 */ 64public class SerializableTestUtility { 65 private static Class serializable; 66 static { 67 try { 68 serializable = Class.forName("java.io.Serializable"); 69 } catch (ClassNotFoundException e) { 70 // TODO Auto-generated catch block 71 e.printStackTrace(); 72 } 73 } 74 75 public interface Handler 76 { 77 public Object[] getTestObjects(); 78 79 public boolean hasSameBehavior(Object a, Object b); 80 } 81 82 public static Handler getHandler(String className) 83 { 84 return (Handler) map.get(className); 85 } 86 87 private static class TimeZoneHandler implements Handler 88 { 89 String[] ZONES = { "GMT", "MET", "IST" }; 90 91 @Override 92 public Object[] getTestObjects() 93 { 94 TimeZone zones[] = new TimeZone[ZONES.length]; 95 96 for(int z = 0; z < ZONES.length; z += 1) { 97 zones[z] = TimeZone.getTimeZone(ZONES[z]); 98 } 99 100 return zones; 101 } 102 103 @Override 104 public boolean hasSameBehavior(Object a, Object b) 105 { 106 TimeZone zone_a = (TimeZone) a; 107 TimeZone zone_b = (TimeZone) b; 108 109 if (!(zone_a.getDisplayName().equals(zone_b.getDisplayName()))) { 110 return false; 111 } 112 113 int a_offsets[] = {0, 0}; 114 int b_offsets[] = {0, 0}; 115 116 boolean bSame = true; 117 for (int i = 0; i < sampleTimes.length; i++) { 118 zone_a.getOffset(sampleTimes[i], false, a_offsets); 119 zone_b.getOffset(sampleTimes[i], false, b_offsets); 120 if (a_offsets[0] != b_offsets[0] || a_offsets[1] != b_offsets[1]) { 121 bSame = false; 122 break; 123 } 124 } 125 return bSame; 126 } 127 } 128 129 private static Locale locales[] = { 130 Locale.CANADA, Locale.CANADA_FRENCH, Locale.CHINA, 131 Locale.CHINESE, Locale.ENGLISH, Locale.FRANCE, Locale.FRENCH, 132 Locale.GERMAN, Locale.GERMANY, Locale.ITALIAN, Locale.ITALY, 133 Locale.JAPAN, Locale.JAPANESE, Locale.KOREA, Locale.KOREAN, 134 Locale.PRC, Locale.SIMPLIFIED_CHINESE, Locale.TAIWAN, 135 Locale.TRADITIONAL_CHINESE, Locale.UK, Locale.US 136 }; 137 138 private static Locale places[] = { 139 Locale.CANADA, Locale.CANADA_FRENCH, Locale.CHINA, 140 Locale.FRANCE, Locale.GERMANY, Locale.ITALY, 141 Locale.JAPAN, Locale.KOREA, Locale.PRC, Locale.TAIWAN, 142 Locale.UK, Locale.US 143 }; 144 145 public static Locale[] getLocales() 146 { 147 return locales; 148 } 149 150 public static boolean compareStrings(String a[], String b[]) 151 { 152 if (a.length != b.length) { 153 return false; 154 } 155 156 for (int i = 0; i < a.length; i += 1) { 157 if (! a[i].equals(b[i])) { 158 return false; 159 } 160 } 161 162 return true; 163 } 164 165 public static boolean compareChars(char a[], char b[]) 166 { 167 if (a.length != b.length) { 168 return false; 169 } 170 171 for (int i = 0; i < a.length; i += 1) { 172 if (a[i] != b[i]) { 173 return false; 174 } 175 } 176 177 return true; 178 } 179 180 private static class SimpleTimeZoneHandler extends TimeZoneHandler 181 { 182 @Override 183 public Object[] getTestObjects() 184 { 185 SimpleTimeZone simpleTimeZones[] = new SimpleTimeZone[6]; 186 187 simpleTimeZones[0] = new SimpleTimeZone(32400000, "MyTimeZone"); 188 189 simpleTimeZones[1] = new SimpleTimeZone(32400000, "Asia/Tokyo"); 190 191 simpleTimeZones[2] = new SimpleTimeZone(32400000, "Asia/Tokyo"); 192 simpleTimeZones[2].setRawOffset(0); 193 194 simpleTimeZones[3] = new SimpleTimeZone(32400000, "Asia/Tokyo"); 195 simpleTimeZones[3].setStartYear(100); 196 197 simpleTimeZones[4] = new SimpleTimeZone(32400000, "Asia/Tokyo"); 198 simpleTimeZones[4].setStartYear(1000); 199 simpleTimeZones[4].setDSTSavings(1800000); 200 simpleTimeZones[4].setStartRule(3, 4, 180000); 201 simpleTimeZones[4].setEndRule(6, 3, 4, 360000); 202 203 simpleTimeZones[5] = new SimpleTimeZone(32400000, "Asia/Tokyo"); 204 simpleTimeZones[5].setStartRule(2, 3, 4, 360000); 205 simpleTimeZones[5].setEndRule(6, 3, 4, 360000); 206 207 return simpleTimeZones; 208 } 209 } 210 211 private static class VTimeZoneHandler extends TimeZoneHandler { 212 @Override 213 public Object[] getTestObjects() { 214 //TODO 215 VTimeZone[] vtzs = new VTimeZone[1]; 216 vtzs[0] = VTimeZone.create("America/New_York"); 217 return vtzs; 218 } 219 } 220 221 private static final int HOUR = 60*60*1000; 222 private static final AnnualTimeZoneRule[] TEST_US_EASTERN = { 223 new AnnualTimeZoneRule("EST", -5*HOUR, 0, 224 new DateTimeRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*HOUR, DateTimeRule.WALL_TIME), 225 1967, 2006), 226 227 new AnnualTimeZoneRule("EST", -5*HOUR, 0, 228 new DateTimeRule(Calendar.NOVEMBER, 1, Calendar.SUNDAY, true, 2*HOUR, DateTimeRule.WALL_TIME), 229 2007, AnnualTimeZoneRule.MAX_YEAR), 230 231 new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, 232 new DateTimeRule(Calendar.APRIL, -1, Calendar.SUNDAY, 2*HOUR, DateTimeRule.WALL_TIME), 233 1967, 1973), 234 235 new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, 236 new DateTimeRule(Calendar.JANUARY, 6, 2*HOUR, DateTimeRule.WALL_TIME), 237 1974, 1974), 238 239 new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, 240 new DateTimeRule(Calendar.FEBRUARY, 23, 2*HOUR, DateTimeRule.WALL_TIME), 241 1975, 1975), 242 243 new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, 244 new DateTimeRule(Calendar.APRIL, -1, Calendar.SUNDAY, 2*HOUR, DateTimeRule.WALL_TIME), 245 1976, 1986), 246 247 new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, 248 new DateTimeRule(Calendar.APRIL, 1, Calendar.SUNDAY, true, 2*HOUR, DateTimeRule.WALL_TIME), 249 1987, 2006), 250 251 new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, 252 new DateTimeRule(Calendar.MARCH, 8, Calendar.SUNDAY, true, 2*HOUR, DateTimeRule.WALL_TIME), 253 2007, AnnualTimeZoneRule.MAX_YEAR) 254 }; 255 256 private static class RuleBasedTimeZoneHandler extends TimeZoneHandler 257 { 258 @Override 259 public Object[] getTestObjects() 260 { 261 RuleBasedTimeZone ruleBasedTimeZones[] = new RuleBasedTimeZone[2]; 262 263 InitialTimeZoneRule ir = new InitialTimeZoneRule("GMT-5", -5*HOUR, 0); 264 265 // GMT-5, no transition 266 ruleBasedTimeZones[0] = new RuleBasedTimeZone("GMT-5", ir); 267 268 269 // US Eastern since 1967 270 ruleBasedTimeZones[1] = new RuleBasedTimeZone("US_East", ir); 271 for (int i = 0; i < TEST_US_EASTERN.length; i++) { 272 ruleBasedTimeZones[1].addTransitionRule(TEST_US_EASTERN[i]); 273 } 274 return ruleBasedTimeZones; 275 } 276 } 277 278 private static class DateTimeRuleHandler implements Handler { 279 @Override 280 public Object[] getTestObjects() { 281 DateTimeRule[] rules = new DateTimeRule[4]; 282 283 // DOM + UTC 284 rules[0] = new DateTimeRule(Calendar.OCTOBER, 10, 13*HOUR, DateTimeRule.UTC_TIME); 285 286 // DOW + WALL 287 rules[1] = new DateTimeRule(Calendar.MARCH, 2, Calendar.SUNDAY, 2*HOUR, DateTimeRule.WALL_TIME); 288 289 // DOW_GEQ_DOM + STD 290 rules[2] = new DateTimeRule(Calendar.MAY, 1, Calendar.MONDAY, true, 0*HOUR, DateTimeRule.STANDARD_TIME); 291 292 // DOW_LEQ_DOM + WALL 293 rules[3] = new DateTimeRule(Calendar.AUGUST, 31, Calendar.SATURDAY, false, 1*HOUR, DateTimeRule.WALL_TIME); 294 295 return rules; 296 } 297 298 @Override 299 public boolean hasSameBehavior(Object a, Object b) { 300 return hasSameRule((DateTimeRule)a, (DateTimeRule)b); 301 } 302 303 static boolean hasSameRule(DateTimeRule dtra, DateTimeRule dtrb) { 304 boolean bSame = false; 305 if (dtra.getDateRuleType() == dtrb.getDateRuleType() 306 && dtra.getRuleMonth() == dtrb.getRuleMonth() 307 && dtra.getTimeRuleType() == dtrb.getTimeRuleType() 308 && dtra.getRuleMillisInDay() == dtrb.getRuleMillisInDay()) { 309 switch (dtra.getDateRuleType()) { 310 case DateTimeRule.DOM: 311 bSame = (dtra.getRuleDayOfMonth() == dtrb.getRuleDayOfMonth()); 312 break; 313 case DateTimeRule.DOW: 314 bSame = (dtra.getRuleDayOfWeek() == dtrb.getRuleDayOfWeek() && 315 dtra.getRuleWeekInMonth() == dtrb.getRuleWeekInMonth()); 316 break; 317 case DateTimeRule.DOW_GEQ_DOM: 318 case DateTimeRule.DOW_LEQ_DOM: 319 bSame = (dtra.getRuleDayOfMonth() == dtrb.getRuleDayOfMonth() && 320 dtra.getRuleDayOfWeek() == dtrb.getRuleDayOfWeek()); 321 break; 322 } 323 } 324 return bSame; 325 } 326 } 327 328 private static boolean compareTimeZoneRules(TimeZoneRule ra, TimeZoneRule rb) { 329 if (ra.getName().equals(rb.getName()) && 330 ra.getRawOffset() == rb.getRawOffset() && 331 ra.getDSTSavings() == rb.getDSTSavings()) { 332 return true; 333 } 334 return false; 335 } 336 337 private static class AnnualTimeZoneRuleHandler implements Handler { 338 @Override 339 public Object[] getTestObjects() { 340 return TEST_US_EASTERN; 341 } 342 343 @Override 344 public boolean hasSameBehavior(Object a, Object b) { 345 AnnualTimeZoneRule ra = (AnnualTimeZoneRule)a; 346 AnnualTimeZoneRule rb = (AnnualTimeZoneRule)b; 347 if (DateTimeRuleHandler.hasSameRule(ra.getRule(), rb.getRule()) && 348 ra.getStartYear() == rb.getStartYear() && 349 ra.getEndYear() == rb.getEndYear()) { 350 return compareTimeZoneRules(ra, rb); 351 } 352 return false; 353 } 354 } 355 356 private static class InitialTimeZoneRuleHandler implements Handler { 357 @Override 358 public Object[] getTestObjects() { 359 TimeZoneRule[] rules = new TimeZoneRule[2]; 360 rules[0] = new InitialTimeZoneRule("EST", -5*HOUR, 0); 361 rules[1] = new InitialTimeZoneRule("PST", -8*HOUR, 0); 362 return rules; 363 } 364 365 @Override 366 public boolean hasSameBehavior(Object a, Object b) { 367 return compareTimeZoneRules((TimeZoneRule)a, (TimeZoneRule)b); 368 } 369 } 370 371 private static class TimeArrayTimeZoneRuleHandler implements Handler { 372 @Override 373 public Object[] getTestObjects() { 374 TimeArrayTimeZoneRule[] rules = new TimeArrayTimeZoneRule[1]; 375 long[] ttime = new long[] {-631152000000L, 0L, 946684800000L}; /* {1950-1-1, 1970-1-1, 2000-1-1} */ 376 rules[0] = new TimeArrayTimeZoneRule("Foo", 1*HOUR, 1*HOUR, ttime, DateTimeRule.UTC_TIME); 377 378 return rules; 379 } 380 @Override 381 public boolean hasSameBehavior(Object a, Object b) { 382 TimeArrayTimeZoneRule ra = (TimeArrayTimeZoneRule)a; 383 TimeArrayTimeZoneRule rb = (TimeArrayTimeZoneRule)b; 384 385 Date da = ra.getFirstStart(0, 0); 386 Date db = rb.getFirstStart(0, 0); 387 long t = da.getTime(); 388 if (da.equals(db)) { 389 da = ra.getFinalStart(0, 0); 390 db = rb.getFinalStart(0, 0); 391 long end = da.getTime(); 392 if (da.equals(db)) { 393 while (t < end) { 394 da = ra.getNextStart(t, 0, 0, false); 395 db = ra.getNextStart(t, 0, 0, false); 396 if (da == null || db == null || !da.equals(db)) { 397 break; 398 } 399 t = da.getTime(); 400 } 401 return compareTimeZoneRules(ra, rb); 402 } 403 } 404 return false; 405 } 406 } 407 408 private static class ULocaleHandler implements Handler 409 { 410 @Override 411 public Object[] getTestObjects() 412 { 413 ULocale uLocales[] = new ULocale[locales.length]; 414 415 for (int i = 0; i < locales.length; i += 1) { 416 uLocales[i] = ULocale.forLocale(locales[i]); 417 } 418 419 return uLocales; 420 } 421 422 @Override 423 public boolean hasSameBehavior(Object a, Object b) 424 { 425 ULocale uloc_a = (ULocale) a; 426 ULocale uloc_b = (ULocale) b; 427 428 return uloc_a.getName().equals(uloc_b.getName()); 429 } 430 } 431 432 public static class DateIntervalHandler implements Handler 433 { 434 private DateInterval dateInterval[] = { 435 new DateInterval(0L, 1164931200000L/*20061201T000000Z*/) 436 }; 437 @Override 438 public Object[] getTestObjects() 439 { 440 return dateInterval; 441 } 442 443 @Override 444 public boolean hasSameBehavior(Object a, Object b) 445 { 446 return a.equals(b); 447 } 448 } 449 450 private static class CurrencyHandler implements Handler 451 { 452 @Override 453 public Object[] getTestObjects() 454 { 455 Currency currencies[] = new Currency[places.length]; 456 457 for (int i = 0; i < places.length; i += 1) { 458 currencies[i] = Currency.getInstance(places[i]); 459 } 460 461 return currencies; 462 } 463 464 @Override 465 public boolean hasSameBehavior(Object a, Object b) 466 { 467 468 Currency curr_a = (Currency) a; 469 Currency curr_b = (Currency) b; 470 471 return a == b 472 || a != null && b != null 473 && curr_a.getCurrencyCode() != null 474 && curr_a.getCurrencyCode().equals(curr_b.getCurrencyCode()); 475 476 } 477 } 478 479 private static String zoneIDs[] = { 480 "Pacific/Honolulu", "America/Anchorage", "America/Los_Angeles", "America/Denver", 481 "America/Chicago", "America/New_York", "Africa/Cairo", "Africa/Addis_Ababa", "Africa/Dar_es_Salaam", 482 "Africa/Freetown", "Africa/Johannesburg", "Africa/Nairobi", "Asia/Bangkok", "Asia/Baghdad", 483 "Asia/Calcutta", "Asia/Hong_Kong", "Asia/Jakarta", "Asia/Jerusalem", "Asia/Manila", "Asia/Tokyo", 484 "Europe/Amsterdam", "Europe/Athens", "Europe/Berlin", "Europe/London", "Europe/Malta", "Europe/Moscow", 485 "Europe/Paris", "Europe/Rome" 486 }; 487 488 private static long sampleTimes[] = { 489 1136073600000L, // 20060101T000000Z 490 1138752000000L, // 20060201T000000Z 491 1141171200000L, // 20060301T000000Z 492 1143849600000L, // 20060401T000000Z 493 1146441600000L, // 20060501T000000Z 494 1149120000000L, // 20060601T000000Z 495 1151712000000L, // 20060701T000000Z 496 1154390400000L, // 20060801T000000Z 497 1157068800000L, // 20060901T000000Z 498 1159660800000L, // 20061001T000000Z 499 1162339200000L, // 20061101T000000Z 500 1164931200000L, // 20061201T000000Z 501 }; 502 503 private static class OlsonTimeZoneHandler implements Handler 504 { 505 @Override 506 public Object[] getTestObjects() 507 { 508 OlsonTimeZone timeZones[] = new OlsonTimeZone[zoneIDs.length]; 509 510 for (int i = 0; i < zoneIDs.length; i += 1) { 511 timeZones[i] = new OlsonTimeZone(zoneIDs[i]); 512 } 513 514 return timeZones; 515 516 } 517 518 @Override 519 public boolean hasSameBehavior(Object a, Object b) 520 { 521 OlsonTimeZone otz_a = (OlsonTimeZone) a; 522 OlsonTimeZone otz_b = (OlsonTimeZone) b; 523 int a_offsets[] = {0, 0}; 524 int b_offsets[] = {0, 0}; 525 526 boolean bSame = true; 527 for (int i = 0; i < sampleTimes.length; i++) { 528 otz_a.getOffset(sampleTimes[i], false, a_offsets); 529 otz_b.getOffset(sampleTimes[i], false, b_offsets); 530 if (a_offsets[0] != b_offsets[0] || a_offsets[1] != b_offsets[1]) { 531 bSame = false; 532 break; 533 } 534 } 535 return bSame; 536 } 537 } 538 539 private static class TimeZoneAdapterHandler implements Handler 540 { 541 @Override 542 public Object[] getTestObjects() 543 { 544 TimeZoneAdapter timeZones[] = new TimeZoneAdapter[zoneIDs.length]; 545 546 for (int i = 0; i < zoneIDs.length; i += 1) { 547 timeZones[i] = new TimeZoneAdapter(TimeZone.getTimeZone(zoneIDs[i])); 548 } 549 550 return timeZones; 551 552 } 553 554 @Override 555 public boolean hasSameBehavior(Object a, Object b) 556 { 557 GregorianCalendar cal = new GregorianCalendar(); 558 TimeZoneAdapter tza_a = (TimeZoneAdapter) a; 559 TimeZoneAdapter tza_b = (TimeZoneAdapter) b; 560 561 int a_offset, b_offset; 562 boolean a_dst, b_dst; 563 boolean bSame = true; 564 for (int i = 0; i < sampleTimes.length; i++) { 565 cal.setTimeInMillis(sampleTimes[i]); 566 int era = cal.get(Calendar.ERA); 567 int year = cal.get(Calendar.YEAR); 568 int month = cal.get(Calendar.MONTH); 569 int day = cal.get(Calendar.DAY_OF_MONTH); 570 int dow = cal.get(Calendar.DAY_OF_WEEK); 571 int mid = cal.get(Calendar.MILLISECONDS_IN_DAY); 572 a_offset = tza_a.getOffset(era, year, month, day, dow, mid); 573 b_offset = tza_b.getOffset(era, year, month, day, dow, mid); 574 Date d = new Date(sampleTimes[i]); 575 a_dst = tza_a.inDaylightTime(d); 576 b_dst = tza_b.inDaylightTime(d); 577 if (a_offset != b_offset || a_dst != b_dst) { 578 bSame = false; 579 break; 580 } 581 } 582 return bSame; 583 } 584 } 585 586 private static class JavaTimeZoneHandler implements Handler { 587 String[] ZONES = { "GMT", "America/New_York", "GMT+05:45" }; 588 589 @Override 590 public Object[] getTestObjects() { 591 JavaTimeZone zones[] = new JavaTimeZone[ZONES.length]; 592 for(int z = 0; z < ZONES.length; z += 1) { 593 java.util.TimeZone tz = java.util.TimeZone.getTimeZone(ZONES[z]); 594 zones[z] = new JavaTimeZone(tz, ZONES[z]); 595 } 596 return zones; 597 } 598 599 @Override 600 public boolean hasSameBehavior(Object a, Object b) 601 { 602 TimeZone zone_a = (TimeZone) a; 603 TimeZone zone_b = (TimeZone) b; 604 605 if (!(TimeZone.getCanonicalID(zone_a.getID()).equals(TimeZone.getCanonicalID(zone_b.getID())))) { 606 return false; 607 } 608 609 int a_offsets[] = {0, 0}; 610 int b_offsets[] = {0, 0}; 611 612 boolean bSame = true; 613 for (int i = 0; i < sampleTimes.length; i++) { 614 zone_a.getOffset(sampleTimes[i], false, a_offsets); 615 zone_b.getOffset(sampleTimes[i], false, b_offsets); 616 if (a_offsets[0] != b_offsets[0] || a_offsets[1] != b_offsets[1]) { 617 bSame = false; 618 break; 619 } 620 } 621 return bSame; 622 } 623 } 624 625 private static class BigDecimalHandler implements Handler 626 { 627 String values[] = { 628 "1234567890.", 629 "123456789.0", 630 "12345678.90", 631 "1234567.890", 632 "123456.7890", 633 "12345.67890", 634 "1234.567890", 635 "123.4567890", 636 "12.34567890", 637 "1.234567890", 638 ".1234567890"}; 639 640 @Override 641 public Object[] getTestObjects() 642 { 643 BigDecimal bds[] = new BigDecimal[values.length]; 644 645 for (int i = 0; i < values.length; i += 1) { 646 bds[i] = new BigDecimal(values[i]); 647 } 648 649 return bds; 650 } 651 652 @Override 653 public boolean hasSameBehavior(Object a, Object b) { 654 BigDecimal bda = (BigDecimal) a; 655 BigDecimal bdb = (BigDecimal) b; 656 657 return bda.toString().equals(bdb.toString()); 658 } 659 } 660 661 private static class MathContextHandler implements Handler 662 { 663 int forms[] = {MathContext.PLAIN, MathContext.ENGINEERING, MathContext.SCIENTIFIC}; 664 int rounds[] = { 665 MathContext.ROUND_CEILING, MathContext.ROUND_DOWN, MathContext.ROUND_FLOOR, 666 MathContext.ROUND_HALF_DOWN, MathContext.ROUND_HALF_EVEN, MathContext.ROUND_HALF_UP, 667 MathContext.ROUND_UNNECESSARY, MathContext.ROUND_UP}; 668 669 @Override 670 public Object[] getTestObjects() 671 { 672 int objectCount = forms.length * rounds.length; 673 MathContext contexts[] = new MathContext[objectCount]; 674 int i = 0; 675 676 for (int f = 0; f < forms.length; f += 1) { 677 for (int r = 0; r < rounds.length; r += 1) { 678 int digits = f * r; 679 boolean lostDigits = (r & 1) != 0; 680 681 contexts[i++] = new MathContext(digits, forms[f], lostDigits, rounds[r]); 682 } 683 } 684 685 return contexts; 686 } 687 688 @Override 689 public boolean hasSameBehavior(Object a, Object b) 690 { 691 MathContext mca = (MathContext) a; 692 MathContext mcb = (MathContext) b; 693 694 return mca.toString().equals(mcb.toString()); 695 } 696 } 697 698 private static abstract class ExceptionHandlerBase implements Handler { 699 @Override 700 public boolean hasSameBehavior(Object a, Object b) { 701 return sameThrowable((Exception) a, (Exception) b); 702 } 703 704 // Exception.equals() does not seem to work. 705 private static final boolean sameThrowable(Throwable a, Throwable b) { 706 return a == null ? b == null : 707 b == null ? false : 708 a.getClass().equals(b.getClass()) && 709 Utility.objectEquals(a.getMessage(), b.getMessage()) && 710 sameThrowable(a.getCause(), b.getCause()); 711 } 712 } 713 714 private static class ICUExceptionHandler extends ExceptionHandlerBase { 715 @Override 716 public Object[] getTestObjects() { 717 return new ICUException[] { 718 new ICUException(), 719 new ICUException("msg1"), 720 new ICUException(new RuntimeException("rte1")), 721 new ICUException("msg2", new RuntimeException("rte2")) 722 }; 723 } 724 } 725 726 private static class ICUUncheckedIOExceptionHandler extends ExceptionHandlerBase { 727 @Override 728 public Object[] getTestObjects() { 729 return new ICUUncheckedIOException[] { 730 new ICUUncheckedIOException(), 731 new ICUUncheckedIOException("msg1"), 732 new ICUUncheckedIOException(new RuntimeException("rte1")), 733 new ICUUncheckedIOException("msg2", new RuntimeException("rte2")) 734 }; 735 } 736 } 737 738 private static class ICUCloneNotSupportedExceptionHandler extends ExceptionHandlerBase { 739 @Override 740 public Object[] getTestObjects() { 741 return new ICUCloneNotSupportedException[] { 742 new ICUCloneNotSupportedException(), 743 new ICUCloneNotSupportedException("msg1"), 744 new ICUCloneNotSupportedException(new RuntimeException("rte1")), 745 new ICUCloneNotSupportedException("msg2", new RuntimeException("rte2")) 746 }; 747 } 748 } 749 750 private static HashMap map = new HashMap(); 751 752 static { 753 map.put("com.ibm.icu.util.TimeZone", new TimeZoneHandler()); 754 map.put("com.ibm.icu.util.SimpleTimeZone", new SimpleTimeZoneHandler()); 755 map.put("com.ibm.icu.util.RuleBasedTimeZone", new RuleBasedTimeZoneHandler()); 756 map.put("com.ibm.icu.util.VTimeZone", new VTimeZoneHandler()); 757 map.put("com.ibm.icu.util.DateTimeRule", new DateTimeRuleHandler()); 758 map.put("com.ibm.icu.util.AnnualTimeZoneRule", new AnnualTimeZoneRuleHandler()); 759 map.put("com.ibm.icu.util.InitialTimeZoneRule", new InitialTimeZoneRuleHandler()); 760 map.put("com.ibm.icu.util.TimeArrayTimeZoneRule", new TimeArrayTimeZoneRuleHandler()); 761 map.put("com.ibm.icu.util.ULocale", new ULocaleHandler()); 762 map.put("com.ibm.icu.util.Currency", new CurrencyHandler()); 763 map.put("com.ibm.icu.impl.JavaTimeZone", new JavaTimeZoneHandler()); 764 map.put("com.ibm.icu.impl.OlsonTimeZone", new OlsonTimeZoneHandler()); 765 map.put("com.ibm.icu.impl.TimeZoneAdapter", new TimeZoneAdapterHandler()); 766 map.put("com.ibm.icu.math.BigDecimal", new BigDecimalHandler()); 767 map.put("com.ibm.icu.math.MathContext", new MathContextHandler()); 768 769 map.put("com.ibm.icu.text.NumberFormat", new FormatHandler.NumberFormatHandler()); 770 map.put("com.ibm.icu.text.DecimalFormat", new FormatHandler.DecimalFormatHandler()); 771 map.put("com.ibm.icu.text.CompactDecimalFormat", new FormatHandler.CompactDecimalFormatHandler()); 772 map.put("com.ibm.icu.text.RuleBasedNumberFormat", new FormatHandler.RuleBasedNumberFormatHandler()); 773 map.put("com.ibm.icu.text.CurrencyPluralInfo", new FormatHandler.CurrencyPluralInfoHandler()); 774 map.put("com.ibm.icu.text.DecimalFormatSymbols", new FormatHandler.DecimalFormatSymbolsHandler()); 775 map.put("com.ibm.icu.text.MessageFormat", new FormatHandler.MessageFormatHandler()); 776 map.put("com.ibm.icu.text.DateFormat", new FormatHandler.DateFormatHandler()); 777 map.put("com.ibm.icu.text.DateFormatSymbols", new FormatHandler.DateFormatSymbolsHandler()); 778 map.put("com.ibm.icu.util.DateInterval", new DateIntervalHandler()); 779 map.put("com.ibm.icu.text.DateIntervalFormat", new FormatHandler.DateIntervalFormatHandler()); 780 map.put("com.ibm.icu.text.DateIntervalInfo", new FormatHandler.DateIntervalInfoHandler()); 781 map.put("com.ibm.icu.text.DateIntervalInfo$PatternInfo", new FormatHandler.PatternInfoHandler()); 782 map.put("com.ibm.icu.text.SimpleDateFormat", new FormatHandler.SimpleDateFormatHandler()); 783 map.put("com.ibm.icu.text.ChineseDateFormat", new FormatHandler.ChineseDateFormatHandler()); 784 map.put("com.ibm.icu.text.ChineseDateFormatSymbols", new FormatHandler.ChineseDateFormatSymbolsHandler()); 785 map.put("com.ibm.icu.impl.DateNumberFormat", new FormatHandler.DateNumberFormatHandler()); 786 map.put("com.ibm.icu.text.PluralFormat", new FormatHandler.PluralFormatHandler()); 787 map.put("com.ibm.icu.text.PluralRules", new FormatHandler.PluralRulesHandler()); 788 map.put("com.ibm.icu.text.PluralRulesSerialProxy", new FormatHandler.PluralRulesSerialProxyHandler()); 789 map.put("com.ibm.icu.text.TimeUnitFormat", new FormatHandler.TimeUnitFormatHandler()); 790 map.put("com.ibm.icu.text.SelectFormat", new FormatHandler.SelectFormatHandler()); 791 map.put("com.ibm.icu.impl.TimeZoneNamesImpl", new FormatHandler.TimeZoneNamesHandler()); 792 map.put("com.ibm.icu.text.TimeZoneFormat", new FormatHandler.TimeZoneFormatHandler()); 793 map.put("com.ibm.icu.impl.TimeZoneGenericNames", new FormatHandler.TimeZoneGenericNamesHandler()); 794 map.put("com.ibm.icu.impl.TZDBTimeZoneNames", new FormatHandler.TZDBTimeZoneNamesHandler()); 795 796 map.put("com.ibm.icu.util.Calendar", new CalendarHandler.BasicCalendarHandler()); 797 map.put("com.ibm.icu.util.BuddhistCalendar", new CalendarHandler.BuddhistCalendarHandler()); 798 map.put("com.ibm.icu.util.ChineseCalendar", new CalendarHandler.ChineseCalendarHandler()); 799 map.put("com.ibm.icu.util.CopticCalendar", new CalendarHandler.CopticCalendarHandler()); 800 map.put("com.ibm.icu.util.DangiCalendar", new CalendarHandler.DangiCalendarHandler()); 801 map.put("com.ibm.icu.util.EthiopicCalendar", new CalendarHandler.EthiopicCalendarHandler()); 802 map.put("com.ibm.icu.util.GregorianCalendar", new CalendarHandler.GregorianCalendarHandler()); 803 map.put("com.ibm.icu.util.HebrewCalendar", new CalendarHandler.HebrewCalendarHandler()); 804 map.put("com.ibm.icu.util.IndianCalendar", new CalendarHandler.IndianCalendarHandler()); 805 map.put("com.ibm.icu.util.IslamicCalendar", new CalendarHandler.IslamicCalendarHandler()); 806 map.put("com.ibm.icu.util.JapaneseCalendar", new CalendarHandler.JapaneseCalendarHandler()); 807 map.put("com.ibm.icu.util.PersianCalendar", new CalendarHandler.PersianCalendarHandler()); 808 map.put("com.ibm.icu.util.TaiwanCalendar", new CalendarHandler.TaiwanCalendarHandler()); 809 810 map.put("com.ibm.icu.text.ArabicShapingException", new ExceptionHandler.ArabicShapingExceptionHandler()); 811 map.put("com.ibm.icu.text.StringPrepParseException", new ExceptionHandler.StringPrepParseExceptionHandler()); 812 map.put("com.ibm.icu.util.UResourceTypeMismatchException", new ExceptionHandler.UResourceTypeMismatchExceptionHandler()); 813 map.put("com.ibm.icu.impl.InvalidFormatException", new ExceptionHandler.InvalidFormatExceptionHandler()); 814 815 map.put("com.ibm.icu.text.NumberFormat$Field", new FormatHandler.NumberFormatFieldHandler()); 816 map.put("com.ibm.icu.text.DateFormat$Field", new FormatHandler.DateFormatFieldHandler()); 817 map.put("com.ibm.icu.text.ChineseDateFormat$Field", new FormatHandler.ChineseDateFormatFieldHandler()); 818 map.put("com.ibm.icu.text.MessageFormat$Field", new FormatHandler.MessageFormatFieldHandler()); 819 820 map.put("com.ibm.icu.impl.duration.BasicDurationFormat", new FormatHandler.BasicDurationFormatHandler()); 821 map.put("com.ibm.icu.impl.RelativeDateFormat", new FormatHandler.RelativeDateFormatHandler()); 822 map.put("com.ibm.icu.util.IllformedLocaleException", new ExceptionHandler.IllformedLocaleExceptionHandler()); 823 map.put("com.ibm.icu.impl.locale.LocaleSyntaxException", new ExceptionHandler.LocaleSyntaxExceptionHandler()); 824 map.put("com.ibm.icu.impl.IllegalIcuArgumentException", new ExceptionHandler.IllegalIcuArgumentExceptionHandler()); 825 826 map.put("com.ibm.icu.text.PluralRules$FixedDecimal", new PluralRulesTest.FixedDecimalHandler()); 827 map.put("com.ibm.icu.util.MeasureUnit", new MeasureUnitTest.MeasureUnitHandler()); 828 map.put("com.ibm.icu.util.TimeUnit", new MeasureUnitTest.MeasureUnitHandler()); 829 map.put("com.ibm.icu.text.MeasureFormat", new MeasureUnitTest.MeasureFormatHandler()); 830 831 map.put("com.ibm.icu.util.ICUException", new ICUExceptionHandler()); 832 map.put("com.ibm.icu.util.ICUUncheckedIOException", new ICUUncheckedIOExceptionHandler()); 833 map.put("com.ibm.icu.util.ICUCloneNotSupportedException", new ICUCloneNotSupportedExceptionHandler()); 834 } 835 836 /* 837 * Serialization Helpers 838 */ 839 static Object[] getSerializedObjects(byte[] serializedBytes) throws ClassNotFoundException, IOException { 840 ByteArrayInputStream bis = new ByteArrayInputStream(serializedBytes); 841 ObjectInputStream ois = new ObjectInputStream(bis); 842 Object inputObjects[] = (Object[]) ois.readObject(); 843 844 ois.close(); 845 return inputObjects; 846 } 847 848 static byte[] getSerializedBytes(Object[] objectsOut) throws IOException { 849 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 850 ObjectOutputStream oos = new ObjectOutputStream(bos); 851 oos.writeObject(objectsOut); 852 853 byte[] serializedBytes = bos.toByteArray(); 854 oos.close(); 855 return serializedBytes; 856 } 857 858 static Object[] getSerializedObjects(File testFile) throws IOException, ClassNotFoundException { 859 FileInputStream fis = new FileInputStream(testFile); 860 ObjectInputStream ois = new ObjectInputStream(fis); 861 Object[] objects = (Object[]) ois.readObject(); 862 fis.close(); 863 return objects; 864 } 865 866 static byte[] copyStreamBytes(InputStream is) throws IOException { 867 byte[] buffer = new byte[1024]; 868 869 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 870 int len; 871 while((len = is.read(buffer, 0, buffer.length)) >= 0) { 872 bos.write(buffer, 0, len); 873 } 874 return bos.toByteArray(); 875 } 876 877 static List<String> getSerializationClassList(Object caller) throws IOException { 878 List<String> classList = new ArrayList(); 879 Enumeration<URL> urlEnum = caller.getClass().getClassLoader().getResources("com/ibm/icu"); 880 while (urlEnum.hasMoreElements()) { 881 URL url = urlEnum.nextElement(); 882 URLHandler handler = URLHandler.get(url); 883 if (handler == null) { 884 System.out.println("Unsupported URL: " + url); 885 continue; 886 } 887 CoverageClassVisitor visitor = new CoverageClassVisitor(classList); 888 handler.guide(visitor, true, false); 889 } 890 return classList; 891 } 892 893 private static class CoverageClassVisitor implements URLHandler.URLVisitor { 894 private List<String> classNames; 895 896 public CoverageClassVisitor(List<String> classNamesList) { 897 this.classNames = classNamesList; 898 } 899 900 /* (non-Javadoc) 901 * @see com.ibm.icu.impl.URLHandler.URLVisitor#visit(java.lang.String) 902 */ 903 @Override 904 public void visit(String classPath) { 905 int ix = classPath.lastIndexOf(".class"); 906 if (ix < 0) { 907 return; 908 } 909 String className = "com.ibm.icu" + classPath.substring(0, ix).replace('/', '.'); 910 911 // Skip things in com.ibm.icu.dev; they're not relevant. 912 if (className.startsWith("com.ibm.icu.dev.")) { 913 return; 914 } 915 Class c; 916 try { 917 c = Class.forName(className); 918 } catch (ClassNotFoundException e) { 919 return; 920 } 921 int m = c.getModifiers(); 922 923 if (className.equals("com.ibm.icu.text.PluralRules$FixedDecimal")) { 924 // Known Issue: "10268", "Serializable interface is not implemented in PluralRules$FixedDecimal" 925 return; 926 } 927 928 if (c.isEnum() || !serializable.isAssignableFrom(c)) { 929 //System.out.println("@@@ Skipping: " + className); 930 return; 931 } 932 if (!Modifier.isPublic(m) || Modifier.isInterface(m)) { 933 //System.out.println("@@@ Skipping: " + className); 934 return; 935 } 936 937 this.classNames.add(className); 938 } 939 } 940 941 public static void serializeObjects(File oof, Object[] objectsOut) throws IOException { 942 FileOutputStream fos = new FileOutputStream(oof); 943 ObjectOutputStream oos = new ObjectOutputStream(fos); 944 oos.writeObject(objectsOut); 945 946 oos.close(); 947 } 948} 949