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