Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: source/test/intltest/tsmthred.cpp

Issue 1621843002: ICU 56 update step 1 (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/icu.git@561
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « source/test/intltest/tsmthred.h ('k') | source/test/intltest/tufmtts.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /******************************************************************** 1 /********************************************************************
2 * COPYRIGHT: 2 * COPYRIGHT:
3 * Copyright (c) 1999-2014, International Business Machines Corporation and 3 * Copyright (c) 1999-2015, International Business Machines Corporation and
4 * others. All Rights Reserved. 4 * others. All Rights Reserved.
5 ********************************************************************/ 5 ********************************************************************/
6 6
7 #if defined(hpux)
8 # ifndef _INCLUDE_POSIX_SOURCE
9 # define _INCLUDE_POSIX_SOURCE
10 # endif
11 #endif
12
13 #include "simplethread.h" 7 #include "simplethread.h"
14 8
15 #include "unicode/utypes.h" 9 #include "unicode/utypes.h"
16 #include "unicode/ustring.h" 10 #include "unicode/ustring.h"
17 #include "umutex.h" 11 #include "umutex.h"
18 #include "cmemory.h" 12 #include "cmemory.h"
19 #include "cstring.h" 13 #include "cstring.h"
20 #include "uparse.h" 14 #include "uparse.h"
21 #include "unicode/localpointer.h" 15 #include "unicode/localpointer.h"
22 #include "unicode/resbund.h" 16 #include "unicode/resbund.h"
23 #include "unicode/udata.h" 17 #include "unicode/udata.h"
24 #include "unicode/uloc.h" 18 #include "unicode/uloc.h"
25 #include "unicode/locid.h" 19 #include "unicode/locid.h"
26 #include "putilimp.h" 20 #include "putilimp.h"
27 #include "intltest.h" 21 #include "intltest.h"
28 #include "tsmthred.h" 22 #include "tsmthred.h"
29 #include "unicode/ushape.h" 23 #include "unicode/ushape.h"
30 #include "unicode/translit.h" 24 #include "unicode/translit.h"
31 #include "sharedobject.h" 25 #include "sharedobject.h"
32 #include "unifiedcache.h" 26 #include "unifiedcache.h"
33 #include "uassert.h" 27 #include "uassert.h"
34 28
35 #if U_PLATFORM_USES_ONLY_WIN32_API
36 /* Prefer native Windows APIs even if POSIX is implemented (i.e., on Cygwin) . */
37 # undef POSIX
38 #elif U_PLATFORM_IMPLEMENTS_POSIX
39 # define POSIX
40 #else
41 # undef POSIX
42 #endif
43
44 /* Needed by z/OS to get usleep */
45 #if U_PLATFORM == U_PF_OS390
46 #define __DOT1 1
47 #define __UU
48 #ifndef _XPG4_2
49 #define _XPG4_2
50 #endif
51 #include <unistd.h>
52 #endif
53 #if defined(POSIX)
54
55 #define HAVE_IMP
56
57 #if (ICU_USE_THREADS == 1)
58 #include <pthread.h>
59 #endif
60
61 #if defined(__hpux) && defined(HPUX_CMA)
62 # if defined(read) // read being defined as cma_read causes trouble with iostre am::read
63 # undef read
64 # endif
65 #endif
66
67 /* Define __EXTENSIONS__ for Solaris and old friends in strict mode. */
68 #ifndef __EXTENSIONS__
69 #define __EXTENSIONS__
70 #endif
71
72 #if U_PLATFORM == U_PF_OS390
73 #include <sys/types.h>
74 #endif
75
76 #if U_PLATFORM != U_PF_OS390
77 #include <signal.h>
78 #endif
79
80 /* Define _XPG4_2 for Solaris and friends. */
81 #ifndef _XPG4_2
82 #define _XPG4_2
83 #endif
84
85 /* Define __USE_XOPEN_EXTENDED for Linux and glibc. */
86 #ifndef __USE_XOPEN_EXTENDED
87 #define __USE_XOPEN_EXTENDED
88 #endif
89
90 /* Define _INCLUDE_XOPEN_SOURCE_EXTENDED for HP/UX (11?). */
91 #ifndef _INCLUDE_XOPEN_SOURCE_EXTENDED
92 #define _INCLUDE_XOPEN_SOURCE_EXTENDED
93 #endif
94
95 #include <unistd.h>
96
97 #endif
98 /* HPUX */
99 #ifdef sleep
100 #undef sleep
101 #endif
102 29
103 #define TSMTHREAD_FAIL(msg) errln("%s at file %s, line %d", msg, __FILE__, __LIN E__) 30 #define TSMTHREAD_FAIL(msg) errln("%s at file %s, line %d", msg, __FILE__, __LIN E__)
104 #define TSMTHREAD_ASSERT(expr) {if (!(expr)) {TSMTHREAD_FAIL("Fail");}} 31 #define TSMTHREAD_ASSERT(expr) {if (!(expr)) {TSMTHREAD_FAIL("Fail");}}
32 #define TSMTHREAD_ASSERT_SUCCESS(status) {if (U_FAILURE(status)) { \
33 errln("file: %s:%d status = %s\n", __FILE__, __LINE__, u_error Name(status));}}
105 34
106 MultithreadTest::MultithreadTest() 35 MultithreadTest::MultithreadTest()
107 { 36 {
108 } 37 }
109 38
110 MultithreadTest::~MultithreadTest() 39 MultithreadTest::~MultithreadTest()
111 { 40 {
112 } 41 }
113 42
114
115
116 #if (ICU_USE_THREADS==0)
117 void MultithreadTest::runIndexedTest( int32_t index, UBool exec,
118 const char* &name, char* /*par*/ ) {
119 if (exec) logln("TestSuite MultithreadTest: ");
120
121 if(index == 0)
122 name = "NO_THREADED_TESTS";
123 else
124 name = "";
125
126 if(exec) { logln("MultithreadTest - test DISABLED. ICU_USE_THREADS set to 0, check your configuration if this is a problem..");
127 }
128 }
129 #else
130
131 #include <stdio.h> 43 #include <stdio.h>
132 #include <string.h> 44 #include <string.h>
133 #include <ctype.h> // tolower, toupper 45 #include <ctype.h> // tolower, toupper
134 46
135 #include "unicode/putil.h" 47 #include "unicode/putil.h"
136 48
137 // for mthreadtest 49 // for mthreadtest
138 #include "unicode/numfmt.h" 50 #include "unicode/numfmt.h"
139 #include "unicode/choicfmt.h" 51 #include "unicode/choicfmt.h"
140 #include "unicode/msgfmt.h" 52 #include "unicode/msgfmt.h"
141 #include "unicode/locid.h" 53 #include "unicode/locid.h"
142 #include "unicode/coll.h" 54 #include "unicode/coll.h"
143 #include "unicode/calendar.h" 55 #include "unicode/calendar.h"
144 #include "ucaconf.h" 56 #include "ucaconf.h"
145 57
146 void SimpleThread::errorFunc() {
147 // *(char *)0 = 3; // Force entry into a debugger via a crash;
148 }
149 58
150 void MultithreadTest::runIndexedTest( int32_t index, UBool exec, 59 void MultithreadTest::runIndexedTest( int32_t index, UBool exec,
151 const char* &name, char* /*par*/ ) { 60 const char* &name, char* /*par*/ ) {
152 if (exec) 61 if (exec)
153 logln("TestSuite MultithreadTest: "); 62 logln("TestSuite MultithreadTest: ");
154 switch (index) { 63 switch (index) {
155 case 0: 64 case 0:
156 name = "TestThreads"; 65 name = "TestThreads";
157 if (exec) 66 if (exec)
158 TestThreads(); 67 TestThreads();
159 break; 68 break;
160 69
(...skipping 15 matching lines...) Expand all
176 case 3: 85 case 3:
177 name = "TestCollators"; 86 name = "TestCollators";
178 #if !UCONFIG_NO_COLLATION 87 #if !UCONFIG_NO_COLLATION
179 if (exec) { 88 if (exec) {
180 TestCollators(); 89 TestCollators();
181 } 90 }
182 #endif /* #if !UCONFIG_NO_COLLATION */ 91 #endif /* #if !UCONFIG_NO_COLLATION */
183 break; 92 break;
184 93
185 case 4: 94 case 4:
186 name = "TestString"; 95 name = "TestString";
187 if (exec) { 96 if (exec) {
188 TestString(); 97 TestString();
189 } 98 }
190 break; 99 break;
191 100
192 case 5: 101 case 5:
193 name = "TestArabicShapingThreads"; 102 name = "TestArabicShapingThreads";
194 if (exec) { 103 if (exec) {
195 TestArabicShapingThreads(); 104 TestArabicShapingThreads();
196 } 105 }
197 break; 106 break;
198 107
199 case 6: 108 case 6:
200 name = "TestAnyTranslit"; 109 name = "TestAnyTranslit";
201 if (exec) { 110 if (exec) {
202 TestAnyTranslit(); 111 TestAnyTranslit();
203 } 112 }
204 break; 113 break;
205 114
206 case 7: 115 case 7:
207 name = "TestConditionVariables"; 116 name = "TestConditionVariables";
208 if (exec) { 117 if (exec) {
209 TestConditionVariables(); 118 TestConditionVariables();
210 } 119 }
211 break; 120 break;
212 case 8: 121 case 8:
213 name = "TestUnifiedCache"; 122 name = "TestUnifiedCache";
214 if (exec) { 123 if (exec) {
215 TestUnifiedCache(); 124 TestUnifiedCache();
216 } 125 }
217 break; 126 break;
127 #if !UCONFIG_NO_TRANSLITERATION
128 case 9:
129 name = "TestBreakTranslit";
130 if (exec) {
131 TestBreakTranslit();
132 }
133 break;
134 #endif
218 default: 135 default:
219 name = ""; 136 name = "";
220 break; //needed to end loop 137 break; //needed to end loop
221 } 138 }
222 } 139 }
223 140
224 141
225 //------------------------------------------------------------------------------ ----- 142 //------------------------------------------------------------------------------ -----
226 // 143 //
227 // TestThreads -- see if threads really work at all. 144 // TestThreads -- see if threads really work at all.
228 // 145 //
229 // Set up N threads pointing at N chars. When they are started, they will 146 // Set up N threads pointing at N chars. When they are started, they will
230 // each sleep 1 second and then set their chars. At the end we make sure they 147 // set their chars. At the end we make sure they are all set.
231 // are all set.
232 // 148 //
233 //------------------------------------------------------------------------------ ----- 149 //------------------------------------------------------------------------------ -----
234 #define THREADTEST_NRTHREADS 8
235 #define ARABICSHAPE_THREADTEST 30
236 150
237 class TestThreadsThread : public SimpleThread 151 class TestThreadsThread : public SimpleThread
238 { 152 {
239 public: 153 public:
240 TestThreadsThread(char* whatToChange) { fWhatToChange = whatToChange; } 154 TestThreadsThread(char* whatToChange) { fWhatToChange = whatToChange; }
241 virtual void run() { SimpleThread::sleep(1000); 155 virtual void run() { Mutex m;
242 Mutex m; 156 *fWhatToChange = '*';
243 *fWhatToChange = '*';
244 } 157 }
245 private: 158 private:
246 char *fWhatToChange; 159 char *fWhatToChange;
247 }; 160 };
248 //------------------------------------------------------------------------------ -----
249 //
250 // TestArabicShapeThreads -- see if calls to u_shapeArabic in many threads wor ks successfully
251 //
252 // Set up N threads pointing at N chars. When they are started, they will make calls to doTailTest which tests
253 // u_shapeArabic, if the calls are successful it will the set * chars.
254 // At the end we make sure all threads managed to run u_shapeArabic successful ly.
255 // This is a unit test for ticket 9473
256 //
257 //------------------------------------------------------------------------------ -----
258 class TestArabicShapeThreads : public SimpleThread
259 {
260 public:
261 TestArabicShapeThreads(char* whatToChange) { fWhatToChange = whatToChange;}
262 virtual void run() {
263 if(doTailTest()==TRUE)
264 *fWhatToChange = '*';
265 }
266 private:
267 char *fWhatToChange;
268
269 UBool doTailTest(void) {
270 static const UChar src[] = { 0x0020, 0x0633, 0 };
271 static const UChar dst_old[] = { 0xFEB1, 0x200B,0 };
272 static const UChar dst_new[] = { 0xFEB1, 0xFE73,0 };
273 UChar dst[3] = { 0x0000, 0x0000,0 };
274 int32_t length;
275 UErrorCode status;
276 IntlTest inteltst = IntlTest();
277
278 status = U_ZERO_ERROR;
279 length = u_shapeArabic(src, -1, dst, UPRV_LENGTHOF(dst),
280 U_SHAPE_LETTERS_SHAPE|U_SHAPE_SEEN_TWOCELL_NEAR, &statu s);
281 if(U_FAILURE(status)) {
282 inteltst.errln("Fail: status %s\n", u_errorName(status));
283 return FALSE;
284 } else if(length!=2) {
285 inteltst.errln("Fail: len %d expected 3\n", length);
286 return FALSE;
287 } else if(u_strncmp(dst,dst_old,UPRV_LENGTHOF(dst))) {
288 inteltst.errln("Fail: got U+%04X U+%04X expected U+%04X U+%04X\n",
289 dst[0],dst[1],dst_old[0],dst_old[1]);
290 return FALSE;
291 }
292 161
293 162
294 //"Trying new tail
295 status = U_ZERO_ERROR;
296 length = u_shapeArabic(src, -1, dst, UPRV_LENGTHOF(dst),
297 U_SHAPE_LETTERS_SHAPE|U_SHAPE_SEEN_TWOCELL_NEAR|U_SHAPE _TAIL_NEW_UNICODE, &status);
298 if(U_FAILURE(status)) {
299 inteltst.errln("Fail: status %s\n", u_errorName(status));
300 return FALSE;
301 } else if(length!=2) {
302 inteltst.errln("Fail: len %d expected 3\n", length);
303 return FALSE;
304 } else if(u_strncmp(dst,dst_new,UPRV_LENGTHOF(dst))) {
305 inteltst.errln("Fail: got U+%04X U+%04X expected U+%04X U+%04X\n",
306 dst[0],dst[1],dst_new[0],dst_new[1]);
307 return FALSE;
308 }
309
310
311 return TRUE;
312
313 }
314
315
316 };
317
318 void MultithreadTest::TestThreads() 163 void MultithreadTest::TestThreads()
319 { 164 {
165 static const int32_t THREADTEST_NRTHREADS = 8;
320 char threadTestChars[THREADTEST_NRTHREADS + 1]; 166 char threadTestChars[THREADTEST_NRTHREADS + 1];
321 SimpleThread *threads[THREADTEST_NRTHREADS]; 167 SimpleThread *threads[THREADTEST_NRTHREADS];
322 int32_t numThreadsStarted = 0; 168 int32_t numThreadsStarted = 0;
323 169
324 int32_t i; 170 int32_t i;
325 for(i=0;i<THREADTEST_NRTHREADS;i++) 171 for(i=0;i<THREADTEST_NRTHREADS;i++)
326 { 172 {
327 threadTestChars[i] = ' '; 173 threadTestChars[i] = ' ';
328 threads[i] = new TestThreadsThread(&threadTestChars[i]); 174 threads[i] = new TestThreadsThread(&threadTestChars[i]);
329 } 175 }
330 threadTestChars[THREADTEST_NRTHREADS] = '\0'; 176 threadTestChars[THREADTEST_NRTHREADS] = '\0';
331 177
332 logln("->" + UnicodeString(threadTestChars) + "<- Firing off threads.. "); 178 logln("->" + UnicodeString(threadTestChars) + "<- Firing off threads.. ");
333 for(i=0;i<THREADTEST_NRTHREADS;i++) 179 for(i=0;i<THREADTEST_NRTHREADS;i++)
334 { 180 {
335 if (threads[i]->start() != 0) { 181 if (threads[i]->start() != 0) {
336 errln("Error starting thread %d", i); 182 errln("Error starting thread %d", i);
337 } 183 }
338 else { 184 else {
339 numThreadsStarted++; 185 numThreadsStarted++;
340 } 186 }
341 SimpleThread::sleep(100);
342 logln(" Subthread started."); 187 logln(" Subthread started.");
343 } 188 }
344 189
190 if (numThreadsStarted != THREADTEST_NRTHREADS) {
191 errln("Not all threads could be started for testing!");
192 return;
193 }
194
345 logln("Waiting for threads to be set.."); 195 logln("Waiting for threads to be set..");
346 if (numThreadsStarted == 0) { 196 for(i=0; i<THREADTEST_NRTHREADS; i++) {
347 errln("No threads could be started for testing!"); 197 threads[i]->join();
348 return; 198 if (threadTestChars[i] != '*') {
349 } 199 errln("%s:%d Thread %d failed.", __FILE__, __LINE__, i);
350 200 }
351 int32_t patience = 40; // seconds to wait
352
353 while(patience--)
354 {
355 int32_t count = 0;
356 umtx_lock(NULL);
357 for(i=0;i<THREADTEST_NRTHREADS;i++)
358 {
359 if(threadTestChars[i] == '*')
360 {
361 count++;
362 }
363 }
364 umtx_unlock(NULL);
365
366 if(count == THREADTEST_NRTHREADS)
367 {
368 logln("->" + UnicodeString(threadTestChars) + "<- Got all threads! c ya");
369 for(i=0;i<THREADTEST_NRTHREADS;i++)
370 {
371 delete threads[i];
372 }
373 return;
374 }
375
376 logln("->" + UnicodeString(threadTestChars) + "<- Waiting..");
377 SimpleThread::sleep(500);
378 }
379
380 errln("->" + UnicodeString(threadTestChars) + "<- PATIENCE EXCEEDED!! Still missing some.");
381 for(i=0;i<THREADTEST_NRTHREADS;i++)
382 {
383 delete threads[i]; 201 delete threads[i];
384 } 202 }
385 } 203 }
386 204
387 205
206 //------------------------------------------------------------------------------ -----
207 //
208 // TestArabicShapeThreads -- see if calls to u_shapeArabic in many threads wor ks successfully
209 //
210 // Set up N threads pointing at N chars. When they are started, they will make calls to doTailTest which tests
211 // u_shapeArabic, if the calls are successful it will the set * chars.
212 // At the end we make sure all threads managed to run u_shapeArabic successful ly.
213 // This is a unit test for ticket 9473
214 //
215 //------------------------------------------------------------------------------ -----
216
217 class TestArabicShapeThreads : public SimpleThread
218 {
219 public:
220 TestArabicShapeThreads() {};
221 virtual void run() { doTailTest(); };
222 private:
223 void doTailTest();
224 };
225
226
227 void TestArabicShapeThreads::doTailTest(void) {
228 static const UChar src[] = { 0x0020, 0x0633, 0 };
229 static const UChar dst_old[] = { 0xFEB1, 0x200B,0 };
230 static const UChar dst_new[] = { 0xFEB1, 0xFE73,0 };
231 UChar dst[3] = { 0x0000, 0x0000,0 };
232 int32_t length;
233 UErrorCode status;
234
235 for (int32_t loopCount = 0; loopCount < 100; loopCount++) {
236 status = U_ZERO_ERROR;
237 length = u_shapeArabic(src, -1, dst, UPRV_LENGTHOF(dst),
238 U_SHAPE_LETTERS_SHAPE|U_SHAPE_SEEN_TWOCELL_NEAR, &status);
239 if(U_FAILURE(status)) {
240 IntlTest::gTest->errln("Fail: status %s\n", u_errorName(status));
241 return;
242 } else if(length!=2) {
243 IntlTest::gTest->errln("Fail: len %d expected 3\n", length);
244 return;
245 } else if(u_strncmp(dst,dst_old,UPRV_LENGTHOF(dst))) {
246 IntlTest::gTest->errln("Fail: got U+%04X U+%04X expected U+%04X U+%0 4X\n",
247 dst[0],dst[1],dst_old[0],dst_old[1]);
248 return;
249 }
250
251
252 //"Trying new tail
253 status = U_ZERO_ERROR;
254 length = u_shapeArabic(src, -1, dst, UPRV_LENGTHOF(dst),
255 U_SHAPE_LETTERS_SHAPE|U_SHAPE_SEEN_TWOCELL_NEAR|U_SHAPE_TAIL_NEW _UNICODE, &status);
256 if(U_FAILURE(status)) {
257 IntlTest::gTest->errln("Fail: status %s\n", u_errorName(status));
258 return;
259 } else if(length!=2) {
260 IntlTest::gTest->errln("Fail: len %d expected 3\n", length);
261 return;
262 } else if(u_strncmp(dst,dst_new,UPRV_LENGTHOF(dst))) {
263 IntlTest::gTest->errln("Fail: got U+%04X U+%04X expected U+%04X U+%0 4X\n",
264 dst[0],dst[1],dst_new[0],dst_new[1]);
265 return;
266 }
267 }
268 return;
269 }
270
271
388 void MultithreadTest::TestArabicShapingThreads() 272 void MultithreadTest::TestArabicShapingThreads()
389 { 273 {
390 char threadTestChars[ARABICSHAPE_THREADTEST + 1]; 274 TestArabicShapeThreads threads[30];
391 SimpleThread *threads[ARABICSHAPE_THREADTEST];
392 int32_t numThreadsStarted = 0;
393 275
394 int32_t i; 276 int32_t i;
395
396 for(i=0;i<ARABICSHAPE_THREADTEST;i++)
397 {
398 threadTestChars[i] = ' ';
399 threads[i] = new TestArabicShapeThreads(&threadTestChars[i]);
400 }
401 threadTestChars[ARABICSHAPE_THREADTEST] = '\0';
402 277
403 logln("-> do TestArabicShapingThreads <- Firing off threads.. "); 278 logln("-> do TestArabicShapingThreads <- Firing off threads.. ");
404 for(i=0;i<ARABICSHAPE_THREADTEST;i++) 279 for(i=0; i < UPRV_LENGTHOF(threads); i++) {
405 { 280 if (threads[i].start() != 0) {
406 if (threads[i]->start() != 0) {
407 errln("Error starting thread %d", i); 281 errln("Error starting thread %d", i);
408 } 282 }
409 else { 283 }
410 numThreadsStarted++; 284
411 } 285 for(i=0; i < UPRV_LENGTHOF(threads); i++) {
412 //SimpleThread::sleep(100); 286 threads[i].join();
413 logln(" Subthread started."); 287 }
414 } 288 logln("->TestArabicShapingThreads <- Got all threads! cya");
415 289 }
416 logln("Waiting for threads to be set.."); 290
417 if (numThreadsStarted == 0) { 291
418 errln("No threads could be started for testing!");
419 return;
420 }
421
422 int32_t patience = 100; // seconds to wait
423
424 while(patience--)
425 {
426 int32_t count = 0;
427 umtx_lock(NULL);
428 for(i=0;i<ARABICSHAPE_THREADTEST;i++)
429 {
430 if(threadTestChars[i] == '*')
431 {
432 count++;
433 }
434 }
435 umtx_unlock(NULL);
436
437 if(count == ARABICSHAPE_THREADTEST)
438 {
439 logln("->TestArabicShapingThreads <- Got all threads! cya");
440 for(i=0;i<ARABICSHAPE_THREADTEST;i++)
441 {
442 delete threads[i];
443 }
444 return;
445 }
446
447 logln("-> TestArabicShapingThreads <- Waiting..");
448 SimpleThread::sleep(500);
449 }
450
451 errln("-> TestArabicShapingThreads <- PATIENCE EXCEEDED!! Still missing some .");
452 for(i=0;i<ARABICSHAPE_THREADTEST;i++)
453 {
454 delete threads[i];
455 }
456 »
457 }
458
459
460 //----------------------------------------------------------------------- 292 //-----------------------------------------------------------------------
461 // 293 //
462 // TestMutex - a simple (non-stress) test to verify that ICU mutexes 294 // TestMutex - a simple (non-stress) test to verify that ICU mutexes
463 // are actually mutexing. Does not test the use of 295 // and condition variables are functioning. Does not test the use of
464 // mutexes within ICU services, but rather that the 296 // mutexes within ICU services, but rather that the
465 // platform's mutex support is at least superficially there. 297 // platform's mutex support is at least superficially there.
466 // 298 //
467 //---------------------------------------------------------------------- 299 //----------------------------------------------------------------------
468 static UMutex gTestMutexA = U_MUTEX_INITIALIZER; 300 static UMutex gTestMutexA = U_MUTEX_INITIALIZER;
469 static UMutex gTestMutexB = U_MUTEX_INITIALIZER; 301 static UConditionVar gThreadsCountChanged = U_CONDITION_INITIALIZER;
470 302
471 static int gThreadsStarted = 0; 303 static int gThreadsStarted = 0;
472 static int gThreadsInMiddle = 0; 304 static int gThreadsInMiddle = 0;
473 static int gThreadsDone = 0; 305 static int gThreadsDone = 0;
474 306
475 static const int TESTMUTEX_THREAD_COUNT = 4; 307 static const int TESTMUTEX_THREAD_COUNT = 40;
476
477 static int safeIncr(int &var, int amt) {
478 // Thread safe (using global mutex) increment of a variable.
479 // Return the updated value.
480 // Can also be used as a safe load of a variable by incrementing it by 0.
481 Mutex m;
482 var += amt;
483 return var;
484 }
485 308
486 class TestMutexThread : public SimpleThread 309 class TestMutexThread : public SimpleThread
487 { 310 {
488 public: 311 public:
489 virtual void run() 312 virtual void run() {
490 {
491 // This is the code that each of the spawned threads runs. 313 // This is the code that each of the spawned threads runs.
492 // All of the spawned threads bunch up together at each of the two mutex es 314 // All threads move together throught the started - middle - done sequen ce together,
493 // because the main holds the mutexes until they do. 315 // waiting for all other threads to reach each point before advancing.
494 //
495 safeIncr(gThreadsStarted, 1);
496 umtx_lock(&gTestMutexA); 316 umtx_lock(&gTestMutexA);
317 gThreadsStarted += 1;
318 umtx_condBroadcast(&gThreadsCountChanged);
319 while (gThreadsStarted < TESTMUTEX_THREAD_COUNT) {
320 if (gThreadsInMiddle != 0) {
321 IntlTest::gTest->errln(
322 "%s:%d gThreadsInMiddle = %d. Expected 0.", __FILE__, __LINE __, gThreadsInMiddle);
323 return;
324 }
325 umtx_condWait(&gThreadsCountChanged, &gTestMutexA);
326 }
327
328 gThreadsInMiddle += 1;
329 umtx_condBroadcast(&gThreadsCountChanged);
330 while (gThreadsInMiddle < TESTMUTEX_THREAD_COUNT) {
331 if (gThreadsDone != 0) {
332 IntlTest::gTest->errln(
333 "%s:%d gThreadsDone = %d. Expected 0.", __FILE__, __LINE__, gThreadsDone);
334 return;
335 }
336 umtx_condWait(&gThreadsCountChanged, &gTestMutexA);
337 }
338
339 gThreadsDone += 1;
340 umtx_condBroadcast(&gThreadsCountChanged);
341 while (gThreadsDone < TESTMUTEX_THREAD_COUNT) {
342 umtx_condWait(&gThreadsCountChanged, &gTestMutexA);
343 }
497 umtx_unlock(&gTestMutexA); 344 umtx_unlock(&gTestMutexA);
498 safeIncr(gThreadsInMiddle, 1);
499 umtx_lock(&gTestMutexB);
500 umtx_unlock(&gTestMutexB);
501 safeIncr(gThreadsDone, 1);
502 } 345 }
503 }; 346 };
504 347
505 void MultithreadTest::TestMutex() 348 void MultithreadTest::TestMutex()
506 { 349 {
507 // Start up the test threads. They should all pile up waiting on
508 // gTestMutexA, which we (the main thread) hold until the test threads
509 // all get there.
510 gThreadsStarted = 0; 350 gThreadsStarted = 0;
511 gThreadsInMiddle = 0; 351 gThreadsInMiddle = 0;
512 gThreadsDone = 0; 352 gThreadsDone = 0;
353 int32_t i = 0;
354 TestMutexThread threads[TESTMUTEX_THREAD_COUNT];
513 umtx_lock(&gTestMutexA); 355 umtx_lock(&gTestMutexA);
514 TestMutexThread *threads[TESTMUTEX_THREAD_COUNT];
515 int i;
516 int32_t numThreadsStarted = 0;
517 for (i=0; i<TESTMUTEX_THREAD_COUNT; i++) { 356 for (i=0; i<TESTMUTEX_THREAD_COUNT; i++) {
518 threads[i] = new TestMutexThread; 357 if (threads[i].start() != 0) {
519 if (threads[i]->start() != 0) { 358 errln("%s:%d Error starting thread %d", __FILE__, __LINE__, i);
520 errln("Error starting thread %d", i); 359 return;
521 } 360 }
522 else { 361 }
523 numThreadsStarted++; 362
524 } 363 // Because we are holding gTestMutexA, all of the threads should be blocked
525 } 364 // at the start of their run() function.
526 if (numThreadsStarted == 0) { 365 if (gThreadsStarted != 0) {
527 errln("No threads could be started for testing!"); 366 errln("%s:%d gThreadsStarted=%d. Expected 0.", __FILE__, __LINE__, gThre adsStarted);
528 return; 367 return;
529 } 368 }
530 369
531 int patience = 0; 370 while (gThreadsInMiddle < TESTMUTEX_THREAD_COUNT) {
532 while (safeIncr(gThreadsStarted, 0) != TESTMUTEX_THREAD_COUNT) { 371 if (gThreadsDone != 0) {
533 if (patience++ > 24) { 372 errln("%s:%d gThreadsDone=%d. Expected 0.", __FILE__, __LINE__, gThr eadsStarted);
534 TSMTHREAD_FAIL("Patience Exceeded"); 373 return;
535 return; 374 }
536 } 375 umtx_condWait(&gThreadsCountChanged, &gTestMutexA);
537 SimpleThread::sleep(500); 376 }
538 } 377
539 // None of the test threads should have advanced past the first mutex. 378 while (gThreadsDone < TESTMUTEX_THREAD_COUNT) {
540 TSMTHREAD_ASSERT(gThreadsInMiddle==0); 379 umtx_condWait(&gThreadsCountChanged, &gTestMutexA);
541 TSMTHREAD_ASSERT(gThreadsDone==0); 380 }
542
543 // All of the test threads have made it to the first mutex.
544 // We (the main thread) now let them advance to the second mutex,
545 // where they should all pile up again.
546 umtx_lock(&gTestMutexB);
547 umtx_unlock(&gTestMutexA); 381 umtx_unlock(&gTestMutexA);
548 382
549 patience = 0;
550 while (safeIncr(gThreadsInMiddle, 0) != TESTMUTEX_THREAD_COUNT) {
551 if (patience++ > 24) {
552 TSMTHREAD_FAIL("Patience Exceeded");
553 return;
554 }
555 SimpleThread::sleep(500);
556 }
557 TSMTHREAD_ASSERT(gThreadsDone==0);
558
559 // All test threads made it to the second mutex.
560 // Now let them proceed from there. They will all terminate.
561 umtx_unlock(&gTestMutexB);
562 patience = 0;
563 while (safeIncr(gThreadsDone, 0) != TESTMUTEX_THREAD_COUNT) {
564 if (patience++ > 24) {
565 TSMTHREAD_FAIL("Patience Exceeded");
566 return;
567 }
568 SimpleThread::sleep(500);
569 }
570
571 // All threads made it by both mutexes.
572
573 for (i=0; i<TESTMUTEX_THREAD_COUNT; i++) { 383 for (i=0; i<TESTMUTEX_THREAD_COUNT; i++) {
574 delete threads[i]; 384 threads[i].join();
575 } 385 }
576
577 } 386 }
578 387
579 388
580 //------------------------------------------------------------------------------ ------------- 389 //------------------------------------------------------------------------------ -------------
581 // 390 //
582 // class ThreadWithStatus - a thread that we can check the status and error cond ition of 391 // TestMultithreadedIntl. Test ICU Formatting in a multi-threaded environment
583 // 392 //
584 //------------------------------------------------------------------------------ ------------- 393 //------------------------------------------------------------------------------ -------------
585 class ThreadWithStatus : public SimpleThread 394
586 {
587 public:
588 UBool getError() { return (fErrors > 0); }
589 UBool getError(UnicodeString& fillinError) { fillinError = fErrorString; re turn (fErrors > 0); }
590 virtual ~ThreadWithStatus(){}
591 protected:
592 ThreadWithStatus() : fErrors(0) {}
593 void error(const UnicodeString &error) {
594 fErrors++; fErrorString = error;
595 SimpleThread::errorFunc();
596 }
597 void error() { error("An error occured."); }
598 private:
599 int32_t fErrors;
600 UnicodeString fErrorString;
601 };
602
603
604
605 //------------------------------------------------------------------------------ -------------
606 //
607 // TestMultithreadedIntl. Test ICU Formatting n a multi-threaded environment
608 //
609 //------------------------------------------------------------------------------ -------------
610
611 395
612 // * Show exactly where the string's differences lie. 396 // * Show exactly where the string's differences lie.
613 UnicodeString showDifference(const UnicodeString& expected, const UnicodeString& result) 397 UnicodeString showDifference(const UnicodeString& expected, const UnicodeString& result)
614 { 398 {
615 UnicodeString res; 399 UnicodeString res;
616 res = expected + "<Expected\n"; 400 res = expected + "<Expected\n";
617 if(expected.length() != result.length()) 401 if(expected.length() != result.length())
618 res += " [ Different lengths ] \n"; 402 res += " [ Different lengths ] \n";
619 else 403 else
620 { 404 {
(...skipping 10 matching lines...) Expand all
631 } 415 }
632 res += "<Differences"; 416 res += "<Differences";
633 res += "\n"; 417 res += "\n";
634 } 418 }
635 res += result + "<Result\n"; 419 res += result + "<Result\n";
636 420
637 return res; 421 return res;
638 } 422 }
639 423
640 424
641
642
643 //------------------------------------------------------------------------------ ------------- 425 //------------------------------------------------------------------------------ -------------
644 // 426 //
645 // FormatThreadTest - a thread that tests performing a number of numberformats . 427 // FormatThreadTest - a thread that tests performing a number of numberformats .
646 // 428 //
647 //------------------------------------------------------------------------------ ------------- 429 //------------------------------------------------------------------------------ -------------
648 430
649 const int kFormatThreadIterations = 100; // # of iterations per thread 431 const int kFormatThreadIterations = 100; // # of iterations per thread
650 const int kFormatThreadThreads = 10; // # of threads to spawn 432 const int kFormatThreadThreads = 10; // # of threads to spawn
651 433
652 #if !UCONFIG_NO_FORMATTING 434 #if !UCONFIG_NO_FORMATTING
653 435
654 436
655 437
656 struct FormatThreadTestData 438 struct FormatThreadTestData
657 { 439 {
658 double number; 440 double number;
659 UnicodeString string; 441 UnicodeString string;
660 FormatThreadTestData(double a, const UnicodeString& b) : number(a),string(b) {} 442 FormatThreadTestData(double a, const UnicodeString& b) : number(a),string(b) {}
(...skipping 17 matching lines...) Expand all
678 Formattable myArgs[] = { 460 Formattable myArgs[] = {
679 Formattable((int32_t)inStatus0), // inStatus0 {0} 461 Formattable((int32_t)inStatus0), // inStatus0 {0}
680 Formattable(errString1), // statusString1 {1} 462 Formattable(errString1), // statusString1 {1}
681 Formattable(countryName2), // inCountry2 {2} 463 Formattable(countryName2), // inCountry2 {2}
682 Formattable(currency3)// currency3 {3,number,currency} 464 Formattable(currency3)// currency3 {3,number,currency}
683 }; 465 };
684 466
685 MessageFormat *fmt = new MessageFormat("MessageFormat's API is broken!!!!!!! !!!!",realStatus); 467 MessageFormat *fmt = new MessageFormat("MessageFormat's API is broken!!!!!!! !!!!",realStatus);
686 fmt->setLocale(theLocale); 468 fmt->setLocale(theLocale);
687 fmt->applyPattern(pattern, realStatus); 469 fmt->applyPattern(pattern, realStatus);
688 470
689 if (U_FAILURE(realStatus)) { 471 if (U_FAILURE(realStatus)) {
690 delete fmt; 472 delete fmt;
691 return; 473 return;
692 } 474 }
693 475
694 FieldPosition ignore = 0; 476 FieldPosition ignore = 0;
695 fmt->format(myArgs,4,result,ignore,realStatus); 477 fmt->format(myArgs,4,result,ignore,realStatus);
696 478
697 delete fmt; 479 delete fmt;
698 } 480 }
699 481
700 /** 482 /**
701 * Class for thread-safe (theoretically) format. 483 * Shared formatters & data used by instances of ThreadSafeFormat.
702 * 484 * Exactly one instance of this class is created, and it is then shared concurr ently
703 * 485 * by the multiple instances of ThreadSafeFormat.
704 * Its constructor, destructor, and init/fini are NOT thread safe. 486 */
487 class ThreadSafeFormatSharedData {
488 public:
489 ThreadSafeFormatSharedData(UErrorCode &status);
490 ~ThreadSafeFormatSharedData();
491 LocalPointer<NumberFormat> fFormat;
492 Formattable fYDDThing;
493 Formattable fBBDThing;
494 UnicodeString fYDDStr;
495 UnicodeString fBBDStr;
496 };
497
498 const ThreadSafeFormatSharedData *gSharedData = NULL;
499
500 ThreadSafeFormatSharedData::ThreadSafeFormatSharedData(UErrorCode &status) {
501 fFormat.adoptInstead(NumberFormat::createCurrencyInstance(Locale::getUS(), s tatus));
502 static const UChar kYDD[] = { 0x59, 0x44, 0x44, 0x00 };
503 static const UChar kBBD[] = { 0x42, 0x42, 0x44, 0x00 };
504 fYDDThing.adoptObject(new CurrencyAmount(123.456, kYDD, status));
505 fBBDThing.adoptObject(new CurrencyAmount(987.654, kBBD, status));
506 if (U_FAILURE(status)) {
507 return;
508 }
509 fFormat->format(fYDDThing, fYDDStr, NULL, status);
510 fFormat->format(fBBDThing, fBBDStr, NULL, status);
511 gSharedData = this;
512 }
513
514 ThreadSafeFormatSharedData::~ThreadSafeFormatSharedData() {
515 gSharedData = NULL;
516 }
517
518 /**
519 * Class for thread-safe testing of format.
520 * Instances of this class appear as members of class FormatThreadTest.
521 * Multiple instances of FormatThreadTest coexist.
522 * ThreadSafeFormat::doStuff() is called concurrently to test the thread safet y of
523 * various shared format operations.
705 */ 524 */
706 class ThreadSafeFormat { 525 class ThreadSafeFormat {
707 public: 526 public:
708 /* give a unique offset to each thread */ 527 /* give a unique offset to each thread */
709 ThreadSafeFormat(); 528 ThreadSafeFormat(UErrorCode &status);
710 UBool doStuff(int32_t offset, UnicodeString &appendErr, UErrorCode &status); 529 UBool doStuff(int32_t offset, UnicodeString &appendErr, UErrorCode &status) co nst;
711 private: 530 private:
712 LocalPointer<NumberFormat> fFormat; // formtter - default constructed currency 531 LocalPointer<NumberFormat> fFormat; // formatter - en_US constructed currency
713 Formattable fYDDThing; // Formattable currency - YDD
714 Formattable fBBDThing; // Formattable currency - BBD
715
716 // statics
717 private:
718 static LocalPointer<NumberFormat> gFormat;
719 static NumberFormat *createFormat(UErrorCode &status);
720 static Formattable gYDDThing, gBBDThing;
721 public:
722 static void init(UErrorCode &status); // avoid static init.
723 static void fini(UErrorCode &status); // avoid static fini
724 }; 532 };
725 533
726 LocalPointer<NumberFormat> ThreadSafeFormat::gFormat; 534
727 Formattable ThreadSafeFormat::gYDDThing; 535 ThreadSafeFormat::ThreadSafeFormat(UErrorCode &status) {
728 Formattable ThreadSafeFormat::gBBDThing; 536 fFormat.adoptInstead(NumberFormat::createCurrencyInstance(Locale::getUS(), sta tus));
729 UnicodeString gYDDStr, gBBDStr;
730 NumberFormat *ThreadSafeFormat::createFormat(UErrorCode &status) {
731 LocalPointer<NumberFormat> fmt(NumberFormat::createCurrencyInstance(Locale::ge tUS(), status));
732 return fmt.orphan();
733 } 537 }
734 538
735
736 static const UChar kYDD[] = { 0x59, 0x44, 0x44, 0x00 };
737 static const UChar kBBD[] = { 0x42, 0x42, 0x44, 0x00 };
738 static const UChar kUSD[] = { 0x55, 0x53, 0x44, 0x00 }; 539 static const UChar kUSD[] = { 0x55, 0x53, 0x44, 0x00 };
739 540
740 void ThreadSafeFormat::init(UErrorCode &status) { 541 UBool ThreadSafeFormat::doStuff(int32_t offset, UnicodeString &appendErr, UError Code &status) const {
741 gFormat.adoptInstead(createFormat(status));
742 gYDDThing.adoptObject(new CurrencyAmount(123.456, kYDD, status));
743 gBBDThing.adoptObject(new CurrencyAmount(987.654, kBBD, status));
744 if (U_FAILURE(status)) {
745 return;
746 }
747 gFormat->format(gYDDThing, gYDDStr, NULL, status);
748 gFormat->format(gBBDThing, gBBDStr, NULL, status);
749 }
750
751 void ThreadSafeFormat::fini(UErrorCode &/*status*/) {
752 gFormat.adoptInstead(NULL);
753 }
754
755 ThreadSafeFormat::ThreadSafeFormat() {
756 }
757
758 UBool ThreadSafeFormat::doStuff(int32_t offset, UnicodeString &appendErr, UError Code &status) {
759 UBool okay = TRUE; 542 UBool okay = TRUE;
760 if(fFormat.isNull()) {
761 fFormat.adoptInstead(createFormat(status));
762 }
763 543
764 if(u_strcmp(fFormat->getCurrency(), kUSD)) { 544 if(u_strcmp(fFormat->getCurrency(), kUSD)) {
765 appendErr.append("fFormat currency != ") 545 appendErr.append("fFormat currency != ")
766 .append(kUSD) 546 .append(kUSD)
767 .append(", =") 547 .append(", =")
768 .append(fFormat->getCurrency()) 548 .append(fFormat->getCurrency())
769 .append("! "); 549 .append("! ");
770 okay = FALSE; 550 okay = FALSE;
771 } 551 }
772 552
773 if(u_strcmp(gFormat->getCurrency(), kUSD)) { 553 if(u_strcmp(gSharedData->fFormat->getCurrency(), kUSD)) {
774 appendErr.append("gFormat currency != ") 554 appendErr.append("gFormat currency != ")
775 .append(kUSD) 555 .append(kUSD)
776 .append(", =") 556 .append(", =")
777 .append(gFormat->getCurrency()) 557 .append(gSharedData->fFormat->getCurrency())
778 .append("! "); 558 .append("! ");
779 okay = FALSE; 559 okay = FALSE;
780 } 560 }
781 UnicodeString str; 561 UnicodeString str;
782 const UnicodeString *o=NULL; 562 const UnicodeString *o=NULL;
783 Formattable f; 563 Formattable f;
784 const NumberFormat *nf = NULL; // only operate on it as const. 564 const NumberFormat *nf = NULL; // only operate on it as const.
785 switch(offset%4) { 565 switch(offset%4) {
786 case 0: f = gYDDThing; o = &gYDDStr; nf = gFormat.getAlias(); break; 566 case 0: f = gSharedData->fYDDThing; o = &gSharedData->fYDDStr; nf = gShared Data->fFormat.getAlias(); break;
787 case 1: f = gBBDThing; o = &gBBDStr; nf = gFormat.getAlias(); break; 567 case 1: f = gSharedData->fBBDThing; o = &gSharedData->fBBDStr; nf = gShared Data->fFormat.getAlias(); break;
788 case 2: f = gYDDThing; o = &gYDDStr; nf = fFormat.getAlias(); break; 568 case 2: f = gSharedData->fYDDThing; o = &gSharedData->fYDDStr; nf = fFormat .getAlias(); break;
789 case 3: f = gBBDThing; o = &gBBDStr; nf = fFormat.getAlias(); break; 569 case 3: f = gSharedData->fBBDThing; o = &gSharedData->fBBDStr; nf = fFormat .getAlias(); break;
790 } 570 }
791 nf->format(f, str, NULL, status); 571 nf->format(f, str, NULL, status);
792 572
793 if(*o != str) { 573 if(*o != str) {
794 appendErr.append(showDifference(*o, str)); 574 appendErr.append(showDifference(*o, str));
795 okay = FALSE; 575 okay = FALSE;
796 } 576 }
797 return okay; 577 return okay;
798 } 578 }
799 579
800 UBool U_CALLCONV isAcceptable(void *, const char *, const char *, const UDataInf o *) { 580 UBool U_CALLCONV isAcceptable(void *, const char *, const char *, const UDataInf o *) {
801 return TRUE; 581 return TRUE;
802 } 582 }
803 583
804 //static UMTX debugMutex = NULL; 584 //static UMTX debugMutex = NULL;
805 //static UMTX gDebugMutex; 585 //static UMTX gDebugMutex;
806 586
807 587
808 class FormatThreadTest : public ThreadWithStatus 588 class FormatThreadTest : public SimpleThread
809 { 589 {
810 public: 590 public:
811 int fNum; 591 int fNum;
812 int fTraceInfo; 592 int fTraceInfo;
813 593
814 ThreadSafeFormat fTSF; 594 LocalPointer<ThreadSafeFormat> fTSF;
815 595
816 FormatThreadTest() // constructor is NOT multithread safe. 596 FormatThreadTest() // constructor is NOT multithread safe.
817 : ThreadWithStatus(), 597 : SimpleThread(),
818 fNum(0), 598 fNum(0),
819 fTraceInfo(0), 599 fTraceInfo(0),
600 fTSF(NULL),
820 fOffset(0) 601 fOffset(0)
821 // the locale to use 602 // the locale to use
822 { 603 {
604 UErrorCode status = U_ZERO_ERROR; // TODO: rearrange code to allow checking of status.
605 fTSF.adoptInstead(new ThreadSafeFormat(status));
823 static int32_t fgOffset = 0; 606 static int32_t fgOffset = 0;
824 fgOffset += 3; 607 fgOffset += 3;
825 fOffset = fgOffset; 608 fOffset = fgOffset;
826 } 609 }
827 610
828 611
829 virtual void run() 612 virtual void run()
830 { 613 {
831 fTraceInfo = 1; 614 fTraceInfo = 1;
832 LocalPointer<NumberFormat> percentFormatter; 615 LocalPointer<NumberFormat> percentFormatter;
833 UErrorCode status = U_ZERO_ERROR; 616 UErrorCode status = U_ZERO_ERROR;
834 617
835 #if 0 618 #if 0
836 // debugging code, 619 // debugging code,
837 for (int i=0; i<4000; i++) { 620 for (int i=0; i<4000; i++) {
838 status = U_ZERO_ERROR; 621 status = U_ZERO_ERROR;
839 UDataMemory *data1 = udata_openChoice(0, "res", "en_US", isAcceptabl e, 0, &status); 622 UDataMemory *data1 = udata_openChoice(0, "res", "en_US", isAcceptabl e, 0, &status);
840 UDataMemory *data2 = udata_openChoice(0, "res", "fr", isAcceptable, 0, &status); 623 UDataMemory *data2 = udata_openChoice(0, "res", "fr", isAcceptable, 0, &status);
841 udata_close(data1); 624 udata_close(data1);
842 udata_close(data2); 625 udata_close(data2);
843 if (U_FAILURE(status)) { 626 if (U_FAILURE(status)) {
844 error("udata_openChoice failed.\n"); 627 error("udata_openChoice failed.\n");
845 break; 628 break;
846 } 629 }
847 } 630 }
848 return; 631 return;
849 #endif 632 #endif
850 633
851 #if 0 634 #if 0
852 // debugging code, 635 // debugging code,
853 int m; 636 int m;
854 for (m=0; m<4000; m++) { 637 for (m=0; m<4000; m++) {
855 status = U_ZERO_ERROR; 638 status = U_ZERO_ERROR;
856 UResourceBundle *res = NULL; 639 UResourceBundle *res = NULL;
857 const char *localeName = NULL; 640 const char *localeName = NULL;
858 641
859 Locale loc = Locale::getEnglish(); 642 Locale loc = Locale::getEnglish();
860 643
861 localeName = loc.getName(); 644 localeName = loc.getName();
862 // localeName = "en"; 645 // localeName = "en";
863 646
864 // ResourceBundle bund = ResourceBundle(0, loc, status); 647 // ResourceBundle bund = ResourceBundle(0, loc, status);
865 //umtx_lock(&gDebugMutex); 648 //umtx_lock(&gDebugMutex);
866 res = ures_open(NULL, localeName, &status); 649 res = ures_open(NULL, localeName, &status);
867 //umtx_unlock(&gDebugMutex); 650 //umtx_unlock(&gDebugMutex);
868 651
869 //umtx_lock(&gDebugMutex); 652 //umtx_lock(&gDebugMutex);
870 ures_close(res); 653 ures_close(res);
871 //umtx_unlock(&gDebugMutex); 654 //umtx_unlock(&gDebugMutex);
872 655
873 if (U_FAILURE(status)) { 656 if (U_FAILURE(status)) {
874 error("Resource bundle construction failed.\n"); 657 error("Resource bundle construction failed.\n");
875 break; 658 break;
876 } 659 }
877 } 660 }
878 return; 661 return;
879 #endif 662 #endif
880 663
881 // Keep this data here to avoid static initialization. 664 // Keep this data here to avoid static initialization.
882 FormatThreadTestData kNumberFormatTestData[] = 665 FormatThreadTestData kNumberFormatTestData[] =
883 { 666 {
884 FormatThreadTestData((double)5.0, UnicodeString("5", "")), 667 FormatThreadTestData((double)5.0, UnicodeString("5", "")),
885 FormatThreadTestData( 6.0, UnicodeString("6", "")), 668 FormatThreadTestData( 6.0, UnicodeString("6", "")),
886 FormatThreadTestData( 20.0, UnicodeString("20", "")), 669 FormatThreadTestData( 20.0, UnicodeString("20", "")),
887 FormatThreadTestData( 8.0, UnicodeString("8", "")), 670 FormatThreadTestData( 8.0, UnicodeString("8", "")),
888 FormatThreadTestData( 8.3, UnicodeString("8.3", "")), 671 FormatThreadTestData( 8.3, UnicodeString("8.3", "")),
889 FormatThreadTestData( 12345, UnicodeString("12,345", "")), 672 FormatThreadTestData( 12345, UnicodeString("12,345", "")),
890 FormatThreadTestData( 81890.23, UnicodeString("81,890.23", "")), 673 FormatThreadTestData( 81890.23, UnicodeString("81,890.23", "")),
891 }; 674 };
892 int32_t kNumberFormatTestDataLength = (int32_t)(sizeof(kNumberFormatTest Data) / 675 int32_t kNumberFormatTestDataLength = UPRV_LENGTHOF(kNumberFormatTestDat a);
893 sizeof(kNumberFormatTest Data[0])); 676
894
895 // Keep this data here to avoid static initialization. 677 // Keep this data here to avoid static initialization.
896 FormatThreadTestData kPercentFormatTestData[] = 678 FormatThreadTestData kPercentFormatTestData[] =
897 { 679 {
898 FormatThreadTestData((double)5.0, CharsToUnicodeString("500\\u00a0%" )), 680 FormatThreadTestData((double)5.0, CharsToUnicodeString("500\\u00a0%" )),
899 FormatThreadTestData( 1.0, CharsToUnicodeString("100\\u00a0%")), 681 FormatThreadTestData( 1.0, CharsToUnicodeString("100\\u00a0%")),
900 FormatThreadTestData( 0.26, CharsToUnicodeString("26\\u00a0%")), 682 FormatThreadTestData( 0.26, CharsToUnicodeString("26\\u00a0%")),
901 FormatThreadTestData( 683 FormatThreadTestData(
902 16384.99, CharsToUnicodeString("1\\u00a0638\\u00a0499\\u00a0% ")), // U+00a0 = NBSP 684 16384.99, CharsToUnicodeString("1\\u00a0638\\u00a0499\\u00a0% ")), // U+00a0 = NBSP
903 FormatThreadTestData( 685 FormatThreadTestData(
904 81890.23, CharsToUnicodeString("8\\u00a0189\\u00a0023\\u00a0 %")), 686 81890.23, CharsToUnicodeString("8\\u00a0189\\u00a0023\\u00a0 %")),
905 }; 687 };
906 int32_t kPercentFormatTestDataLength = 688 int32_t kPercentFormatTestDataLength = UPRV_LENGTHOF(kPercentFormatTestD ata);
907 (int32_t)(sizeof(kPercentFormatTestData) / sizeof(kPercentFormat TestData[0]));
908 int32_t iteration; 689 int32_t iteration;
909 690
910 status = U_ZERO_ERROR; 691 status = U_ZERO_ERROR;
911 LocalPointer<NumberFormat> formatter(NumberFormat::createInstance(Locale ::getEnglish(),status)); 692 LocalPointer<NumberFormat> formatter(NumberFormat::createInstance(Locale ::getEnglish(),status));
912 if(U_FAILURE(status)) { 693 if(U_FAILURE(status)) {
913 error("Error on NumberFormat::createInstance()."); 694 IntlTest::gTest->dataerrln("%s:%d Error %s on NumberFormat::createIn stance().",
695 __FILE__, __LINE__, u_errorName(status));
914 goto cleanupAndReturn; 696 goto cleanupAndReturn;
915 } 697 }
916 698
917 percentFormatter.adoptInstead(NumberFormat::createPercentInstance(Locale ::getFrench(),status)); 699 percentFormatter.adoptInstead(NumberFormat::createPercentInstance(Locale ::getFrench(),status));
918 if(U_FAILURE(status)) { 700 if(U_FAILURE(status)) {
919 error("Error on NumberFormat::createPercentInstance()."); 701 IntlTest::gTest->errln("%s:%d Error %s on NumberFormat::createPercen tInstance().",
702 __FILE__, __LINE__, u_errorName(status));
920 goto cleanupAndReturn; 703 goto cleanupAndReturn;
921 } 704 }
922 705
923 for(iteration = 0;!getError() && iteration<kFormatThreadIterations;itera tion++) 706 for(iteration = 0;!IntlTest::gTest->getErrors() && iteration<kFormatThre adIterations;iteration++)
924 { 707 {
925 708
926 int32_t whichLine = (iteration + fOffset)%kNumberFormatTestDataLengt h; 709 int32_t whichLine = (iteration + fOffset)%kNumberFormatTestDataLengt h;
927 710
928 UnicodeString output; 711 UnicodeString output;
929 712
930 formatter->format(kNumberFormatTestData[whichLine].number, output); 713 formatter->format(kNumberFormatTestData[whichLine].number, output);
931 714
932 if(0 != output.compare(kNumberFormatTestData[whichLine].string)) { 715 if(0 != output.compare(kNumberFormatTestData[whichLine].string)) {
933 error("format().. expected " + kNumberFormatTestData[whichLine]. string 716 IntlTest::gTest->errln("format().. expected " + kNumberFormatTes tData[whichLine].string
934 + " got " + output); 717 + " got " + output);
935 goto cleanupAndReturn; 718 goto cleanupAndReturn;
936 } 719 }
937 720
938 // Now check percent. 721 // Now check percent.
939 output.remove(); 722 output.remove();
940 whichLine = (iteration + fOffset)%kPercentFormatTestDataLength; 723 whichLine = (iteration + fOffset)%kPercentFormatTestDataLength;
941 724
942 percentFormatter->format(kPercentFormatTestData[whichLine].number, o utput); 725 percentFormatter->format(kPercentFormatTestData[whichLine].number, o utput);
943 if(0 != output.compare(kPercentFormatTestData[whichLine].string)) 726 if(0 != output.compare(kPercentFormatTestData[whichLine].string))
944 { 727 {
945 error("percent format().. \n" + 728 IntlTest::gTest->errln("percent format().. \n" +
946 showDifference(kPercentFormatTestData[whichLine].string, output)); 729 showDifference(kPercentFormatTestData[whichLine].string, output));
947 goto cleanupAndReturn; 730 goto cleanupAndReturn;
948 } 731 }
949 732
950 // Test message error 733 // Test message error
951 const int kNumberOfMessageTests = 3; 734 const int kNumberOfMessageTests = 3;
952 UErrorCode statusToCheck; 735 UErrorCode statusToCheck;
953 UnicodeString patternToCheck; 736 UnicodeString patternToCheck;
954 Locale messageLocale; 737 Locale messageLocale;
955 Locale countryToCheck; 738 Locale countryToCheck;
956 double currencyToCheck; 739 double currencyToCheck;
957 740
958 UnicodeString expected; 741 UnicodeString expected;
959 742
960 // load the cases. 743 // load the cases.
961 switch((iteration+fOffset) % kNumberOfMessageTests) 744 switch((iteration+fOffset) % kNumberOfMessageTests)
962 { 745 {
963 default: 746 default:
964 case 0: 747 case 0:
965 statusToCheck= U_FILE_ACCESS_ERROR; 748 statusToCheck= U_FILE_ACCESS_ERROR;
966 patternToCheck= "0:Someone from {2} is receiving a #{0}" 749 patternToCheck= "0:Someone from {2} is receiving a #{0}"
967 " error - {1}. Their telephone call is co sting " 750 " error - {1}. Their telephone call is co sting "
968 "{3,number,currency}."; // number,currenc y 751 "{3,number,currency}."; // number,currenc y
969 messageLocale= Locale("en","US"); 752 messageLocale= Locale("en","US");
970 countryToCheck= Locale("","HR"); 753 countryToCheck= Locale("","HR");
971 currencyToCheck= 8192.77; 754 currencyToCheck= 8192.77;
972 expected= "0:Someone from Croatia is receiving a #4 error - " 755 expected= "0:Someone from Croatia is receiving a #4 error - "
973 "U_FILE_ACCESS_ERROR. Their telephone call is costin g $8,192.77."; 756 "U_FILE_ACCESS_ERROR. Their telephone call is costin g $8,192.77.";
974 break; 757 break;
975 case 1: 758 case 1:
976 statusToCheck= U_INDEX_OUTOFBOUNDS_ERROR; 759 statusToCheck= U_INDEX_OUTOFBOUNDS_ERROR;
977 patternToCheck= "1:A customer in {2} is rece iving a #{0} error - {1}. Their telephone call is costing {3,number,currency}."; // number,currency 760 patternToCheck= "1:A customer in {2} is rece iving a #{0} error - {1}. "
761 "Their telephone call is cos ting {3,number,currency}."; // number,currency
978 messageLocale= Locale("de","DE@currency=DEM "); 762 messageLocale= Locale("de","DE@currency=DEM ");
979 countryToCheck= Locale("","BF"); 763 countryToCheck= Locale("","BF");
980 currencyToCheck= 2.32; 764 currencyToCheck= 2.32;
981 expected= CharsToUnicodeString( 765 expected= CharsToUnicodeString(
982 "1:A customer in Burkina Fas o is receiving a #8 error - U_INDEX_OUTOFBOUNDS_ERROR. Their telephone call is c osting 2,32\\u00A0DM."); 766 "1:A customer in Burkina Fas o is receiving a #8 error - U_INDEX_OUTOFBOUNDS_ERROR. "
767 "Their telephone call is cos ting 2,32\\u00A0DM.");
983 break; 768 break;
984 case 2: 769 case 2:
985 statusToCheck= U_MEMORY_ALLOCATION_ERROR; 770 statusToCheck= U_MEMORY_ALLOCATION_ERROR;
986 patternToCheck= "2:user in {2} is receiving a #{0} error - {1} . " 771 patternToCheck= "2:user in {2} is receiving a #{0} error - {1} . "
987 "They insist they just spent {3,number,currenc y} " 772 "They insist they just spent {3,number,currenc y} "
988 "on memory."; // number,currency 773 "on memory."; // number,currency
989 messageLocale= Locale("de","AT@currency=ATS "); // Austrian German 774 messageLocale= Locale("de","AT@currency=ATS "); // Austrian German
990 countryToCheck= Locale("","US"); // hmm 775 countryToCheck= Locale("","US"); // hmm
991 currencyToCheck= 40193.12; 776 currencyToCheck= 40193.12;
992 expected= CharsToUnicodeString( 777 expected= CharsToUnicodeString(
993 "2:user in Vereinigte Staaten is receiving a #7 erro r" 778 "2:user in Vereinigte Staaten is receiving a #7 erro r"
994 " - U_MEMORY_ALLOCATION_ERROR. They insist they just spent" 779 " - U_MEMORY_ALLOCATION_ERROR. They insist they just spent"
995 " \\u00f6S\\u00A040.193,12 on memory."); 780 " \\u00f6S\\u00A040\\u00A0193,12 on memory.");
996 break; 781 break;
997 } 782 }
998 783
999 UnicodeString result; 784 UnicodeString result;
1000 UErrorCode status = U_ZERO_ERROR; 785 UErrorCode status = U_ZERO_ERROR;
1001 formatErrorMessage(status,patternToCheck,messageLocale,statusToCheck , 786 formatErrorMessage(status,patternToCheck,messageLocale,statusToCheck ,
1002 countryToCheck,currencyToCheck,result); 787 countryToCheck,currencyToCheck,result);
1003 if(U_FAILURE(status)) 788 if(U_FAILURE(status))
1004 { 789 {
1005 UnicodeString tmp(u_errorName(status)); 790 UnicodeString tmp(u_errorName(status));
1006 error("Failure on message format, pattern=" + patternToCheck + 791 IntlTest::gTest->errln("Failure on message format, pattern=" + p atternToCheck +
1007 ", error = " + tmp); 792 ", error = " + tmp);
1008 goto cleanupAndReturn; 793 goto cleanupAndReturn;
1009 } 794 }
1010 795
1011 if(result != expected) 796 if(result != expected)
1012 { 797 {
1013 error("PatternFormat: \n" + showDifference(expected,result)); 798 IntlTest::gTest->errln("PatternFormat: \n" + showDifference(expe cted,result));
1014 goto cleanupAndReturn; 799 goto cleanupAndReturn;
1015 } 800 }
1016 // test the Thread Safe Format 801 // test the Thread Safe Format
1017 UnicodeString appendErr; 802 UnicodeString appendErr;
1018 if(!fTSF.doStuff(fNum, appendErr, status)) { 803 if(!fTSF->doStuff(fNum, appendErr, status)) {
1019 error(appendErr); 804 IntlTest::gTest->errln(appendErr);
1020 goto cleanupAndReturn; 805 goto cleanupAndReturn;
1021 } 806 }
1022 } /* end of for loop */ 807 } /* end of for loop */
1023 808
1024 809
1025 810
1026 cleanupAndReturn: 811 cleanupAndReturn:
1027 // while (fNum == 4) {SimpleThread::sleep(10000);} // Force a failure by preventing thread from finishing
1028 fTraceInfo = 2; 812 fTraceInfo = 2;
1029 } 813 }
1030 814
1031 private: 815 private:
1032 int32_t fOffset; // where we are testing from. 816 int32_t fOffset; // where we are testing from.
1033 }; 817 };
1034 818
1035 // ** The actual test function. 819 // ** The actual test function.
1036 820
1037 void MultithreadTest::TestThreadedIntl() 821 void MultithreadTest::TestThreadedIntl()
1038 { 822 {
1039 int i;
1040 UnicodeString theErr; 823 UnicodeString theErr;
1041 UBool haveDisplayedInfo[kFormatThreadThreads];
1042 static const int32_t PATIENCE_SECONDS = 45;
1043 824
1044 UErrorCode threadSafeErr = U_ZERO_ERROR; 825 UErrorCode threadSafeErr = U_ZERO_ERROR;
1045 826
1046 ThreadSafeFormat::init(threadSafeErr); 827 ThreadSafeFormatSharedData sharedData(threadSafeErr);
1047 assertSuccess("initializing ThreadSafeFormat", threadSafeErr, TRUE); 828 assertSuccess("initializing ThreadSafeFormat", threadSafeErr, TRUE);
1048 829
1049 // 830 //
1050 // Create and start the test threads 831 // Create and start the test threads
1051 // 832 //
1052 logln("Spawning: %d threads * %d iterations each.", 833 logln("Spawning: %d threads * %d iterations each.",
1053 kFormatThreadThreads, kFormatThreadIterations); 834 kFormatThreadThreads, kFormatThreadIterations);
1054 LocalArray<FormatThreadTest> tests(new FormatThreadTest[kFormatThreadThreads ]); 835 FormatThreadTest tests[kFormatThreadThreads];
1055 for(int32_t j = 0; j < kFormatThreadThreads; j++) { 836 int32_t j;
837 for(j = 0; j < UPRV_LENGTHOF(tests); j++) {
1056 tests[j].fNum = j; 838 tests[j].fNum = j;
1057 int32_t threadStatus = tests[j].start(); 839 int32_t threadStatus = tests[j].start();
1058 if (threadStatus != 0) { 840 if (threadStatus != 0) {
1059 errln("System Error %d starting thread number %d.", threadStatus, j) ; 841 errln("%s:%d System Error %d starting thread number %d.",
1060 SimpleThread::errorFunc(); 842 __FILE__, __LINE__, threadStatus, j);
1061 return; 843 return;
1062 } 844 }
1063 haveDisplayedInfo[j] = FALSE;
1064 } 845 }
1065 846
1066 847
1067 // Spin, waiting for the test threads to finish. 848 for (j=0; j<UPRV_LENGTHOF(tests); j++) {
1068 UBool stillRunning; 849 tests[j].join();
1069 UDate startTime, endTime; 850 logln("Thread # %d is complete..", j);
1070 startTime = Calendar::getNow(); 851 }
1071 double lastComplaint = 0;
1072 do {
1073 /* Spin until the test threads complete. */
1074 stillRunning = FALSE;
1075 endTime = Calendar::getNow();
1076 double elapsedSeconds = ((int32_t)(endTime - startTime)/U_MILLIS_PER_SE COND);
1077 if (elapsedSeconds > PATIENCE_SECONDS) {
1078 errln("Patience exceeded. Test is taking too long.");
1079 return;
1080 } else if((elapsedSeconds-lastComplaint) > 2.0) {
1081 infoln("%.1f seconds elapsed (still waiting..)", elapsedSeconds);
1082 lastComplaint = elapsedSeconds;
1083 }
1084 /*
1085 The following sleep must be here because the *BSD operating systems
1086 have a brain dead thread scheduler. They starve the child threads from
1087 CPU time.
1088 */
1089 SimpleThread::sleep(1); // yield
1090 for(i=0;i<kFormatThreadThreads;i++) {
1091 if (tests[i].isRunning()) {
1092 stillRunning = TRUE;
1093 } else if (haveDisplayedInfo[i] == FALSE) {
1094 logln("Thread # %d is complete..", i);
1095 if(tests[i].getError(theErr)) {
1096 dataerrln(UnicodeString("#") + i + ": " + theErr);
1097 SimpleThread::errorFunc();
1098 }
1099 haveDisplayedInfo[i] = TRUE;
1100 }
1101 }
1102 } while (stillRunning);
1103
1104 //
1105 // All threads have finished.
1106 //
1107 ThreadSafeFormat::fini(threadSafeErr);
1108 assertSuccess("finalizing ThreadSafeFormat", threadSafeErr, TRUE);
1109 } 852 }
1110 #endif /* #if !UCONFIG_NO_FORMATTING */ 853 #endif /* #if !UCONFIG_NO_FORMATTING */
1111 854
1112 855
1113 856
1114 857
1115 858
1116 //------------------------------------------------------------------------------ ------------- 859 //------------------------------------------------------------------------------ -------------
1117 // 860 //
1118 // Collation threading test 861 // Collation threading test
(...skipping 19 matching lines...) Expand all
1138 return TRUE; 881 return TRUE;
1139 } 882 }
1140 return FALSE; 883 return FALSE;
1141 } 884 }
1142 885
1143 static UCollationResult 886 static UCollationResult
1144 normalizeResult(int32_t result) { 887 normalizeResult(int32_t result) {
1145 return result<0 ? UCOL_LESS : result==0 ? UCOL_EQUAL : UCOL_GREATER; 888 return result<0 ? UCOL_LESS : result==0 ? UCOL_EQUAL : UCOL_GREATER;
1146 } 889 }
1147 890
1148 class CollatorThreadTest : public ThreadWithStatus 891 class CollatorThreadTest : public SimpleThread
1149 { 892 {
1150 private: 893 private:
1151 const Collator *coll; 894 const Collator *coll;
1152 const Line *lines; 895 const Line *lines;
1153 int32_t noLines; 896 int32_t noLines;
1154 UBool isAtLeastUCA62; 897 UBool isAtLeastUCA62;
1155 public: 898 public:
1156 CollatorThreadTest() : ThreadWithStatus(), 899 CollatorThreadTest() : SimpleThread(),
1157 coll(NULL), 900 coll(NULL),
1158 lines(NULL), 901 lines(NULL),
1159 noLines(0), 902 noLines(0),
1160 isAtLeastUCA62(TRUE) 903 isAtLeastUCA62(TRUE)
1161 { 904 {
1162 }; 905 };
1163 void setCollator(Collator *c, Line *l, int32_t nl, UBool atLeastUCA62) 906 void setCollator(Collator *c, Line *l, int32_t nl, UBool atLeastUCA62)
1164 { 907 {
1165 coll = c; 908 coll = c;
1166 lines = l; 909 lines = l;
(...skipping 13 matching lines...) Expand all
1180 if(skipLineBecauseOfBug(lines[i].buff, lines[i].buflen)) { continue; } 923 if(skipLineBecauseOfBug(lines[i].buff, lines[i].buflen)) { continue; }
1181 924
1182 int32_t resLen = coll->getSortKey(lines[i].buff, lines[i].buflen, ne wSk, 1024); 925 int32_t resLen = coll->getSortKey(lines[i].buff, lines[i].buflen, ne wSk, 1024);
1183 926
1184 if(oldSk != NULL) { 927 if(oldSk != NULL) {
1185 int32_t skres = strcmp((char *)oldSk, (char *)newSk); 928 int32_t skres = strcmp((char *)oldSk, (char *)newSk);
1186 int32_t cmpres = coll->compare(lines[prev].buff, lines[prev].buf len, lines[i].buff, lines[i].buflen); 929 int32_t cmpres = coll->compare(lines[prev].buff, lines[prev].buf len, lines[i].buff, lines[i].buflen);
1187 int32_t cmpres2 = coll->compare(lines[i].buff, lines[i].buflen, lines[prev].buff, lines[prev].buflen); 930 int32_t cmpres2 = coll->compare(lines[i].buff, lines[i].buflen, lines[prev].buff, lines[prev].buflen);
1188 931
1189 if(cmpres != -cmpres2) { 932 if(cmpres != -cmpres2) {
1190 error(UnicodeString("Compare result not symmetrical on line ") + (i + 1)); 933 IntlTest::gTest->errln(UnicodeString("Compare result not sym metrical on line ") + (i + 1));
1191 break; 934 break;
1192 } 935 }
1193 936
1194 if(cmpres != normalizeResult(skres)) { 937 if(cmpres != normalizeResult(skres)) {
1195 error(UnicodeString("Difference between coll->compare and so rtkey compare on line ") + (i + 1)); 938 IntlTest::gTest->errln(UnicodeString("Difference between col l->compare and sortkey compare on line ") + (i + 1));
1196 break; 939 break;
1197 } 940 }
1198 941
1199 int32_t res = cmpres; 942 int32_t res = cmpres;
1200 if(res == 0 && !isAtLeastUCA62) { 943 if(res == 0 && !isAtLeastUCA62) {
1201 // Up to UCA 6.1, the collation test files use a custom tie- breaker, 944 // Up to UCA 6.1, the collation test files use a custom tie- breaker,
1202 // comparing the raw input strings. 945 // comparing the raw input strings.
1203 res = u_strcmpCodePointOrder(lines[prev].buff, lines[i].buff ); 946 res = u_strcmpCodePointOrder(lines[prev].buff, lines[i].buff );
1204 // Starting with UCA 6.2, the collation test files use the s tandard UCA tie-breaker, 947 // Starting with UCA 6.2, the collation test files use the s tandard UCA tie-breaker,
1205 // comparing the NFD versions of the input strings, 948 // comparing the NFD versions of the input strings,
1206 // which we do via setting strength=identical. 949 // which we do via setting strength=identical.
1207 } 950 }
1208 if(res > 0) { 951 if(res > 0) {
1209 error(UnicodeString("Line is not greater or equal than previ ous line, for line ") + (i + 1)); 952 IntlTest::gTest->errln(UnicodeString("Line is not greater or equal than previous line, for line ") + (i + 1));
1210 break; 953 break;
1211 } 954 }
1212 } 955 }
1213 956
1214 oldSk = newSk; 957 oldSk = newSk;
1215 oldLen = resLen; 958 oldLen = resLen;
1216 (void)oldLen; // Suppress set but not used warning. 959 (void)oldLen; // Suppress set but not used warning.
1217 prev = i; 960 prev = i;
1218 961
1219 newSk = (newSk == sk1)?sk2:sk1; 962 newSk = (newSk == sk1)?sk2:sk1;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1261 testFile = fopen(buffer, "rb"); 1004 testFile = fopen(buffer, "rb");
1262 1005
1263 if(testFile == 0) { 1006 if(testFile == 0) {
1264 strcpy(buffer+bufLen, "_STUB"); 1007 strcpy(buffer+bufLen, "_STUB");
1265 strcat(buffer, ext); 1008 strcat(buffer, ext);
1266 testFile = fopen(buffer, "rb"); 1009 testFile = fopen(buffer, "rb");
1267 1010
1268 if (testFile == 0) { 1011 if (testFile == 0) {
1269 *(buffer+bufLen) = 0; 1012 *(buffer+bufLen) = 0;
1270 dataerrln("could not open any of the conformance test files, tri ed opening base %s", buffer); 1013 dataerrln("could not open any of the conformance test files, tri ed opening base %s", buffer);
1271 return; 1014 return;
1272 } else { 1015 } else {
1273 infoln( 1016 infoln(
1274 "INFO: Working with the stub file.\n" 1017 "INFO: Working with the stub file.\n"
1275 "If you need the full conformance test, please\n" 1018 "If you need the full conformance test, please\n"
1276 "download the appropriate data files from:\n" 1019 "download the appropriate data files from:\n"
1277 "http://source.icu-project.org/repos/icu/tools/trunk/unicode tools/com/ibm/text/data/"); 1020 "http://source.icu-project.org/repos/icu/tools/trunk/unicode tools/com/ibm/text/data/");
1278 } 1021 }
1279 } 1022 }
1280 } 1023 }
1281 1024
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1315 if(U_FAILURE(status)) { 1058 if(U_FAILURE(status)) {
1316 errcheckln(status, "Couldn't open UCA collator"); 1059 errcheckln(status, "Couldn't open UCA collator");
1317 return; 1060 return;
1318 } 1061 }
1319 coll->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status); 1062 coll->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status);
1320 coll->setAttribute(UCOL_CASE_FIRST, UCOL_OFF, status); 1063 coll->setAttribute(UCOL_CASE_FIRST, UCOL_OFF, status);
1321 coll->setAttribute(UCOL_CASE_LEVEL, UCOL_OFF, status); 1064 coll->setAttribute(UCOL_CASE_LEVEL, UCOL_OFF, status);
1322 coll->setAttribute(UCOL_STRENGTH, isAtLeastUCA62 ? UCOL_IDENTICAL : UCOL_TER TIARY, status); 1065 coll->setAttribute(UCOL_STRENGTH, isAtLeastUCA62 ? UCOL_IDENTICAL : UCOL_TER TIARY, status);
1323 coll->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_NON_IGNORABLE, status); 1066 coll->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_NON_IGNORABLE, status);
1324 1067
1325 int32_t noSpawned = 0;
1326 int32_t spawnResult = 0; 1068 int32_t spawnResult = 0;
1327 LocalArray<CollatorThreadTest> tests(new CollatorThreadTest[kCollatorThreadT hreads]); 1069 LocalArray<CollatorThreadTest> tests(new CollatorThreadTest[kCollatorThreadT hreads]);
1328 1070
1329 logln(UnicodeString("Spawning: ") + kCollatorThreadThreads + " threads * " + kFormatThreadIterations + " iterations each."); 1071 logln(UnicodeString("Spawning: ") + kCollatorThreadThreads + " threads * " + kFormatThreadIterations + " iterations each.");
1330 int32_t j = 0; 1072 int32_t j = 0;
1331 for(j = 0; j < kCollatorThreadThreads; j++) { 1073 for(j = 0; j < kCollatorThreadThreads; j++) {
1332 //logln("Setting collator %i", j); 1074 //logln("Setting collator %i", j);
1333 tests[j].setCollator(coll.getAlias(), lines.getAlias(), lineNum, isAtLea stUCA62); 1075 tests[j].setCollator(coll.getAlias(), lines.getAlias(), lineNum, isAtLea stUCA62);
1334 } 1076 }
1335 for(j = 0; j < kCollatorThreadThreads; j++) { 1077 for(j = 0; j < kCollatorThreadThreads; j++) {
1336 log("%i ", j); 1078 log("%i ", j);
1337 spawnResult = tests[j].start(); 1079 spawnResult = tests[j].start();
1338 if(spawnResult != 0) { 1080 if(spawnResult != 0) {
1339 infoln("THREAD INFO: Couldn't spawn more than %i threads", noSpawned ); 1081 errln("%s:%d THREAD INFO: thread %d failed to start with status %d", __FILE__, __LINE__, j, spawnResult);
1340 break; 1082 return;
1341 } 1083 }
1342 noSpawned++;
1343 } 1084 }
1344 logln("Spawned all"); 1085 logln("Spawned all");
1345 if (noSpawned == 0) { 1086
1346 errln("No threads could be spawned."); 1087 for(int32_t i=0;i<kCollatorThreadThreads;i++) {
1347 return; 1088 tests[i].join();
1089 //logln(UnicodeString("Test #") + i + " is complete.. ");
1348 } 1090 }
1349
1350 for(int32_t patience = kCollatorThreadPatience;patience > 0; patience --)
1351 {
1352 logln("Waiting...");
1353
1354 int32_t i;
1355 int32_t terrs = 0;
1356 int32_t completed =0;
1357
1358 for(i=0;i<kCollatorThreadThreads;i++)
1359 {
1360 if (tests[i].isRunning() == FALSE)
1361 {
1362 completed++;
1363
1364 //logln(UnicodeString("Test #") + i + " is complete.. ");
1365
1366 UnicodeString theErr;
1367 if(tests[i].getError(theErr))
1368 {
1369 terrs++;
1370 errln(UnicodeString("#") + i + ": " + theErr);
1371 }
1372 // print out the error, too, if any.
1373 }
1374 }
1375 logln("Completed %i tests", completed);
1376
1377 if(completed == noSpawned)
1378 {
1379 logln("Done! All %i tests are finished", noSpawned);
1380
1381 if(terrs)
1382 {
1383 errln("There were errors.");
1384 SimpleThread::errorFunc();
1385 }
1386 return;
1387 }
1388
1389 SimpleThread::sleep(900);
1390 }
1391 errln("patience exceeded. ");
1392 SimpleThread::errorFunc();
1393 } 1091 }
1394 1092
1395 #endif /* #if !UCONFIG_NO_COLLATION */ 1093 #endif /* #if !UCONFIG_NO_COLLATION */
1396 1094
1397 1095
1398 1096
1399 1097
1400 //------------------------------------------------------------------------------ ------------- 1098 //------------------------------------------------------------------------------ -------------
1401 // 1099 //
1402 // StringThreadTest2 1100 // StringThreadTest2
1403 // 1101 //
1404 //------------------------------------------------------------------------------ ------------- 1102 //------------------------------------------------------------------------------ -------------
1405 1103
1406 const int kStringThreadIterations = 2500;// # of iterations per thread 1104 const int kStringThreadIterations = 2500;// # of iterations per thread
1407 const int kStringThreadThreads = 10; // # of threads to spawn 1105 const int kStringThreadThreads = 10; // # of threads to spawn
1408 const int kStringThreadPatience = 120; // time in seconds to wait for all thre ads
1409 1106
1410 1107
1411 class StringThreadTest2 : public ThreadWithStatus 1108 class StringThreadTest2 : public SimpleThread
1412 { 1109 {
1413 public: 1110 public:
1414 int fNum; 1111 int fNum;
1415 int fTraceInfo; 1112 int fTraceInfo;
1416 const UnicodeString *fSharedString; 1113 static const UnicodeString *gSharedString;
1417 1114
1418 StringThreadTest2(const UnicodeString *sharedString, int num) // constructor is NOT multithread safe. 1115 StringThreadTest2() // constructor is NOT multithread safe.
1419 : ThreadWithStatus(), 1116 : SimpleThread(),
1420 fNum(num), 1117 fTraceInfo(0)
1421 fTraceInfo(0),
1422 fSharedString(sharedString)
1423 { 1118 {
1424 }; 1119 };
1425 1120
1426 1121
1427 virtual void run() 1122 virtual void run()
1428 { 1123 {
1429 fTraceInfo = 1; 1124 fTraceInfo = 1;
1430 int loopCount = 0; 1125 int loopCount = 0;
1431 1126
1432 for (loopCount = 0; loopCount < kStringThreadIterations; loopCount++) { 1127 for (loopCount = 0; loopCount < kStringThreadIterations; loopCount++) {
1433 if (*fSharedString != "This is the original test string.") { 1128 if (*gSharedString != "This is the original test string.") {
1434 error("Original string is corrupt."); 1129 IntlTest::gTest->errln("%s:%d Original string is corrupt.", __FI LE__, __LINE__);
1435 break; 1130 break;
1436 } 1131 }
1437 UnicodeString s1 = *fSharedString; 1132 UnicodeString s1 = *gSharedString;
1438 s1 += "cat this"; 1133 s1 += "cat this";
1439 UnicodeString s2(s1); 1134 UnicodeString s2(s1);
1440 UnicodeString s3 = *fSharedString; 1135 UnicodeString s3 = *gSharedString;
1441 s2 = s3; 1136 s2 = s3;
1442 s3.truncate(12); 1137 s3.truncate(12);
1443 s2.truncate(0); 1138 s2.truncate(0);
1444 } 1139 }
1445 1140
1446 // while (fNum == 4) {SimpleThread::sleep(10000);} // Force a failure by preventing thread from finishing
1447 fTraceInfo = 2; 1141 fTraceInfo = 2;
1448 } 1142 }
1449 1143
1450 }; 1144 };
1451 1145
1146 const UnicodeString *StringThreadTest2::gSharedString = NULL;
1147
1452 // ** The actual test function. 1148 // ** The actual test function.
1453 1149
1150
1454 void MultithreadTest::TestString() 1151 void MultithreadTest::TestString()
1455 { 1152 {
1456 int patience;
1457 int terrs = 0;
1458 int j; 1153 int j;
1154 StringThreadTest2::gSharedString = new UnicodeString("This is the original t est string.");
1155 StringThreadTest2 tests[kStringThreadThreads];
1459 1156
1460 UnicodeString *testString = new UnicodeString("This is the original test str ing.");
1461
1462 // Not using LocalArray<StringThreadTest2> tests[kStringThreadThreads];
1463 // because we don't always want to delete them.
1464 // See the comments below the cleanupAndReturn label.
1465 StringThreadTest2 *tests[kStringThreadThreads];
1466 for(j = 0; j < kStringThreadThreads; j++) {
1467 tests[j] = new StringThreadTest2(testString, j);
1468 }
1469
1470 logln(UnicodeString("Spawning: ") + kStringThreadThreads + " threads * " + k StringThreadIterations + " iterations each."); 1157 logln(UnicodeString("Spawning: ") + kStringThreadThreads + " threads * " + k StringThreadIterations + " iterations each.");
1471 for(j = 0; j < kStringThreadThreads; j++) { 1158 for(j = 0; j < kStringThreadThreads; j++) {
1472 int32_t threadStatus = tests[j]->start(); 1159 int32_t threadStatus = tests[j].start();
1473 if (threadStatus != 0) { 1160 if (threadStatus != 0) {
1474 errln("System Error %d starting thread number %d.", threadStatus, j) ; 1161 errln("%s:%d System Error %d starting thread number %d.", __FILE__, __LINE__, threadStatus, j);
1475 SimpleThread::errorFunc();
1476 goto cleanupAndReturn;
1477 } 1162 }
1478 } 1163 }
1479 1164
1480 for(patience = kStringThreadPatience;patience > 0; patience --) 1165 // Force a failure, to verify test is functioning and can report errors.
1481 { 1166 // const_cast<UnicodeString *>(StringThreadTest2::gSharedString)->setCharAt( 5, 'x');
1482 logln("Waiting...");
1483 1167
1484 int32_t i; 1168 for(j=0; j<kStringThreadThreads; j++) {
1485 terrs = 0; 1169 tests[j].join();
1486 int32_t completed =0; 1170 logln(UnicodeString("Test #") + j + " is complete.. ");
1487
1488 for(i=0;i<kStringThreadThreads;i++) {
1489 if (tests[i]->isRunning() == FALSE)
1490 {
1491 completed++;
1492
1493 logln(UnicodeString("Test #") + i + " is complete.. ");
1494
1495 UnicodeString theErr;
1496 if(tests[i]->getError(theErr))
1497 {
1498 terrs++;
1499 errln(UnicodeString("#") + i + ": " + theErr);
1500 }
1501 // print out the error, too, if any.
1502 }
1503 }
1504
1505 if(completed == kStringThreadThreads)
1506 {
1507 logln("Done!");
1508 if(terrs) {
1509 errln("There were errors.");
1510 }
1511 break;
1512 }
1513
1514 SimpleThread::sleep(900);
1515 } 1171 }
1516 1172
1517 if (patience <= 0) { 1173 delete StringThreadTest2::gSharedString;
1518 errln("patience exceeded. "); 1174 StringThreadTest2::gSharedString = NULL;
1519 // while (TRUE) {SimpleThread::sleep(10000);} // TODO: for debugging . Sleep forever on failure.
1520 terrs++;
1521 }
1522
1523 if (terrs > 0) {
1524 SimpleThread::errorFunc();
1525 }
1526
1527 cleanupAndReturn:
1528 if (terrs == 0) {
1529 /*
1530 Don't clean up if there are errors. This prevents crashes if the
1531 threads are still running and using this data. This will only happen
1532 if there is an error with the test, ICU, or the machine is too slow.
1533 It's better to leak than crash.
1534 */
1535 for(j = 0; j < kStringThreadThreads; j++) {
1536 delete tests[j];
1537 }
1538 delete testString;
1539 }
1540 } 1175 }
1541 1176
1542 1177
1178 //
1543 // Test for ticket #10673, race in cache code in AnyTransliterator. 1179 // Test for ticket #10673, race in cache code in AnyTransliterator.
1544 // It's difficult to make the original unsafe code actually fail, but 1180 // It's difficult to make the original unsafe code actually fail, but
1545 // this test will fairly reliably take the code path for races in 1181 // this test will fairly reliably take the code path for races in
1546 // populating the cache. 1182 // populating the cache.
1183 //
1547 1184
1548 #if !UCONFIG_NO_TRANSLITERATION 1185 #if !UCONFIG_NO_TRANSLITERATION
1186 Transliterator *gSharedTranslit = NULL;
1549 class TxThread: public SimpleThread { 1187 class TxThread: public SimpleThread {
1550 private:
1551 Transliterator *fSharedTranslit;
1552 public: 1188 public:
1553 UBool fSuccess; 1189 TxThread() {};
1554 TxThread(Transliterator *tx) : fSharedTranslit(tx), fSuccess(FALSE) {};
1555 ~TxThread(); 1190 ~TxThread();
1556 void run(); 1191 void run();
1557 }; 1192 };
1558 1193
1559 TxThread::~TxThread() {} 1194 TxThread::~TxThread() {}
1560 void TxThread::run() { 1195 void TxThread::run() {
1561 UnicodeString greekString("\\u03B4\\u03B9\\u03B1\\u03C6\\u03BF\\u03C1\\u03B5 \\u03C4\\u03B9\\u03BA\\u03BF\\u03CD\\u03C2"); 1196 UnicodeString greekString("\\u03B4\\u03B9\\u03B1\\u03C6\\u03BF\\u03C1\\u03B5 \\u03C4\\u03B9\\u03BA\\u03BF\\u03CD\\u03C2");
1562 greekString = greekString.unescape(); 1197 greekString = greekString.unescape();
1563 fSharedTranslit->transliterate(greekString); 1198 gSharedTranslit->transliterate(greekString);
1564 fSuccess = greekString[0] == 0x64; // 'd'. The whole transliterated string i s "diaphoretikous" (accented u). 1199 if (greekString[0] != 0x64) // 'd'. The whole transliterated string is "diaphoretikous" (accented u).
1200 {
1201 IntlTest::gTest->errln("%s:%d Transliteration failed.", __FILE__, __LINE __);
1202 }
1565 } 1203 }
1566 #endif 1204 #endif
1567 1205
1568 1206
1569 void MultithreadTest::TestAnyTranslit() { 1207 void MultithreadTest::TestAnyTranslit() {
1570 #if !UCONFIG_NO_TRANSLITERATION 1208 #if !UCONFIG_NO_TRANSLITERATION
1571 UErrorCode status = U_ZERO_ERROR; 1209 UErrorCode status = U_ZERO_ERROR;
1572 LocalPointer<Transliterator> tx(Transliterator::createInstance("Any-Latin", UTRANS_FORWARD, status)); 1210 LocalPointer<Transliterator> tx(Transliterator::createInstance("Any-Latin", UTRANS_FORWARD, status));
1573 if (U_FAILURE(status)) { 1211 if (U_FAILURE(status)) {
1574 dataerrln("File %s, Line %d: Error, status = %s", __FILE__, __LINE__, u_ errorName(status)); 1212 dataerrln("File %s, Line %d: Error, status = %s", __FILE__, __LINE__, u_ errorName(status));
1575 return; 1213 return;
1576 } 1214 }
1577 TxThread * threads[4]; 1215 gSharedTranslit = tx.getAlias();
1216 TxThread threads[4];
1578 int32_t i; 1217 int32_t i;
1579 for (i=0; i<4; i++) { 1218 for (i=0; i<UPRV_LENGTHOF(threads); i++) {
1580 threads[i] = new TxThread(tx.getAlias()); 1219 threads[i].start();
1581 } 1220 }
1582 for (i=0; i<4; i++) { 1221
1583 threads[i]->start(); 1222 for (i=0; i<UPRV_LENGTHOF(threads); i++) {
1223 threads[i].join();
1584 } 1224 }
1585 int32_t patience = 100; 1225 gSharedTranslit = NULL;
1586 UBool success;
1587 UBool someThreadRunning;
1588 do {
1589 someThreadRunning = FALSE;
1590 success = TRUE;
1591 for (i=0; i<4; i++) {
1592 if (threads[i]->isRunning()) {
1593 someThreadRunning = TRUE;
1594 SimpleThread::sleep(10);
1595 break;
1596 } else {
1597 if (threads[i]->fSuccess == FALSE) {
1598 success = FALSE;
1599 }
1600 }
1601 }
1602 } while (someThreadRunning && --patience > 0);
1603
1604 if (patience <= 0) {
1605 errln("File %s, Line %d: Error, one or more threads did not complete.", __FILE__, __LINE__);
1606 }
1607 if (success == FALSE) {
1608 errln("File %s, Line %d: Error, transliteration result incorrect.", __FI LE__, __LINE__);
1609 }
1610
1611 for (i=0; i<4; i++) {
1612 delete threads[i];
1613 }
1614 #endif // !UCONFIG_NO_TRANSLITERATION 1226 #endif // !UCONFIG_NO_TRANSLITERATION
1615 } 1227 }
1616 1228
1617 1229
1230 //
1618 // Condition Variables Test 1231 // Condition Variables Test
1619 // Create a swarm of threads. 1232 // Create a swarm of threads.
1620 // Using a mutex and a condition variables each thread 1233 // Using a mutex and a condition variables each thread
1621 // Increments a global count of started threads. 1234 // Increments a global count of started threads.
1622 // Broadcasts that it has started. 1235 // Broadcasts that it has started.
1623 // Waits on the condition that all threads have started. 1236 // Waits on the condition that all threads have started.
1624 // Increments a global count of finished threads. 1237 // Increments a global count of finished threads.
1625 // Waits on the condition that all threads have finished. 1238 // Waits on the condition that all threads have finished.
1626 // Exits. 1239 // Exits.
1240 //
1627 1241
1628 class CondThread: public SimpleThread { 1242 class CondThread: public SimpleThread {
1629 public: 1243 public:
1630 CondThread() :fFinished(false) {}; 1244 CondThread() :fFinished(false) {};
1631 ~CondThread() {}; 1245 ~CondThread() {};
1632 void run(); 1246 void run();
1633 bool fFinished; 1247 bool fFinished;
1634 }; 1248 };
1635 1249
1636 static UMutex gCTMutex = U_MUTEX_INITIALIZER; 1250 static UMutex gCTMutex = U_MUTEX_INITIALIZER;
1637 static UConditionVar gCTConditionVar = U_CONDITION_INITIALIZER; 1251 static UConditionVar gCTConditionVar = U_CONDITION_INITIALIZER;
1638 int gConditionTestOne = 1; // Value one. Non-const, extern linkage to inhibit 1252 int gConditionTestOne = 1; // Value one. Non-const, extern linkage to inhibit
1639 // compiler assuming a known value. 1253 // compiler assuming a known value.
1640 int gStartedThreads; 1254 int gStartedThreads;
1641 int gFinishedThreads; 1255 int gFinishedThreads;
1642 static const int NUMTHREADS = 10; 1256 static const int NUMTHREADS = 10;
1643 1257
1644 static MultithreadTest *gThisTest = NULL; // Make test frame work functions avai lable to
1645 // non-member functions.
1646 1258
1647 // Worker thread function. 1259 // Worker thread function.
1648 void CondThread::run() { 1260 void CondThread::run() {
1649 umtx_lock(&gCTMutex); 1261 umtx_lock(&gCTMutex);
1650 gStartedThreads += gConditionTestOne; 1262 gStartedThreads += gConditionTestOne;
1651 umtx_condBroadcast(&gCTConditionVar); 1263 umtx_condBroadcast(&gCTConditionVar);
1652 1264
1653 while (gStartedThreads < NUMTHREADS) { 1265 while (gStartedThreads < NUMTHREADS) {
1654 if (gFinishedThreads != 0) { 1266 if (gFinishedThreads != 0) {
1655 gThisTest->errln("File %s, Line %d: Error, gStartedThreads = %d, gFi nishedThreads = %d", 1267 IntlTest::gTest->errln("File %s, Line %d: Error, gStartedThreads = % d, gFinishedThreads = %d",
1656 __FILE__, __LINE__, gStartedThreads, gFinishedThrea ds); 1268 __FILE__, __LINE__, gStartedThreads, gFinishedThrea ds);
1657 } 1269 }
1658 umtx_condWait(&gCTConditionVar, &gCTMutex); 1270 umtx_condWait(&gCTConditionVar, &gCTMutex);
1659 } 1271 }
1660 1272
1661 gFinishedThreads += gConditionTestOne; 1273 gFinishedThreads += gConditionTestOne;
1662 fFinished = true; 1274 fFinished = true;
1663 umtx_condBroadcast(&gCTConditionVar); 1275 umtx_condBroadcast(&gCTConditionVar);
1664 1276
1665 while (gFinishedThreads < NUMTHREADS) { 1277 while (gFinishedThreads < NUMTHREADS) {
1666 umtx_condWait(&gCTConditionVar, &gCTMutex); 1278 umtx_condWait(&gCTConditionVar, &gCTMutex);
1667 } 1279 }
1668 umtx_unlock(&gCTMutex); 1280 umtx_unlock(&gCTMutex);
1669 } 1281 }
1670 1282
1671 void MultithreadTest::TestConditionVariables() { 1283 void MultithreadTest::TestConditionVariables() {
1672 gThisTest = this;
1673 gStartedThreads = 0; 1284 gStartedThreads = 0;
1674 gFinishedThreads = 0; 1285 gFinishedThreads = 0;
1675 int i; 1286 int i;
1676 1287
1677 umtx_lock(&gCTMutex); 1288 umtx_lock(&gCTMutex);
1678 CondThread *threads[NUMTHREADS]; 1289 CondThread *threads[NUMTHREADS];
1679 for (i=0; i<NUMTHREADS; ++i) { 1290 for (i=0; i<NUMTHREADS; ++i) {
1680 threads[i] = new CondThread; 1291 threads[i] = new CondThread;
1681 threads[i]->start(); 1292 threads[i]->start();
1682 } 1293 }
1683 1294
1684 while (gStartedThreads < NUMTHREADS) { 1295 while (gStartedThreads < NUMTHREADS) {
1685 umtx_condWait(&gCTConditionVar, &gCTMutex); 1296 umtx_condWait(&gCTConditionVar, &gCTMutex);
1686 } 1297 }
1687 1298
1688 while (gFinishedThreads < NUMTHREADS) { 1299 while (gFinishedThreads < NUMTHREADS) {
1689 umtx_condWait(&gCTConditionVar, &gCTMutex); 1300 umtx_condWait(&gCTConditionVar, &gCTMutex);
1690 } 1301 }
1691 1302
1692 umtx_unlock(&gCTMutex); 1303 umtx_unlock(&gCTMutex);
1693 1304
1694 for (i=0; i<NUMTHREADS; ++i) { 1305 for (i=0; i<NUMTHREADS; ++i) {
1695 if (!threads[i]->fFinished) { 1306 if (!threads[i]->fFinished) {
1696 errln("File %s, Line %d: Error, threads[%d]->fFinished == false", __ FILE__, __LINE__, i); 1307 errln("File %s, Line %d: Error, threads[%d]->fFinished == false", __ FILE__, __LINE__, i);
1697 } 1308 }
1309 }
1310
1311 for (i=0; i<NUMTHREADS; ++i) {
1312 threads[i]->join();
1698 delete threads[i]; 1313 delete threads[i];
1699 } 1314 }
1700 } 1315 }
1701 1316
1702 static const char *gCacheLocales[] = {"en_US", "en_GB", "fr_FR", "fr"}; 1317
1703 static int32_t gObjectsCreated = 0; 1318 //
1319 // Unified Cache Test
1320 //
1321
1322 // Each thread fetches a pair of objects. There are 8 distinct pairs:
1323 // ("en_US", "bs"), ("en_GB", "ca"), ("fr_FR", "ca_AD") etc.
1324 // These pairs represent 8 distinct languages
1325
1326 // Note that only one value per language gets created in the cache.
1327 // In particular each cached value can have multiple keys.
1328 static const char *gCacheLocales[] = {
1329 "en_US", "en_GB", "fr_FR", "fr",
1330 "de", "sr_ME", "sr_BA", "sr_CS"};
1331 static const char *gCacheLocales2[] = {
1332 "bs", "ca", "ca_AD", "ca_ES",
1333 "en_US", "fi", "ff_CM", "ff_GN"};
1334
1335 static int32_t gObjectsCreated = 0; // protected by gCTMutex
1704 static const int32_t CACHE_LOAD = 3; 1336 static const int32_t CACHE_LOAD = 3;
1705 1337
1706 class UCTMultiThreadItem : public SharedObject { 1338 class UCTMultiThreadItem : public SharedObject {
1707 public: 1339 public:
1708 char *value; 1340 char *value;
1709 UCTMultiThreadItem(const char *x) : value(NULL) { 1341 UCTMultiThreadItem(const char *x) : value(NULL) {
1710 value = uprv_strdup(x); 1342 value = uprv_strdup(x);
1711 } 1343 }
1712 virtual ~UCTMultiThreadItem() { 1344 virtual ~UCTMultiThreadItem() {
1713 uprv_free(value); 1345 uprv_free(value);
1714 } 1346 }
1715 }; 1347 };
1716 1348
1717 U_NAMESPACE_BEGIN 1349 U_NAMESPACE_BEGIN
1718 1350
1719 template<> U_EXPORT 1351 template<> U_EXPORT
1720 const UCTMultiThreadItem *LocaleCacheKey<UCTMultiThreadItem>::createObject( 1352 const UCTMultiThreadItem *LocaleCacheKey<UCTMultiThreadItem>::createObject(
1721 const void * /*unused*/, UErrorCode & /* status */) const { 1353 const void *context, UErrorCode &status) const {
1722 // Since multiple threads are hitting the cache for the first time, 1354 const UnifiedCache *cacheContext = (const UnifiedCache *) context;
1723 // no objects should be created yet. 1355
1356 if (uprv_strcmp(fLoc.getLanguage(), fLoc.getName()) != 0) {
1357 const UCTMultiThreadItem *result = NULL;
1358 if (cacheContext == NULL) {
1359 UnifiedCache::getByLocale(fLoc.getLanguage(), result, status);
1360 return result;
1361 }
1362 cacheContext->get(LocaleCacheKey<UCTMultiThreadItem>(fLoc.getLanguage()) , result, status);
1363 return result;
1364 }
1365
1724 umtx_lock(&gCTMutex); 1366 umtx_lock(&gCTMutex);
1725 if (gObjectsCreated != 0) { 1367 bool firstObject = (gObjectsCreated == 0);
1726 gThisTest->errln("Expected no objects to be created yet."); 1368 if (firstObject) {
1369 // Force the first object creation that comes through to wait
1370 // until other have completed. Verifies that cache doesn't
1371 // deadlock when a creation is slow.
1372
1373 // Note that gObjectsCreated needs to be incremeneted from 0 to 1
1374 // early, to keep subsequent threads from entering this path.
1375 gObjectsCreated = 1;
1376 while (gObjectsCreated < 3) {
1377 umtx_condWait(&gCTConditionVar, &gCTMutex);
1378 }
1727 } 1379 }
1728 umtx_unlock(&gCTMutex); 1380 umtx_unlock(&gCTMutex);
1729 1381
1730 // Big, expensive object that takes 1 second to create. 1382 const UCTMultiThreadItem *result =
1731 SimpleThread::sleep(1000); 1383 new UCTMultiThreadItem(fLoc.getLanguage());
1384 if (result == NULL) {
1385 status = U_MEMORY_ALLOCATION_ERROR;
1386 } else {
1387 result->addRef();
1388 }
1389
1390 // Log that we created an object. The first object was already counted,
1391 // don't do it again.
1392 umtx_lock(&gCTMutex);
1393 if (!firstObject) {
1394 gObjectsCreated += 1;
1395 }
1396 umtx_condBroadcast(&gCTConditionVar);
1397 umtx_unlock(&gCTMutex);
1732 1398
1733 // Log that we created an object.
1734 umtx_lock(&gCTMutex);
1735 ++gObjectsCreated;
1736 umtx_unlock(&gCTMutex);
1737 UCTMultiThreadItem *result = new UCTMultiThreadItem(fLoc.getName());
1738 result->addRef();
1739 return result; 1399 return result;
1740 } 1400 }
1741 1401
1742 U_NAMESPACE_END 1402 U_NAMESPACE_END
1743 1403
1744 class UnifiedCacheThread: public SimpleThread { 1404 class UnifiedCacheThread: public SimpleThread {
1745 public: 1405 public:
1746 UnifiedCacheThread(const char *loc) : fLoc(loc) {}; 1406 UnifiedCacheThread(
1407 const UnifiedCache *cache,
1408 const char *loc,
1409 const char *loc2) : fCache(cache), fLoc(loc), fLoc2(loc2) {};
1747 ~UnifiedCacheThread() {}; 1410 ~UnifiedCacheThread() {};
1748 void run(); 1411 void run();
1749 const char *fLoc; 1412 void exerciseByLocale(const Locale &);
1413 const UnifiedCache *fCache;
1414 Locale fLoc;
1415 Locale fLoc2;
1750 }; 1416 };
1751 1417
1418 void UnifiedCacheThread::exerciseByLocale(const Locale &locale) {
1419 UErrorCode status = U_ZERO_ERROR;
1420 const UCTMultiThreadItem *origItem = NULL;
1421 fCache->get(
1422 LocaleCacheKey<UCTMultiThreadItem>(locale), fCache, origItem, status );
1423 U_ASSERT(U_SUCCESS(status));
1424 if (uprv_strcmp(locale.getLanguage(), origItem->value)) {
1425 IntlTest::gTest->errln(
1426 "%s:%d Expected %s, got %s", __FILE__, __LINE__,
1427 locale.getLanguage(),
1428 origItem->value);
1429 }
1430
1431 // Fetch the same item again many times. We should always get the same
1432 // pointer since this client is already holding onto it
1433 for (int32_t i = 0; i < 1000; ++i) {
1434 const UCTMultiThreadItem *item = NULL;
1435 fCache->get(
1436 LocaleCacheKey<UCTMultiThreadItem>(locale), fCache, item, status );
1437 if (item != origItem) {
1438 IntlTest::gTest->errln(
1439 "%s:%d Expected to get the same pointer",
1440 __FILE__,
1441 __LINE__);
1442 }
1443 if (item != NULL) {
1444 item->removeRef();
1445 }
1446 }
1447 origItem->removeRef();
1448 }
1449
1752 void UnifiedCacheThread::run() { 1450 void UnifiedCacheThread::run() {
1753 UErrorCode status = U_ZERO_ERROR; 1451 // Run the exercise with 2 different locales so that we can exercise
1754 const UnifiedCache *cache = UnifiedCache::getInstance(status); 1452 // eviction more. If each thread exerices just one locale, then
1755 U_ASSERT(status == U_ZERO_ERROR); 1453 // eviction can't start until the threads end.
1756 const UCTMultiThreadItem *item = NULL; 1454 exerciseByLocale(fLoc);
1757 cache->get(LocaleCacheKey<UCTMultiThreadItem>(fLoc), item, status); 1455 exerciseByLocale(fLoc2);
1758 U_ASSERT(item != NULL);
1759 if (uprv_strcmp(fLoc, item->value)) {
1760 gThisTest->errln("Expected %s, got %s", fLoc, item->value);
1761 }
1762 item->removeRef();
1763
1764 // Mark this thread as finished
1765 umtx_lock(&gCTMutex);
1766 ++gFinishedThreads;
1767 umtx_condBroadcast(&gCTConditionVar);
1768 umtx_unlock(&gCTMutex);
1769 } 1456 }
1770 1457
1771 void MultithreadTest::TestUnifiedCache() { 1458 void MultithreadTest::TestUnifiedCache() {
1459
1460 // Start with our own local cache so that we have complete control
1461 // and set the eviction policy to evict starting with 2 unused
1462 // values
1772 UErrorCode status = U_ZERO_ERROR; 1463 UErrorCode status = U_ZERO_ERROR;
1773 const UnifiedCache *cache = UnifiedCache::getInstance(status); 1464 UnifiedCache::getInstance(status);
1774 U_ASSERT(cache != NULL); 1465 UnifiedCache cache(status);
1775 cache->flush(); 1466 cache.setEvictionPolicy(2, 0, status);
1776 gThisTest = this; 1467 U_ASSERT(U_SUCCESS(status));
1468
1777 gFinishedThreads = 0; 1469 gFinishedThreads = 0;
1778 gObjectsCreated = 0; 1470 gObjectsCreated = 0;
1779 1471
1780 UnifiedCacheThread *threads[CACHE_LOAD][UPRV_LENGTHOF(gCacheLocales)]; 1472 UnifiedCacheThread *threads[CACHE_LOAD][UPRV_LENGTHOF(gCacheLocales)];
1781 for (int32_t i=0; i<CACHE_LOAD; ++i) { 1473 for (int32_t i=0; i<CACHE_LOAD; ++i) {
1782 for (int32_t j=0; j<UPRV_LENGTHOF(gCacheLocales); ++j) { 1474 for (int32_t j=0; j<UPRV_LENGTHOF(gCacheLocales); ++j) {
1783 threads[i][j] = new UnifiedCacheThread(gCacheLocales[j]); 1475 // Each thread works with a pair of locales.
1476 threads[i][j] = new UnifiedCacheThread(
1477 &cache, gCacheLocales[j], gCacheLocales2[j]);
1784 threads[i][j]->start(); 1478 threads[i][j]->start();
1785 } 1479 }
1786 } 1480 }
1787 // Wait on all the threads to complete verify that LENGTHOF(gCacheLocales) 1481
1788 // objects were created. 1482 for (int32_t i=0; i<CACHE_LOAD; ++i) {
1789 umtx_lock(&gCTMutex); 1483 for (int32_t j=0; j<UPRV_LENGTHOF(gCacheLocales); ++j) {
1790 while (gFinishedThreads < CACHE_LOAD*UPRV_LENGTHOF(gCacheLocales)) { 1484 threads[i][j]->join();
1791 umtx_condWait(&gCTConditionVar, &gCTMutex); 1485 }
1792 } 1486 }
1793 assertEquals("Objects created", UPRV_LENGTHOF(gCacheLocales), gObjectsCreate d); 1487 // Because of cache eviction, we can't assert exactly how many
1794 umtx_unlock(&gCTMutex); 1488 // distinct objects get created over the course of this run.
1489 // However we know that at least 8 objects get created because that
1490 // is how many distinct languages we have in our test.
1491 if (gObjectsCreated < 8) {
1492 errln("%s:%d Too few objects created.", __FILE__, __LINE__);
1493 }
1494 // We know that each thread cannot create more than 2 objects in
1495 // the cache, and there are UPRV_LENGTHOF(gCacheLocales) pairs of
1496 // objects fetched from the cache. If the threads run in series because
1497 // of eviction, at worst case each thread creates two objects.
1498 if (gObjectsCreated > 2 * CACHE_LOAD * UPRV_LENGTHOF(gCacheLocales)) {
1499 errln("%s:%d Too many objects created, got %d, expected %d", __FILE__, _ _LINE__, gObjectsCreated, 2 * CACHE_LOAD * UPRV_LENGTHOF(gCacheLocales));
1500
1501 }
1502
1503 assertEquals("unused values", 2, cache.unusedCount());
1795 1504
1796 // clean up threads 1505 // clean up threads
1797 for (int32_t i=0; i<CACHE_LOAD; ++i) { 1506 for (int32_t i=0; i<CACHE_LOAD; ++i) {
1798 for (int32_t j=0; j<UPRV_LENGTHOF(gCacheLocales); ++j) { 1507 for (int32_t j=0; j<UPRV_LENGTHOF(gCacheLocales); ++j) {
1799 delete threads[i][j]; 1508 delete threads[i][j];
1800 } 1509 }
1801 } 1510 }
1802 } 1511 }
1803 1512
1804 #endif // ICU_USE_THREADS 1513 #if !UCONFIG_NO_TRANSLITERATION
1514 //
1515 // BreakTransliterator Threading Test
1516 // This is a test for bug #11603. Test verified to fail prior to fix.
1517 //
1518
1519 static const Transliterator *gSharedTransliterator;
1520 static const UnicodeString *gTranslitInput;
1521 static const UnicodeString *gTranslitExpected;
1522
1523 class BreakTranslitThread: public SimpleThread {
1524 public:
1525 BreakTranslitThread() {};
1526 ~BreakTranslitThread() {};
1527 void run();
1528 };
1529
1530 void BreakTranslitThread::run() {
1531 for (int i=0; i<10; i++) {
1532 icu::UnicodeString s(*gTranslitInput);
1533 gSharedTransliterator->transliterate(s);
1534 if (*gTranslitExpected != s) {
1535 IntlTest::gTest->errln("%s:%d Transliteration threading failure.", _ _FILE__, __LINE__);
1536 break;
1537 }
1538 }
1539 }
1540
1541 void MultithreadTest::TestBreakTranslit() {
1542 UErrorCode status = U_ZERO_ERROR;
1543 UnicodeString input(
1544 "\\u0E42\\u0E14\\u0E22\\u0E1E\\u0E37\\u0E49\\u0E19\\u0E10\\u0E32\\u0E19\ \u0E41\\u0E25\\u0E49\\u0E27,");
1545 input = input.unescape();
1546 gTranslitInput = &input;
1547
1548 gSharedTransliterator = Transliterator::createInstance(
1549 UNICODE_STRING_SIMPLE("Any-Latin; Lower; NFD; [:Diacritic:]Remove; NFC; Latin-ASCII;"), UTRANS_FORWARD, status);
1550 if (!gSharedTransliterator) {
1551 return;
1552 }
1553 TSMTHREAD_ASSERT_SUCCESS(status);
1554
1555 UnicodeString expected(*gTranslitInput);
1556 gSharedTransliterator->transliterate(expected);
1557 gTranslitExpected = &expected;
1558
1559 BreakTranslitThread threads[4];
1560 for (int i=0; i<UPRV_LENGTHOF(threads); ++i) {
1561 threads[i].start();
1562 }
1563 for (int i=0; i<UPRV_LENGTHOF(threads); ++i) {
1564 threads[i].join();
1565 }
1566
1567 delete gSharedTransliterator;
1568 gTranslitInput = NULL;
1569 gTranslitExpected = NULL;
1570 }
1571
1572 #endif /* !UCONFIG_NO_TRANSLITERATION */
OLDNEW
« no previous file with comments | « source/test/intltest/tsmthred.h ('k') | source/test/intltest/tufmtts.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698