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