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