1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/********************************************************************
21b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert * COPYRIGHT:
3fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * Copyright (c) 1999-2014, International Business Machines Corporation and
4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * others. All Rights Reserved.
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ********************************************************************/
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined(hpux)
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru# ifndef _INCLUDE_POSIX_SOURCE
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#  define _INCLUDE_POSIX_SOURCE
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru# endif
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "simplethread.h"
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h"
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ustring.h"
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "umutex.h"
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h"
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h"
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uparse.h"
2150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "unicode/localpointer.h"
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/resbund.h"
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/udata.h"
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/uloc.h"
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/locid.h"
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "putilimp.h"
2754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#include "intltest.h"
2854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#include "tsmthred.h"
2954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#include "unicode/ushape.h"
30fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/translit.h"
31f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#include "sharedobject.h"
32f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#include "unifiedcache.h"
33f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#include "uassert.h"
34103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
35103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_PLATFORM_USES_ONLY_WIN32_API
36103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    /* Prefer native Windows APIs even if POSIX is implemented (i.e., on Cygwin). */
37103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#   undef POSIX
38103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#elif U_PLATFORM_IMPLEMENTS_POSIX
39103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#   define POSIX
40103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#else
41103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#   undef POSIX
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
44b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* Needed by z/OS to get usleep */
45103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_PLATFORM == U_PF_OS390
46b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define __DOT1 1
47b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define __UU
48b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifndef _XPG4_2
49b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define _XPG4_2
50b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
51b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include <unistd.h>
52b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
53103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if defined(POSIX)
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define HAVE_IMP
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if (ICU_USE_THREADS == 1)
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <pthread.h>
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined(__hpux) && defined(HPUX_CMA)
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru# if defined(read)  // read being defined as cma_read causes trouble with iostream::read
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#  undef read
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru# endif
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Define __EXTENSIONS__ for Solaris and old friends in strict mode. */
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifndef __EXTENSIONS__
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define __EXTENSIONS__
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
72103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_PLATFORM == U_PF_OS390
73b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include <sys/types.h>
74b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
75b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
76103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_PLATFORM != U_PF_OS390
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <signal.h>
78b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Define _XPG4_2 for Solaris and friends. */
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifndef _XPG4_2
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define _XPG4_2
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Define __USE_XOPEN_EXTENDED for Linux and glibc. */
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifndef __USE_XOPEN_EXTENDED
871b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert#define __USE_XOPEN_EXTENDED
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Define _INCLUDE_XOPEN_SOURCE_EXTENDED for HP/UX (11?). */
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifndef _INCLUDE_XOPEN_SOURCE_EXTENDED
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define _INCLUDE_XOPEN_SOURCE_EXTENDED
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <unistd.h>
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* HPUX */
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef sleep
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#undef sleep
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define TSMTHREAD_FAIL(msg) errln("%s at file %s, line %d", msg, __FILE__, __LINE__)
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define TSMTHREAD_ASSERT(expr) {if (!(expr)) {TSMTHREAD_FAIL("Fail");}}
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMultithreadTest::MultithreadTest()
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMultithreadTest::~MultithreadTest()
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if (ICU_USE_THREADS==0)
1171b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubertvoid MultithreadTest::runIndexedTest( int32_t index, UBool exec,
118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                const char* &name, char* /*par*/ ) {
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (exec) logln("TestSuite MultithreadTest: ");
120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(index == 0)
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      name = "NO_THREADED_TESTS";
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  else
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      name = "";
125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(exec) { logln("MultithreadTest - test DISABLED.  ICU_USE_THREADS set to 0, check your configuration if this is a problem..");
127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <stdio.h>
132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <string.h>
133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <ctype.h>    // tolower, toupper
134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/putil.h"
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
13750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// for mthreadtest
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/numfmt.h"
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/choicfmt.h"
140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/msgfmt.h"
141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/locid.h"
14254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#include "unicode/coll.h"
143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/calendar.h"
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ucaconf.h"
145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid SimpleThread::errorFunc() {
147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // *(char *)0 = 3;            // Force entry into a debugger via a crash;
148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1501b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubertvoid MultithreadTest::runIndexedTest( int32_t index, UBool exec,
151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                const char* &name, char* /*par*/ ) {
152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (exec)
153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        logln("TestSuite MultithreadTest: ");
154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    switch (index) {
155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case 0:
156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        name = "TestThreads";
157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (exec)
158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            TestThreads();
159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case 1:
162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        name = "TestMutex";
163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (exec)
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            TestMutex();
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case 2:
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        name = "TestThreadedIntl";
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (exec) {
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            TestThreadedIntl();
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case 3:
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      name = "TestCollators";
178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_COLLATION
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if (exec) {
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            TestCollators();
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_COLLATION */
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case 4:
1861b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        name = "TestString";
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (exec) {
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            TestString();
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
192fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    case 5:
1931b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        name = "TestArabicShapingThreads";
19454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        if (exec) {
19554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            TestArabicShapingThreads();
19654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        }
19754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        break;
19854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
199fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    case 6:
200fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        name = "TestAnyTranslit";
201fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if (exec) {
202fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            TestAnyTranslit();
203fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
204fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        break;
2051b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
206f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    case 7:
207f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        name = "TestConditionVariables";
208f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        if (exec) {
209f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            TestConditionVariables();
210f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        }
211f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        break;
212f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    case 8:
213f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        name = "TestUnifiedCache";
214f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        if (exec) {
215f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            TestUnifiedCache();
216f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        }
217f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        break;
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    default:
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        name = "";
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break; //needed to end loop
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-----------------------------------------------------------------------------------
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//   TestThreads -- see if threads really work at all.
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//   Set up N threads pointing at N chars. When they are started, they will
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//   each sleep 1 second and then set their chars. At the end we make sure they
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//   are all set.
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-----------------------------------------------------------------------------------
234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define THREADTEST_NRTHREADS 8
23554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#define ARABICSHAPE_THREADTEST 30
236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass TestThreadsThread : public SimpleThread
238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querupublic:
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TestThreadsThread(char* whatToChange) { fWhatToChange = whatToChange; }
2411b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    virtual void run() { SimpleThread::sleep(1000);
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         Mutex m;
2431b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert                         *fWhatToChange = '*';
244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruprivate:
246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char *fWhatToChange;
247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
24854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius//-----------------------------------------------------------------------------------
24954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius//
25054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius//   TestArabicShapeThreads -- see if calls to u_shapeArabic in many threads works successfully
25154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius//
25254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius//   Set up N threads pointing at N chars. When they are started, they will make calls to doTailTest which tests
2531b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert//   u_shapeArabic, if the calls are successful it will the set * chars.
25454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius//   At the end we make sure all threads managed to run u_shapeArabic successfully.
25554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius//   This is a unit test for ticket 9473
25654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius//
25754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius//-----------------------------------------------------------------------------------
2581b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubertclass TestArabicShapeThreads : public SimpleThread
25954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius{
26054dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliuspublic:
26154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    TestArabicShapeThreads(char* whatToChange) { fWhatToChange = whatToChange;}
2621b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    virtual void run() {
26354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius	    if(doTailTest()==TRUE)
2641b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert			*fWhatToChange = '*';
26554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    }
26654dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusprivate:
26754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    char *fWhatToChange;
26854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
26954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius	UBool doTailTest(void) {
27054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  static const UChar src[] = { 0x0020, 0x0633, 0 };
27154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  static const UChar dst_old[] = { 0xFEB1, 0x200B,0 };
27254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  static const UChar dst_new[] = { 0xFEB1, 0xFE73,0 };
27354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  UChar dst[3] = { 0x0000, 0x0000,0 };
27454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  int32_t length;
27554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  UErrorCode status;
27654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  IntlTest inteltst =  IntlTest();
2771b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
27854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  status = U_ZERO_ERROR;
279f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius  length = u_shapeArabic(src, -1, dst, UPRV_LENGTHOF(dst),
28054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                         U_SHAPE_LETTERS_SHAPE|U_SHAPE_SEEN_TWOCELL_NEAR, &status);
28154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  if(U_FAILURE(status)) {
2821b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert	   inteltst.errln("Fail: status %s\n", u_errorName(status));
28354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius	return FALSE;
28454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  } else if(length!=2) {
28554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    inteltst.errln("Fail: len %d expected 3\n", length);
28654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius	return FALSE;
287f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius  } else if(u_strncmp(dst,dst_old,UPRV_LENGTHOF(dst))) {
28854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    inteltst.errln("Fail: got U+%04X U+%04X expected U+%04X U+%04X\n",
28954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            dst[0],dst[1],dst_old[0],dst_old[1]);
29054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius	return FALSE;
29154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  }
29254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
29354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
29454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  //"Trying new tail
29554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  status = U_ZERO_ERROR;
296f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius  length = u_shapeArabic(src, -1, dst, UPRV_LENGTHOF(dst),
29754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                         U_SHAPE_LETTERS_SHAPE|U_SHAPE_SEEN_TWOCELL_NEAR|U_SHAPE_TAIL_NEW_UNICODE, &status);
29854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  if(U_FAILURE(status)) {
2991b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    inteltst.errln("Fail: status %s\n", u_errorName(status));
30054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius	return FALSE;
30154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  } else if(length!=2) {
30254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    inteltst.errln("Fail: len %d expected 3\n", length);
30354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius	return FALSE;
304f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius  } else if(u_strncmp(dst,dst_new,UPRV_LENGTHOF(dst))) {
30554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    inteltst.errln("Fail: got U+%04X U+%04X expected U+%04X U+%04X\n",
30654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            dst[0],dst[1],dst_new[0],dst_new[1]);
30754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius	return FALSE;
3081b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  }
3091b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
3101b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
31154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  return TRUE;
3121b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
31354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
31454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
31554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
31654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius};
317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid MultithreadTest::TestThreads()
319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char threadTestChars[THREADTEST_NRTHREADS + 1];
321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SimpleThread *threads[THREADTEST_NRTHREADS];
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t numThreadsStarted = 0;
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i;
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(i=0;i<THREADTEST_NRTHREADS;i++)
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        threadTestChars[i] = ' ';
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        threads[i] = new TestThreadsThread(&threadTestChars[i]);
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    threadTestChars[THREADTEST_NRTHREADS] = '\0';
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    logln("->" + UnicodeString(threadTestChars) + "<- Firing off threads.. ");
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(i=0;i<THREADTEST_NRTHREADS;i++)
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (threads[i]->start() != 0) {
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            errln("Error starting thread %d", i);
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else {
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            numThreadsStarted++;
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        SimpleThread::sleep(100);
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        logln(" Subthread started.");
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    logln("Waiting for threads to be set..");
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (numThreadsStarted == 0) {
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        errln("No threads could be started for testing!");
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t patience = 40; // seconds to wait
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(patience--)
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t count = 0;
356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        umtx_lock(NULL);
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(i=0;i<THREADTEST_NRTHREADS;i++)
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(threadTestChars[i] == '*')
360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                count++;
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        umtx_unlock(NULL);
3651b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(count == THREADTEST_NRTHREADS)
367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            logln("->" + UnicodeString(threadTestChars) + "<- Got all threads! cya");
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for(i=0;i<THREADTEST_NRTHREADS;i++)
370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                delete threads[i];
372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        logln("->" + UnicodeString(threadTestChars) + "<- Waiting..");
377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        SimpleThread::sleep(500);
378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    errln("->" + UnicodeString(threadTestChars) + "<- PATIENCE EXCEEDED!! Still missing some.");
381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(i=0;i<THREADTEST_NRTHREADS;i++)
382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete threads[i];
384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
38854dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusvoid MultithreadTest::TestArabicShapingThreads()
38954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius{
39054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    char threadTestChars[ARABICSHAPE_THREADTEST + 1];
39154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    SimpleThread *threads[ARABICSHAPE_THREADTEST];
39254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    int32_t numThreadsStarted = 0;
39354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
39454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    int32_t i;
3951b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
39654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    for(i=0;i<ARABICSHAPE_THREADTEST;i++)
39754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    {
39854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        threadTestChars[i] = ' ';
39954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        threads[i] = new TestArabicShapeThreads(&threadTestChars[i]);
40054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    }
40154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    threadTestChars[ARABICSHAPE_THREADTEST] = '\0';
40254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
40354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    logln("-> do TestArabicShapingThreads <- Firing off threads.. ");
40454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    for(i=0;i<ARABICSHAPE_THREADTEST;i++)
40554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    {
40654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        if (threads[i]->start() != 0) {
40754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            errln("Error starting thread %d", i);
40854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        }
40954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        else {
41054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            numThreadsStarted++;
41154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        }
41254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        //SimpleThread::sleep(100);
41354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        logln(" Subthread started.");
41454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    }
41554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
41654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    logln("Waiting for threads to be set..");
41754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    if (numThreadsStarted == 0) {
41854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        errln("No threads could be started for testing!");
41954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        return;
42054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    }
42154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
42254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    int32_t patience = 100; // seconds to wait
42354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
42454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    while(patience--)
42554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    {
42654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        int32_t count = 0;
42754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        umtx_lock(NULL);
42854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        for(i=0;i<ARABICSHAPE_THREADTEST;i++)
42954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        {
43054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            if(threadTestChars[i] == '*')
43154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            {
43254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                count++;
43354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            }
43454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        }
43554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        umtx_unlock(NULL);
4361b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
43754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        if(count == ARABICSHAPE_THREADTEST)
43854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        {
43954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            logln("->TestArabicShapingThreads <- Got all threads! cya");
44054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            for(i=0;i<ARABICSHAPE_THREADTEST;i++)
44154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            {
44254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                delete threads[i];
44354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            }
44454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            return;
44554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        }
44654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
44754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        logln("-> TestArabicShapingThreads <- Waiting..");
44854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        SimpleThread::sleep(500);
44954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    }
45054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
45154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    errln("-> TestArabicShapingThreads <- PATIENCE EXCEEDED!! Still missing some.");
45254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    for(i=0;i<ARABICSHAPE_THREADTEST;i++)
45354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    {
45454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        delete threads[i];
45554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    }
45654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
45754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
45854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
4591b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-----------------------------------------------------------------------
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  TestMutex  - a simple (non-stress) test to verify that ICU mutexes
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//               are actually mutexing.  Does not test the use of
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//               mutexes within ICU services, but rather that the
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//               platform's mutex support is at least superficially there.
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//----------------------------------------------------------------------
46854dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic UMutex    gTestMutexA = U_MUTEX_INITIALIZER;
46954dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic UMutex    gTestMutexB = U_MUTEX_INITIALIZER;
470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
4711b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubertstatic int     gThreadsStarted = 0;
472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int     gThreadsInMiddle = 0;
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int     gThreadsDone = 0;
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int TESTMUTEX_THREAD_COUNT = 4;
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int safeIncr(int &var, int amt) {
478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Thread safe (using global mutex) increment of a variable.
479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Return the updated value.
480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Can also be used as a safe load of a variable by incrementing it by 0.
481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Mutex m;
482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    var += amt;
483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return var;
484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass TestMutexThread : public SimpleThread
487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querupublic:
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    virtual void run()
490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // This is the code that each of the spawned threads runs.
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // All of the spawned threads bunch up together at each of the two mutexes
493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // because the main holds the mutexes until they do.
494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //
495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        safeIncr(gThreadsStarted, 1);
496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        umtx_lock(&gTestMutexA);
497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        umtx_unlock(&gTestMutexA);
498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        safeIncr(gThreadsInMiddle, 1);
499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        umtx_lock(&gTestMutexB);
500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        umtx_unlock(&gTestMutexB);
501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        safeIncr(gThreadsDone, 1);
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid MultithreadTest::TestMutex()
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Start up the test threads.  They should all pile up waiting on
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // gTestMutexA, which we (the main thread) hold until the test threads
509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //   all get there.
510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    gThreadsStarted = 0;
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    gThreadsInMiddle = 0;
512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    gThreadsDone = 0;
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    umtx_lock(&gTestMutexA);
514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TestMutexThread  *threads[TESTMUTEX_THREAD_COUNT];
515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int i;
516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t numThreadsStarted = 0;
517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (i=0; i<TESTMUTEX_THREAD_COUNT; i++) {
518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        threads[i] = new TestMutexThread;
519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (threads[i]->start() != 0) {
520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            errln("Error starting thread %d", i);
521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else {
523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            numThreadsStarted++;
524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (numThreadsStarted == 0) {
527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        errln("No threads could be started for testing!");
528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int patience = 0;
532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (safeIncr(gThreadsStarted, 0) != TESTMUTEX_THREAD_COUNT) {
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (patience++ > 24) {
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            TSMTHREAD_FAIL("Patience Exceeded");
535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        SimpleThread::sleep(500);
538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // None of the test threads should have advanced past the first mutex.
540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TSMTHREAD_ASSERT(gThreadsInMiddle==0);
541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TSMTHREAD_ASSERT(gThreadsDone==0);
542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //  All of the test threads have made it to the first mutex.
544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //  We (the main thread) now let them advance to the second mutex,
545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //   where they should all pile up again.
546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    umtx_lock(&gTestMutexB);
547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    umtx_unlock(&gTestMutexA);
548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    patience = 0;
550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (safeIncr(gThreadsInMiddle, 0) != TESTMUTEX_THREAD_COUNT) {
551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (patience++ > 24) {
552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            TSMTHREAD_FAIL("Patience Exceeded");
553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        SimpleThread::sleep(500);
556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TSMTHREAD_ASSERT(gThreadsDone==0);
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //  All test threads made it to the second mutex.
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //   Now let them proceed from there.  They will all terminate.
5611b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    umtx_unlock(&gTestMutexB);
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    patience = 0;
563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (safeIncr(gThreadsDone, 0) != TESTMUTEX_THREAD_COUNT) {
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (patience++ > 24) {
565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            TSMTHREAD_FAIL("Patience Exceeded");
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        SimpleThread::sleep(500);
569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // All threads made it by both mutexes.
572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (i=0; i<TESTMUTEX_THREAD_COUNT; i++) {
574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete threads[i];
575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------------------------------
581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// class ThreadWithStatus - a thread that we can check the status and error condition of
583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------------------------------
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass ThreadWithStatus : public SimpleThread
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querupublic:
5881b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    UBool  getError() { return (fErrors > 0); }
5891b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    UBool  getError(UnicodeString& fillinError) { fillinError = fErrorString; return (fErrors > 0); }
590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    virtual ~ThreadWithStatus(){}
591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruprotected:
592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ThreadWithStatus() :  fErrors(0) {}
5931b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    void error(const UnicodeString &error) {
5941b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        fErrors++; fErrorString = error;
5951b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        SimpleThread::errorFunc();
596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    void error() { error("An error occured."); }
598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruprivate:
599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t fErrors;
600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString fErrorString;
601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------------------------------
606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
6071b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert//   TestMultithreadedIntl.  Test ICU Formatting n a multi-threaded environment
608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------------------------------
610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// * Show exactly where the string's differences lie.
613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString showDifference(const UnicodeString& expected, const UnicodeString& result)
614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString res;
616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    res = expected + "<Expected\n";
617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(expected.length() != result.length())
618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        res += " [ Different lengths ] \n";
619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else
620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(int32_t i=0;i<expected.length();i++)
622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(expected[i] == result[i])
624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                res += " ";
626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            else
628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                res += "|";
630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        res += "<Differences";
633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        res += "\n";
634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    res += result + "<Result\n";
636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return res;
638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------------------------------
644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//   FormatThreadTest - a thread that tests performing a number of numberformats.
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------------------------------
648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
64959d709d503bab6e2b61931737e662dd293b40578ccorneliusconst int kFormatThreadIterations = 100;  // # of iterations per thread
6501b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubertconst int kFormatThreadThreads    = 10;  // # of threads to spawn
651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING
653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct FormatThreadTestData
657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    double number;
659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString string;
660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FormatThreadTestData(double a, const UnicodeString& b) : number(a),string(b) {}
661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} ;
662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// "Someone from {2} is receiving a #{0} error - {1}. Their telephone call is costing {3 number,currency}."
665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
66659d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void formatErrorMessage(UErrorCode &realStatus, const UnicodeString& pattern, const Locale& theLocale,
667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     UErrorCode inStatus0, /* statusString 1 */ const Locale &inCountry2, double currency3, // these numbers are the message arguments.
668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     UnicodeString &result)
669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(realStatus))
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return; // you messed up
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString errString1(u_errorName(inStatus0));
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString countryName2;
676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    inCountry2.getDisplayCountry(theLocale,countryName2);
677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Formattable myArgs[] = {
679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Formattable((int32_t)inStatus0),   // inStatus0      {0}
680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Formattable(errString1), // statusString1 {1}
681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Formattable(countryName2),  // inCountry2 {2}
682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Formattable(currency3)// currency3  {3,number,currency}
683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    };
684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    MessageFormat *fmt = new MessageFormat("MessageFormat's API is broken!!!!!!!!!!!",realStatus);
686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fmt->setLocale(theLocale);
687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fmt->applyPattern(pattern, realStatus);
6881b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(realStatus)) {
690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete fmt;
691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
6941b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    FieldPosition ignore = 0;
695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fmt->format(myArgs,4,result,ignore,realStatus);
696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete fmt;
698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
70059d709d503bab6e2b61931737e662dd293b40578ccornelius/**
7011b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  * Shared formatters &  data used by instances of ThreadSafeFormat.
7021b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  * Exactly one instance of this class is created, and it is then shared concurrently
7031b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  * by the multiple instances of ThreadSafeFormat.
7041b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  */
7051b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubertclass ThreadSafeFormatSharedData {
7061b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  public:
7071b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    ThreadSafeFormatSharedData(UErrorCode &status);
7081b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    ~ThreadSafeFormatSharedData();
7091b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    LocalPointer<NumberFormat>  fFormat;
7101b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    Formattable    fYDDThing;
7111b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    Formattable    fBBDThing;
7121b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    UnicodeString  fYDDStr;
7131b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    UnicodeString  fBBDStr;
7141b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert};
7151b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
7161b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubertconst ThreadSafeFormatSharedData *gSharedData = NULL;
7171b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
7181b7d32f919554dda9c193b32188251337bc756f1Fredrik RoubertThreadSafeFormatSharedData::ThreadSafeFormatSharedData(UErrorCode &status) {
7191b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    fFormat.adoptInstead(NumberFormat::createCurrencyInstance(Locale::getUS(), status));
7201b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    static const UChar kYDD[] = { 0x59, 0x44, 0x44, 0x00 };
7211b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    static const UChar kBBD[] = { 0x42, 0x42, 0x44, 0x00 };
7221b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    fYDDThing.adoptObject(new CurrencyAmount(123.456, kYDD, status));
7231b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    fBBDThing.adoptObject(new CurrencyAmount(987.654, kBBD, status));
7241b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    if (U_FAILURE(status)) {
7251b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        return;
7261b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    }
7271b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    fFormat->format(fYDDThing, fYDDStr, NULL, status);
7281b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    fFormat->format(fBBDThing, fBBDStr, NULL, status);
7291b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    gSharedData = this;
7301b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert}
7311b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
7321b7d32f919554dda9c193b32188251337bc756f1Fredrik RoubertThreadSafeFormatSharedData::~ThreadSafeFormatSharedData() {
7331b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    gSharedData = NULL;
7341b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert}
7351b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
7361b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert/**
7371b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert * Class for thread-safe testing of format.
7381b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert *   Instances of this class appear as members of class FormatThreadTest.
7391b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert *   Multiple instances of FormatThreadTest coexist.
7401b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert *   ThreadSafeFormat::doStuff() is called concurrently to test the thread safety of
7411b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert *   various shared format operations.
74259d709d503bab6e2b61931737e662dd293b40578ccornelius */
74359d709d503bab6e2b61931737e662dd293b40578ccorneliusclass ThreadSafeFormat {
74459d709d503bab6e2b61931737e662dd293b40578ccorneliuspublic:
74559d709d503bab6e2b61931737e662dd293b40578ccornelius  /* give a unique offset to each thread */
7461b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  ThreadSafeFormat(UErrorCode &status);
7471b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  UBool doStuff(int32_t offset, UnicodeString &appendErr, UErrorCode &status) const;
74859d709d503bab6e2b61931737e662dd293b40578ccorneliusprivate:
7491b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  LocalPointer<NumberFormat> fFormat; // formatter - en_US constructed currency
75059d709d503bab6e2b61931737e662dd293b40578ccornelius};
75159d709d503bab6e2b61931737e662dd293b40578ccornelius
75259d709d503bab6e2b61931737e662dd293b40578ccornelius
7531b7d32f919554dda9c193b32188251337bc756f1Fredrik RoubertThreadSafeFormat::ThreadSafeFormat(UErrorCode &status) {
7541b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  fFormat.adoptInstead(NumberFormat::createCurrencyInstance(Locale::getUS(), status));
75559d709d503bab6e2b61931737e662dd293b40578ccornelius}
75659d709d503bab6e2b61931737e662dd293b40578ccornelius
7571b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubertstatic const UChar kUSD[] = { 0x55, 0x53, 0x44, 0x00 };
75859d709d503bab6e2b61931737e662dd293b40578ccornelius
7591b7d32f919554dda9c193b32188251337bc756f1Fredrik RoubertUBool ThreadSafeFormat::doStuff(int32_t offset, UnicodeString &appendErr, UErrorCode &status) const {
76059d709d503bab6e2b61931737e662dd293b40578ccornelius  UBool okay = TRUE;
76159d709d503bab6e2b61931737e662dd293b40578ccornelius
76259d709d503bab6e2b61931737e662dd293b40578ccornelius  if(u_strcmp(fFormat->getCurrency(), kUSD)) {
76359d709d503bab6e2b61931737e662dd293b40578ccornelius    appendErr.append("fFormat currency != ")
76459d709d503bab6e2b61931737e662dd293b40578ccornelius      .append(kUSD)
76559d709d503bab6e2b61931737e662dd293b40578ccornelius      .append(", =")
76659d709d503bab6e2b61931737e662dd293b40578ccornelius      .append(fFormat->getCurrency())
76759d709d503bab6e2b61931737e662dd293b40578ccornelius      .append("! ");
76859d709d503bab6e2b61931737e662dd293b40578ccornelius    okay = FALSE;
76959d709d503bab6e2b61931737e662dd293b40578ccornelius  }
77059d709d503bab6e2b61931737e662dd293b40578ccornelius
7711b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  if(u_strcmp(gSharedData->fFormat->getCurrency(), kUSD)) {
77259d709d503bab6e2b61931737e662dd293b40578ccornelius    appendErr.append("gFormat currency != ")
77359d709d503bab6e2b61931737e662dd293b40578ccornelius      .append(kUSD)
77459d709d503bab6e2b61931737e662dd293b40578ccornelius      .append(", =")
7751b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      .append(gSharedData->fFormat->getCurrency())
77659d709d503bab6e2b61931737e662dd293b40578ccornelius      .append("! ");
77759d709d503bab6e2b61931737e662dd293b40578ccornelius    okay = FALSE;
77859d709d503bab6e2b61931737e662dd293b40578ccornelius  }
77959d709d503bab6e2b61931737e662dd293b40578ccornelius  UnicodeString str;
78059d709d503bab6e2b61931737e662dd293b40578ccornelius  const UnicodeString *o=NULL;
78159d709d503bab6e2b61931737e662dd293b40578ccornelius  Formattable f;
78259d709d503bab6e2b61931737e662dd293b40578ccornelius  const NumberFormat *nf = NULL; // only operate on it as const.
78359d709d503bab6e2b61931737e662dd293b40578ccornelius  switch(offset%4) {
7841b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  case 0:  f = gSharedData->fYDDThing;  o = &gSharedData->fYDDStr;  nf = gSharedData->fFormat.getAlias();  break;
7851b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  case 1:  f = gSharedData->fBBDThing;  o = &gSharedData->fBBDStr;  nf = gSharedData->fFormat.getAlias();  break;
7861b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  case 2:  f = gSharedData->fYDDThing;  o = &gSharedData->fYDDStr;  nf = fFormat.getAlias();  break;
7871b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  case 3:  f = gSharedData->fBBDThing;  o = &gSharedData->fBBDStr;  nf = fFormat.getAlias();  break;
78859d709d503bab6e2b61931737e662dd293b40578ccornelius  }
78959d709d503bab6e2b61931737e662dd293b40578ccornelius  nf->format(f, str, NULL, status);
79059d709d503bab6e2b61931737e662dd293b40578ccornelius
79159d709d503bab6e2b61931737e662dd293b40578ccornelius  if(*o != str) {
79259d709d503bab6e2b61931737e662dd293b40578ccornelius    appendErr.append(showDifference(*o, str));
79359d709d503bab6e2b61931737e662dd293b40578ccornelius    okay = FALSE;
79459d709d503bab6e2b61931737e662dd293b40578ccornelius  }
79559d709d503bab6e2b61931737e662dd293b40578ccornelius  return okay;
79659d709d503bab6e2b61931737e662dd293b40578ccornelius}
797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool U_CALLCONV isAcceptable(void *, const char *, const char *, const UDataInfo *) {
799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//static UMTX debugMutex = NULL;
803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//static UMTX gDebugMutex;
804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass FormatThreadTest : public ThreadWithStatus
807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querupublic:
809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int     fNum;
810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int     fTraceInfo;
811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
8121b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    LocalPointer<ThreadSafeFormat> fTSF;
81359d709d503bab6e2b61931737e662dd293b40578ccornelius
814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FormatThreadTest() // constructor is NOT multithread safe.
815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        : ThreadWithStatus(),
816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fNum(0),
817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fTraceInfo(0),
8181b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        fTSF(NULL),
819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fOffset(0)
820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // the locale to use
821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
8221b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        UErrorCode status = U_ZERO_ERROR;      // TODO: rearrange code to allow checking of status.
8231b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        fTSF.adoptInstead(new ThreadSafeFormat(status));
824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        static int32_t fgOffset = 0;
825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fgOffset += 3;
826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fOffset = fgOffset;
827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    virtual void run()
831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fTraceInfo                     = 1;
83350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        LocalPointer<NumberFormat> percentFormatter;
834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UErrorCode status = U_ZERO_ERROR;
835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if 0
8371b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        // debugging code,
838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (int i=0; i<4000; i++) {
839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            status = U_ZERO_ERROR;
840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UDataMemory *data1 = udata_openChoice(0, "res", "en_US", isAcceptable, 0, &status);
841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UDataMemory *data2 = udata_openChoice(0, "res", "fr", isAcceptable, 0, &status);
842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            udata_close(data1);
843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            udata_close(data2);
844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (U_FAILURE(status)) {
845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                error("udata_openChoice failed.\n");
846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if 0
8531b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        // debugging code,
854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int m;
855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (m=0; m<4000; m++) {
856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            status         = U_ZERO_ERROR;
857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UResourceBundle *res   = NULL;
858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const char *localeName = NULL;
859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            Locale  loc = Locale::getEnglish();
861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            localeName = loc.getName();
863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // localeName = "en";
864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // ResourceBundle bund = ResourceBundle(0, loc, status);
866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            //umtx_lock(&gDebugMutex);
867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            res = ures_open(NULL, localeName, &status);
868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            //umtx_unlock(&gDebugMutex);
869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            //umtx_lock(&gDebugMutex);
871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ures_close(res);
872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            //umtx_unlock(&gDebugMutex);
873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (U_FAILURE(status)) {
875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                error("Resource bundle construction failed.\n");
876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Keep this data here to avoid static initialization.
8831b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        FormatThreadTestData kNumberFormatTestData[] =
884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            FormatThreadTestData((double)5.0, UnicodeString("5", "")),
886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                FormatThreadTestData( 6.0, UnicodeString("6", "")),
887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                FormatThreadTestData( 20.0, UnicodeString("20", "")),
888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                FormatThreadTestData( 8.0, UnicodeString("8", "")),
889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                FormatThreadTestData( 8.3, UnicodeString("8.3", "")),
890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                FormatThreadTestData( 12345, UnicodeString("12,345", "")),
891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                FormatThreadTestData( 81890.23, UnicodeString("81,890.23", "")),
892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        };
8931b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        int32_t kNumberFormatTestDataLength = UPRV_LENGTHOF(kNumberFormatTestData);
8941b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Keep this data here to avoid static initialization.
8961b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        FormatThreadTestData kPercentFormatTestData[] =
897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            FormatThreadTestData((double)5.0, CharsToUnicodeString("500\\u00a0%")),
899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                FormatThreadTestData( 1.0, CharsToUnicodeString("100\\u00a0%")),
900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                FormatThreadTestData( 0.26, CharsToUnicodeString("26\\u00a0%")),
9011b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert                FormatThreadTestData(
902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                   16384.99, CharsToUnicodeString("1\\u00a0638\\u00a0499\\u00a0%")), // U+00a0 = NBSP
9031b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert                FormatThreadTestData(
904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    81890.23, CharsToUnicodeString("8\\u00a0189\\u00a0023\\u00a0%")),
905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        };
9061b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        int32_t kPercentFormatTestDataLength = UPRV_LENGTHOF(kPercentFormatTestData);
907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t iteration;
9081b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        status = U_ZERO_ERROR;
91050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        LocalPointer<NumberFormat> formatter(NumberFormat::createInstance(Locale::getEnglish(),status));
911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(U_FAILURE(status)) {
9126d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru            error("Error on NumberFormat::createInstance().");
913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            goto cleanupAndReturn;
914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
9151b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
91650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        percentFormatter.adoptInstead(NumberFormat::createPercentInstance(Locale::getFrench(),status));
917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(U_FAILURE(status))             {
9186d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru            error("Error on NumberFormat::createPercentInstance().");
919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            goto cleanupAndReturn;
920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
9211b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(iteration = 0;!getError() && iteration<kFormatThreadIterations;iteration++)
923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
9241b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t whichLine = (iteration + fOffset)%kNumberFormatTestDataLength;
9261b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UnicodeString  output;
9281b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            formatter->format(kNumberFormatTestData[whichLine].number, output);
9301b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(0 != output.compare(kNumberFormatTestData[whichLine].string)) {
9321b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert                error("format().. expected " + kNumberFormatTestData[whichLine].string
933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        + " got " + output);
934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                goto cleanupAndReturn;
935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
9361b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Now check percent.
938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            output.remove();
939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            whichLine = (iteration + fOffset)%kPercentFormatTestDataLength;
9401b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            percentFormatter->format(kPercentFormatTestData[whichLine].number, output);
942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(0 != output.compare(kPercentFormatTestData[whichLine].string))
943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
9441b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert                error("percent format().. \n" +
945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        showDifference(kPercentFormatTestData[whichLine].string,output));
946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                goto cleanupAndReturn;
947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
9481b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
9491b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert            // Test message error
950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const int       kNumberOfMessageTests = 3;
951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UErrorCode      statusToCheck;
952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UnicodeString   patternToCheck;
953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            Locale          messageLocale;
954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            Locale          countryToCheck;
955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            double          currencyToCheck;
9561b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UnicodeString   expected;
9581b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // load the cases.
960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            switch((iteration+fOffset) % kNumberOfMessageTests)
961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            default:
963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            case 0:
964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                statusToCheck=                      U_FILE_ACCESS_ERROR;
965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                patternToCheck=        "0:Someone from {2} is receiving a #{0}"
966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                       " error - {1}. Their telephone call is costing "
967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                       "{3,number,currency}."; // number,currency
968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                messageLocale=                      Locale("en","US");
969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                countryToCheck=                     Locale("","HR");
970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                currencyToCheck=                    8192.77;
971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                expected=  "0:Someone from Croatia is receiving a #4 error - "
972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            "U_FILE_ACCESS_ERROR. Their telephone call is costing $8,192.77.";
973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            case 1:
975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                statusToCheck=                      U_INDEX_OUTOFBOUNDS_ERROR;
9761b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert                patternToCheck=                     "1:A customer in {2} is receiving a #{0} error - {1}. "
9771b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert                                                    "Their telephone call is costing {3,number,currency}."; // number,currency
978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                messageLocale=                      Locale("de","DE@currency=DEM");
979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                countryToCheck=                     Locale("","BF");
980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                currencyToCheck=                    2.32;
981c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                expected=                           CharsToUnicodeString(
9821b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert                                                    "1:A customer in Burkina Faso is receiving a #8 error - U_INDEX_OUTOFBOUNDS_ERROR. "
9831b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert                                                    "Their telephone call is costing 2,32\\u00A0DM.");
984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            case 2:
986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                statusToCheck=                      U_MEMORY_ALLOCATION_ERROR;
987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                patternToCheck=   "2:user in {2} is receiving a #{0} error - {1}. "
988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  "They insist they just spent {3,number,currency} "
989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  "on memory."; // number,currency
990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                messageLocale=                      Locale("de","AT@currency=ATS"); // Austrian German
991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                countryToCheck=                     Locale("","US"); // hmm
992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                currencyToCheck=                    40193.12;
993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                expected=       CharsToUnicodeString(
994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            "2:user in Vereinigte Staaten is receiving a #7 error"
995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            " - U_MEMORY_ALLOCATION_ERROR. They insist they just spent"
996c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                            " \\u00f6S\\u00A040.193,12 on memory.");
997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
9991b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
1000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UnicodeString result;
1001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UErrorCode status = U_ZERO_ERROR;
1002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            formatErrorMessage(status,patternToCheck,messageLocale,statusToCheck,
1003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                countryToCheck,currencyToCheck,result);
1004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(U_FAILURE(status))
1005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UnicodeString tmp(u_errorName(status));
1007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                error("Failure on message format, pattern=" + patternToCheck +
1008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        ", error = " + tmp);
1009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                goto cleanupAndReturn;
1010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
10111b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
1012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(result != expected)
1013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                error("PatternFormat: \n" + showDifference(expected,result));
1015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                goto cleanupAndReturn;
1016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
101759d709d503bab6e2b61931737e662dd293b40578ccornelius            // test the Thread Safe Format
101859d709d503bab6e2b61931737e662dd293b40578ccornelius            UnicodeString appendErr;
10191b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert            if(!fTSF->doStuff(fNum, appendErr, status)) {
102059d709d503bab6e2b61931737e662dd293b40578ccornelius              error(appendErr);
102159d709d503bab6e2b61931737e662dd293b40578ccornelius              goto cleanupAndReturn;
102259d709d503bab6e2b61931737e662dd293b40578ccornelius            }
1023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }   /*  end of for loop */
102459d709d503bab6e2b61931737e662dd293b40578ccornelius
102559d709d503bab6e2b61931737e662dd293b40578ccornelius
102659d709d503bab6e2b61931737e662dd293b40578ccornelius
1027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerucleanupAndReturn:
1028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //  while (fNum == 4) {SimpleThread::sleep(10000);}   // Force a failure by preventing thread from finishing
1029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fTraceInfo = 2;
1030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
10311b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
1032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruprivate:
1033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t fOffset; // where we are testing from.
1034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
1035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ** The actual test function.
1037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid MultithreadTest::TestThreadedIntl()
1039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int i;
1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString theErr;
1042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool   haveDisplayedInfo[kFormatThreadThreads];
1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static const int32_t PATIENCE_SECONDS = 45;
1044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
104559d709d503bab6e2b61931737e662dd293b40578ccornelius    UErrorCode threadSafeErr = U_ZERO_ERROR;
104659d709d503bab6e2b61931737e662dd293b40578ccornelius
10471b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    ThreadSafeFormatSharedData sharedData(threadSafeErr);
104859d709d503bab6e2b61931737e662dd293b40578ccornelius    assertSuccess("initializing ThreadSafeFormat", threadSafeErr, TRUE);
104959d709d503bab6e2b61931737e662dd293b40578ccornelius
1050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //
1051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //  Create and start the test threads
1052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //
1053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    logln("Spawning: %d threads * %d iterations each.",
1054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                kFormatThreadThreads, kFormatThreadIterations);
105550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    LocalArray<FormatThreadTest> tests(new FormatThreadTest[kFormatThreadThreads]);
1056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(int32_t j = 0; j < kFormatThreadThreads; j++) {
1057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        tests[j].fNum = j;
1058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t threadStatus = tests[j].start();
1059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (threadStatus != 0) {
1060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            errln("System Error %d starting thread number %d.", threadStatus, j);
1061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            SimpleThread::errorFunc();
106250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            return;
1063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        haveDisplayedInfo[j] = FALSE;
1065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Spin, waiting for the test threads to finish.
1069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool   stillRunning;
1070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDate startTime, endTime;
1071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    startTime = Calendar::getNow();
107259d709d503bab6e2b61931737e662dd293b40578ccornelius    double lastComplaint = 0;
1073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    do {
1074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*  Spin until the test threads  complete. */
1075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        stillRunning = FALSE;
1076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        endTime = Calendar::getNow();
107759d709d503bab6e2b61931737e662dd293b40578ccornelius        double elapsedSeconds =  ((int32_t)(endTime - startTime)/U_MILLIS_PER_SECOND);
107859d709d503bab6e2b61931737e662dd293b40578ccornelius        if (elapsedSeconds > PATIENCE_SECONDS) {
1079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            errln("Patience exceeded. Test is taking too long.");
1080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
108159d709d503bab6e2b61931737e662dd293b40578ccornelius        } else if((elapsedSeconds-lastComplaint) > 2.0) {
108259d709d503bab6e2b61931737e662dd293b40578ccornelius            infoln("%.1f seconds elapsed (still waiting..)", elapsedSeconds);
108359d709d503bab6e2b61931737e662dd293b40578ccornelius            lastComplaint = elapsedSeconds;
1084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
1086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         The following sleep must be here because the *BSD operating systems
1087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         have a brain dead thread scheduler. They starve the child threads from
1088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         CPU time.
1089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        */
1090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        SimpleThread::sleep(1); // yield
1091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(i=0;i<kFormatThreadThreads;i++) {
1092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (tests[i].isRunning()) {
1093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                stillRunning = TRUE;
1094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else if (haveDisplayedInfo[i] == FALSE) {
1095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                logln("Thread # %d is complete..", i);
1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(tests[i].getError(theErr)) {
10976d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru                    dataerrln(UnicodeString("#") + i + ": " + theErr);
1098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    SimpleThread::errorFunc();
1099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                haveDisplayedInfo[i] = TRUE;
1101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } while (stillRunning);
1104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //
1106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //  All threads have finished.
1107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //
110859d709d503bab6e2b61931737e662dd293b40578ccornelius    assertSuccess("finalizing ThreadSafeFormat", threadSafeErr, TRUE);
1109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */
1111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------------------------------
1117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
1118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Collation threading test
1119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
1120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------------------------------
1121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_COLLATION
1122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define kCollatorThreadThreads   10  // # of threads to spawn
1124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define kCollatorThreadPatience kCollatorThreadThreads*30
1125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct Line {
1127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar buff[25];
1128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t buflen;
1129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} ;
1130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
113154dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic UBool
113254dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusskipLineBecauseOfBug(const UChar *s, int32_t length) {
113354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    // TODO: Fix ICU ticket #8052
113454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    if(length >= 3 &&
113554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            (s[0] == 0xfb2 || s[0] == 0xfb3) &&
113654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            s[1] == 0x334 &&
113754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            (s[2] == 0xf73 || s[2] == 0xf75 || s[2] == 0xf81)) {
113854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        return TRUE;
113954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    }
114054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    return FALSE;
114154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
114254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
114354dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic UCollationResult
114454dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusnormalizeResult(int32_t result) {
114554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    return result<0 ? UCOL_LESS : result==0 ? UCOL_EQUAL : UCOL_GREATER;
114654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
114754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
1148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass CollatorThreadTest : public ThreadWithStatus
1149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
11501b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubertprivate:
115154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    const Collator *coll;
1152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const Line *lines;
1153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t noLines;
115454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    UBool isAtLeastUCA62;
1155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querupublic:
1156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CollatorThreadTest()  : ThreadWithStatus(),
1157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        coll(NULL),
1158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        lines(NULL),
115954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        noLines(0),
116054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        isAtLeastUCA62(TRUE)
1161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    };
116354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    void setCollator(Collator *c, Line *l, int32_t nl, UBool atLeastUCA62)
1164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        coll = c;
1166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        lines = l;
1167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        noLines = nl;
116854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        isAtLeastUCA62 = atLeastUCA62;
1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    virtual void run() {
1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uint8_t sk1[1024], sk2[1024];
1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uint8_t *oldSk = NULL, *newSk = sk1;
117354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        int32_t oldLen = 0;
117454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        int32_t prev = 0;
1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t i = 0;
117627f654740f2a26ad62a5c155af9199af9e69b889claireho
1177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(i = 0; i < noLines; i++) {
117854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            if(lines[i].buflen == 0) { continue; }
117954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
118054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            if(skipLineBecauseOfBug(lines[i].buff, lines[i].buflen)) { continue; }
118127f654740f2a26ad62a5c155af9199af9e69b889claireho
118254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            int32_t resLen = coll->getSortKey(lines[i].buff, lines[i].buflen, newSk, 1024);
118327f654740f2a26ad62a5c155af9199af9e69b889claireho
1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(oldSk != NULL) {
118554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                int32_t skres = strcmp((char *)oldSk, (char *)newSk);
118654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                int32_t cmpres = coll->compare(lines[prev].buff, lines[prev].buflen, lines[i].buff, lines[i].buflen);
118754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                int32_t cmpres2 = coll->compare(lines[i].buff, lines[i].buflen, lines[prev].buff, lines[prev].buflen);
118827f654740f2a26ad62a5c155af9199af9e69b889claireho
1189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(cmpres != -cmpres2) {
11908393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    error(UnicodeString("Compare result not symmetrical on line ") + (i + 1));
1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
1192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
119327f654740f2a26ad62a5c155af9199af9e69b889claireho
119454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                if(cmpres != normalizeResult(skres)) {
119554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                    error(UnicodeString("Difference between coll->compare and sortkey compare on line ") + (i + 1));
1196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
119827f654740f2a26ad62a5c155af9199af9e69b889claireho
119954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                int32_t res = cmpres;
120054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                if(res == 0 && !isAtLeastUCA62) {
120154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                    // Up to UCA 6.1, the collation test files use a custom tie-breaker,
120254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                    // comparing the raw input strings.
120354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                    res = u_strcmpCodePointOrder(lines[prev].buff, lines[i].buff);
120454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                    // Starting with UCA 6.2, the collation test files use the standard UCA tie-breaker,
120554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                    // comparing the NFD versions of the input strings,
120654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                    // which we do via setting strength=identical.
120754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                }
1208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(res > 0) {
120954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                    error(UnicodeString("Line is not greater or equal than previous line, for line ") + (i + 1));
1210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
1211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
121327f654740f2a26ad62a5c155af9199af9e69b889claireho
1214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            oldSk = newSk;
1215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            oldLen = resLen;
121659d709d503bab6e2b61931737e662dd293b40578ccornelius            (void)oldLen;   // Suppress set but not used warning.
121754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            prev = i;
121827f654740f2a26ad62a5c155af9199af9e69b889claireho
1219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            newSk = (newSk == sk1)?sk2:sk1;
1220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
1223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid MultithreadTest::TestCollators()
1225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
1228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FILE *testFile = NULL;
1229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char testDataPath[1024];
1230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    strcpy(testDataPath, IntlTest::getSourceTestData(status));
1231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
1232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        errln("ERROR: could not open test data %s", u_errorName(status));
1233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
1234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    strcat(testDataPath, "CollationTest_");
1236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char* type = "NON_IGNORABLE";
1238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *ext = ".txt";
1240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(testFile) {
1241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fclose(testFile);
1242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char buffer[1024];
1244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    strcpy(buffer, testDataPath);
1245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    strcat(buffer, type);
1246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    size_t bufLen = strlen(buffer);
1247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // we try to open 3 files:
1249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // path/CollationTest_type.txt
1250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // path/CollationTest_type_SHORT.txt
1251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // path/CollationTest_type_STUB.txt
1252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // we are going to test with the first one that we manage to open.
1253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    strcpy(buffer+bufLen, ext);
1255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    testFile = fopen(buffer, "rb");
1257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(testFile == 0) {
1259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        strcpy(buffer+bufLen, "_SHORT");
1260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        strcat(buffer, ext);
1261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        testFile = fopen(buffer, "rb");
1262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(testFile == 0) {
1264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            strcpy(buffer+bufLen, "_STUB");
1265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            strcat(buffer, ext);
1266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            testFile = fopen(buffer, "rb");
1267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (testFile == 0) {
1269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                *(buffer+bufLen) = 0;
12706d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru                dataerrln("could not open any of the conformance test files, tried opening base %s", buffer);
12711b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert                return;
1272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
1273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                infoln(
1274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    "INFO: Working with the stub file.\n"
1275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    "If you need the full conformance test, please\n"
1276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    "download the appropriate data files from:\n"
1277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    "http://source.icu-project.org/repos/icu/tools/trunk/unicodetools/com/ibm/text/data/");
1278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
128254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    LocalArray<Line> lines(new Line[200000]);
128354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    memset(lines.getAlias(), 0, sizeof(Line)*200000);
1284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t lineNum = 0;
1285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar bufferU[1024];
1287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t first = 0;
1288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (fgets(buffer, 1024, testFile) != NULL) {
129054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        if(*buffer == 0 || buffer[0] == '#') {
129154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            // Store empty and comment lines so that errors are reported
129254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            // for the real test file lines.
129354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            lines[lineNum].buflen = 0;
129454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            lines[lineNum].buff[0] = 0;
129554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        } else {
129654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            int32_t buflen = u_parseString(buffer, bufferU, 1024, &first, &status);
129754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            lines[lineNum].buflen = buflen;
129854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            u_memcpy(lines[lineNum].buff, bufferU, buflen);
129954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            lines[lineNum].buff[buflen] = 0;
1300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        lineNum++;
1302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fclose(testFile);
1304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(status)) {
13056d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru      dataerrln("Couldn't read the test file!");
1306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      return;
1307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
130954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    UVersionInfo uniVersion;
131054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    static const UVersionInfo v62 = { 6, 2, 0, 0 };
131154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    u_getUnicodeVersion(uniVersion);
131254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    UBool isAtLeastUCA62 = uprv_memcmp(uniVersion, v62, 4) >= 0;
131354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
131454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    LocalPointer<Collator> coll(Collator::createInstance(Locale::getRoot(), status));
1315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(status)) {
13166d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru        errcheckln(status, "Couldn't open UCA collator");
1317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
1318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
131954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    coll->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status);
132054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    coll->setAttribute(UCOL_CASE_FIRST, UCOL_OFF, status);
132154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    coll->setAttribute(UCOL_CASE_LEVEL, UCOL_OFF, status);
132254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    coll->setAttribute(UCOL_STRENGTH, isAtLeastUCA62 ? UCOL_IDENTICAL : UCOL_TERTIARY, status);
132354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    coll->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_NON_IGNORABLE, status);
1324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t noSpawned = 0;
1326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t spawnResult = 0;
132750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    LocalArray<CollatorThreadTest> tests(new CollatorThreadTest[kCollatorThreadThreads]);
1328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    logln(UnicodeString("Spawning: ") + kCollatorThreadThreads + " threads * " + kFormatThreadIterations + " iterations each.");
1330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t j = 0;
1331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(j = 0; j < kCollatorThreadThreads; j++) {
1332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //logln("Setting collator %i", j);
133354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        tests[j].setCollator(coll.getAlias(), lines.getAlias(), lineNum, isAtLeastUCA62);
1334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(j = 0; j < kCollatorThreadThreads; j++) {
1336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        log("%i ", j);
1337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        spawnResult = tests[j].start();
1338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(spawnResult != 0) {
1339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            infoln("THREAD INFO: Couldn't spawn more than %i threads", noSpawned);
1340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
1341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        noSpawned++;
1343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    logln("Spawned all");
1345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (noSpawned == 0) {
1346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        errln("No threads could be spawned.");
1347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
1348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(int32_t patience = kCollatorThreadPatience;patience > 0; patience --)
1351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        logln("Waiting...");
1353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t i;
1355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t terrs = 0;
1356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t completed =0;
1357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(i=0;i<kCollatorThreadThreads;i++)
1359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (tests[i].isRunning() == FALSE)
1361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                completed++;
1363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                //logln(UnicodeString("Test #") + i + " is complete.. ");
1365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UnicodeString theErr;
1367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(tests[i].getError(theErr))
1368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                {
1369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    terrs++;
1370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    errln(UnicodeString("#") + i + ": " + theErr);
1371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // print out the error, too, if any.
1373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        logln("Completed %i tests", completed);
1376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(completed == noSpawned)
1378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            logln("Done! All %i tests are finished", noSpawned);
1380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(terrs)
1382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                errln("There were errors.");
1384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                SimpleThread::errorFunc();
1385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
1387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        SimpleThread::sleep(900);
1390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    errln("patience exceeded. ");
1392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SimpleThread::errorFunc();
1393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_COLLATION */
1396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------------------------------
1401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
14021b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert//   StringThreadTest2
1403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
1404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------------------------------
1405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int kStringThreadIterations = 2500;// # of iterations per thread
1407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int kStringThreadThreads    = 10;  // # of threads to spawn
1408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int kStringThreadPatience   = 120; // time in seconds to wait for all threads
1409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass StringThreadTest2 : public ThreadWithStatus
1412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querupublic:
1414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int                 fNum;
1415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int                 fTraceInfo;
1416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UnicodeString *fSharedString;
1417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    StringThreadTest2(const UnicodeString *sharedString, int num) // constructor is NOT multithread safe.
1419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        : ThreadWithStatus(),
1420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fNum(num),
1421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fTraceInfo(0),
1422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fSharedString(sharedString)
1423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    };
1425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    virtual void run()
1428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fTraceInfo    = 1;
1430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int loopCount = 0;
1431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (loopCount = 0; loopCount < kStringThreadIterations; loopCount++) {
1433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (*fSharedString != "This is the original test string.") {
1434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                error("Original string is corrupt.");
1435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
1436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UnicodeString s1 = *fSharedString;
1438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            s1 += "cat this";
1439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UnicodeString s2(s1);
1440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UnicodeString s3 = *fSharedString;
1441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            s2 = s3;
1442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            s3.truncate(12);
1443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            s2.truncate(0);
1444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //  while (fNum == 4) {SimpleThread::sleep(10000);}   // Force a failure by preventing thread from finishing
1447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fTraceInfo = 2;
1448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
14491b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
1450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
1451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ** The actual test function.
1453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid MultithreadTest::TestString()
1455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int     patience;
1457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int     terrs = 0;
1458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int     j;
1459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString *testString = new UnicodeString("This is the original test string.");
1461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
146250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // Not using LocalArray<StringThreadTest2> tests[kStringThreadThreads];
146350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // because we don't always want to delete them.
146450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // See the comments below the cleanupAndReturn label.
1465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    StringThreadTest2  *tests[kStringThreadThreads];
1466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(j = 0; j < kStringThreadThreads; j++) {
1467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        tests[j] = new StringThreadTest2(testString, j);
1468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
14691b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
1470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    logln(UnicodeString("Spawning: ") + kStringThreadThreads + " threads * " + kStringThreadIterations + " iterations each.");
1471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(j = 0; j < kStringThreadThreads; j++) {
1472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t threadStatus = tests[j]->start();
1473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (threadStatus != 0) {
1474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            errln("System Error %d starting thread number %d.", threadStatus, j);
14751b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert            SimpleThread::errorFunc();
1476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            goto cleanupAndReturn;
1477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(patience = kStringThreadPatience;patience > 0; patience --)
1481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        logln("Waiting...");
1483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t i;
1485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        terrs = 0;
1486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t completed =0;
1487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(i=0;i<kStringThreadThreads;i++) {
1489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (tests[i]->isRunning() == FALSE)
1490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                completed++;
14921b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
1493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                logln(UnicodeString("Test #") + i + " is complete.. ");
14941b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
1495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UnicodeString theErr;
1496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(tests[i]->getError(theErr))
1497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                {
1498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    terrs++;
1499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    errln(UnicodeString("#") + i + ": " + theErr);
1500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // print out the error, too, if any.
1502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
15041b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
1505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(completed == kStringThreadThreads)
1506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            logln("Done!");
1508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(terrs) {
1509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                errln("There were errors.");
1510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
1512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        SimpleThread::sleep(900);
1515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (patience <= 0) {
1518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        errln("patience exceeded. ");
1519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // while (TRUE) {SimpleThread::sleep(10000);}   // TODO:   for debugging.  Sleep forever on failure.
1520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        terrs++;
1521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (terrs > 0) {
15241b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        SimpleThread::errorFunc();
1525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerucleanupAndReturn:
1528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (terrs == 0) {
1529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
1530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Don't clean up if there are errors. This prevents crashes if the
1531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        threads are still running and using this data. This will only happen
1532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if there is an error with the test, ICU, or the machine is too slow.
1533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        It's better to leak than crash.
1534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        */
1535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(j = 0; j < kStringThreadThreads; j++) {
1536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delete tests[j];
1537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete testString;
1539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1542fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
1543fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// Test for ticket #10673, race in cache code in AnyTransliterator.
1544fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// It's difficult to make the original unsafe code actually fail, but
15451b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert// this test will fairly reliably take the code path for races in
1546fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// populating the cache.
1547fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
1548fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#if !UCONFIG_NO_TRANSLITERATION
1549fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusclass TxThread: public SimpleThread {
1550fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  private:
1551fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    Transliterator *fSharedTranslit;
1552fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  public:
1553fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UBool fSuccess;
1554fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    TxThread(Transliterator *tx) : fSharedTranslit(tx), fSuccess(FALSE) {};
1555fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    ~TxThread();
1556fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    void run();
1557fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius};
1558fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
1559fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusTxThread::~TxThread() {}
1560fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid TxThread::run() {
1561fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UnicodeString greekString("\\u03B4\\u03B9\\u03B1\\u03C6\\u03BF\\u03C1\\u03B5\\u03C4\\u03B9\\u03BA\\u03BF\\u03CD\\u03C2");
1562fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    greekString = greekString.unescape();
1563fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fSharedTranslit->transliterate(greekString);
1564fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fSuccess = greekString[0] == 0x64; // 'd'. The whole transliterated string is "diaphoretikous" (accented u).
1565fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
1566fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#endif
15671b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
1568fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
1569fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid MultithreadTest::TestAnyTranslit() {
1570fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#if !UCONFIG_NO_TRANSLITERATION
1571fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UErrorCode status = U_ZERO_ERROR;
1572fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    LocalPointer<Transliterator> tx(Transliterator::createInstance("Any-Latin", UTRANS_FORWARD, status));
1573fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if (U_FAILURE(status)) {
1574fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        dataerrln("File %s, Line %d: Error, status = %s", __FILE__, __LINE__, u_errorName(status));
1575fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return;
1576fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
1577fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    TxThread * threads[4];
1578fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    int32_t i;
1579fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    for (i=0; i<4; i++) {
1580fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        threads[i] = new TxThread(tx.getAlias());
1581fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
1582fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    for (i=0; i<4; i++) {
1583fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        threads[i]->start();
1584fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
1585fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    int32_t patience = 100;
1586fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UBool success;
1587fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UBool someThreadRunning;
1588fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    do {
1589fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        someThreadRunning = FALSE;
1590fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        success = TRUE;
1591fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        for (i=0; i<4; i++) {
1592fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            if (threads[i]->isRunning()) {
1593fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                someThreadRunning = TRUE;
1594fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                SimpleThread::sleep(10);
1595fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                break;
1596fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            } else {
1597fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                if (threads[i]->fSuccess == FALSE) {
1598fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    success = FALSE;
1599fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                }
1600fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            }
1601fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
1602fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    } while (someThreadRunning && --patience > 0);
1603fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
1604fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if (patience <= 0) {
1605fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        errln("File %s, Line %d: Error, one or more threads did not complete.", __FILE__, __LINE__);
1606fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
1607fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if (success == FALSE) {
1608fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        errln("File %s, Line %d: Error, transliteration result incorrect.", __FILE__, __LINE__);
1609fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
16101b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
1611fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    for (i=0; i<4; i++) {
1612fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        delete threads[i];
1613fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
1614fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#endif  // !UCONFIG_NO_TRANSLITERATION
1615fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
1616fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
1617f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1618f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius// Condition Variables Test
1619f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius//   Create a swarm of threads.
1620f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius//   Using a mutex and a condition variables each thread
1621f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius//     Increments a global count of started threads.
1622f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius//     Broadcasts that it has started.
1623f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius//     Waits on the condition that all threads have started.
1624f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius//     Increments a global count of finished threads.
1625f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius//     Waits on the condition that all threads have finished.
1626f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius//     Exits.
1627f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1628f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusclass CondThread: public SimpleThread {
1629f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius  public:
1630f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    CondThread() :fFinished(false)  {};
1631f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    ~CondThread() {};
1632f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    void run();
1633f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    bool  fFinished;
1634f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius};
1635f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1636f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic UMutex gCTMutex = U_MUTEX_INITIALIZER;
1637f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic UConditionVar gCTConditionVar = U_CONDITION_INITIALIZER;
1638f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusint gConditionTestOne = 1;   // Value one. Non-const, extern linkage to inhibit
1639f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                             //   compiler assuming a known value.
16401b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubertint gStartedThreads;
1641f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusint gFinishedThreads;
1642f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic const int NUMTHREADS = 10;
1643f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1644f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic MultithreadTest *gThisTest = NULL; // Make test frame work functions available to
1645f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                                          //   non-member functions.
1646f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1647f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius// Worker thread function.
1648f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusvoid CondThread::run() {
16491b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    umtx_lock(&gCTMutex);
1650f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    gStartedThreads += gConditionTestOne;
1651f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    umtx_condBroadcast(&gCTConditionVar);
16521b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
1653f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    while (gStartedThreads < NUMTHREADS) {
1654f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        if (gFinishedThreads != 0) {
16551b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert            gThisTest->errln("File %s, Line %d: Error, gStartedThreads = %d, gFinishedThreads = %d",
1656f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                             __FILE__, __LINE__, gStartedThreads, gFinishedThreads);
1657f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        }
1658f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        umtx_condWait(&gCTConditionVar, &gCTMutex);
1659f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1660f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1661f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    gFinishedThreads += gConditionTestOne;
1662f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    fFinished = true;
1663f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    umtx_condBroadcast(&gCTConditionVar);
1664f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1665f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    while (gFinishedThreads < NUMTHREADS) {
1666f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        umtx_condWait(&gCTConditionVar, &gCTMutex);
1667f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1668f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    umtx_unlock(&gCTMutex);
1669f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1670f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1671f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusvoid MultithreadTest::TestConditionVariables() {
1672f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    gThisTest = this;
1673f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    gStartedThreads = 0;
1674f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    gFinishedThreads = 0;
1675f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    int i;
1676f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1677f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    umtx_lock(&gCTMutex);
1678f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    CondThread *threads[NUMTHREADS];
1679f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    for (i=0; i<NUMTHREADS; ++i) {
1680f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        threads[i] = new CondThread;
1681f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        threads[i]->start();
1682f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1683f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1684f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    while (gStartedThreads < NUMTHREADS) {
1685f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        umtx_condWait(&gCTConditionVar, &gCTMutex);
1686f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1687f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1688f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    while (gFinishedThreads < NUMTHREADS) {
1689f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        umtx_condWait(&gCTConditionVar, &gCTMutex);
1690f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1691f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1692f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    umtx_unlock(&gCTMutex);
1693f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1694f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    for (i=0; i<NUMTHREADS; ++i) {
1695f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        if (!threads[i]->fFinished) {
1696f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            errln("File %s, Line %d: Error, threads[%d]->fFinished == false", __FILE__, __LINE__, i);
1697f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        }
1698f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        delete threads[i];
1699f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1700f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1701f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1702f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic const char *gCacheLocales[] = {"en_US", "en_GB", "fr_FR", "fr"};
1703f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic int32_t gObjectsCreated = 0;
1704f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic const int32_t CACHE_LOAD = 3;
1705f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1706f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusclass UCTMultiThreadItem : public SharedObject {
1707f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius  public:
1708f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    char *value;
17091b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    UCTMultiThreadItem(const char *x) : value(NULL) {
1710f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        value = uprv_strdup(x);
1711f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
17121b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    virtual ~UCTMultiThreadItem() {
1713f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        uprv_free(value);
1714f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1715f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius};
1716f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1717f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_NAMESPACE_BEGIN
1718f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1719f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliustemplate<> U_EXPORT
1720f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusconst UCTMultiThreadItem *LocaleCacheKey<UCTMultiThreadItem>::createObject(
1721f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        const void * /*unused*/, UErrorCode & /* status */) const {
1722f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    // Since multiple threads are hitting the cache for the first time,
1723f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    // no objects should be created yet.
1724f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    umtx_lock(&gCTMutex);
1725f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (gObjectsCreated != 0) {
1726f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        gThisTest->errln("Expected no objects to be created yet.");
1727f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1728f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    umtx_unlock(&gCTMutex);
1729f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1730f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    // Big, expensive object that takes 1 second to create.
1731f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    SimpleThread::sleep(1000);
1732f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1733f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    // Log that we created an object.
1734f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    umtx_lock(&gCTMutex);
1735f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    ++gObjectsCreated;
1736f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    umtx_unlock(&gCTMutex);
1737f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    UCTMultiThreadItem *result = new UCTMultiThreadItem(fLoc.getName());
1738f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    result->addRef();
1739f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return result;
1740f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1741f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1742f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_NAMESPACE_END
1743f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1744f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusclass UnifiedCacheThread: public SimpleThread {
1745f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius  public:
1746f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    UnifiedCacheThread(const char *loc) : fLoc(loc) {};
1747f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    ~UnifiedCacheThread() {};
1748f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    void run();
1749f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    const char *fLoc;
1750f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius};
1751f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1752f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusvoid UnifiedCacheThread::run() {
1753f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    UErrorCode status = U_ZERO_ERROR;
1754f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    const UnifiedCache *cache = UnifiedCache::getInstance(status);
1755f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    U_ASSERT(status == U_ZERO_ERROR);
1756f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    const UCTMultiThreadItem *item = NULL;
1757f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    cache->get(LocaleCacheKey<UCTMultiThreadItem>(fLoc), item, status);
1758f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    U_ASSERT(item != NULL);
1759f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (uprv_strcmp(fLoc, item->value)) {
1760f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius      gThisTest->errln("Expected %s, got %s", fLoc, item->value);
1761f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1762f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    item->removeRef();
1763f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1764f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    // Mark this thread as finished
1765f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    umtx_lock(&gCTMutex);
1766f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    ++gFinishedThreads;
1767f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    umtx_condBroadcast(&gCTConditionVar);
1768f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    umtx_unlock(&gCTMutex);
1769f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1770f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1771f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusvoid MultithreadTest::TestUnifiedCache() {
1772f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    UErrorCode status = U_ZERO_ERROR;
1773f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    const UnifiedCache *cache = UnifiedCache::getInstance(status);
1774f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    U_ASSERT(cache != NULL);
1775f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    cache->flush();
1776f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    gThisTest = this;
1777f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    gFinishedThreads = 0;
1778f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    gObjectsCreated = 0;
1779f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1780f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    UnifiedCacheThread *threads[CACHE_LOAD][UPRV_LENGTHOF(gCacheLocales)];
1781f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    for (int32_t i=0; i<CACHE_LOAD; ++i) {
1782f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        for (int32_t j=0; j<UPRV_LENGTHOF(gCacheLocales); ++j) {
1783f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            threads[i][j] = new UnifiedCacheThread(gCacheLocales[j]);
1784f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            threads[i][j]->start();
1785f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        }
1786f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1787f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    // Wait on all the threads to complete verify that LENGTHOF(gCacheLocales)
1788f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    // objects were created.
1789f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    umtx_lock(&gCTMutex);
1790f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    while (gFinishedThreads < CACHE_LOAD*UPRV_LENGTHOF(gCacheLocales)) {
1791f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        umtx_condWait(&gCTConditionVar, &gCTMutex);
1792f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1793f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    assertEquals("Objects created", UPRV_LENGTHOF(gCacheLocales), gObjectsCreated);
1794f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    umtx_unlock(&gCTMutex);
1795f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1796f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    // clean up threads
1797f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    for (int32_t i=0; i<CACHE_LOAD; ++i) {
1798f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        for (int32_t j=0; j<UPRV_LENGTHOF(gCacheLocales); ++j) {
1799f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            delete threads[i][j];
1800f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        }
1801f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1802f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1803f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif // ICU_USE_THREADS
1805