• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /********************************************************************
2  * COPYRIGHT:
3  * Copyright (c) 1997-2010, International Business Machines Corporation and
4  * others. All Rights Reserved.
5  ********************************************************************/
6 /********************************************************************************
7 *
8 * File CDATTST.C
9 *
10 * Modification History:
11 *        Name                     Description
12 *     Madhu Katragadda               Creation
13 *********************************************************************************
14 */
15 
16 /* C API TEST FOR DATE FORMAT */
17 
18 #include "unicode/utypes.h"
19 
20 #if !UCONFIG_NO_FORMATTING
21 
22 #include "unicode/uloc.h"
23 #include "unicode/udat.h"
24 #include "unicode/ucal.h"
25 #include "unicode/unum.h"
26 #include "unicode/ustring.h"
27 #include "cintltst.h"
28 #include "cdattst.h"
29 #include "cformtst.h"
30 #include "cmemory.h"
31 
32 #include <math.h>
33 
34 static void TestExtremeDates(void);
35 static void TestAllLocales(void);
36 static void TestRelativeCrash(void);
37 
38 #define LEN(a) (sizeof(a)/sizeof(a[0]))
39 
40 void addDateForTest(TestNode** root);
41 
42 #define TESTCASE(x) addTest(root, &x, "tsformat/cdattst/" #x)
43 
addDateForTest(TestNode ** root)44 void addDateForTest(TestNode** root)
45 {
46     TESTCASE(TestDateFormat);
47     TESTCASE(TestRelativeDateFormat);
48     TESTCASE(TestSymbols);
49     TESTCASE(TestDateFormatCalendar);
50     TESTCASE(TestExtremeDates);
51     TESTCASE(TestAllLocales);
52     TESTCASE(TestRelativeCrash);
53 }
54 /* Testing the DateFormat API */
TestDateFormat()55 static void TestDateFormat()
56 {
57     UDateFormat *def, *fr, *it, *de, *def1, *fr_pat;
58     UDateFormat *any;
59     UDateFormat *copy;
60     UErrorCode status = U_ZERO_ERROR;
61     UChar* result = NULL;
62     const UCalendar *cal;
63     const UNumberFormat *numformat1, *numformat2;
64     UChar temp[50];
65     int32_t numlocales;
66     UDate d1;
67     int i;
68     int32_t resultlength;
69     int32_t resultlengthneeded;
70     int32_t parsepos;
71     UDate d = 837039928046.0;
72     double num = -10456.37;
73     /*const char* str="yyyy.MM.dd G 'at' hh:mm:ss z";
74     const char t[]="2/3/76 2:50 AM";*/
75     /*Testing udat_open() to open a dateformat */
76 
77     ctest_setTimeZone(NULL, &status);
78 
79     log_verbose("\nTesting udat_open() with various parameters\n");
80     fr = udat_open(UDAT_FULL, UDAT_DEFAULT, "fr_FR", NULL,0, NULL, 0,&status);
81     if(U_FAILURE(status))
82     {
83         log_data_err("FAIL: error in creating the dateformat using full time style with french locale -> %s (Are you missing data?)\n",
84             myErrorName(status) );
85         return;
86     }
87     /* this is supposed to open default date format, but later on it treats it like it is "en_US"
88        - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
89     /* def = udat_open(UDAT_SHORT, UDAT_SHORT, NULL, NULL, 0, &status); */
90     def = udat_open(UDAT_SHORT, UDAT_SHORT, "en_US", NULL, 0,NULL, 0, &status);
91     if(U_FAILURE(status))
92     {
93         log_err("FAIL: error in creating the dateformat using short date and time style\n %s\n",
94             myErrorName(status) );
95         return;
96     }
97     it = udat_open(UDAT_DEFAULT, UDAT_MEDIUM, "it_IT", NULL, 0, NULL, 0,&status);
98     if(U_FAILURE(status))
99     {
100         log_err("FAIL: error in creating the dateformat using medium date style with italian locale\n %s\n",
101             myErrorName(status) );
102         return;
103     }
104     de = udat_open(UDAT_LONG, UDAT_LONG, "de_DE", NULL, 0, NULL, 0,&status);
105     if(U_FAILURE(status))
106     {
107         log_err("FAIL: error in creating the dateformat using long time and date styles with german locale\n %s\n",
108             myErrorName(status));
109         return;
110     }
111     /*creating a default dateformat */
112     def1 = udat_open(UDAT_SHORT, UDAT_SHORT, NULL, NULL, 0,NULL, 0, &status);
113     if(U_FAILURE(status))
114     {
115         log_err("FAIL: error in creating the dateformat using short date and time style\n %s\n",
116             myErrorName(status) );
117         return;
118     }
119 
120 
121     /*Testing udat_getAvailable() and udat_countAvailable()*/
122     log_verbose("\nTesting getAvailableLocales and countAvailable()\n");
123     numlocales=udat_countAvailable();
124     /* use something sensible w/o hardcoding the count */
125     if(numlocales < 0)
126         log_data_err("FAIL: error in countAvailable\n");
127     log_verbose("The number of locales for which date/time formatting patterns are available is %d\n", numlocales);
128 
129     for(i=0;i<numlocales;i++) {
130       UErrorCode subStatus = U_ZERO_ERROR;
131       log_verbose("Testing open of %s\n", udat_getAvailable(i));
132       any = udat_open(UDAT_SHORT, UDAT_SHORT, udat_getAvailable(i), NULL ,0, NULL, 0, &subStatus);
133       if(U_FAILURE(subStatus)) {
134         log_data_err("FAIL: date format %s (getAvailable(%d)) is not instantiable: %s\n", udat_getAvailable(i), i, u_errorName(subStatus));
135       }
136       udat_close(any);
137     }
138 
139     /*Testing udat_clone()*/
140     log_verbose("\nTesting the udat_clone() function of date format\n");
141     copy=udat_clone(def, &status);
142     if(U_FAILURE(status)){
143         log_err("Error in creating the clone using udat_clone: %s\n", myErrorName(status) );
144     }
145     /*if(def != copy)
146         log_err("Error in udat_clone");*/ /*how should i check for equality???? */
147 
148     /*Testing udat_format()*/
149     log_verbose("\nTesting the udat_format() function of date format\n");
150     u_uastrcpy(temp, "7/10/96 4:05 PM");
151     /*format using def */
152     resultlength=0;
153     resultlengthneeded=udat_format(def, d, NULL, resultlength, NULL, &status);
154     if(status==U_BUFFER_OVERFLOW_ERROR)
155     {
156         status=U_ZERO_ERROR;
157         resultlength=resultlengthneeded+1;
158         if(result != NULL) {
159             free(result);
160             result = NULL;
161         }
162         result=(UChar*)malloc(sizeof(UChar) * resultlength);
163         udat_format(def, d, result, resultlength, NULL, &status);
164     }
165     if(U_FAILURE(status) || !result)
166     {
167         log_err("FAIL: Error in formatting using udat_format(.....) %s\n", myErrorName(status) );
168         return;
169     }
170     else
171         log_verbose("PASS: formatting successful\n");
172     if(u_strcmp(result, temp)==0)
173         log_verbose("PASS: Date Format for US locale successful using udat_format()\n");
174     else {
175         char xbuf[2048];
176         char gbuf[2048];
177         u_austrcpy(xbuf, temp);
178         u_austrcpy(gbuf, result);
179         log_err("FAIL: Date Format for US locale failed using udat_format() - expected %s got %s\n", xbuf, gbuf);
180     }
181     /*format using fr */
182 
183     u_unescape("10 juil. 1996 16:05:28 heure avanc\\u00E9e du Pacifique", temp, 50);
184     if(result != NULL) {
185         free(result);
186         result = NULL;
187     }
188     result=myDateFormat(fr, d);
189     if(u_strcmp(result, temp)==0)
190         log_verbose("PASS: Date Format for french locale successful using udat_format()\n");
191     else
192         log_data_err("FAIL: Date Format for french locale failed using udat_format().\n" );
193 
194     /*format using it */
195     u_uastrcpy(temp, "10/lug/1996 16:05:28");
196 
197     {
198         UChar *fmtted;
199         char g[100];
200         char x[100];
201 
202         fmtted = myDateFormat(it,d);
203         u_austrcpy(g, fmtted);
204         u_austrcpy(x, temp);
205         if(u_strcmp(fmtted, temp)==0) {
206             log_verbose("PASS: Date Format for italian locale successful uisng udat_format() - wanted %s, got %s\n", x, g);
207         } else {
208             log_data_err("FAIL: Date Format for italian locale failed using udat_format() - wanted %s, got %s\n", x, g);
209         }
210     }
211 
212     /*Testing parsing using udat_parse()*/
213     log_verbose("\nTesting parsing using udat_parse()\n");
214     u_uastrcpy(temp,"2/3/76 2:50 AM");
215     parsepos=0;
216     status=U_ZERO_ERROR;
217 
218     d1=udat_parse(def, temp, u_strlen(temp), &parsepos, &status);
219     if(U_FAILURE(status))
220     {
221         log_err("FAIL: Error in parsing using udat_parse(.....) %s\n", myErrorName(status) );
222     }
223     else
224         log_verbose("PASS: parsing succesful\n");
225     /*format it back and check for equality */
226 
227 
228     if(u_strcmp(myDateFormat(def, d1),temp)!=0)
229         log_err("FAIL: error in parsing\n");
230 
231     /*Testing parsing using udat_parse()*/
232     log_verbose("\nTesting parsing using udat_parse()\n");
233     u_uastrcpy(temp,"2/Don't parse this part");
234     status=U_ZERO_ERROR;
235 
236     d1=udat_parse(def, temp, u_strlen(temp), NULL, &status);
237     if(status != U_PARSE_ERROR)
238     {
239         log_err("FAIL: udat_parse(\"bad string\") passed when it should have failed\n");
240     }
241     else
242         log_verbose("PASS: parsing succesful\n");
243 
244 
245 
246     /*Testing udat_openPattern()  */
247     status=U_ZERO_ERROR;
248     log_verbose("\nTesting the udat_openPattern with a specified pattern\n");
249     /*for french locale */
250     fr_pat=udat_open(UDAT_IGNORE, UDAT_IGNORE,"fr_FR",NULL,0,temp, u_strlen(temp), &status);
251     if(U_FAILURE(status))
252     {
253         log_err("FAIL: Error in creating a date format using udat_openPattern \n %s\n",
254             myErrorName(status) );
255     }
256     else
257         log_verbose("PASS: creating dateformat using udat_openPattern() succesful\n");
258 
259 
260         /*Testing applyPattern and toPattern */
261     log_verbose("\nTesting applyPattern and toPattern()\n");
262     udat_applyPattern(def1, FALSE, temp, u_strlen(temp));
263     log_verbose("Extracting the pattern\n");
264 
265     resultlength=0;
266     resultlengthneeded=udat_toPattern(def1, FALSE, NULL, resultlength, &status);
267     if(status==U_BUFFER_OVERFLOW_ERROR)
268     {
269         status=U_ZERO_ERROR;
270         resultlength=resultlengthneeded + 1;
271         result=(UChar*)malloc(sizeof(UChar) * resultlength);
272         udat_toPattern(def1, FALSE, result, resultlength, &status);
273     }
274     if(U_FAILURE(status))
275     {
276         log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n",
277             myErrorName(status) );
278     }
279     if(u_strcmp(result, temp)!=0)
280         log_err("FAIL: Error in extracting the pattern\n");
281     else
282         log_verbose("PASS: applyPattern and toPattern work fine\n");
283 
284     if(result != NULL) {
285         free(result);
286         result = NULL;
287     }
288 
289 
290     /*Testing getter and setter functions*/
291     /*isLenient and setLenient()*/
292     log_verbose("\nTesting the isLenient and setLenient properties\n");
293     udat_setLenient(fr, udat_isLenient(it));
294     if(udat_isLenient(fr) != udat_isLenient(it))
295         log_err("ERROR: setLenient() failed\n");
296     else
297         log_verbose("PASS: setLenient() successful\n");
298 
299 
300     /*Test get2DigitYearStart set2DigitYearStart */
301     log_verbose("\nTesting the get and set 2DigitYearStart properties\n");
302     d1= udat_get2DigitYearStart(fr_pat,&status);
303     if(U_FAILURE(status)) {
304             log_err("ERROR: udat_get2DigitYearStart failed %s\n", myErrorName(status) );
305     }
306     status = U_ZERO_ERROR;
307     udat_set2DigitYearStart(def1 ,d1, &status);
308     if(U_FAILURE(status)) {
309         log_err("ERROR: udat_set2DigitYearStart failed %s\n", myErrorName(status) );
310     }
311     if(udat_get2DigitYearStart(fr_pat, &status) != udat_get2DigitYearStart(def1, &status))
312         log_err("FAIL: error in set2DigitYearStart\n");
313     else
314         log_verbose("PASS: set2DigitYearStart successful\n");
315     /*try setting it to another value */
316     udat_set2DigitYearStart(de, 2000.0, &status);
317     if(U_FAILURE(status)){
318         log_verbose("ERROR: udat_set2DigitYearStart failed %s\n", myErrorName(status) );
319     }
320     if(udat_get2DigitYearStart(de, &status) != 2000)
321         log_err("FAIL: error in set2DigitYearStart\n");
322     else
323         log_verbose("PASS: set2DigitYearStart successful\n");
324 
325 
326 
327     /*Test getNumberFormat() and setNumberFormat() */
328     log_verbose("\nTesting the get and set NumberFormat properties of date format\n");
329     numformat1=udat_getNumberFormat(fr_pat);
330     udat_setNumberFormat(def1, numformat1);
331     numformat2=udat_getNumberFormat(def1);
332     if(u_strcmp(myNumformat(numformat1, num), myNumformat(numformat2, num)) !=0)
333         log_err("FAIL: error in setNumberFormat or getNumberFormat()\n");
334     else
335         log_verbose("PASS:setNumberFormat and getNumberFormat succesful\n");
336 
337     /*try setting the number format to another format */
338     numformat1=udat_getNumberFormat(def);
339     udat_setNumberFormat(def1, numformat1);
340     numformat2=udat_getNumberFormat(def1);
341     if(u_strcmp(myNumformat(numformat1, num), myNumformat(numformat2, num)) !=0)
342         log_err("FAIL: error in setNumberFormat or getNumberFormat()\n");
343     else
344         log_verbose("PASS: setNumberFormat and getNumberFormat succesful\n");
345 
346 
347 
348     /*Test getCalendar and setCalendar*/
349     log_verbose("\nTesting the udat_getCalendar() and udat_setCalendar() properties\n");
350     cal=udat_getCalendar(fr_pat);
351 
352 
353     udat_setCalendar(def1, cal);
354     if(!ucal_equivalentTo(udat_getCalendar(fr_pat), udat_getCalendar(def1)))
355         log_err("FAIL: Error in setting and getting the calendar\n");
356     else
357         log_verbose("PASS: getting and setting calendar successful\n");
358 
359     if(result!=NULL) {
360         free(result);
361     }
362 
363     /*Closing the UDateForamt */
364     udat_close(def);
365     udat_close(fr);
366     udat_close(it);
367     udat_close(de);
368     udat_close(def1);
369     udat_close(fr_pat);
370     udat_close(copy);
371 
372     ctest_resetTimeZone();
373 }
374 
375 /*
376 Test combined relative date formatting (relative date + non-relative time).
377 This is a bit tricky since we can't have static test data for comparison, the
378 relative date formatting is relative to the time the tests are run. We generate
379 the data for comparison dynamically. However, the tests could fail if they are
380 run right at midnight Pacific time and the call to ucal_getNow() is before midnight
381 while the calls to udat_format are after midnight or span midnight.
382 */
383 static const UDate dayInterval = 24.0*60.0*60.0*1000.0;
384 static const UChar trdfZone[] = { 0x0055, 0x0053, 0x002F, 0x0050, 0x0061, 0x0063, 0x0069, 0x0066, 0x0069, 0x0063, 0 }; /* US/Pacific */
385 static const char trdfLocale[] = "en_US";
386 static const UChar minutesPatn[] = { 0x006D, 0x006D, 0 }; /* "mm" */
387 static const UChar monthLongPatn[] = { 0x004D, 0x004D, 0x004D, 0x004D, 0 }; /* "MMMM" */
388 static const UChar monthMediumPatn[] = { 0x004D, 0x004D, 0x004D, 0 }; /* "MMM" */
389 static const UChar monthShortPatn[] = { 0x004D, 0 }; /* "M" */
390 static const UDateFormatStyle dateStylesList[] = { UDAT_FULL, UDAT_LONG, UDAT_MEDIUM, UDAT_SHORT, UDAT_NONE };
391 static const UChar *monthPatnsList[] = { monthLongPatn, monthLongPatn, monthMediumPatn, monthShortPatn, NULL };
392 static const UChar newTimePatn[] = { 0x0048, 0x0048, 0x002C, 0x006D, 0x006D, 0 }; /* "HH,mm" */
393 static const UChar minutesStr[] = { 0x0034, 0x0039, 0 }; /* "49", minutes string to search for in output */
394 enum { kDateOrTimeOutMax = 96, kDateAndTimeOutMax = 192 };
395 
TestRelativeDateFormat()396 static void TestRelativeDateFormat()
397 {
398     UDate today = 0.0;
399     const UDateFormatStyle * stylePtr;
400     const UChar ** monthPtnPtr;
401     UErrorCode status = U_ZERO_ERROR;
402     UCalendar * ucal = ucal_open(trdfZone, -1, trdfLocale, UCAL_GREGORIAN, &status);
403     if ( U_SUCCESS(status) ) {
404         int32_t    year, month, day;
405         ucal_setMillis(ucal, ucal_getNow(), &status);
406         year = ucal_get(ucal, UCAL_YEAR, &status);
407         month = ucal_get(ucal, UCAL_MONTH, &status);
408         day = ucal_get(ucal, UCAL_DATE, &status);
409         ucal_setDateTime(ucal, year, month, day, 18, 49, 0, &status); /* set to today at 18:49:00 */
410         today = ucal_getMillis(ucal, &status);
411         ucal_close(ucal);
412     }
413     if ( U_FAILURE(status) || today == 0.0 ) {
414         log_data_err("Generate UDate for a specified time today fails, error %s - (Are you missing data?)\n", myErrorName(status) );
415         return;
416     }
417     for (stylePtr = dateStylesList, monthPtnPtr = monthPatnsList; *stylePtr != UDAT_NONE; ++stylePtr, ++monthPtnPtr) {
418         UDateFormat* fmtRelDateTime;
419         UDateFormat* fmtRelDate;
420         UDateFormat* fmtTime;
421         int32_t dayOffset, limit;
422         UFieldPosition fp;
423 		UChar   strDateTime[kDateAndTimeOutMax];
424 		UChar   strDate[kDateOrTimeOutMax];
425 		UChar   strTime[kDateOrTimeOutMax];
426 		UChar * strPtr;
427         int32_t dtpatLen;
428 
429         fmtRelDateTime = udat_open(UDAT_SHORT, *stylePtr | UDAT_RELATIVE, trdfLocale, trdfZone, -1, NULL, 0, &status);
430         if ( U_FAILURE(status) ) {
431             log_data_err("udat_open timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s (Are you missing data?)\n", *stylePtr, myErrorName(status) );
432             continue;
433         }
434         fmtRelDate = udat_open(UDAT_NONE, *stylePtr | UDAT_RELATIVE, trdfLocale, trdfZone, -1, NULL, 0, &status);
435         if ( U_FAILURE(status) ) {
436             log_err("udat_open timeStyle NONE dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
437             udat_close(fmtRelDateTime);
438             continue;
439         }
440         fmtTime = udat_open(UDAT_SHORT, UDAT_NONE, trdfLocale, trdfZone, -1, NULL, 0, &status);
441         if ( U_FAILURE(status) ) {
442             log_err("udat_open timeStyle SHORT dateStyle NONE fails, error %s\n", myErrorName(status) );
443             udat_close(fmtRelDateTime);
444             udat_close(fmtRelDate);
445             continue;
446         }
447 
448         dtpatLen = udat_toPatternRelativeDate(fmtRelDateTime, strDate, kDateAndTimeOutMax, &status);
449         if ( U_FAILURE(status) ) {
450         	log_err("udat_toPatternRelativeDate timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
451         	status = U_ZERO_ERROR;
452         } else if ( u_strstr(strDate, *monthPtnPtr) == NULL || dtpatLen != u_strlen(strDate) ) {
453         	log_err("udat_toPatternRelativeDate timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) date pattern incorrect\n", *stylePtr );
454         }
455         dtpatLen = udat_toPatternRelativeTime(fmtRelDateTime, strTime, kDateAndTimeOutMax, &status);
456         if ( U_FAILURE(status) ) {
457         	log_err("udat_toPatternRelativeTime timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
458         	status = U_ZERO_ERROR;
459         } else if ( u_strstr(strTime, minutesPatn) == NULL || dtpatLen != u_strlen(strTime) ) {
460         	log_err("udat_toPatternRelativeTime timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) time pattern incorrect\n", *stylePtr );
461         }
462         dtpatLen = udat_toPattern(fmtRelDateTime, FALSE, strDateTime, kDateAndTimeOutMax, &status);
463         if ( U_FAILURE(status) ) {
464         	log_err("udat_toPattern timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
465         	status = U_ZERO_ERROR;
466         } else if ( u_strstr(strDateTime, strDate) == NULL || u_strstr(strDateTime, strTime) == NULL || dtpatLen != u_strlen(strDateTime) ) {
467         	log_err("udat_toPattern timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) dateTime pattern incorrect\n", *stylePtr );
468         }
469         udat_applyPatternRelative(fmtRelDateTime, strDate, u_strlen(strDate), newTimePatn, u_strlen(newTimePatn), &status);
470         if ( U_FAILURE(status) ) {
471         	log_err("udat_applyPatternRelative timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
472         	status = U_ZERO_ERROR;
473         } else {
474         	udat_toPattern(fmtRelDateTime, FALSE, strDateTime, kDateAndTimeOutMax, &status);
475         	if ( U_FAILURE(status) ) {
476         		log_err("udat_toPattern timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
477         		status = U_ZERO_ERROR;
478         	} else if ( u_strstr(strDateTime, newTimePatn) == NULL ) {
479         		log_err("udat_applyPatternRelative timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) didn't update time pattern\n", *stylePtr );
480         	}
481         }
482         udat_applyPatternRelative(fmtRelDateTime, strDate, u_strlen(strDate), strTime, u_strlen(strTime), &status); /* restore original */
483 
484         fp.field = UDAT_MINUTE_FIELD;
485         for (dayOffset = -2, limit = 2; dayOffset <= limit; ++dayOffset) {
486             UDate   dateToUse = today + (float)dayOffset*dayInterval;
487 
488             udat_format(fmtRelDateTime, dateToUse, strDateTime, kDateAndTimeOutMax, &fp, &status);
489             if ( U_FAILURE(status) ) {
490                 log_err("udat_format timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
491                 status = U_ZERO_ERROR;
492             } else {
493                 udat_format(fmtRelDate, dateToUse, strDate, kDateOrTimeOutMax, NULL, &status);
494                 if ( U_FAILURE(status) ) {
495                     log_err("udat_format timeStyle NONE dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
496                     status = U_ZERO_ERROR;
497                 } else if ( u_strstr(strDateTime, strDate) == NULL ) {
498                     log_err("relative date string not found in udat_format timeStyle SHORT dateStyle (%d | UDAT_RELATIVE)\n", *stylePtr );
499                 }
500 
501                 udat_format(fmtTime, dateToUse, strTime, kDateOrTimeOutMax, NULL, &status);
502                 if ( U_FAILURE(status) ) {
503                     log_err("udat_format timeStyle SHORT dateStyle NONE fails, error %s\n", myErrorName(status) );
504                     status = U_ZERO_ERROR;
505                 } else if ( u_strstr(strDateTime, strTime) == NULL ) {
506                     log_err("time string not found in udat_format timeStyle SHORT dateStyle (%d | UDAT_RELATIVE)\n", *stylePtr );
507                 }
508 
509                 strPtr = u_strstr(strDateTime, minutesStr);
510                 if ( strPtr != NULL ) {
511                     int32_t beginIndex = strPtr - strDateTime;
512                     if ( fp.beginIndex != beginIndex ) {
513                         log_err("UFieldPosition beginIndex %d, expected %d, in udat_format timeStyle SHORT dateStyle (%d | UDAT_RELATIVE)\n", fp.beginIndex, beginIndex, *stylePtr );
514                     }
515                 } else {
516                     log_err("minutes string not found in udat_format timeStyle SHORT dateStyle (%d | UDAT_RELATIVE)\n", *stylePtr );
517                 }
518             }
519         }
520 
521         udat_close(fmtRelDateTime);
522         udat_close(fmtRelDate);
523         udat_close(fmtTime);
524      }
525 }
526 
527 /*Testing udat_getSymbols() and udat_setSymbols() and udat_countSymbols()*/
TestSymbols()528 static void TestSymbols()
529 {
530     UDateFormat *def, *fr;
531     UErrorCode status = U_ZERO_ERROR;
532     UChar *value=NULL;
533     UChar *result = NULL;
534     int32_t resultlength;
535     int32_t resultlengthout;
536     UChar *pattern;
537 
538 
539     /*creating a dateformat with french locale */
540     log_verbose("\ncreating a date format with french locale\n");
541     fr = udat_open(UDAT_FULL, UDAT_DEFAULT, "fr_FR", NULL, 0, NULL, 0, &status);
542     if(U_FAILURE(status))
543     {
544         log_data_err("error in creating the dateformat using full time style with french locale -> %s (Are you missing data?)\n",
545             myErrorName(status) );
546         return;
547     }
548     /*creating a default dateformat */
549     log_verbose("\ncreating a date format with default locale\n");
550     /* this is supposed to open default date format, but later on it treats it like it is "en_US"
551        - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
552     /* def = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,NULL, NULL, 0, &status); */
553     def = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,"en_US", NULL, 0, NULL, 0, &status);
554     if(U_FAILURE(status))
555     {
556         log_err("error in creating the dateformat using short date and time style\n %s\n",
557             myErrorName(status) );
558         return;
559     }
560 
561 
562     /*Testing countSymbols, getSymbols and setSymbols*/
563     log_verbose("\nTesting countSymbols\n");
564     /*since the month names has the last string empty and week names are 1 based 1.e first string in the weeknames array is empty */
565     if(udat_countSymbols(def, UDAT_ERAS)!=2 || udat_countSymbols(def, UDAT_MONTHS)!=12 ||
566         udat_countSymbols(def, UDAT_SHORT_MONTHS)!=12 || udat_countSymbols(def, UDAT_WEEKDAYS)!=8 ||
567         udat_countSymbols(def, UDAT_SHORT_WEEKDAYS)!=8 || udat_countSymbols(def, UDAT_AM_PMS)!=2 ||
568         udat_countSymbols(def, UDAT_QUARTERS) != 4 || udat_countSymbols(def, UDAT_SHORT_QUARTERS) != 4 ||
569         udat_countSymbols(def, UDAT_LOCALIZED_CHARS)!=1)
570     {
571         log_err("FAIL: error in udat_countSymbols\n");
572     }
573     else
574         log_verbose("PASS: udat_countSymbols() successful\n");
575 
576     /*testing getSymbols*/
577     log_verbose("\nTesting getSymbols\n");
578     pattern=(UChar*)malloc(sizeof(UChar) * 10);
579     u_uastrcpy(pattern, "jeudi");
580     resultlength=0;
581     resultlengthout=udat_getSymbols(fr, UDAT_WEEKDAYS, 5 , NULL, resultlength, &status);
582     if(status==U_BUFFER_OVERFLOW_ERROR)
583     {
584         status=U_ZERO_ERROR;
585         resultlength=resultlengthout+1;
586         if(result != NULL) {
587             free(result);
588             result = NULL;
589         }
590         result=(UChar*)malloc(sizeof(UChar) * resultlength);
591         udat_getSymbols(fr, UDAT_WEEKDAYS, 5, result, resultlength, &status);
592 
593     }
594     if(U_FAILURE(status))
595     {
596         log_err("FAIL: Error in udat_getSymbols().... %s\n", myErrorName(status) );
597     }
598     else
599         log_verbose("PASS: getSymbols succesful\n");
600 
601     if(u_strcmp(result, pattern)==0)
602         log_verbose("PASS: getSymbols retrieved the right value\n");
603     else
604         log_data_err("FAIL: getSymbols retrieved the wrong value\n");
605 
606     /*run series of tests to test getsymbols regressively*/
607     log_verbose("\nTesting getSymbols() regressively\n");
608     VerifygetSymbols(fr, UDAT_WEEKDAYS, 1, "dimanche");
609     VerifygetSymbols(def, UDAT_WEEKDAYS, 1, "Sunday");
610     VerifygetSymbols(fr, UDAT_SHORT_WEEKDAYS, 7, "sam.");
611     VerifygetSymbols(def, UDAT_SHORT_WEEKDAYS, 7, "Sat");
612     VerifygetSymbols(def, UDAT_MONTHS, 11, "December");
613     VerifygetSymbols(def, UDAT_MONTHS, 0, "January");
614     VerifygetSymbols(fr, UDAT_ERAS, 0, "av. J.-C.");
615     VerifygetSymbols(def, UDAT_AM_PMS, 0, "AM");
616     VerifygetSymbols(def, UDAT_AM_PMS, 1, "PM");
617     VerifygetSymbols(fr, UDAT_SHORT_MONTHS, 0, "janv.");
618     VerifygetSymbols(def, UDAT_SHORT_MONTHS, 11, "Dec");
619     VerifygetSymbols(fr, UDAT_QUARTERS, 0, "1er trimestre");
620     VerifygetSymbols(def, UDAT_QUARTERS, 3, "4th quarter");
621     VerifygetSymbols(fr, UDAT_SHORT_QUARTERS, 1, "T2");
622     VerifygetSymbols(def, UDAT_SHORT_QUARTERS, 2, "Q3");
623     VerifygetSymbols(def,UDAT_LOCALIZED_CHARS, 0, "GyMdkHmsSEDFwWahKzYeugAZvcLQqV");
624 
625 
626     if(result != NULL) {
627         free(result);
628         result = NULL;
629     }
630 free(pattern);
631 
632     log_verbose("\nTesting setSymbols\n");
633     /*applying the pattern so that setSymbolss works */
634     resultlength=0;
635     resultlengthout=udat_toPattern(fr, FALSE, NULL, resultlength, &status);
636     if(status==U_BUFFER_OVERFLOW_ERROR)
637     {
638         status=U_ZERO_ERROR;
639         resultlength=resultlengthout + 1;
640         pattern=(UChar*)malloc(sizeof(UChar) * resultlength);
641         udat_toPattern(fr, FALSE, pattern, resultlength, &status);
642     }
643     if(U_FAILURE(status))
644     {
645         log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n",
646             myErrorName(status) );
647     }
648 
649     udat_applyPattern(def, FALSE, pattern, u_strlen(pattern));
650     resultlength=0;
651     resultlengthout=udat_toPattern(def, FALSE, NULL, resultlength,&status);
652     if(status==U_BUFFER_OVERFLOW_ERROR)
653     {
654         status=U_ZERO_ERROR;
655         resultlength=resultlengthout + 1;
656         if(result != NULL) {
657             free(result);
658             result = NULL;
659         }
660         result=(UChar*)malloc(sizeof(UChar) * resultlength);
661         udat_toPattern(fr, FALSE,result, resultlength, &status);
662     }
663     if(U_FAILURE(status))
664     {
665         log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n",
666             myErrorName(status) );
667     }
668     if(u_strcmp(result, pattern)==0)
669         log_verbose("Pattern applied properly\n");
670     else
671         log_err("pattern could not be applied properly\n");
672 
673 free(pattern);
674     /*testing set symbols */
675     resultlength=0;
676     resultlengthout=udat_getSymbols(fr, UDAT_MONTHS, 11 , NULL, resultlength, &status);
677     if(status==U_BUFFER_OVERFLOW_ERROR){
678         status=U_ZERO_ERROR;
679         resultlength=resultlengthout+1;
680         if(result != NULL) {
681             free(result);
682             result = NULL;
683         }
684         result=(UChar*)malloc(sizeof(UChar) * resultlength);
685         udat_getSymbols(fr, UDAT_MONTHS, 11, result, resultlength, &status);
686 
687     }
688     if(U_FAILURE(status))
689         log_err("FAIL: error in getSymbols() %s\n", myErrorName(status) );
690     resultlength=resultlengthout+1;
691 
692     udat_setSymbols(def, UDAT_MONTHS, 11, result, resultlength, &status);
693     if(U_FAILURE(status))
694         {
695             log_err("FAIL: Error in udat_setSymbols() : %s\n", myErrorName(status) );
696         }
697     else
698         log_verbose("PASS: SetSymbols successful\n");
699 
700     resultlength=0;
701     resultlengthout=udat_getSymbols(def, UDAT_MONTHS, 11, NULL, resultlength, &status);
702     if(status==U_BUFFER_OVERFLOW_ERROR){
703         status=U_ZERO_ERROR;
704         resultlength=resultlengthout+1;
705         value=(UChar*)malloc(sizeof(UChar) * resultlength);
706         udat_getSymbols(def, UDAT_MONTHS, 11, value, resultlength, &status);
707     }
708     if(U_FAILURE(status))
709         log_err("FAIL: error in retrieving the value using getSymbols i.e roundtrip\n");
710 
711     if(u_strcmp(result, value)!=0)
712         log_data_err("FAIL: Error in settting and getting symbols\n");
713     else
714         log_verbose("PASS: setSymbols successful\n");
715 
716 
717     /*run series of tests to test setSymbols regressively*/
718     log_verbose("\nTesting setSymbols regressively\n");
719     VerifysetSymbols(def, UDAT_ERAS, 0, "BeforeChrist");
720     VerifysetSymbols(def, UDAT_ERA_NAMES, 1, "AnnoDomini");
721     VerifysetSymbols(def, UDAT_WEEKDAYS, 1, "Sundayweek");
722     VerifysetSymbols(def, UDAT_SHORT_WEEKDAYS, 7, "Satweek");
723     VerifysetSymbols(def, UDAT_NARROW_WEEKDAYS, 4, "M");
724     VerifysetSymbols(def, UDAT_STANDALONE_WEEKDAYS, 1, "Sonntagweek");
725     VerifysetSymbols(def, UDAT_STANDALONE_SHORT_WEEKDAYS, 7, "Sams");
726     VerifysetSymbols(def, UDAT_STANDALONE_NARROW_WEEKDAYS, 4, "V");
727     VerifysetSymbols(fr, UDAT_MONTHS, 11, "december");
728     VerifysetSymbols(fr, UDAT_SHORT_MONTHS, 0, "Jan");
729     VerifysetSymbols(fr, UDAT_NARROW_MONTHS, 1, "R");
730     VerifysetSymbols(fr, UDAT_STANDALONE_MONTHS, 11, "dezember");
731     VerifysetSymbols(fr, UDAT_STANDALONE_SHORT_MONTHS, 7, "Aug");
732     VerifysetSymbols(fr, UDAT_STANDALONE_NARROW_MONTHS, 2, "M");
733     VerifysetSymbols(fr, UDAT_QUARTERS, 0, "1. Quart");
734     VerifysetSymbols(fr, UDAT_SHORT_QUARTERS, 1, "QQ2");
735     VerifysetSymbols(fr, UDAT_STANDALONE_QUARTERS, 2, "3rd Quar.");
736     VerifysetSymbols(fr, UDAT_STANDALONE_SHORT_QUARTERS, 3, "4QQ");
737 
738 
739     /*run series of tests to test get and setSymbols regressively*/
740     log_verbose("\nTesting get and set symbols regressively\n");
741     VerifygetsetSymbols(fr, def, UDAT_WEEKDAYS, 1);
742     VerifygetsetSymbols(fr, def, UDAT_WEEKDAYS, 7);
743     VerifygetsetSymbols(fr, def, UDAT_SHORT_WEEKDAYS, 1);
744     VerifygetsetSymbols(fr, def, UDAT_SHORT_WEEKDAYS, 7);
745     VerifygetsetSymbols(fr, def, UDAT_MONTHS, 0);
746     VerifygetsetSymbols(fr, def, UDAT_SHORT_MONTHS, 0);
747     VerifygetsetSymbols(fr, def, UDAT_ERAS,1);
748     VerifygetsetSymbols(fr, def, UDAT_LOCALIZED_CHARS, 0);
749     VerifygetsetSymbols(fr, def, UDAT_AM_PMS, 1);
750 
751 
752     /*closing*/
753 
754     udat_close(fr);
755     udat_close(def);
756     if(result != NULL) {
757         free(result);
758         result = NULL;
759     }
760     free(value);
761 
762 }
763 
764 /**
765  * Test DateFormat(Calendar) API
766  */
TestDateFormatCalendar()767 static void TestDateFormatCalendar() {
768     UDateFormat *date=0, *time=0, *full=0;
769     UCalendar *cal=0;
770     UChar buf[256];
771     char cbuf[256];
772     int32_t pos;
773     UDate when;
774     UErrorCode ec = U_ZERO_ERROR;
775 
776     ctest_setTimeZone(NULL, &ec);
777 
778     /* Create a formatter for date fields. */
779     date = udat_open(UDAT_NONE, UDAT_SHORT, "en_US", NULL, 0, NULL, 0, &ec);
780     if (U_FAILURE(ec)) {
781         log_data_err("FAIL: udat_open(NONE, SHORT, en_US) failed with %s (Are you missing data?)\n",
782                 u_errorName(ec));
783         goto FAIL;
784     }
785 
786     /* Create a formatter for time fields. */
787     time = udat_open(UDAT_SHORT, UDAT_NONE, "en_US", NULL, 0, NULL, 0, &ec);
788     if (U_FAILURE(ec)) {
789         log_err("FAIL: udat_open(SHORT, NONE, en_US) failed with %s\n",
790                 u_errorName(ec));
791         goto FAIL;
792     }
793 
794     /* Create a full format for output */
795     full = udat_open(UDAT_FULL, UDAT_FULL, "en_US", NULL, 0, NULL, 0, &ec);
796     if (U_FAILURE(ec)) {
797         log_err("FAIL: udat_open(FULL, FULL, en_US) failed with %s\n",
798                 u_errorName(ec));
799         goto FAIL;
800     }
801 
802     /* Create a calendar */
803     cal = ucal_open(NULL, 0, "en_US", UCAL_GREGORIAN, &ec);
804     if (U_FAILURE(ec)) {
805         log_err("FAIL: ucal_open(en_US) failed with %s\n",
806                 u_errorName(ec));
807         goto FAIL;
808     }
809 
810     /* Parse the date */
811     ucal_clear(cal);
812     u_uastrcpy(buf, "4/5/2001");
813     pos = 0;
814     udat_parseCalendar(date, cal, buf, -1, &pos, &ec);
815     if (U_FAILURE(ec)) {
816         log_err("FAIL: udat_parseCalendar(4/5/2001) failed at %d with %s\n",
817                 pos, u_errorName(ec));
818         goto FAIL;
819     }
820 
821     /* Parse the time */
822     u_uastrcpy(buf, "5:45 PM");
823     pos = 0;
824     udat_parseCalendar(time, cal, buf, -1, &pos, &ec);
825     if (U_FAILURE(ec)) {
826         log_err("FAIL: udat_parseCalendar(17:45) failed at %d with %s\n",
827                 pos, u_errorName(ec));
828         goto FAIL;
829     }
830 
831     /* Check result */
832     when = ucal_getMillis(cal, &ec);
833     if (U_FAILURE(ec)) {
834         log_err("FAIL: ucal_getMillis() failed with %s\n", u_errorName(ec));
835         goto FAIL;
836     }
837     udat_format(full, when, buf, sizeof(buf), NULL, &ec);
838     if (U_FAILURE(ec)) {
839         log_err("FAIL: udat_format() failed with %s\n", u_errorName(ec));
840         goto FAIL;
841     }
842     u_austrcpy(cbuf, buf);
843     /* Thursday, April 5, 2001 5:45:00 PM PDT 986517900000 */
844     if (when == 986517900000.0) {
845         log_verbose("Ok: Parsed result: %s\n", cbuf);
846     } else {
847         log_err("FAIL: Parsed result: %s, exp 4/5/2001 5:45 PM\n", cbuf);
848     }
849 
850  FAIL:
851     udat_close(date);
852     udat_close(time);
853     udat_close(full);
854     ucal_close(cal);
855 
856     ctest_resetTimeZone();
857 }
858 
859 /*INTERNAL FUNCTIONS USED*/
860 /* N.B.:  use idx instead of index to avoid 'shadow' warnings in strict mode. */
VerifygetSymbols(UDateFormat * datfor,UDateFormatSymbolType type,int32_t idx,const char * expected)861 static void VerifygetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, int32_t idx, const char* expected)
862 {
863     UChar *pattern=NULL;
864     UErrorCode status = U_ZERO_ERROR;
865     UChar *result=NULL;
866     int32_t resultlength, resultlengthout;
867 
868 
869     pattern=(UChar*)malloc(sizeof(UChar) * (strlen(expected)+1));
870     u_uastrcpy(pattern, expected);
871     resultlength=0;
872     resultlengthout=udat_getSymbols(datfor, type, idx , NULL, resultlength, &status);
873     if(status==U_BUFFER_OVERFLOW_ERROR)
874     {
875         status=U_ZERO_ERROR;
876         resultlength=resultlengthout+1;
877         result=(UChar*)malloc(sizeof(UChar) * resultlength);
878         udat_getSymbols(datfor, type, idx, result, resultlength, &status);
879 
880     }
881     if(U_FAILURE(status))
882     {
883         log_err("FAIL: Error in udat_getSymbols()... %s\n", myErrorName(status) );
884         return;
885     }
886     if(u_strcmp(result, pattern)==0)
887         log_verbose("PASS: getSymbols retrieved the right value\n");
888     else{
889         log_data_err("FAIL: getSymbols retrieved the wrong value\n Expected %s Got %s\n", austrdup(pattern),
890             austrdup(result) );
891     }
892     free(result);
893     free(pattern);
894 }
895 
VerifysetSymbols(UDateFormat * datfor,UDateFormatSymbolType type,int32_t idx,const char * expected)896 static void VerifysetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, int32_t idx, const char* expected)
897 {
898     UChar *result=NULL;
899     UChar *value=NULL;
900     int32_t resultlength, resultlengthout;
901     UErrorCode status = U_ZERO_ERROR;
902 
903     value=(UChar*)malloc(sizeof(UChar) * (strlen(expected) + 1));
904     u_uastrcpy(value, expected);
905     udat_setSymbols(datfor, type, idx, value, u_strlen(value), &status);
906     if(U_FAILURE(status))
907         {
908             log_err("FAIL: Error in udat_setSymbols()  %s\n", myErrorName(status) );
909             return;
910         }
911 
912     resultlength=0;
913     resultlengthout=udat_getSymbols(datfor, type, idx, NULL, resultlength, &status);
914     if(status==U_BUFFER_OVERFLOW_ERROR){
915         status=U_ZERO_ERROR;
916         resultlength=resultlengthout+1;
917         result=(UChar*)malloc(sizeof(UChar) * resultlength);
918         udat_getSymbols(datfor, type, idx, result, resultlength, &status);
919     }
920     if(U_FAILURE(status)){
921         log_err("FAIL: error in retrieving the value using getSymbols after setting it previously\n %s\n",
922             myErrorName(status) );
923         return;
924     }
925 
926     if(u_strcmp(result, value)!=0){
927         log_err("FAIL:Error in setting and then getting symbols\n Expected %s Got %s\n", austrdup(value),
928             austrdup(result) );
929     }
930     else
931         log_verbose("PASS: setSymbols successful\n");
932 
933     free(value);
934     free(result);
935 }
936 
937 
VerifygetsetSymbols(UDateFormat * from,UDateFormat * to,UDateFormatSymbolType type,int32_t idx)938 static void VerifygetsetSymbols(UDateFormat* from, UDateFormat* to, UDateFormatSymbolType type, int32_t idx)
939 {
940     UChar *result=NULL;
941     UChar *value=NULL;
942     int32_t resultlength, resultlengthout;
943     UErrorCode status = U_ZERO_ERROR;
944 
945     resultlength=0;
946     resultlengthout=udat_getSymbols(from, type, idx , NULL, resultlength, &status);
947     if(status==U_BUFFER_OVERFLOW_ERROR){
948         status=U_ZERO_ERROR;
949         resultlength=resultlengthout+1;
950         result=(UChar*)malloc(sizeof(UChar) * resultlength);
951         udat_getSymbols(from, type, idx, result, resultlength, &status);
952     }
953     if(U_FAILURE(status)){
954         log_err("FAIL: error in getSymbols() %s\n", myErrorName(status) );
955         return;
956     }
957 
958     resultlength=resultlengthout+1;
959     udat_setSymbols(to, type, idx, result, resultlength, &status);
960     if(U_FAILURE(status))
961         {
962             log_err("FAIL: Error in udat_setSymbols() : %s\n", myErrorName(status) );
963             return;
964         }
965 
966     resultlength=0;
967     resultlengthout=udat_getSymbols(to, type, idx, NULL, resultlength, &status);
968     if(status==U_BUFFER_OVERFLOW_ERROR){
969         status=U_ZERO_ERROR;
970         resultlength=resultlengthout+1;
971         value=(UChar*)malloc(sizeof(UChar) * resultlength);
972         udat_getSymbols(to, type, idx, value, resultlength, &status);
973     }
974     if(U_FAILURE(status)){
975         log_err("FAIL: error in retrieving the value using getSymbols i.e roundtrip\n %s\n",
976             myErrorName(status) );
977         return;
978     }
979 
980     if(u_strcmp(result, value)!=0){
981         log_data_err("FAIL:Error in setting and then getting symbols\n Expected %s Got %s\n", austrdup(result),
982             austrdup(value) );
983     }
984     else
985         log_verbose("PASS: setSymbols successful\n");
986 
987     free(value);
988     free(result);
989 }
990 
991 
myNumformat(const UNumberFormat * numfor,double d)992 static UChar* myNumformat(const UNumberFormat* numfor, double d)
993 {
994     UChar *result2=NULL;
995     int32_t resultlength, resultlengthneeded;
996     UErrorCode status = U_ZERO_ERROR;
997 
998     resultlength=0;
999     resultlengthneeded=unum_formatDouble(numfor, d, NULL, resultlength, NULL, &status);
1000     if(status==U_BUFFER_OVERFLOW_ERROR)
1001     {
1002         status=U_ZERO_ERROR;
1003         resultlength=resultlengthneeded+1;
1004         /*result2=(UChar*)malloc(sizeof(UChar) * resultlength);*/ /* this leaks */
1005         result2=(UChar*)ctst_malloc(sizeof(UChar) * resultlength); /*this won't*/
1006         unum_formatDouble(numfor, d, result2, resultlength, NULL, &status);
1007     }
1008     if(U_FAILURE(status))
1009     {
1010         log_err("FAIL: Error in formatting using unum_format(.....) %s\n", myErrorName(status) );
1011         return 0;
1012     }
1013 
1014     return result2;
1015 }
1016 
1017 /**
1018  * The search depth for TestExtremeDates.  The total number of
1019  * dates that will be tested is (2^EXTREME_DATES_DEPTH) - 1.
1020  */
1021 #define EXTREME_DATES_DEPTH 8
1022 
1023 /**
1024  * Support for TestExtremeDates (below).
1025  *
1026  * Test a single date to see whether udat_format handles it properly.
1027  */
_aux1ExtremeDates(UDateFormat * fmt,UDate date,UChar * buf,int32_t buflen,char * cbuf,UErrorCode * ec)1028 static UBool _aux1ExtremeDates(UDateFormat* fmt, UDate date,
1029                                UChar* buf, int32_t buflen, char* cbuf,
1030                                UErrorCode* ec) {
1031     int32_t len = udat_format(fmt, date, buf, buflen, 0, ec);
1032     if (!assertSuccess("udat_format", ec)) return FALSE;
1033     u_austrncpy(cbuf, buf, buflen);
1034     if (len < 4) {
1035         log_err("FAIL: udat_format(%g) => \"%s\"\n", date, cbuf);
1036     } else {
1037         log_verbose("udat_format(%g) => \"%s\"\n", date, cbuf);
1038     }
1039     return TRUE;
1040 }
1041 
1042 /**
1043  * Support for TestExtremeDates (below).
1044  *
1045  * Recursively test between 'small' and 'large', up to the depth
1046  * limit specified by EXTREME_DATES_DEPTH.
1047  */
_aux2ExtremeDates(UDateFormat * fmt,UDate small,UDate large,UChar * buf,int32_t buflen,char * cbuf,int32_t count,UErrorCode * ec)1048 static UBool _aux2ExtremeDates(UDateFormat* fmt, UDate small, UDate large,
1049                                UChar* buf, int32_t buflen, char* cbuf,
1050                                int32_t count,
1051                                UErrorCode* ec) {
1052     /* Logarithmic midpoint; see below */
1053     UDate mid = (UDate) exp((log(small) + log(large)) / 2);
1054     if (count == EXTREME_DATES_DEPTH) {
1055         return TRUE;
1056     }
1057     return
1058         _aux1ExtremeDates(fmt, mid, buf, buflen, cbuf, ec) &&
1059         _aux2ExtremeDates(fmt, small, mid, buf, buflen, cbuf, count+1, ec) &&
1060         _aux2ExtremeDates(fmt, mid, large, buf, buflen, cbuf, count+1, ec);
1061 }
1062 
1063 /**
1064  * http://www.jtcsv.com/cgibin/icu-bugs?findid=3659
1065  *
1066  * For certain large dates, udat_format crashes on MacOS.  This test
1067  * attempts to reproduce this problem by doing a recursive logarithmic*
1068  * binary search of a predefined interval (from 'small' to 'large').
1069  *
1070  * The limit of the search is given by EXTREME_DATES_DEPTH, above.
1071  *
1072  * *The search has to be logarithmic, not linear.  A linear search of the
1073  *  range 0..10^30, for example, will find 0.5*10^30, then 0.25*10^30 and
1074  *  0.75*10^30, etc.  A logarithmic search will find 10^15, then 10^7.5
1075  *  and 10^22.5, etc.
1076  */
TestExtremeDates()1077 static void TestExtremeDates() {
1078     UDateFormat *fmt;
1079     UErrorCode ec;
1080     UChar buf[256];
1081     char cbuf[256];
1082     const double small = 1000; /* 1 sec */
1083     const double large = 1e+30; /* well beyond usable UDate range */
1084 
1085     /* There is no need to test larger values from 1e+30 to 1e+300;
1086        the failures occur around 1e+27, and never above 1e+30. */
1087 
1088     ec = U_ZERO_ERROR;
1089     fmt = udat_open(UDAT_LONG, UDAT_LONG, "en_US",
1090                     0, 0, 0, 0, &ec);
1091     if (U_FAILURE(ec)) {
1092         log_data_err("FAIL: udat_open (%s) (Are you missing data?)\n", u_errorName(ec));
1093         return;
1094     }
1095 
1096     _aux2ExtremeDates(fmt, small, large, buf, LEN(buf), cbuf, 0, &ec);
1097 
1098     udat_close(fmt);
1099 }
1100 
TestAllLocales(void)1101 static void TestAllLocales(void) {
1102     int32_t idx, dateIdx, timeIdx, localeCount;
1103     static const UDateFormatStyle style[] = {
1104         UDAT_FULL, UDAT_LONG, UDAT_MEDIUM, UDAT_SHORT
1105     };
1106     localeCount = uloc_countAvailable();
1107     for (idx = 0; idx < localeCount; idx++) {
1108         for (dateIdx = 0; dateIdx < (int32_t)(sizeof(style)/sizeof(style[0])); dateIdx++) {
1109             for (timeIdx = 0; timeIdx < (int32_t)(sizeof(style)/sizeof(style[0])); timeIdx++) {
1110                 UErrorCode status = U_ZERO_ERROR;
1111                 udat_close(udat_open(style[dateIdx], style[timeIdx],
1112                     uloc_getAvailable(idx), NULL, 0, NULL, 0, &status));
1113                 if (U_FAILURE(status)) {
1114                     log_err("FAIL: udat_open(%s) failed with (%s) dateIdx=%d, timeIdx=%d\n",
1115                         uloc_getAvailable(idx), u_errorName(status), dateIdx, timeIdx);
1116                 }
1117             }
1118         }
1119     }
1120 }
1121 
TestRelativeCrash(void)1122 static void TestRelativeCrash(void) {
1123        static const UChar tzName[] = { 0x0055, 0x0053, 0x002F, 0x0050, 0x0061, 0x0063, 0x0069, 0x0066, 0x0069, 0x0063, 0 };
1124        static const UDate aDate = -631152000000.0;
1125 
1126     UErrorCode status = U_ZERO_ERROR;
1127     UErrorCode expectStatus = U_ILLEGAL_ARGUMENT_ERROR;
1128     UDateFormat icudf;
1129 
1130     icudf = udat_open(UDAT_NONE, UDAT_SHORT_RELATIVE, "en", tzName, -1, NULL, 0, &status);
1131     if ( U_SUCCESS(status) ) {
1132         const char *what = "???";
1133         {
1134             UErrorCode subStatus = U_ZERO_ERROR;
1135             what = "udat_set2DigitYearStart";
1136             log_verbose("Trying %s on a relative date..\n", what);
1137             udat_set2DigitYearStart(icudf, aDate, &subStatus);
1138             if(subStatus == expectStatus) {
1139                 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1140             } else {
1141                 log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
1142             }
1143         }
1144         {
1145             /* clone works polymorphically. try it anyways */
1146             UErrorCode subStatus = U_ZERO_ERROR;
1147             UDateFormat *oth;
1148             what = "clone";
1149             log_verbose("Trying %s on a relative date..\n", what);
1150             oth = udat_clone(icudf, &subStatus);
1151             if(subStatus == U_ZERO_ERROR) {
1152                 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1153                 udat_close(oth); /* ? */
1154             } else {
1155                 log_err("FAIL: didn't crash on %s, but got  %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
1156             }
1157         }
1158         {
1159             UErrorCode subStatus = U_ZERO_ERROR;
1160             what = "udat_get2DigitYearStart";
1161             log_verbose("Trying %s on a relative date..\n", what);
1162             udat_get2DigitYearStart(icudf, &subStatus);
1163             if(subStatus == expectStatus) {
1164                 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1165             } else {
1166                 log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
1167             }
1168         }
1169         {
1170             /* Now udat_toPattern works for relative date formatters, unless localized is TRUE */
1171             UErrorCode subStatus = U_ZERO_ERROR;
1172             what = "udat_toPattern";
1173             log_verbose("Trying %s on a relative date..\n", what);
1174             udat_toPattern(icudf, TRUE,NULL,0, &subStatus);
1175             if(subStatus == expectStatus) {
1176                 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1177             } else {
1178                 log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
1179             }
1180         }
1181         {
1182             UErrorCode subStatus = U_ZERO_ERROR;
1183             what = "udat_applyPattern";
1184             log_verbose("Trying %s on a relative date..\n", what);
1185             udat_applyPattern(icudf, FALSE,tzName,-1);
1186             subStatus = U_ILLEGAL_ARGUMENT_ERROR; /* what it should be, if this took an errorcode. */
1187             if(subStatus == expectStatus) {
1188                 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1189             } else {
1190                 log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
1191             }
1192         }
1193         {
1194             UErrorCode subStatus = U_ZERO_ERROR;
1195             what = "udat_getSymbols";
1196             log_verbose("Trying %s on a relative date..\n", what);
1197             udat_getSymbols(icudf, UDAT_ERAS,0,NULL,0, &subStatus);  /* bogus values */
1198             if(subStatus == expectStatus) {
1199                 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1200             } else {
1201                 log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
1202             }
1203         }
1204         {
1205             UErrorCode subStatus = U_ZERO_ERROR;
1206             UChar symbolValue = 0x0041;
1207             what = "udat_setSymbols";
1208             log_verbose("Trying %s on a relative date..\n", what);
1209             udat_setSymbols(icudf, UDAT_ERAS,0,&symbolValue,1, &subStatus);  /* bogus values */
1210             if(subStatus == expectStatus) {
1211                 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1212             } else {
1213                 log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
1214             }
1215         }
1216         {
1217             UErrorCode subStatus = U_ZERO_ERROR;
1218             what = "udat_countSymbols";
1219             log_verbose("Trying %s on a relative date..\n", what);
1220             udat_countSymbols(icudf, UDAT_ERAS);
1221             subStatus = U_ILLEGAL_ARGUMENT_ERROR; /* should have an errorcode. */
1222             if(subStatus == expectStatus) {
1223                 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1224             } else {
1225                 log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
1226             }
1227         }
1228 
1229         udat_close(icudf);
1230     } else {
1231          log_data_err("FAIL: err calling udat_open() ->%s (Are you missing data?)\n", u_errorName(status));
1232     }
1233 }
1234 
1235 #endif /* #if !UCONFIG_NO_FORMATTING */
1236