X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/2ca993e82fb37b597a3c73ecd1586a139a6579c5..refs/heads/master:/icuSources/test/cintltst/ccaltst.c?ds=sidebyside diff --git a/icuSources/test/cintltst/ccaltst.c b/icuSources/test/cintltst/ccaltst.c index 9333b51f..4e9679ab 100644 --- a/icuSources/test/cintltst/ccaltst.c +++ b/icuSources/test/cintltst/ccaltst.c @@ -1,3 +1,5 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html /******************************************************************** * Copyright (c) 1997-2016, International Business Machines * Corporation and others. All Rights Reserved. @@ -38,8 +40,10 @@ void TestGetTZTransition(void); void TestGetWindowsTimeZoneID(void); void TestGetTimeZoneIDByWindowsID(void); -void TestClear(void); -void TestGetDayPeriods(); /* Apple-specific */ +void TestJpnCalAddSetNextEra(void); +void TestClear(void); /* Apple-specific */ +void TestPersianCalOverflow(void); /* Apple-specific */ +void TestGetDayPeriods(void); /* Apple-specific */ void addCalTest(TestNode** root); @@ -62,7 +66,9 @@ void addCalTest(TestNode** root) addTest(root, &TestGetTZTransition, "tsformat/ccaltst/TestGetTZTransition"); addTest(root, &TestGetWindowsTimeZoneID, "tsformat/ccaltst/TestGetWindowsTimeZoneID"); addTest(root, &TestGetTimeZoneIDByWindowsID, "tsformat/ccaltst/TestGetTimeZoneIDByWindowsID"); + addTest(root, &TestJpnCalAddSetNextEra, "tsformat/ccaltst/TestJpnCalAddSetNextEra"); addTest(root, &TestClear, "tsformat/ccaltst/TestClear"); + addTest(root, &TestPersianCalOverflow, "tsformat/ccaltst/TestPersianCalOverflow"); addTest(root, &TestGetDayPeriods, "tsformat/ccaltst/TestGetDayPeriods"); /* Apple-specific */ } @@ -113,8 +119,9 @@ static void TestCalendar() UDateFormat *datdef = 0; UChar *result = 0; int32_t resultlength, resultlengthneeded; - char tempMsgBuf[256]; - UChar zone1[32], zone2[32]; + char tempMsgBuf[1024]; // u_austrcpy() of some formatted dates & times. + char tempMsgBuf2[256]; // u_austrcpy() of some formatted dates & times. + UChar zone1[64], zone2[64]; const char *tzver = 0; UChar canonicalID[64]; UBool isSystemID = FALSE; @@ -228,10 +235,10 @@ static void TestCalendar() log_err("FAIL: ucal_getDSTSavings(PST) => %d, expect %d\n", i, 1*60*60*1000); } - /*Test ucal_set/getDefaultTimeZone*/ + /*Test ucal_set/getDefaultTimeZone and ucal_getHostTimeZone */ status = U_ZERO_ERROR; i = ucal_getDefaultTimeZone(zone1, UPRV_LENGTHOF(zone1), &status); - if (U_FAILURE(status)) { + if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) { log_err("FAIL: ucal_getDefaultTimeZone() => %s\n", u_errorName(status)); } else { @@ -247,6 +254,17 @@ static void TestCalendar() } else { if (u_strcmp(zone2, EUROPE_PARIS) != 0) { log_data_err("FAIL: ucal_getDefaultTimeZone() did not return Europe/Paris (Are you missing data?)\n"); + } else { + // Redetect the host timezone, it should be the same as zone1 even though ICU's default timezone has been changed. + i = ucal_getHostTimeZone(zone2, UPRV_LENGTHOF(zone2), &status); + if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) { + log_err("FAIL: ucal_getHostTimeZone() => %s\n", u_errorName(status)); + } else { + if (u_strcmp(zone1, zone2) != 0) { + log_err("FAIL: ucal_getHostTimeZone() should give the same host timezone even if the default changed. (Got '%s', Expected '%s').\n", + u_austrcpy(tempMsgBuf, zone2), u_austrcpy(tempMsgBuf2, zone1)); + } + } } } } @@ -259,7 +277,7 @@ static void TestCalendar() tzver = ucal_getTZDataVersion(&status); if (U_FAILURE(status)) { log_err_status(status, "FAIL: ucal_getTZDataVersion() => %s\n", u_errorName(status)); - } else if (uprv_strlen(tzver) != 5 /*4 digits + 1 letter*/) { + } else if (uprv_strlen(tzver) < 5 || uprv_strlen(tzver) > 7 /*4 digits + 1-3 letters*/) { log_err("FAIL: Bad version string was returned by ucal_getTZDataVersion\n"); } else { log_verbose("PASS: ucal_getTZDataVersion returned %s\n", tzver); @@ -346,6 +364,11 @@ static void TestCalendar() datdef=udat_open(UDAT_FULL,UDAT_FULL ,NULL, NULL, 0,NULL,0,&status); if(U_FAILURE(status)){ log_data_err("FAIL: error in creating the dateformat : %s (Are you missing data?)\n", u_errorName(status)); + ucal_close(caldef2); + ucal_close(calfr); + ucal_close(calit); + ucal_close(calfrclone); + ucal_close(caldef); return; } log_verbose("PASS: The current date and time fetched is %s\n", u_austrcpy(tempMsgBuf, myDateFormat(datdef, now)) ); @@ -525,6 +548,10 @@ static void TestGetSetDateAPI() if(U_FAILURE(status)) { log_data_err("error in creating the dateformat : %s (Are you missing data?)\n", u_errorName(status)); + ucal_close(caldef); + ucal_close(caldef2); + ucal_close(caldef3); + udat_close(datdef); return; } @@ -686,7 +713,7 @@ static void TestGetSetDateAPI() /*Testing if setDate works fine */ log_verbose("\nTesting the ucal_setDate() function \n"); - u_uastrcpy(temp, "Dec 17, 1971, 11:05:28 PM"); + u_uastrcpy(temp, "Dec 17, 1971 at 11:05:28 PM"); ucal_setDate(caldef,1971, UCAL_DECEMBER, 17, &status); if(U_FAILURE(status)){ log_err("error in setting the calendar date : %s\n", u_errorName(status)); @@ -717,7 +744,7 @@ static void TestGetSetDateAPI() /*Testing if setDateTime works fine */ log_verbose("\nTesting the ucal_setDateTime() function \n"); - u_uastrcpy(temp, "May 3, 1972, 4:30:42 PM"); + u_uastrcpy(temp, "May 3, 1972 at 4:30:42 PM"); ucal_setDateTime(caldef,1972, UCAL_MAY, 3, 16, 30, 42, &status); if(U_FAILURE(status)){ log_err("error in setting the calendar date : %s\n", u_errorName(status)); @@ -935,7 +962,7 @@ static void TestAddRollExtensive() u_uastrcpy(tzID, "PST"); /*open the calendar used */ - cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_GREGORIAN, &status);; + cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_GREGORIAN, &status); if (U_FAILURE(status)) { log_data_err("ucal_open() failed : %s - (Are you missing data?)\n", u_errorName(status)); return; @@ -1123,7 +1150,7 @@ static void TestGetLimits() u_uastrcpy(tzID, "PST"); /*open the calendar used */ - cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_GREGORIAN, &status);; + cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_GREGORIAN, &status); if (U_FAILURE(status)) { log_data_err("ucal_open() for gregorian calendar failed in TestGetLimits: %s - (Are you missing data?)\n", u_errorName(status)); return; @@ -1221,7 +1248,7 @@ static void TestDOWProgression() char tempMsgBuf[256]; u_strcpy(tzID, fgGMTID); /*open the calendar used */ - cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);; + cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status); if (U_FAILURE(status)) { log_data_err("ucal_open failed: %s - (Are you missing data?)\n", u_errorName(status)); return; @@ -1238,30 +1265,33 @@ static void TestDOWProgression() log_verbose("\nTesting the DOW progression\n"); initialDOW = ucal_get(cal, UCAL_DAY_OF_WEEK, &status); - if (U_FAILURE(status)) { log_data_err("ucal_get() failed: %s (Are you missing data?)\n", u_errorName(status) ); return; } - newDOW = initialDOW; - do { - DOW = newDOW; - log_verbose("DOW = %d...\n", DOW); - date1=ucal_getMillis(cal, &status); - if(U_FAILURE(status)){ log_err("ucal_getMiilis() failed: %s\n", u_errorName(status)); return;} - log_verbose("%s\n", u_austrcpy(tempMsgBuf, myDateFormat(datfor, date1))); - - ucal_add(cal,UCAL_DAY_OF_WEEK, delta, &status); - if (U_FAILURE(status)) { log_err("ucal_add() failed: %s\n", u_errorName(status)); return; } - - newDOW = ucal_get(cal, UCAL_DAY_OF_WEEK, &status); - if (U_FAILURE(status)) { log_err("ucal_get() failed: %s\n", u_errorName(status)); return; } - expectedDOW = 1 + (DOW + delta - 1) % 7; - date1=ucal_getMillis(cal, &status); - if(U_FAILURE(status)){ log_err("ucal_getMiilis() failed: %s\n", u_errorName(status)); return;} - if (newDOW != expectedDOW) { - log_err("Day of week should be %d instead of %d on %s", expectedDOW, newDOW, - u_austrcpy(tempMsgBuf, myDateFormat(datfor, date1)) ); - return; + if (U_FAILURE(status)) { + log_data_err("ucal_get() failed: %s (Are you missing data?)\n", u_errorName(status) ); + } else { + newDOW = initialDOW; + do { + DOW = newDOW; + log_verbose("DOW = %d...\n", DOW); + date1=ucal_getMillis(cal, &status); + if(U_FAILURE(status)){ log_err("ucal_getMiilis() failed: %s\n", u_errorName(status)); break;} + log_verbose("%s\n", u_austrcpy(tempMsgBuf, myDateFormat(datfor, date1))); + + ucal_add(cal,UCAL_DAY_OF_WEEK, delta, &status); + if (U_FAILURE(status)) { log_err("ucal_add() failed: %s\n", u_errorName(status)); break; } + + newDOW = ucal_get(cal, UCAL_DAY_OF_WEEK, &status); + if (U_FAILURE(status)) { log_err("ucal_get() failed: %s\n", u_errorName(status)); break; } + expectedDOW = 1 + (DOW + delta - 1) % 7; + date1=ucal_getMillis(cal, &status); + if(U_FAILURE(status)){ log_err("ucal_getMiilis() failed: %s\n", u_errorName(status)); break;} + if (newDOW != expectedDOW) { + log_err("Day of week should be %d instead of %d on %s", expectedDOW, newDOW, + u_austrcpy(tempMsgBuf, myDateFormat(datfor, date1)) ); + break; + } } + while (newDOW != initialDOW); } - while (newDOW != initialDOW); ucal_close(cal); udat_close(datfor); @@ -1294,16 +1324,16 @@ static void testZones(int32_t yr, int32_t mo, int32_t dt, int32_t hr, int32_t mn char tempMsgBuf[256]; u_strcpy(tzID, fgGMTID); - gmtcal=ucal_open(tzID, 3, "en_US", UCAL_TRADITIONAL, &status);; + gmtcal=ucal_open(tzID, 3, "en_US", UCAL_TRADITIONAL, &status); if (U_FAILURE(status)) { log_data_err("ucal_open failed: %s - (Are you missing data?)\n", u_errorName(status)); - return; + goto cleanup; } u_uastrcpy(tzID, "PST"); cal = ucal_open(tzID, 3, "en_US", UCAL_TRADITIONAL, &status); if (U_FAILURE(status)) { log_err("ucal_open failed: %s\n", u_errorName(status)); - return; + goto cleanup; } datfor=udat_open(UDAT_MEDIUM,UDAT_MEDIUM ,NULL, fgGMTID,-1,NULL, 0, &status); @@ -1314,13 +1344,13 @@ static void testZones(int32_t yr, int32_t mo, int32_t dt, int32_t hr, int32_t mn ucal_setDateTime(gmtcal, yr, mo - 1, dt, hr, mn, sc, &status); if (U_FAILURE(status)) { log_data_err("ucal_setDateTime failed: %s (Are you missing data?)\n", u_errorName(status)); - return; + goto cleanup; } ucal_set(gmtcal, UCAL_MILLISECOND, 0); date1 = ucal_getMillis(gmtcal, &status); if (U_FAILURE(status)) { log_err("ucal_getMillis failed: %s\n", u_errorName(status)); - return; + goto cleanup; } log_verbose("date = %s\n", u_austrcpy(tempMsgBuf, myDateFormat(datfor, date1)) ); @@ -1328,7 +1358,7 @@ static void testZones(int32_t yr, int32_t mo, int32_t dt, int32_t hr, int32_t mn ucal_setMillis(cal, date1, &status); if (U_FAILURE(status)) { log_err("ucal_setMillis() failed: %s\n", u_errorName(status)); - return; + goto cleanup; } offset = ucal_get(cal, UCAL_ZONE_OFFSET, &status); @@ -1336,7 +1366,7 @@ static void testZones(int32_t yr, int32_t mo, int32_t dt, int32_t hr, int32_t mn if (U_FAILURE(status)) { log_err("ucal_get() failed: %s\n", u_errorName(status)); - return; + goto cleanup; } temp=(double)((double)offset / 1000.0 / 60.0 / 60.0); /*printf("offset for %s %f hr\n", austrdup(myDateFormat(datfor, date1)), temp);*/ @@ -1347,7 +1377,7 @@ static void testZones(int32_t yr, int32_t mo, int32_t dt, int32_t hr, int32_t mn ucal_get(cal, UCAL_MILLISECOND, &status) - offset; if (U_FAILURE(status)) { log_err("ucal_get() failed: %s\n", u_errorName(status)); - return; + goto cleanup; } expected = ((hr * 60 + mn) * 60 + sc) * 1000; @@ -1357,6 +1387,8 @@ static void testZones(int32_t yr, int32_t mo, int32_t dt, int32_t hr, int32_t mn } else log_verbose("PASS: the offset between local and GMT is correct\n"); + +cleanup: ucal_close(gmtcal); ucal_close(cal); udat_close(datfor); @@ -1631,7 +1663,7 @@ static void TestGetKeywordValuesForLocale() { ALLList = ulist_getListFromEnum(ALL); for (j = 0; j < size; j++) { if ((value = uenum_next(all, &valueLength, &status)) != NULL && U_SUCCESS(status)) { - if (!ulist_containsString(ALLList, value, uprv_strlen(value))) { + if (!ulist_containsString(ALLList, value, (int32_t)uprv_strlen(value))) { log_err("Locale %s have %s not in ALL\n", loc, value); matchAll = FALSE; break; @@ -1732,10 +1764,17 @@ static const TestDaysOfWeek daysOfWeek_hi_IN[] = { /* Sunday only */ { UCAL_SATURDAY, UCAL_WEEKDAY, 0 }, { UCAL_SUNDAY, UCAL_WEEKEND, 0 }, }; +static const TestDaysOfWeek daysOfWeek_en_UG[] = { /* Sunday only */ + { UCAL_MONDAY, UCAL_WEEKDAY, 0 }, + { UCAL_FRIDAY, UCAL_WEEKDAY, 0 }, + { UCAL_SATURDAY, UCAL_WEEKDAY, 0 }, + { UCAL_SUNDAY, UCAL_WEEKEND, 0 }, +}; static const TestDaysOfWeekList testDays[] = { { "en_US", daysOfWeek_en_US, UPRV_LENGTHOF(daysOfWeek_en_US) }, { "ar_OM", daysOfWeek_ar_OM, UPRV_LENGTHOF(daysOfWeek_ar_OM) }, { "hi_IN", daysOfWeek_hi_IN, UPRV_LENGTHOF(daysOfWeek_hi_IN) }, + { "en_UG", daysOfWeek_en_UG, UPRV_LENGTHOF(daysOfWeek_en_UG) }, { "en_US@rg=OMZZZZ", daysOfWeek_ar_OM, UPRV_LENGTHOF(daysOfWeek_ar_OM) }, { "hi@rg=USZZZZ", daysOfWeek_en_US, UPRV_LENGTHOF(daysOfWeek_en_US) }, }; @@ -1967,7 +2006,7 @@ void TestAmbiguousWallTime() { UDate t, expected; u_uastrcpy(tzID, "America/New_York"); - ucal = ucal_open(tzID, -1, NULL, UCAL_DEFAULT, &status); + ucal = ucal_open(tzID, -1, "en_US", UCAL_DEFAULT, &status); if (U_FAILURE(status)) { log_err("FAIL: Failed to create a calendar"); return; @@ -2379,6 +2418,11 @@ static const UChar tzTronto[] = /* America/Toronto */ static const UChar sBogus[] = /* Bogus */ {0x42,0x6F,0x67,0x75,0x73,0x00}; +#ifndef U_DEBUG +static const UChar sBogusWithVariantCharacters[] = /* Bogus with Variant characters: Hèℓℓô Wôřℓδ */ + {0x48,0xE8,0x2113,0x2113,0xF4,0x20,0x57,0xF4,0x159,0x2113,0x3B4,0x00}; +#endif + void TestGetWindowsTimeZoneID() { UErrorCode status; UChar winID[64]; @@ -2445,7 +2489,6 @@ void TestGetTimeZoneIDByWindowsID() { log_err("FAIL: TZ ID for Eastern Standard Time - CA\n"); } } - { status = U_ZERO_ERROR; len = ucal_getTimeZoneIDForWindowsID(sBogus, -1, NULL, tzID, UPRV_LENGTHOF(tzID), &status); @@ -2455,6 +2498,73 @@ void TestGetTimeZoneIDByWindowsID() { log_err("FAIL: TZ ID for Bogus\n"); } } +#ifndef U_DEBUG + // This test is only for release mode because it will cause an assertion failure in debug builds. + // We don't check the API result for errors as the only purpose of this test is to ensure that + // input variant characters don't cause abort() to be called and/or that ICU doesn't crash. + { + status = U_ZERO_ERROR; + len = ucal_getTimeZoneIDForWindowsID(sBogusWithVariantCharacters, -1, NULL, tzID, UPRV_LENGTHOF(tzID), &status); + } +#endif +} + +// The following currently assumes that Reiwa is the last known/valid era. +// Filed ICU-20551 to generalize this when we have more time... +void TestJpnCalAddSetNextEra() { + UErrorCode status = U_ZERO_ERROR; + UCalendar *jCal = ucal_open(NULL, 0, "ja_JP@calendar=japanese", UCAL_DEFAULT, &status); + if ( U_FAILURE(status) ) { + log_data_err("FAIL: ucal_open for ja_JP@calendar=japanese, status %s\n", u_errorName(status)); + } else { + ucal_clear(jCal); // This sets to 1970, in Showa + int32_t sEra = ucal_get(jCal, UCAL_ERA, &status); // Don't assume era number for Showa + if ( U_FAILURE(status) ) { + log_data_err("FAIL: ucal_get ERA for Showa, status %s\n", u_errorName(status)); + } else { + int32_t iEra, eYear; + int32_t startYears[4] = { 1926, 1989, 2019, 0 }; // start years for Showa, Heisei, Reiwa; 0 marks invalid era + for (iEra = 1; iEra < 4; iEra++) { + status = U_ZERO_ERROR; + ucal_clear(jCal); + ucal_set(jCal, UCAL_ERA, sEra+iEra); + eYear = ucal_get(jCal, UCAL_EXTENDED_YEAR, &status); + if ( U_FAILURE(status) ) { + log_err("FAIL: set %d, ucal_get EXTENDED_YEAR, status %s\n", iEra, u_errorName(status)); + } else if (startYears[iEra] == 0) { // Apple-specific section, for iEra==3 + // invalid era, start should be in the far future with non-negative millis + if (eYear < 10000) { + log_err("ERROR: set %d, invalid era should have faraway start year, but get %d\n", iEra, eYear); + } + UDate date = ucal_getMillis(jCal, &status); + if ( U_FAILURE(status) ) { + log_err("FAIL: set %d, ucal_getMillis, status %s\n", iEra, u_errorName(status)); + } else if (date < 0) { + log_err("ERROR: set %d, ucal_getMillis should be positive, but get %.1f\n", iEra, date); + } + } else if (eYear != startYears[iEra]) { + log_err("ERROR: set %d, expected start year %d but get %d\n", iEra, startYears[iEra], eYear); + } else { + ucal_add(jCal, UCAL_ERA, 1, &status); + if ( U_FAILURE(status) ) { + log_err("FAIL: set %d, ucal_add ERA 1, status %s\n", iEra, u_errorName(status)); + } else { + eYear = ucal_get(jCal, UCAL_EXTENDED_YEAR, &status); + if ( U_FAILURE(status) ) { + log_err("FAIL: set %d then add ERA 1, ucal_get EXTENDED_YEAR, status %s\n", iEra, u_errorName(status)); + } else { + // If this is the last valid era, we expect adding an era to pin to the current era + int32_t nextEraStart = (startYears[iEra+1] == 0)? startYears[iEra]: startYears[iEra+1]; + if (eYear != nextEraStart) { + log_err("ERROR: set %d then add ERA 1, expected start year %d but get %d\n", iEra, nextEraStart, eYear); + } + } + } + } + } + } + ucal_close(jCal); + } } typedef struct { @@ -2506,6 +2616,37 @@ void TestClear() { } } +void TestPersianCalOverflow() { + const char * locale = "bs_Cyrl@calendar=persian"; + UErrorCode status = U_ZERO_ERROR; + UCalendar * ucal = ucal_open(NULL, 0, locale, UCAL_DEFAULT, &status); + if ( U_FAILURE(status) ) { + log_data_err("FAIL: ucal_open for locale %s, status %s\n", locale, u_errorName(status)); + } else { + int32_t maxMonth = ucal_getLimit(ucal, UCAL_MONTH, UCAL_MAXIMUM, &status); + int32_t maxDayOfMonth = ucal_getLimit(ucal, UCAL_DATE, UCAL_MAXIMUM, &status); + if ( U_FAILURE(status) ) { + log_err("FAIL: ucal_getLimit MONTH/DATE for locale %s, status %s\n", locale, u_errorName(status)); + } else { + int32_t jd, month, dayOfMonth; + for (jd = 67023580; jd <= 67023584; jd++) { // year 178171, int32_t overflow if jd >= 67023582 + status = U_ZERO_ERROR; + ucal_clear(ucal); + ucal_set(ucal, UCAL_JULIAN_DAY, jd); + month = ucal_get(ucal, UCAL_MONTH, &status); + dayOfMonth = ucal_get(ucal, UCAL_DATE, &status); + if ( U_FAILURE(status) ) { + log_err("FAIL: ucal_get MONTH/DATE for locale %s, julianDay %d, status %s\n", locale, jd, u_errorName(status)); + } else if (month > maxMonth || dayOfMonth > maxDayOfMonth) { + log_err("FAIL: locale %s, julianDay %d; maxMonth %d, got month %d; maxDayOfMonth %d, got dayOfMonth %d\n", + locale, jd, maxMonth, month, maxDayOfMonth, dayOfMonth); + } + } + } + ucal_close(ucal); + } +} + /* Apple-specific */ typedef struct { const char * locale;