]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_4_2-src/main/tests/core/src/com/ibm/icu/dev/test/util/ICUServiceThreadTest.java
go
[Dictionary.git] / jars / icu4j-4_4_2-src / main / tests / core / src / com / ibm / icu / dev / test / util / ICUServiceThreadTest.java
1 /**\r
2  *******************************************************************************\r
3  * Copyright (C) 2001-2010, International Business Machines Corporation and    *\r
4  * others. All Rights Reserved.                                                *\r
5  *******************************************************************************\r
6  */\r
7 package com.ibm.icu.dev.test.util;\r
8 \r
9 import java.text.Collator;\r
10 import java.util.ArrayList;\r
11 import java.util.Arrays;\r
12 import java.util.Collection;\r
13 import java.util.Comparator;\r
14 import java.util.HashSet;\r
15 import java.util.Iterator;\r
16 import java.util.List;\r
17 import java.util.Locale;\r
18 import java.util.Map;\r
19 import java.util.MissingResourceException;\r
20 import java.util.Random;\r
21 import java.util.Set;\r
22 import java.util.SortedMap;\r
23 import java.util.Map.Entry;\r
24 \r
25 import com.ibm.icu.dev.test.TestFmwk;\r
26 import com.ibm.icu.dev.test.TestLog;\r
27 import com.ibm.icu.impl.ICULocaleService;\r
28 import com.ibm.icu.impl.ICUService;\r
29 import com.ibm.icu.impl.ICUService.Factory;\r
30 import com.ibm.icu.impl.ICUService.SimpleFactory;\r
31 import com.ibm.icu.util.ULocale;\r
32 \r
33 public class ICUServiceThreadTest extends TestFmwk\r
34 {\r
35     private static final boolean PRINTSTATS = false;\r
36 \r
37     public static void main(String[] args) throws Exception {\r
38         ICUServiceThreadTest test = new ICUServiceThreadTest();\r
39         test.run(args);\r
40 \r
41         // get\r
42         // getvisibleids\r
43         // getdisplayname(locale)\r
44         // factories\r
45 \r
46         // registerFactory\r
47         // unregisterFactory\r
48 \r
49         // 1) concurrent access\r
50         // 2) access while factories change\r
51         // 3) iteration while factories change\r
52         // 4) concurrent conflicting access\r
53     }\r
54 \r
55     private static final String[] countries = {\r
56         "ab", "bc", "cd", "de", "ef", "fg", "gh", "ji", "ij", "jk"\r
57     };\r
58     private static final String[] languages = {\r
59         "", "ZY", "YX", "XW", "WV", "VU", "UT", "TS", "SR", "RQ", "QP"\r
60     };\r
61     private static final String[] variants = {\r
62         "", "", "", "GOLD", "SILVER", "BRONZE"\r
63     };\r
64 \r
65     private static class TestFactory extends SimpleFactory {\r
66         TestFactory(String id) {\r
67             super(new ULocale(id), id, true);\r
68         }\r
69 \r
70         public String getDisplayName(String idForDisplay, ULocale locale) {\r
71             return (visible && idForDisplay.equals(this.id)) ? "(" + locale.toString() + ") " + idForDisplay : null;\r
72         }\r
73 \r
74         public String toString() {\r
75             return "Factory_" + id;\r
76         }\r
77     }\r
78     /**\r
79      * Convenience override of getDisplayNames(ULocale, Comparator, String) that\r
80      * uses the default collator for the locale as the comparator to\r
81      * sort the display names, and null for the matchID.\r
82      */\r
83     public static SortedMap getDisplayNames(ICUService service, ULocale locale) {\r
84         Collator col;\r
85         try {\r
86             col = Collator.getInstance(locale.toLocale());\r
87         }\r
88         catch (MissingResourceException e) {\r
89             // if no collator resources, we can't collate\r
90             col = null;\r
91         }\r
92         return service.getDisplayNames(locale, col, null);\r
93     }\r
94     private static final Random r = new Random(); // this is a multi thread test, can't 'unrandomize'\r
95 \r
96     private static String getCLV() {\r
97         String c = countries[r.nextInt(countries.length)];\r
98         String l = languages[r.nextInt(languages.length)];\r
99         String v = variants[r.nextInt(variants.length)];\r
100         return new Locale(c, l, v).toString();\r
101     }\r
102 \r
103     private static boolean WAIT = true;\r
104     private static boolean GO = false;\r
105     private static long TIME = 5000;\r
106 \r
107     public static void runThreads() {\r
108         runThreads(TIME);\r
109     }\r
110 \r
111     public static void runThreads(long time) {\r
112         try {\r
113             GO = true;\r
114             WAIT = false;\r
115 \r
116             Thread.sleep(time);\r
117 \r
118             WAIT = true;\r
119             GO = false;\r
120 \r
121             Thread.sleep(300);\r
122         }\r
123         catch (InterruptedException e) {\r
124         }\r
125     }\r
126 \r
127     static class TestThread extends Thread {\r
128         //private final String name;\r
129         protected ICUService service;\r
130         private final long delay;\r
131         protected final TestLog log;\r
132 \r
133         public TestThread(String name, ICUService service, long delay, TestLog log) {\r
134             //this.name = name + " ";\r
135             this.service = service;\r
136             this.delay = delay;\r
137             this.log = new DelegatingLog(log);\r
138             this.setDaemon(true);\r
139         }\r
140 \r
141         public void run() {\r
142             while (WAIT) {\r
143                 Thread.yield();\r
144             }\r
145 \r
146             try {\r
147                 while (GO) {\r
148                     iterate();\r
149                     if (delay > 0) {\r
150                         Thread.sleep(delay);\r
151                     }\r
152                 }\r
153             }\r
154             catch (InterruptedException e) {\r
155             }\r
156         }\r
157 \r
158         protected void iterate() {\r
159         }\r
160 \r
161         /*\r
162           public boolean logging() {\r
163           return log != null;\r
164           }\r
165 \r
166           public void log(String msg) {\r
167           if (logging()) {\r
168           log.log(name + msg);\r
169           }\r
170           }\r
171 \r
172           public void logln(String msg) {\r
173           if (logging()) {\r
174           log.logln(name + msg);\r
175           }\r
176           }\r
177 \r
178           public void err(String msg) {\r
179           if (logging()) {\r
180           log.err(name + msg);\r
181           }\r
182           }\r
183 \r
184           public void errln(String msg) {\r
185           if (logging()) {\r
186           log.errln(name + msg);\r
187           }\r
188           }\r
189 \r
190           public void warn(String msg) {\r
191           if (logging()) {\r
192           log.info(name + msg);\r
193           }\r
194           }\r
195 \r
196           public void warnln(String msg) {\r
197           if (logging()) {\r
198           log.infoln(name + msg);\r
199           }\r
200           }\r
201         */\r
202     }\r
203 \r
204     static class RegisterFactoryThread extends TestThread {\r
205         RegisterFactoryThread(String name, ICUService service, long delay, TestLog log) {\r
206             super("REG " + name, service, delay, log);\r
207         }\r
208 \r
209         protected void iterate() {\r
210             Factory f = new TestFactory(getCLV());\r
211             service.registerFactory(f);\r
212             log.logln(f.toString());\r
213         }\r
214     }\r
215 \r
216     static class UnregisterFactoryThread extends TestThread {\r
217         private Random r;\r
218         List factories;\r
219 \r
220         UnregisterFactoryThread(String name, ICUService service, long delay, TestLog log) {\r
221             super("UNREG " + name, service, delay, log);\r
222 \r
223             r = new Random();\r
224             factories = service.factories();\r
225         }\r
226 \r
227         public void iterate() {\r
228             int s = factories.size();\r
229             if (s == 0) {\r
230                 factories = service.factories();\r
231             } else {\r
232                 int n = r.nextInt(s);\r
233                 Factory f = (Factory)factories.remove(n);\r
234                 boolean success = service.unregisterFactory(f);\r
235                 log.logln("factory: " + f + (success ? " succeeded." : " *** failed."));\r
236             }\r
237         }\r
238     }\r
239 \r
240     static class UnregisterFactoryListThread extends TestThread {\r
241         Factory[] factories;\r
242         int n;\r
243 \r
244         UnregisterFactoryListThread(String name, ICUService service, long delay, Factory[] factories, TestLog log) {\r
245             super("UNREG " + name, service, delay, log);\r
246 \r
247             this.factories = factories;\r
248         }\r
249 \r
250         public void iterate() {\r
251             if (n < factories.length) {\r
252                 Factory f = factories[n++];\r
253                 boolean success = service.unregisterFactory(f);\r
254                 log.logln("factory: " + f + (success ? " succeeded." : " *** failed."));\r
255             }\r
256         }\r
257     }\r
258 \r
259 \r
260     static class GetVisibleThread extends TestThread {\r
261         GetVisibleThread(String name, ICUService service, long delay, TestLog log) {\r
262             super("VIS " + name, service, delay, log);\r
263         }\r
264 \r
265         protected void iterate() {\r
266             Set ids = service.getVisibleIDs();\r
267             Iterator iter = ids.iterator();\r
268             int n = 10;\r
269             while (--n >= 0 && iter.hasNext()) {\r
270                 String id = (String)iter.next();\r
271                 Object result = service.get(id);\r
272                 log.logln("iter: " + n + " id: " + id + " result: " + result);\r
273             }\r
274         }\r
275     }\r
276 \r
277     static class GetDisplayThread extends TestThread {\r
278         ULocale locale;\r
279 \r
280         GetDisplayThread(String name, ICUService service, long delay, ULocale locale, TestLog log) {\r
281             super("DIS " + name, service, delay, log);\r
282 \r
283             this.locale = locale;\r
284         }\r
285 \r
286         protected void iterate() {\r
287             Map names = getDisplayNames(service,locale);\r
288             Iterator iter = names.entrySet().iterator();\r
289             int n = 10;\r
290             while (--n >= 0 && iter.hasNext()) {\r
291                 Entry e = (Entry)iter.next();\r
292                 String dname = (String)e.getKey();\r
293                 String id = (String)e.getValue();\r
294                 Object result = service.get(id);\r
295 \r
296                 // Note: IllegalMonitorStateException is thrown by the code\r
297                 // below on IBM JRE5 for AIX 64bit.  For some reason, converting\r
298                 // int to String out of this statement resolves the issue.\r
299 \r
300                 //log.logln(" iter: " + n +\r
301                 String num = Integer.toString(n);\r
302                 log.logln(" iter: " + num +\r
303                           " dname: " + dname +\r
304                           " id: " + id +\r
305                           " result: " + result);\r
306             }\r
307         }\r
308     }\r
309 \r
310     static class GetThread extends TestThread {\r
311         private String[] actualID;\r
312 \r
313         GetThread(String name, ICUService service, long delay, TestLog log) {\r
314             super("GET " + name, service, delay, log);\r
315 \r
316             actualID = new String[1];\r
317         }\r
318 \r
319         protected void iterate() {\r
320             String id = getCLV();\r
321             Object o = service.get(id, actualID);\r
322             if (o != null) {\r
323                 log.logln(" id: " + id + " actual: " + actualID[0] + " result: " + o);\r
324             }\r
325         }\r
326     }\r
327 \r
328     static class GetListThread extends TestThread {\r
329         private final String[] list;\r
330         private int n;\r
331 \r
332         GetListThread(String name, ICUService service, long delay, String[] list, TestLog log) {\r
333             super("GETL " + name, service, delay, log);\r
334 \r
335             this.list = list;\r
336         }\r
337 \r
338         protected void iterate() {\r
339             if (--n < 0) {\r
340                 n = list.length - 1;\r
341             }\r
342             String id = list[n];\r
343             Object o = service.get(id);\r
344             log.logln(" id: " + id + " result: " + o);\r
345         }\r
346     }\r
347 \r
348     // return a collection of unique factories, might be fewer than requested\r
349     Collection getFactoryCollection(int requested) {\r
350         Set locales = new HashSet();\r
351         for (int i = 0; i < requested; ++i) {\r
352             locales.add(getCLV());\r
353         }\r
354         List factories = new ArrayList(locales.size());\r
355         Iterator iter = locales.iterator();\r
356         while (iter.hasNext()) {\r
357             factories.add(new TestFactory((String)iter.next()));\r
358         }\r
359         return factories;\r
360     }\r
361 \r
362     void registerFactories(ICUService service, Collection c) {\r
363         Iterator iter = c.iterator();\r
364         while (iter.hasNext()) {\r
365             service.registerFactory((Factory)iter.next());\r
366         }\r
367     }\r
368 \r
369     ICUService stableService() {\r
370         if (stableService == null) {\r
371             stableService = new ICULocaleService();\r
372             registerFactories(stableService, getFactoryCollection(50));\r
373         }\r
374         return stableService;\r
375     }\r
376     private ICUService stableService;\r
377 \r
378     // run multiple get on a stable service\r
379     public void Test00_ConcurrentGet() {\r
380         for(int i = 0; i < 10; ++i) {\r
381             new GetThread("[" + Integer.toString(i) + "]",  stableService(), 0, this).start();\r
382         }\r
383         runThreads();\r
384         if (PRINTSTATS) System.out.println(stableService.stats());\r
385     }\r
386 \r
387     // run multiple getVisibleID on a stable service\r
388     public void Test01_ConcurrentGetVisible() {\r
389         for(int i = 0; i < 10; ++i) {\r
390             new GetVisibleThread("[" + Integer.toString(i) + "]",  stableService(), 0, this).start();\r
391         }\r
392         runThreads();\r
393         if (PRINTSTATS) System.out.println(stableService.stats());\r
394     }\r
395 \r
396     // run multiple getDisplayName on a stable service\r
397     public void Test02_ConcurrentGetDisplay() {\r
398         String[] localeNames = {\r
399             "en", "es", "de", "fr", "zh", "it", "no", "sv"\r
400         };\r
401         for(int i = 0; i < localeNames.length; ++i) {\r
402             String locale = localeNames[i];\r
403             new GetDisplayThread("[" + locale + "]",\r
404                                  stableService(),\r
405                                  0,\r
406                                  new ULocale(locale),\r
407                                  this).start();\r
408         }\r
409         runThreads();\r
410         if (PRINTSTATS) System.out.println(stableService.stats());\r
411     }\r
412 \r
413     // run register/unregister on a service\r
414     public void Test03_ConcurrentRegUnreg() {\r
415         ICUService service = new ICULocaleService();\r
416         for (int i = 0; i < 5; ++i) {\r
417             new RegisterFactoryThread("[" + i + "]", service, 0, this).start();\r
418         }\r
419         for (int i = 0; i < 5; ++i) {\r
420             new UnregisterFactoryThread("[" + i + "]", service, 0, this).start();\r
421         }\r
422         runThreads();\r
423         if (PRINTSTATS) System.out.println(service.stats());\r
424     }\r
425 \r
426     public void Test04_WitheringService() {\r
427         ICUService service = new ICULocaleService();\r
428 \r
429         Collection fc = getFactoryCollection(50);\r
430         registerFactories(service, fc);\r
431 \r
432         Factory[] factories = (Factory[])fc.toArray(new Factory[fc.size()]);\r
433         Comparator comp = new Comparator() {\r
434                 public int compare(Object lhs, Object rhs) {\r
435                     return lhs.toString().compareTo(rhs.toString());\r
436                 }\r
437             };\r
438         Arrays.sort(factories, comp);\r
439 \r
440         new GetThread("", service, 0, this).start();\r
441         new UnregisterFactoryListThread("", service, 3, factories, this).start();\r
442 \r
443         runThreads(2000);\r
444         if (PRINTSTATS) System.out.println(service.stats());\r
445     }\r
446 \r
447     // "all hell breaks loose"\r
448     // one register and one unregister thread, delay 500ms\r
449     // two display threads with different locales, delay 500ms;\r
450     // one visible id thread, delay 50ms\r
451     // fifteen get threads, delay 0\r
452     // run for ten seconds\r
453     public void Test05_ConcurrentEverything() {\r
454         ICUService service = new ICULocaleService();\r
455 \r
456         new RegisterFactoryThread("", service, 500, this).start();\r
457 \r
458         for(int i = 0; i < 15; ++i) {\r
459             new GetThread("[" + Integer.toString(i) + "]", service, 0, this).start();\r
460         }\r
461 \r
462         new GetVisibleThread("",  service, 50, this).start();\r
463 \r
464         String[] localeNames = {\r
465             "en", "de"\r
466         };\r
467         for(int i = 0; i < localeNames.length; ++i) {\r
468             String locale = localeNames[i];\r
469             new GetDisplayThread("[" + locale + "]",\r
470                                  stableService(),\r
471                                  500,\r
472                                  new ULocale(locale),\r
473                                  this).start();\r
474         }\r
475 \r
476         new UnregisterFactoryThread("", service, 500, this).start();\r
477 \r
478         // yoweee!!!\r
479         runThreads(9500);\r
480         if (PRINTSTATS) System.out.println(service.stats());\r
481     }\r
482 }\r