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