1/********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1999-2012, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6
7#if defined(hpux)
8# ifndef _INCLUDE_POSIX_SOURCE
9#  define _INCLUDE_POSIX_SOURCE
10# endif
11#endif
12
13#include "simplethread.h"
14
15#include "unicode/utypes.h"
16#include "unicode/ustring.h"
17#include "umutex.h"
18#include "cmemory.h"
19#include "cstring.h"
20#include "uparse.h"
21#include "unicode/localpointer.h"
22#include "unicode/resbund.h"
23#include "unicode/udata.h"
24#include "unicode/uloc.h"
25#include "unicode/locid.h"
26#include "putilimp.h"
27#include "intltest.h"
28#include "tsmthred.h"
29#include "unicode/ushape.h"
30
31
32#if U_PLATFORM_USES_ONLY_WIN32_API
33    /* Prefer native Windows APIs even if POSIX is implemented (i.e., on Cygwin). */
34#   undef POSIX
35#elif U_PLATFORM_IMPLEMENTS_POSIX
36#   define POSIX
37#else
38#   undef POSIX
39#endif
40
41
42#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
43/* Needed by z/OS to get usleep */
44#if U_PLATFORM == U_PF_OS390
45#define __DOT1 1
46#define __UU
47#ifndef _XPG4_2
48#define _XPG4_2
49#endif
50#include <unistd.h>
51#endif
52#if defined(POSIX)
53
54#define HAVE_IMP
55
56#if (ICU_USE_THREADS == 1)
57#include <pthread.h>
58#endif
59
60#if defined(__hpux) && defined(HPUX_CMA)
61# if defined(read)  // read being defined as cma_read causes trouble with iostream::read
62#  undef read
63# endif
64#endif
65
66/* Define __EXTENSIONS__ for Solaris and old friends in strict mode. */
67#ifndef __EXTENSIONS__
68#define __EXTENSIONS__
69#endif
70
71#if U_PLATFORM == U_PF_OS390
72#include <sys/types.h>
73#endif
74
75#if U_PLATFORM != U_PF_OS390
76#include <signal.h>
77#endif
78
79/* Define _XPG4_2 for Solaris and friends. */
80#ifndef _XPG4_2
81#define _XPG4_2
82#endif
83
84/* Define __USE_XOPEN_EXTENDED for Linux and glibc. */
85#ifndef __USE_XOPEN_EXTENDED
86#define __USE_XOPEN_EXTENDED
87#endif
88
89/* Define _INCLUDE_XOPEN_SOURCE_EXTENDED for HP/UX (11?). */
90#ifndef _INCLUDE_XOPEN_SOURCE_EXTENDED
91#define _INCLUDE_XOPEN_SOURCE_EXTENDED
92#endif
93
94#include <unistd.h>
95
96#endif
97/* HPUX */
98#ifdef sleep
99#undef sleep
100#endif
101
102#define TSMTHREAD_FAIL(msg) errln("%s at file %s, line %d", msg, __FILE__, __LINE__)
103#define TSMTHREAD_ASSERT(expr) {if (!(expr)) {TSMTHREAD_FAIL("Fail");}}
104
105MultithreadTest::MultithreadTest()
106{
107}
108
109MultithreadTest::~MultithreadTest()
110{
111}
112
113
114
115#if (ICU_USE_THREADS==0)
116void MultithreadTest::runIndexedTest( int32_t index, UBool exec,
117                const char* &name, char* /*par*/ ) {
118  if (exec) logln("TestSuite MultithreadTest: ");
119
120  if(index == 0)
121      name = "NO_THREADED_TESTS";
122  else
123      name = "";
124
125  if(exec) { logln("MultithreadTest - test DISABLED.  ICU_USE_THREADS set to 0, check your configuration if this is a problem..");
126  }
127}
128#else
129
130#include <stdio.h>
131#include <string.h>
132#include <ctype.h>    // tolower, toupper
133
134#include "unicode/putil.h"
135
136// for mthreadtest
137#include "unicode/numfmt.h"
138#include "unicode/choicfmt.h"
139#include "unicode/msgfmt.h"
140#include "unicode/locid.h"
141#include "unicode/coll.h"
142#include "unicode/calendar.h"
143#include "ucaconf.h"
144
145void SimpleThread::errorFunc() {
146    // *(char *)0 = 3;            // Force entry into a debugger via a crash;
147}
148
149void MultithreadTest::runIndexedTest( int32_t index, UBool exec,
150                const char* &name, char* /*par*/ ) {
151    if (exec)
152        logln("TestSuite MultithreadTest: ");
153    switch (index) {
154    case 0:
155        name = "TestThreads";
156        if (exec)
157            TestThreads();
158        break;
159
160    case 1:
161        name = "TestMutex";
162        if (exec)
163            TestMutex();
164        break;
165
166    case 2:
167        name = "TestThreadedIntl";
168#if !UCONFIG_NO_FORMATTING
169        if (exec) {
170            TestThreadedIntl();
171        }
172#endif
173        break;
174
175    case 3:
176      name = "TestCollators";
177#if !UCONFIG_NO_COLLATION
178      if (exec) {
179            TestCollators();
180      }
181#endif /* #if !UCONFIG_NO_COLLATION */
182      break;
183
184    case 4:
185        name = "TestString";
186        if (exec) {
187            TestString();
188        }
189        break;
190
191	case 5:
192        name = "TestArabicShapingThreads";
193        if (exec) {
194            TestArabicShapingThreads();
195        }
196        break;
197
198
199    default:
200        name = "";
201        break; //needed to end loop
202    }
203}
204
205
206//-----------------------------------------------------------------------------------
207//
208//   TestThreads -- see if threads really work at all.
209//
210//   Set up N threads pointing at N chars. When they are started, they will
211//   each sleep 1 second and then set their chars. At the end we make sure they
212//   are all set.
213//
214//-----------------------------------------------------------------------------------
215#define THREADTEST_NRTHREADS 8
216#define ARABICSHAPE_THREADTEST 30
217
218class TestThreadsThread : public SimpleThread
219{
220public:
221    TestThreadsThread(char* whatToChange) { fWhatToChange = whatToChange; }
222    virtual void run() { SimpleThread::sleep(1000);
223                         Mutex m;
224                         *fWhatToChange = '*';
225    }
226private:
227    char *fWhatToChange;
228};
229//-----------------------------------------------------------------------------------
230//
231//   TestArabicShapeThreads -- see if calls to u_shapeArabic in many threads works successfully
232//
233//   Set up N threads pointing at N chars. When they are started, they will make calls to doTailTest which tests
234//   u_shapeArabic, if the calls are successful it will the set * chars.
235//   At the end we make sure all threads managed to run u_shapeArabic successfully.
236//   This is a unit test for ticket 9473
237//
238//-----------------------------------------------------------------------------------
239class TestArabicShapeThreads : public SimpleThread
240{
241public:
242    TestArabicShapeThreads(char* whatToChange) { fWhatToChange = whatToChange;}
243    virtual void run() {
244	    if(doTailTest()==TRUE)
245			*fWhatToChange = '*';
246    }
247private:
248    char *fWhatToChange;
249
250	UBool doTailTest(void) {
251  static const UChar src[] = { 0x0020, 0x0633, 0 };
252  static const UChar dst_old[] = { 0xFEB1, 0x200B,0 };
253  static const UChar dst_new[] = { 0xFEB1, 0xFE73,0 };
254  UChar dst[3] = { 0x0000, 0x0000,0 };
255  int32_t length;
256  UErrorCode status;
257  IntlTest inteltst =  IntlTest();
258
259  status = U_ZERO_ERROR;
260  length = u_shapeArabic(src, -1, dst, LENGTHOF(dst),
261                         U_SHAPE_LETTERS_SHAPE|U_SHAPE_SEEN_TWOCELL_NEAR, &status);
262  if(U_FAILURE(status)) {
263	   inteltst.errln("Fail: status %s\n", u_errorName(status));
264	return FALSE;
265  } else if(length!=2) {
266    inteltst.errln("Fail: len %d expected 3\n", length);
267	return FALSE;
268  } else if(u_strncmp(dst,dst_old,LENGTHOF(dst))) {
269    inteltst.errln("Fail: got U+%04X U+%04X expected U+%04X U+%04X\n",
270            dst[0],dst[1],dst_old[0],dst_old[1]);
271	return FALSE;
272  }
273
274
275  //"Trying new tail
276  status = U_ZERO_ERROR;
277  length = u_shapeArabic(src, -1, dst, LENGTHOF(dst),
278                         U_SHAPE_LETTERS_SHAPE|U_SHAPE_SEEN_TWOCELL_NEAR|U_SHAPE_TAIL_NEW_UNICODE, &status);
279  if(U_FAILURE(status)) {
280    inteltst.errln("Fail: status %s\n", u_errorName(status));
281	return FALSE;
282  } else if(length!=2) {
283    inteltst.errln("Fail: len %d expected 3\n", length);
284	return FALSE;
285  } else if(u_strncmp(dst,dst_new,LENGTHOF(dst))) {
286    inteltst.errln("Fail: got U+%04X U+%04X expected U+%04X U+%04X\n",
287            dst[0],dst[1],dst_new[0],dst_new[1]);
288	return FALSE;
289  }
290
291
292  return TRUE;
293
294}
295
296
297};
298
299void MultithreadTest::TestThreads()
300{
301    char threadTestChars[THREADTEST_NRTHREADS + 1];
302    SimpleThread *threads[THREADTEST_NRTHREADS];
303    int32_t numThreadsStarted = 0;
304
305    int32_t i;
306    for(i=0;i<THREADTEST_NRTHREADS;i++)
307    {
308        threadTestChars[i] = ' ';
309        threads[i] = new TestThreadsThread(&threadTestChars[i]);
310    }
311    threadTestChars[THREADTEST_NRTHREADS] = '\0';
312
313    logln("->" + UnicodeString(threadTestChars) + "<- Firing off threads.. ");
314    for(i=0;i<THREADTEST_NRTHREADS;i++)
315    {
316        if (threads[i]->start() != 0) {
317            errln("Error starting thread %d", i);
318        }
319        else {
320            numThreadsStarted++;
321        }
322        SimpleThread::sleep(100);
323        logln(" Subthread started.");
324    }
325
326    logln("Waiting for threads to be set..");
327    if (numThreadsStarted == 0) {
328        errln("No threads could be started for testing!");
329        return;
330    }
331
332    int32_t patience = 40; // seconds to wait
333
334    while(patience--)
335    {
336        int32_t count = 0;
337        umtx_lock(NULL);
338        for(i=0;i<THREADTEST_NRTHREADS;i++)
339        {
340            if(threadTestChars[i] == '*')
341            {
342                count++;
343            }
344        }
345        umtx_unlock(NULL);
346
347        if(count == THREADTEST_NRTHREADS)
348        {
349            logln("->" + UnicodeString(threadTestChars) + "<- Got all threads! cya");
350            for(i=0;i<THREADTEST_NRTHREADS;i++)
351            {
352                delete threads[i];
353            }
354            return;
355        }
356
357        logln("->" + UnicodeString(threadTestChars) + "<- Waiting..");
358        SimpleThread::sleep(500);
359    }
360
361    errln("->" + UnicodeString(threadTestChars) + "<- PATIENCE EXCEEDED!! Still missing some.");
362    for(i=0;i<THREADTEST_NRTHREADS;i++)
363    {
364        delete threads[i];
365    }
366}
367
368
369void MultithreadTest::TestArabicShapingThreads()
370{
371    char threadTestChars[ARABICSHAPE_THREADTEST + 1];
372    SimpleThread *threads[ARABICSHAPE_THREADTEST];
373    int32_t numThreadsStarted = 0;
374
375    int32_t i;
376
377    for(i=0;i<ARABICSHAPE_THREADTEST;i++)
378    {
379        threadTestChars[i] = ' ';
380        threads[i] = new TestArabicShapeThreads(&threadTestChars[i]);
381    }
382    threadTestChars[ARABICSHAPE_THREADTEST] = '\0';
383
384    logln("-> do TestArabicShapingThreads <- Firing off threads.. ");
385    for(i=0;i<ARABICSHAPE_THREADTEST;i++)
386    {
387        if (threads[i]->start() != 0) {
388            errln("Error starting thread %d", i);
389        }
390        else {
391            numThreadsStarted++;
392        }
393        //SimpleThread::sleep(100);
394        logln(" Subthread started.");
395    }
396
397    logln("Waiting for threads to be set..");
398    if (numThreadsStarted == 0) {
399        errln("No threads could be started for testing!");
400        return;
401    }
402
403    int32_t patience = 100; // seconds to wait
404
405    while(patience--)
406    {
407        int32_t count = 0;
408        umtx_lock(NULL);
409        for(i=0;i<ARABICSHAPE_THREADTEST;i++)
410        {
411            if(threadTestChars[i] == '*')
412            {
413                count++;
414            }
415        }
416        umtx_unlock(NULL);
417
418        if(count == ARABICSHAPE_THREADTEST)
419        {
420            logln("->TestArabicShapingThreads <- Got all threads! cya");
421            for(i=0;i<ARABICSHAPE_THREADTEST;i++)
422            {
423                delete threads[i];
424            }
425            return;
426        }
427
428        logln("-> TestArabicShapingThreads <- Waiting..");
429        SimpleThread::sleep(500);
430    }
431
432    errln("-> TestArabicShapingThreads <- PATIENCE EXCEEDED!! Still missing some.");
433    for(i=0;i<ARABICSHAPE_THREADTEST;i++)
434    {
435        delete threads[i];
436    }
437
438}
439
440
441//-----------------------------------------------------------------------
442//
443//  TestMutex  - a simple (non-stress) test to verify that ICU mutexes
444//               are actually mutexing.  Does not test the use of
445//               mutexes within ICU services, but rather that the
446//               platform's mutex support is at least superficially there.
447//
448//----------------------------------------------------------------------
449static UMutex    gTestMutexA = U_MUTEX_INITIALIZER;
450static UMutex    gTestMutexB = U_MUTEX_INITIALIZER;
451
452static int     gThreadsStarted = 0;
453static int     gThreadsInMiddle = 0;
454static int     gThreadsDone = 0;
455
456static const int TESTMUTEX_THREAD_COUNT = 4;
457
458static int safeIncr(int &var, int amt) {
459    // Thread safe (using global mutex) increment of a variable.
460    // Return the updated value.
461    // Can also be used as a safe load of a variable by incrementing it by 0.
462    Mutex m;
463    var += amt;
464    return var;
465}
466
467class TestMutexThread : public SimpleThread
468{
469public:
470    virtual void run()
471    {
472        // This is the code that each of the spawned threads runs.
473        // All of the spawned threads bunch up together at each of the two mutexes
474        // because the main holds the mutexes until they do.
475        //
476        safeIncr(gThreadsStarted, 1);
477        umtx_lock(&gTestMutexA);
478        umtx_unlock(&gTestMutexA);
479        safeIncr(gThreadsInMiddle, 1);
480        umtx_lock(&gTestMutexB);
481        umtx_unlock(&gTestMutexB);
482        safeIncr(gThreadsDone, 1);
483    }
484};
485
486void MultithreadTest::TestMutex()
487{
488    // Start up the test threads.  They should all pile up waiting on
489    // gTestMutexA, which we (the main thread) hold until the test threads
490    //   all get there.
491    gThreadsStarted = 0;
492    gThreadsInMiddle = 0;
493    gThreadsDone = 0;
494    umtx_lock(&gTestMutexA);
495    TestMutexThread  *threads[TESTMUTEX_THREAD_COUNT];
496    int i;
497    int32_t numThreadsStarted = 0;
498    for (i=0; i<TESTMUTEX_THREAD_COUNT; i++) {
499        threads[i] = new TestMutexThread;
500        if (threads[i]->start() != 0) {
501            errln("Error starting thread %d", i);
502        }
503        else {
504            numThreadsStarted++;
505        }
506    }
507    if (numThreadsStarted == 0) {
508        errln("No threads could be started for testing!");
509        return;
510    }
511
512    int patience = 0;
513    while (safeIncr(gThreadsStarted, 0) != TESTMUTEX_THREAD_COUNT) {
514        if (patience++ > 24) {
515            TSMTHREAD_FAIL("Patience Exceeded");
516            return;
517        }
518        SimpleThread::sleep(500);
519    }
520    // None of the test threads should have advanced past the first mutex.
521    TSMTHREAD_ASSERT(gThreadsInMiddle==0);
522    TSMTHREAD_ASSERT(gThreadsDone==0);
523
524    //  All of the test threads have made it to the first mutex.
525    //  We (the main thread) now let them advance to the second mutex,
526    //   where they should all pile up again.
527    umtx_lock(&gTestMutexB);
528    umtx_unlock(&gTestMutexA);
529
530    patience = 0;
531    while (safeIncr(gThreadsInMiddle, 0) != TESTMUTEX_THREAD_COUNT) {
532        if (patience++ > 24) {
533            TSMTHREAD_FAIL("Patience Exceeded");
534            return;
535        }
536        SimpleThread::sleep(500);
537    }
538    TSMTHREAD_ASSERT(gThreadsDone==0);
539
540    //  All test threads made it to the second mutex.
541    //   Now let them proceed from there.  They will all terminate.
542    umtx_unlock(&gTestMutexB);
543    patience = 0;
544    while (safeIncr(gThreadsDone, 0) != TESTMUTEX_THREAD_COUNT) {
545        if (patience++ > 24) {
546            TSMTHREAD_FAIL("Patience Exceeded");
547            return;
548        }
549        SimpleThread::sleep(500);
550    }
551
552    // All threads made it by both mutexes.
553
554    for (i=0; i<TESTMUTEX_THREAD_COUNT; i++) {
555        delete threads[i];
556    }
557
558}
559
560
561//-------------------------------------------------------------------------------------------
562//
563// class ThreadWithStatus - a thread that we can check the status and error condition of
564//
565//-------------------------------------------------------------------------------------------
566class ThreadWithStatus : public SimpleThread
567{
568public:
569    UBool  getError() { return (fErrors > 0); }
570    UBool  getError(UnicodeString& fillinError) { fillinError = fErrorString; return (fErrors > 0); }
571    virtual ~ThreadWithStatus(){}
572protected:
573    ThreadWithStatus() :  fErrors(0) {}
574    void error(const UnicodeString &error) {
575        fErrors++; fErrorString = error;
576        SimpleThread::errorFunc();
577    }
578    void error() { error("An error occured."); }
579private:
580    int32_t fErrors;
581    UnicodeString fErrorString;
582};
583
584
585
586//-------------------------------------------------------------------------------------------
587//
588//   TestMultithreadedIntl.  Test ICU Formatting n a multi-threaded environment
589//
590//-------------------------------------------------------------------------------------------
591
592
593// * Show exactly where the string's differences lie.
594UnicodeString showDifference(const UnicodeString& expected, const UnicodeString& result)
595{
596    UnicodeString res;
597    res = expected + "<Expected\n";
598    if(expected.length() != result.length())
599        res += " [ Different lengths ] \n";
600    else
601    {
602        for(int32_t i=0;i<expected.length();i++)
603        {
604            if(expected[i] == result[i])
605            {
606                res += " ";
607            }
608            else
609            {
610                res += "|";
611            }
612        }
613        res += "<Differences";
614        res += "\n";
615    }
616    res += result + "<Result\n";
617
618    return res;
619}
620
621
622
623
624//-------------------------------------------------------------------------------------------
625//
626//   FormatThreadTest - a thread that tests performing a number of numberformats.
627//
628//-------------------------------------------------------------------------------------------
629
630const int kFormatThreadIterations = 20;  // # of iterations per thread
631const int kFormatThreadThreads    = 10;  // # of threads to spawn
632const int kFormatThreadPatience   = 60;  // time in seconds to wait for all threads
633
634#if !UCONFIG_NO_FORMATTING
635
636
637
638struct FormatThreadTestData
639{
640    double number;
641    UnicodeString string;
642    FormatThreadTestData(double a, const UnicodeString& b) : number(a),string(b) {}
643} ;
644
645
646// "Someone from {2} is receiving a #{0} error - {1}. Their telephone call is costing {3 number,currency}."
647
648void formatErrorMessage(UErrorCode &realStatus, const UnicodeString& pattern, const Locale& theLocale,
649                     UErrorCode inStatus0, /* statusString 1 */ const Locale &inCountry2, double currency3, // these numbers are the message arguments.
650                     UnicodeString &result)
651{
652    if(U_FAILURE(realStatus))
653        return; // you messed up
654
655    UnicodeString errString1(u_errorName(inStatus0));
656
657    UnicodeString countryName2;
658    inCountry2.getDisplayCountry(theLocale,countryName2);
659
660    Formattable myArgs[] = {
661        Formattable((int32_t)inStatus0),   // inStatus0      {0}
662        Formattable(errString1), // statusString1 {1}
663        Formattable(countryName2),  // inCountry2 {2}
664        Formattable(currency3)// currency3  {3,number,currency}
665    };
666
667    MessageFormat *fmt = new MessageFormat("MessageFormat's API is broken!!!!!!!!!!!",realStatus);
668    fmt->setLocale(theLocale);
669    fmt->applyPattern(pattern, realStatus);
670
671    if (U_FAILURE(realStatus)) {
672        delete fmt;
673        return;
674    }
675
676    FieldPosition ignore = 0;
677    fmt->format(myArgs,4,result,ignore,realStatus);
678
679    delete fmt;
680}
681
682
683UBool U_CALLCONV isAcceptable(void *, const char *, const char *, const UDataInfo *) {
684    return TRUE;
685}
686
687//static UMTX debugMutex = NULL;
688//static UMTX gDebugMutex;
689
690
691class FormatThreadTest : public ThreadWithStatus
692{
693public:
694    int     fNum;
695    int     fTraceInfo;
696
697    FormatThreadTest() // constructor is NOT multithread safe.
698        : ThreadWithStatus(),
699        fNum(0),
700        fTraceInfo(0),
701        fOffset(0)
702        // the locale to use
703    {
704        static int32_t fgOffset = 0;
705        fgOffset += 3;
706        fOffset = fgOffset;
707    }
708
709
710    virtual void run()
711    {
712        fTraceInfo                     = 1;
713        LocalPointer<NumberFormat> percentFormatter;
714        UErrorCode status = U_ZERO_ERROR;
715
716#if 0
717        // debugging code,
718        for (int i=0; i<4000; i++) {
719            status = U_ZERO_ERROR;
720            UDataMemory *data1 = udata_openChoice(0, "res", "en_US", isAcceptable, 0, &status);
721            UDataMemory *data2 = udata_openChoice(0, "res", "fr", isAcceptable, 0, &status);
722            udata_close(data1);
723            udata_close(data2);
724            if (U_FAILURE(status)) {
725                error("udata_openChoice failed.\n");
726                break;
727            }
728        }
729        return;
730#endif
731
732#if 0
733        // debugging code,
734        int m;
735        for (m=0; m<4000; m++) {
736            status         = U_ZERO_ERROR;
737            UResourceBundle *res   = NULL;
738            const char *localeName = NULL;
739
740            Locale  loc = Locale::getEnglish();
741
742            localeName = loc.getName();
743            // localeName = "en";
744
745            // ResourceBundle bund = ResourceBundle(0, loc, status);
746            //umtx_lock(&gDebugMutex);
747            res = ures_open(NULL, localeName, &status);
748            //umtx_unlock(&gDebugMutex);
749
750            //umtx_lock(&gDebugMutex);
751            ures_close(res);
752            //umtx_unlock(&gDebugMutex);
753
754            if (U_FAILURE(status)) {
755                error("Resource bundle construction failed.\n");
756                break;
757            }
758        }
759        return;
760#endif
761
762        // Keep this data here to avoid static initialization.
763        FormatThreadTestData kNumberFormatTestData[] =
764        {
765            FormatThreadTestData((double)5.0, UnicodeString("5", "")),
766                FormatThreadTestData( 6.0, UnicodeString("6", "")),
767                FormatThreadTestData( 20.0, UnicodeString("20", "")),
768                FormatThreadTestData( 8.0, UnicodeString("8", "")),
769                FormatThreadTestData( 8.3, UnicodeString("8.3", "")),
770                FormatThreadTestData( 12345, UnicodeString("12,345", "")),
771                FormatThreadTestData( 81890.23, UnicodeString("81,890.23", "")),
772        };
773        int32_t kNumberFormatTestDataLength = (int32_t)(sizeof(kNumberFormatTestData) /
774                                                        sizeof(kNumberFormatTestData[0]));
775
776        // Keep this data here to avoid static initialization.
777        FormatThreadTestData kPercentFormatTestData[] =
778        {
779            FormatThreadTestData((double)5.0, CharsToUnicodeString("500\\u00a0%")),
780                FormatThreadTestData( 1.0, CharsToUnicodeString("100\\u00a0%")),
781                FormatThreadTestData( 0.26, CharsToUnicodeString("26\\u00a0%")),
782                FormatThreadTestData(
783                   16384.99, CharsToUnicodeString("1\\u00a0638\\u00a0499\\u00a0%")), // U+00a0 = NBSP
784                FormatThreadTestData(
785                    81890.23, CharsToUnicodeString("8\\u00a0189\\u00a0023\\u00a0%")),
786        };
787        int32_t kPercentFormatTestDataLength =
788                (int32_t)(sizeof(kPercentFormatTestData) / sizeof(kPercentFormatTestData[0]));
789        int32_t iteration;
790
791        status = U_ZERO_ERROR;
792        LocalPointer<NumberFormat> formatter(NumberFormat::createInstance(Locale::getEnglish(),status));
793        if(U_FAILURE(status)) {
794            error("Error on NumberFormat::createInstance().");
795            goto cleanupAndReturn;
796        }
797
798        percentFormatter.adoptInstead(NumberFormat::createPercentInstance(Locale::getFrench(),status));
799        if(U_FAILURE(status))             {
800            error("Error on NumberFormat::createPercentInstance().");
801            goto cleanupAndReturn;
802        }
803
804        for(iteration = 0;!getError() && iteration<kFormatThreadIterations;iteration++)
805        {
806
807            int32_t whichLine = (iteration + fOffset)%kNumberFormatTestDataLength;
808
809            UnicodeString  output;
810
811            formatter->format(kNumberFormatTestData[whichLine].number, output);
812
813            if(0 != output.compare(kNumberFormatTestData[whichLine].string)) {
814                error("format().. expected " + kNumberFormatTestData[whichLine].string
815                        + " got " + output);
816                goto cleanupAndReturn;
817            }
818
819            // Now check percent.
820            output.remove();
821            whichLine = (iteration + fOffset)%kPercentFormatTestDataLength;
822
823            percentFormatter->format(kPercentFormatTestData[whichLine].number, output);
824            if(0 != output.compare(kPercentFormatTestData[whichLine].string))
825            {
826                error("percent format().. \n" +
827                        showDifference(kPercentFormatTestData[whichLine].string,output));
828                goto cleanupAndReturn;
829            }
830
831            // Test message error
832            const int       kNumberOfMessageTests = 3;
833            UErrorCode      statusToCheck;
834            UnicodeString   patternToCheck;
835            Locale          messageLocale;
836            Locale          countryToCheck;
837            double          currencyToCheck;
838
839            UnicodeString   expected;
840
841            // load the cases.
842            switch((iteration+fOffset) % kNumberOfMessageTests)
843            {
844            default:
845            case 0:
846                statusToCheck=                      U_FILE_ACCESS_ERROR;
847                patternToCheck=        "0:Someone from {2} is receiving a #{0}"
848                                       " error - {1}. Their telephone call is costing "
849                                       "{3,number,currency}."; // number,currency
850                messageLocale=                      Locale("en","US");
851                countryToCheck=                     Locale("","HR");
852                currencyToCheck=                    8192.77;
853                expected=  "0:Someone from Croatia is receiving a #4 error - "
854                            "U_FILE_ACCESS_ERROR. Their telephone call is costing $8,192.77.";
855                break;
856            case 1:
857                statusToCheck=                      U_INDEX_OUTOFBOUNDS_ERROR;
858                patternToCheck=                     "1:A customer in {2} is receiving a #{0} error - {1}. Their telephone call is costing {3,number,currency}."; // number,currency
859                messageLocale=                      Locale("de","DE@currency=DEM");
860                countryToCheck=                     Locale("","BF");
861                currencyToCheck=                    2.32;
862                expected=                           CharsToUnicodeString(
863                                                    "1:A customer in Burkina Faso is receiving a #8 error - U_INDEX_OUTOFBOUNDS_ERROR. Their telephone call is costing 2,32\\u00A0DEM.");
864                break;
865            case 2:
866                statusToCheck=                      U_MEMORY_ALLOCATION_ERROR;
867                patternToCheck=   "2:user in {2} is receiving a #{0} error - {1}. "
868                                  "They insist they just spent {3,number,currency} "
869                                  "on memory."; // number,currency
870                messageLocale=                      Locale("de","AT@currency=ATS"); // Austrian German
871                countryToCheck=                     Locale("","US"); // hmm
872                currencyToCheck=                    40193.12;
873                expected=       CharsToUnicodeString(
874                            "2:user in Vereinigte Staaten is receiving a #7 error"
875                            " - U_MEMORY_ALLOCATION_ERROR. They insist they just spent"
876                            " \\u00f6S\\u00A040.193,12 on memory.");
877                break;
878            }
879
880            UnicodeString result;
881            UErrorCode status = U_ZERO_ERROR;
882            formatErrorMessage(status,patternToCheck,messageLocale,statusToCheck,
883                                countryToCheck,currencyToCheck,result);
884            if(U_FAILURE(status))
885            {
886                UnicodeString tmp(u_errorName(status));
887                error("Failure on message format, pattern=" + patternToCheck +
888                        ", error = " + tmp);
889                goto cleanupAndReturn;
890            }
891
892            if(result != expected)
893            {
894                error("PatternFormat: \n" + showDifference(expected,result));
895                goto cleanupAndReturn;
896            }
897        }   /*  end of for loop */
898
899cleanupAndReturn:
900        //  while (fNum == 4) {SimpleThread::sleep(10000);}   // Force a failure by preventing thread from finishing
901        fTraceInfo = 2;
902    }
903
904private:
905    int32_t fOffset; // where we are testing from.
906};
907
908// ** The actual test function.
909
910void MultithreadTest::TestThreadedIntl()
911{
912    int i;
913    UnicodeString theErr;
914    UBool   haveDisplayedInfo[kFormatThreadThreads];
915    static const int32_t PATIENCE_SECONDS = 45;
916
917    //
918    //  Create and start the test threads
919    //
920    logln("Spawning: %d threads * %d iterations each.",
921                kFormatThreadThreads, kFormatThreadIterations);
922    LocalArray<FormatThreadTest> tests(new FormatThreadTest[kFormatThreadThreads]);
923    for(int32_t j = 0; j < kFormatThreadThreads; j++) {
924        tests[j].fNum = j;
925        int32_t threadStatus = tests[j].start();
926        if (threadStatus != 0) {
927            errln("System Error %d starting thread number %d.", threadStatus, j);
928            SimpleThread::errorFunc();
929            return;
930        }
931        haveDisplayedInfo[j] = FALSE;
932    }
933
934
935    // Spin, waiting for the test threads to finish.
936    UBool   stillRunning;
937    UDate startTime, endTime;
938    startTime = Calendar::getNow();
939    do {
940        /*  Spin until the test threads  complete. */
941        stillRunning = FALSE;
942        endTime = Calendar::getNow();
943        if (((int32_t)(endTime - startTime)/U_MILLIS_PER_SECOND) > PATIENCE_SECONDS) {
944            errln("Patience exceeded. Test is taking too long.");
945            return;
946        }
947        /*
948         The following sleep must be here because the *BSD operating systems
949         have a brain dead thread scheduler. They starve the child threads from
950         CPU time.
951        */
952        SimpleThread::sleep(1); // yield
953        for(i=0;i<kFormatThreadThreads;i++) {
954            if (tests[i].isRunning()) {
955                stillRunning = TRUE;
956            } else if (haveDisplayedInfo[i] == FALSE) {
957                logln("Thread # %d is complete..", i);
958                if(tests[i].getError(theErr)) {
959                    dataerrln(UnicodeString("#") + i + ": " + theErr);
960                    SimpleThread::errorFunc();
961                }
962                haveDisplayedInfo[i] = TRUE;
963            }
964        }
965    } while (stillRunning);
966
967    //
968    //  All threads have finished.
969    //
970}
971#endif /* #if !UCONFIG_NO_FORMATTING */
972
973
974
975
976
977//-------------------------------------------------------------------------------------------
978//
979// Collation threading test
980//
981//-------------------------------------------------------------------------------------------
982#if !UCONFIG_NO_COLLATION
983
984#define kCollatorThreadThreads   10  // # of threads to spawn
985#define kCollatorThreadPatience kCollatorThreadThreads*30
986
987struct Line {
988    UChar buff[25];
989    int32_t buflen;
990} ;
991
992static UBool
993skipLineBecauseOfBug(const UChar *s, int32_t length) {
994    // TODO: Fix ICU ticket #8052
995    if(length >= 3 &&
996            (s[0] == 0xfb2 || s[0] == 0xfb3) &&
997            s[1] == 0x334 &&
998            (s[2] == 0xf73 || s[2] == 0xf75 || s[2] == 0xf81)) {
999        return TRUE;
1000    }
1001    return FALSE;
1002}
1003
1004static UCollationResult
1005normalizeResult(int32_t result) {
1006    return result<0 ? UCOL_LESS : result==0 ? UCOL_EQUAL : UCOL_GREATER;
1007}
1008
1009class CollatorThreadTest : public ThreadWithStatus
1010{
1011private:
1012    const Collator *coll;
1013    const Line *lines;
1014    int32_t noLines;
1015    UBool isAtLeastUCA62;
1016public:
1017    CollatorThreadTest()  : ThreadWithStatus(),
1018        coll(NULL),
1019        lines(NULL),
1020        noLines(0),
1021        isAtLeastUCA62(TRUE)
1022    {
1023    };
1024    void setCollator(Collator *c, Line *l, int32_t nl, UBool atLeastUCA62)
1025    {
1026        coll = c;
1027        lines = l;
1028        noLines = nl;
1029        isAtLeastUCA62 = atLeastUCA62;
1030    }
1031    virtual void run() {
1032        uint8_t sk1[1024], sk2[1024];
1033        uint8_t *oldSk = NULL, *newSk = sk1;
1034        int32_t oldLen = 0;
1035        int32_t prev = 0;
1036        int32_t i = 0;
1037
1038        for(i = 0; i < noLines; i++) {
1039            if(lines[i].buflen == 0) { continue; }
1040
1041            if(skipLineBecauseOfBug(lines[i].buff, lines[i].buflen)) { continue; }
1042
1043            int32_t resLen = coll->getSortKey(lines[i].buff, lines[i].buflen, newSk, 1024);
1044
1045            if(oldSk != NULL) {
1046                int32_t skres = strcmp((char *)oldSk, (char *)newSk);
1047                int32_t cmpres = coll->compare(lines[prev].buff, lines[prev].buflen, lines[i].buff, lines[i].buflen);
1048                int32_t cmpres2 = coll->compare(lines[i].buff, lines[i].buflen, lines[prev].buff, lines[prev].buflen);
1049
1050                if(cmpres != -cmpres2) {
1051                    error(UnicodeString("Compare result not symmetrical on line ") + (i + 1));
1052                    break;
1053                }
1054
1055                if(cmpres != normalizeResult(skres)) {
1056                    error(UnicodeString("Difference between coll->compare and sortkey compare on line ") + (i + 1));
1057                    break;
1058                }
1059
1060                int32_t res = cmpres;
1061                if(res == 0 && !isAtLeastUCA62) {
1062                    // Up to UCA 6.1, the collation test files use a custom tie-breaker,
1063                    // comparing the raw input strings.
1064                    res = u_strcmpCodePointOrder(lines[prev].buff, lines[i].buff);
1065                    // Starting with UCA 6.2, the collation test files use the standard UCA tie-breaker,
1066                    // comparing the NFD versions of the input strings,
1067                    // which we do via setting strength=identical.
1068                }
1069                if(res > 0) {
1070                    error(UnicodeString("Line is not greater or equal than previous line, for line ") + (i + 1));
1071                    break;
1072                }
1073            }
1074
1075            oldSk = newSk;
1076            oldLen = resLen;
1077            prev = i;
1078
1079            newSk = (newSk == sk1)?sk2:sk1;
1080        }
1081    }
1082};
1083
1084void MultithreadTest::TestCollators()
1085{
1086
1087    UErrorCode status = U_ZERO_ERROR;
1088    FILE *testFile = NULL;
1089    char testDataPath[1024];
1090    strcpy(testDataPath, IntlTest::getSourceTestData(status));
1091    if (U_FAILURE(status)) {
1092        errln("ERROR: could not open test data %s", u_errorName(status));
1093        return;
1094    }
1095    strcat(testDataPath, "CollationTest_");
1096
1097    const char* type = "NON_IGNORABLE";
1098
1099    const char *ext = ".txt";
1100    if(testFile) {
1101        fclose(testFile);
1102    }
1103    char buffer[1024];
1104    strcpy(buffer, testDataPath);
1105    strcat(buffer, type);
1106    size_t bufLen = strlen(buffer);
1107
1108    // we try to open 3 files:
1109    // path/CollationTest_type.txt
1110    // path/CollationTest_type_SHORT.txt
1111    // path/CollationTest_type_STUB.txt
1112    // we are going to test with the first one that we manage to open.
1113
1114    strcpy(buffer+bufLen, ext);
1115
1116    testFile = fopen(buffer, "rb");
1117
1118    if(testFile == 0) {
1119        strcpy(buffer+bufLen, "_SHORT");
1120        strcat(buffer, ext);
1121        testFile = fopen(buffer, "rb");
1122
1123        if(testFile == 0) {
1124            strcpy(buffer+bufLen, "_STUB");
1125            strcat(buffer, ext);
1126            testFile = fopen(buffer, "rb");
1127
1128            if (testFile == 0) {
1129                *(buffer+bufLen) = 0;
1130                dataerrln("could not open any of the conformance test files, tried opening base %s", buffer);
1131                return;
1132            } else {
1133                infoln(
1134                    "INFO: Working with the stub file.\n"
1135                    "If you need the full conformance test, please\n"
1136                    "download the appropriate data files from:\n"
1137                    "http://source.icu-project.org/repos/icu/tools/trunk/unicodetools/com/ibm/text/data/");
1138            }
1139        }
1140    }
1141
1142    LocalArray<Line> lines(new Line[200000]);
1143    memset(lines.getAlias(), 0, sizeof(Line)*200000);
1144    int32_t lineNum = 0;
1145
1146    UChar bufferU[1024];
1147    uint32_t first = 0;
1148
1149    while (fgets(buffer, 1024, testFile) != NULL) {
1150        if(*buffer == 0 || buffer[0] == '#') {
1151            // Store empty and comment lines so that errors are reported
1152            // for the real test file lines.
1153            lines[lineNum].buflen = 0;
1154            lines[lineNum].buff[0] = 0;
1155        } else {
1156            int32_t buflen = u_parseString(buffer, bufferU, 1024, &first, &status);
1157            lines[lineNum].buflen = buflen;
1158            u_memcpy(lines[lineNum].buff, bufferU, buflen);
1159            lines[lineNum].buff[buflen] = 0;
1160        }
1161        lineNum++;
1162    }
1163    fclose(testFile);
1164    if(U_FAILURE(status)) {
1165      dataerrln("Couldn't read the test file!");
1166      return;
1167    }
1168
1169    UVersionInfo uniVersion;
1170    static const UVersionInfo v62 = { 6, 2, 0, 0 };
1171    u_getUnicodeVersion(uniVersion);
1172    UBool isAtLeastUCA62 = uprv_memcmp(uniVersion, v62, 4) >= 0;
1173
1174    LocalPointer<Collator> coll(Collator::createInstance(Locale::getRoot(), status));
1175    if(U_FAILURE(status)) {
1176        errcheckln(status, "Couldn't open UCA collator");
1177        return;
1178    }
1179    coll->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status);
1180    coll->setAttribute(UCOL_CASE_FIRST, UCOL_OFF, status);
1181    coll->setAttribute(UCOL_CASE_LEVEL, UCOL_OFF, status);
1182    coll->setAttribute(UCOL_STRENGTH, isAtLeastUCA62 ? UCOL_IDENTICAL : UCOL_TERTIARY, status);
1183    coll->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_NON_IGNORABLE, status);
1184
1185    int32_t noSpawned = 0;
1186    int32_t spawnResult = 0;
1187    LocalArray<CollatorThreadTest> tests(new CollatorThreadTest[kCollatorThreadThreads]);
1188
1189    logln(UnicodeString("Spawning: ") + kCollatorThreadThreads + " threads * " + kFormatThreadIterations + " iterations each.");
1190    int32_t j = 0;
1191    for(j = 0; j < kCollatorThreadThreads; j++) {
1192        //logln("Setting collator %i", j);
1193        tests[j].setCollator(coll.getAlias(), lines.getAlias(), lineNum, isAtLeastUCA62);
1194    }
1195    for(j = 0; j < kCollatorThreadThreads; j++) {
1196        log("%i ", j);
1197        spawnResult = tests[j].start();
1198        if(spawnResult != 0) {
1199            infoln("THREAD INFO: Couldn't spawn more than %i threads", noSpawned);
1200            break;
1201        }
1202        noSpawned++;
1203    }
1204    logln("Spawned all");
1205    if (noSpawned == 0) {
1206        errln("No threads could be spawned.");
1207        return;
1208    }
1209
1210    for(int32_t patience = kCollatorThreadPatience;patience > 0; patience --)
1211    {
1212        logln("Waiting...");
1213
1214        int32_t i;
1215        int32_t terrs = 0;
1216        int32_t completed =0;
1217
1218        for(i=0;i<kCollatorThreadThreads;i++)
1219        {
1220            if (tests[i].isRunning() == FALSE)
1221            {
1222                completed++;
1223
1224                //logln(UnicodeString("Test #") + i + " is complete.. ");
1225
1226                UnicodeString theErr;
1227                if(tests[i].getError(theErr))
1228                {
1229                    terrs++;
1230                    errln(UnicodeString("#") + i + ": " + theErr);
1231                }
1232                // print out the error, too, if any.
1233            }
1234        }
1235        logln("Completed %i tests", completed);
1236
1237        if(completed == noSpawned)
1238        {
1239            logln("Done! All %i tests are finished", noSpawned);
1240
1241            if(terrs)
1242            {
1243                errln("There were errors.");
1244                SimpleThread::errorFunc();
1245            }
1246            return;
1247        }
1248
1249        SimpleThread::sleep(900);
1250    }
1251    errln("patience exceeded. ");
1252    SimpleThread::errorFunc();
1253}
1254
1255#endif /* #if !UCONFIG_NO_COLLATION */
1256
1257
1258
1259
1260//-------------------------------------------------------------------------------------------
1261//
1262//   StringThreadTest2
1263//
1264//-------------------------------------------------------------------------------------------
1265
1266const int kStringThreadIterations = 2500;// # of iterations per thread
1267const int kStringThreadThreads    = 10;  // # of threads to spawn
1268const int kStringThreadPatience   = 120; // time in seconds to wait for all threads
1269
1270
1271class StringThreadTest2 : public ThreadWithStatus
1272{
1273public:
1274    int                 fNum;
1275    int                 fTraceInfo;
1276    const UnicodeString *fSharedString;
1277
1278    StringThreadTest2(const UnicodeString *sharedString, int num) // constructor is NOT multithread safe.
1279        : ThreadWithStatus(),
1280        fNum(num),
1281        fTraceInfo(0),
1282        fSharedString(sharedString)
1283    {
1284    };
1285
1286
1287    virtual void run()
1288    {
1289        fTraceInfo    = 1;
1290        int loopCount = 0;
1291
1292        for (loopCount = 0; loopCount < kStringThreadIterations; loopCount++) {
1293            if (*fSharedString != "This is the original test string.") {
1294                error("Original string is corrupt.");
1295                break;
1296            }
1297            UnicodeString s1 = *fSharedString;
1298            s1 += "cat this";
1299            UnicodeString s2(s1);
1300            UnicodeString s3 = *fSharedString;
1301            s2 = s3;
1302            s3.truncate(12);
1303            s2.truncate(0);
1304        }
1305
1306        //  while (fNum == 4) {SimpleThread::sleep(10000);}   // Force a failure by preventing thread from finishing
1307        fTraceInfo = 2;
1308    }
1309
1310};
1311
1312// ** The actual test function.
1313
1314void MultithreadTest::TestString()
1315{
1316    int     patience;
1317    int     terrs = 0;
1318    int     j;
1319
1320    UnicodeString *testString = new UnicodeString("This is the original test string.");
1321
1322    // Not using LocalArray<StringThreadTest2> tests[kStringThreadThreads];
1323    // because we don't always want to delete them.
1324    // See the comments below the cleanupAndReturn label.
1325    StringThreadTest2  *tests[kStringThreadThreads];
1326    for(j = 0; j < kStringThreadThreads; j++) {
1327        tests[j] = new StringThreadTest2(testString, j);
1328    }
1329
1330    logln(UnicodeString("Spawning: ") + kStringThreadThreads + " threads * " + kStringThreadIterations + " iterations each.");
1331    for(j = 0; j < kStringThreadThreads; j++) {
1332        int32_t threadStatus = tests[j]->start();
1333        if (threadStatus != 0) {
1334            errln("System Error %d starting thread number %d.", threadStatus, j);
1335            SimpleThread::errorFunc();
1336            goto cleanupAndReturn;
1337        }
1338    }
1339
1340    for(patience = kStringThreadPatience;patience > 0; patience --)
1341    {
1342        logln("Waiting...");
1343
1344        int32_t i;
1345        terrs = 0;
1346        int32_t completed =0;
1347
1348        for(i=0;i<kStringThreadThreads;i++) {
1349            if (tests[i]->isRunning() == FALSE)
1350            {
1351                completed++;
1352
1353                logln(UnicodeString("Test #") + i + " is complete.. ");
1354
1355                UnicodeString theErr;
1356                if(tests[i]->getError(theErr))
1357                {
1358                    terrs++;
1359                    errln(UnicodeString("#") + i + ": " + theErr);
1360                }
1361                // print out the error, too, if any.
1362            }
1363        }
1364
1365        if(completed == kStringThreadThreads)
1366        {
1367            logln("Done!");
1368            if(terrs) {
1369                errln("There were errors.");
1370            }
1371            break;
1372        }
1373
1374        SimpleThread::sleep(900);
1375    }
1376
1377    if (patience <= 0) {
1378        errln("patience exceeded. ");
1379        // while (TRUE) {SimpleThread::sleep(10000);}   // TODO:   for debugging.  Sleep forever on failure.
1380        terrs++;
1381    }
1382
1383    if (terrs > 0) {
1384        SimpleThread::errorFunc();
1385    }
1386
1387cleanupAndReturn:
1388    if (terrs == 0) {
1389        /*
1390        Don't clean up if there are errors. This prevents crashes if the
1391        threads are still running and using this data. This will only happen
1392        if there is an error with the test, ICU, or the machine is too slow.
1393        It's better to leak than crash.
1394        */
1395        for(j = 0; j < kStringThreadThreads; j++) {
1396            delete tests[j];
1397        }
1398        delete testString;
1399    }
1400}
1401
1402#endif // ICU_USE_THREADS
1403