J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved. |
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| 4 | * |
| 5 | * This code is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of the GNU General Public License version 2 only, as |
| 7 | * published by the Free Software Foundation. |
| 8 | * |
| 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| 12 | * version 2 for more details (a copy is included in the LICENSE file that |
| 13 | * accompanied this code). |
| 14 | * |
| 15 | * You should have received a copy of the GNU General Public License version |
| 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
| 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| 18 | * |
| 19 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| 20 | * CA 95054 USA or visit www.sun.com if you need additional information or |
| 21 | * have any questions. |
| 22 | */ |
| 23 | /* |
| 24 | * @test |
| 25 | * @bug 5102289 6278334 |
| 26 | * @summary Test the default Control implementation. The expiration |
| 27 | * functionality of newBundle, getTimeToLive, and needsReload is |
| 28 | * tested by ExpirationTest.sh. The factory methods are tested |
| 29 | * separately. |
| 30 | * @build TestResourceRB |
| 31 | * @build NonResourceBundle |
| 32 | * @run main DefaultControlTest |
| 33 | */ |
| 34 | |
| 35 | import java.util.*; |
| 36 | import static java.util.ResourceBundle.Control.*; |
| 37 | |
| 38 | public class DefaultControlTest { |
| 39 | // The ResourceBundle.Control instance |
| 40 | static final ResourceBundle.Control CONTROL |
| 41 | = ResourceBundle.Control.getControl(FORMAT_DEFAULT); |
| 42 | |
| 43 | static final ResourceBundle BUNDLE = new ResourceBundle() { |
| 44 | public Enumeration<String> getKeys() { return null; } |
| 45 | protected Object handleGetObject(String key) { return null; } |
| 46 | }; |
| 47 | |
| 48 | static final String CLAZZ = FORMAT_CLASS.get(0); |
| 49 | |
| 50 | static final String PROPERTIES = FORMAT_PROPERTIES.get(0); |
| 51 | |
| 52 | static final ClassLoader LOADER = DefaultControlTest.class.getClassLoader(); |
| 53 | |
| 54 | // Full arguments for NPE testing |
| 55 | static final Object[] FULLARGS = { "any", |
| 56 | Locale.US, |
| 57 | FORMAT_PROPERTIES.get(0), |
| 58 | LOADER, |
| 59 | BUNDLE }; |
| 60 | |
| 61 | static int errors; |
| 62 | |
| 63 | public static void main(String[] args) { |
| 64 | checkConstants(); |
| 65 | |
| 66 | // Test getFormats(String) |
| 67 | testGetFormats(); |
| 68 | |
| 69 | // Test getCandidateLocales(String, Locale) |
| 70 | testGetCandidateLocales(); |
| 71 | |
| 72 | // Test getFallbackLocale(String, Locale) |
| 73 | testGetFallbackLocale(); |
| 74 | |
| 75 | // Test newBundle(String, Locale, String, ClassLoader, boolean) |
| 76 | testNewBundle(); |
| 77 | |
| 78 | // Test toBundleName(String, Locale) |
| 79 | testToBundleName(); |
| 80 | |
| 81 | // Test getTimeToLive(String, Locale) |
| 82 | testGetTimeToLive(); |
| 83 | |
| 84 | // Test needsReload(String, Locale, String, ClassLoader, |
| 85 | // ResourceBundle, long) |
| 86 | testNeedsReload(); |
| 87 | |
| 88 | // Test toResourceName(String, String) |
| 89 | testToResourceName(); |
| 90 | |
| 91 | if (errors > 0) { |
| 92 | throw new RuntimeException("FAILED: " + errors + " error(s)"); |
| 93 | } |
| 94 | } |
| 95 | |
| 96 | private static void checkConstants() { |
| 97 | // Check FORMAT_* |
| 98 | if (!CONTROL.FORMAT_DEFAULT.equals(Arrays.asList("java.class", |
| 99 | "java.properties"))) { |
| 100 | error("Wrong Control.FORMAT_DEFAULT"); |
| 101 | } |
| 102 | checkImmutableList(CONTROL.FORMAT_DEFAULT); |
| 103 | if (!CONTROL.FORMAT_CLASS.equals(Arrays.asList("java.class"))) { |
| 104 | error("Wrong Control.FORMAT_CLASS"); |
| 105 | } |
| 106 | checkImmutableList(CONTROL.FORMAT_CLASS); |
| 107 | if (!CONTROL.FORMAT_PROPERTIES.equals(Arrays.asList("java.properties"))) { |
| 108 | error("Wrong Control.FORMAT_PROPERTIES"); |
| 109 | } |
| 110 | checkImmutableList(CONTROL.FORMAT_PROPERTIES); |
| 111 | |
| 112 | // Check TTL_* |
| 113 | if (CONTROL.TTL_DONT_CACHE != -1) { |
| 114 | error("Wrong Control.TTL_DONT_CACHE: %d%n", CONTROL.TTL_DONT_CACHE); |
| 115 | } |
| 116 | if (CONTROL.TTL_NO_EXPIRATION_CONTROL != -2) { |
| 117 | error("Wrong Control.TTL_NO_EXPIRATION_CONTROL: %d%n", |
| 118 | CONTROL.TTL_NO_EXPIRATION_CONTROL); |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | private static void checkImmutableList(List<String> list) { |
| 123 | try { |
| 124 | list.add("hello"); |
| 125 | error("%s is mutable%n", list); |
| 126 | } catch (UnsupportedOperationException e) { |
| 127 | } |
| 128 | } |
| 129 | |
| 130 | private static void testGetFormats() { |
| 131 | List<String> list = CONTROL.getFormats("foo"); |
| 132 | if (list != CONTROL.FORMAT_DEFAULT) { |
| 133 | error("getFormats returned " + list); |
| 134 | } |
| 135 | try { |
| 136 | list = CONTROL.getFormats(null); |
| 137 | error("getFormats doesn't throw NPE."); |
| 138 | } catch (NullPointerException e) { |
| 139 | } |
| 140 | } |
| 141 | |
| 142 | private static void testGetCandidateLocales() { |
| 143 | Map<Locale, Locale[]> candidateData = new HashMap<Locale, Locale[]>(); |
| 144 | candidateData.put(new Locale("ja", "JP", "YOK"), new Locale[] { |
| 145 | new Locale("ja", "JP", "YOK"), |
| 146 | new Locale("ja", "JP"), |
| 147 | new Locale("ja"), |
| 148 | new Locale("") }); |
| 149 | candidateData.put(new Locale("ja", "JP"), new Locale[] { |
| 150 | new Locale("ja", "JP"), |
| 151 | new Locale("ja"), |
| 152 | new Locale("") }); |
| 153 | candidateData.put(new Locale("ja"), new Locale[] { |
| 154 | new Locale("ja"), |
| 155 | new Locale("") }); |
| 156 | |
| 157 | candidateData.put(new Locale("ja", "", "YOK"), new Locale[] { |
| 158 | new Locale("ja", "", "YOK"), |
| 159 | new Locale("ja"), |
| 160 | new Locale("") }); |
| 161 | candidateData.put(new Locale("", "JP", "YOK"), new Locale[] { |
| 162 | new Locale("", "JP", "YOK"), |
| 163 | new Locale("", "JP"), |
| 164 | new Locale("") }); |
| 165 | candidateData.put(new Locale("", "", "YOK"), new Locale[] { |
| 166 | new Locale("", "", "YOK"), |
| 167 | new Locale("") }); |
| 168 | candidateData.put(new Locale("", "JP"), new Locale[] { |
| 169 | new Locale("", "JP"), |
| 170 | new Locale("") }); |
| 171 | candidateData.put(new Locale(""), new Locale[] { |
| 172 | new Locale("") }); |
| 173 | |
| 174 | for (Locale locale : candidateData.keySet()) { |
| 175 | List<Locale> candidates = CONTROL.getCandidateLocales("any", locale); |
| 176 | List<Locale> expected = Arrays.asList(candidateData.get(locale)); |
| 177 | if (!candidates.equals(expected)) { |
| 178 | error("Wrong candidates for %s: got %s, expected %s%n", |
| 179 | toString(locale), candidates, expected); |
| 180 | } |
| 181 | } |
| 182 | final int NARGS = 2; |
| 183 | for (int mask = 0; mask < (1 << NARGS)-1; mask++) { |
| 184 | Object[] data = getNpeArgs(NARGS, mask); |
| 185 | try { |
| 186 | List<Locale> candidates = CONTROL.getCandidateLocales((String) data[0], |
| 187 | (Locale) data[1]); |
| 188 | error("getCandidateLocales(%s, %s) doesn't throw NPE.%n", |
| 189 | data[0], toString((Locale)data[1])); |
| 190 | } catch (NullPointerException e) { |
| 191 | } |
| 192 | } |
| 193 | } |
| 194 | |
| 195 | private static void testGetFallbackLocale() { |
| 196 | Locale current = Locale.getDefault(); |
| 197 | Locale.setDefault(Locale.ITALY); |
| 198 | try { |
| 199 | Locale loc = CONTROL.getFallbackLocale("any", Locale.FRANCE); |
| 200 | if (loc != Locale.ITALY) { |
| 201 | error("getFallbackLocale: got %s, expected %s%n", |
| 202 | toString(loc), toString(Locale.ITALY)); |
| 203 | } |
| 204 | loc = CONTROL.getFallbackLocale("any", Locale.ITALY); |
| 205 | if (loc != null) { |
| 206 | error("getFallbackLocale: got %s, expected null%n", toString(loc)); |
| 207 | } |
| 208 | } finally { |
| 209 | Locale.setDefault(current); |
| 210 | } |
| 211 | |
| 212 | final int NARGS = 2; |
| 213 | for (int mask = 0; mask < (1 << NARGS)-1; mask++) { |
| 214 | Object[] data = getNpeArgs(NARGS, mask); |
| 215 | try { |
| 216 | Locale loc = CONTROL.getFallbackLocale((String) data[0], (Locale) data[1]); |
| 217 | error("getFallbackLocale(%s, %s) doesn't throw NPE.%n", data[0], data[1]); |
| 218 | } catch (NullPointerException e) { |
| 219 | } |
| 220 | } |
| 221 | } |
| 222 | |
| 223 | private static void testNewBundle() { |
| 224 | int testNo = 0; |
| 225 | ResourceBundle rb = null; |
| 226 | try { |
| 227 | testNo = 1; |
| 228 | rb = CONTROL.newBundle("StressOut", Locale.JAPANESE, |
| 229 | PROPERTIES, LOADER, false); |
| 230 | String s = rb.getString("data"); |
| 231 | if (!s.equals("Japan")) { |
| 232 | error("newBundle: #%d got %s, expected Japan%n", testNo, s); |
| 233 | } |
| 234 | |
| 235 | testNo = 2; |
| 236 | rb = CONTROL.newBundle("TestResourceRB", new Locale(""), |
| 237 | CLAZZ, LOADER, false); |
| 238 | s = rb.getString("type"); |
| 239 | if (!s.equals(CLAZZ)) { |
| 240 | error("newBundle: #%d got %s, expected %s%n", testNo, s, CLAZZ); |
| 241 | } |
| 242 | } catch (Throwable e) { |
| 243 | error("newBundle: #%d threw %s%n", testNo, e); |
| 244 | e.printStackTrace(); |
| 245 | } |
| 246 | |
| 247 | // Test exceptions |
| 248 | |
| 249 | try { |
| 250 | // MalformedDataRB contains an invalid Unicode notation which |
| 251 | // causes to throw an IllegalArgumentException. |
| 252 | rb = CONTROL.newBundle("MalformedDataRB", Locale.ENGLISH, |
| 253 | PROPERTIES, LOADER, false); |
| 254 | error("newBundle: doesn't throw IllegalArgumentException with malformed data."); |
| 255 | } catch (IllegalArgumentException iae) { |
| 256 | } catch (Exception e) { |
| 257 | error("newBundle: threw %s%n", e); |
| 258 | } |
| 259 | |
| 260 | try { |
| 261 | rb = CONTROL.newBundle("StressOut", Locale.JAPANESE, |
| 262 | "foo.bar", LOADER, false); |
| 263 | error("newBundle: doesn't throw IllegalArgumentException with invalid format."); |
| 264 | } catch (IllegalArgumentException iae) { |
| 265 | } catch (Exception e) { |
| 266 | error("newBundle: threw %s%n", e); |
| 267 | } |
| 268 | |
| 269 | try { |
| 270 | rb = CONTROL.newBundle("NonResourceBundle", new Locale(""), |
| 271 | "java.class", LOADER, false); |
| 272 | error("newBundle: doesn't throw ClassCastException with a non-ResourceBundle subclass."); |
| 273 | } catch (ClassCastException cce) { |
| 274 | } catch (Exception e) { |
| 275 | error("newBundle: threw %s%n", e); |
| 276 | } |
| 277 | |
| 278 | // NPE test |
| 279 | final int NARGS = 4; |
| 280 | for (int mask = 0; mask < (1 << NARGS)-1; mask++) { |
| 281 | Object[] data = getNpeArgs(NARGS, mask); |
| 282 | Locale loc = (Locale) data[1]; |
| 283 | try { |
| 284 | rb = CONTROL.newBundle((String) data[0], loc, |
| 285 | (String) data[2], (ClassLoader) data[3], |
| 286 | false); |
| 287 | error("newBundle(%s, %s, %s, %s, false) doesn't throw NPE.%n", |
| 288 | data[0], toString(loc), data[2], data[3]); |
| 289 | } catch (NullPointerException npe) { |
| 290 | } catch (Exception e) { |
| 291 | error("newBundle(%s, %s, %s, %s, false) threw %s.%n", |
| 292 | data[0], toString(loc), data[2], data[3], e); |
| 293 | } |
| 294 | } |
| 295 | } |
| 296 | |
| 297 | private static void testGetTimeToLive() { |
| 298 | long ttl = CONTROL.getTimeToLive("any", Locale.US); |
| 299 | if (ttl != CONTROL.TTL_NO_EXPIRATION_CONTROL) { |
| 300 | error("getTimeToLive: got %d, expected %d%n", ttl, |
| 301 | CONTROL.TTL_NO_EXPIRATION_CONTROL); |
| 302 | } |
| 303 | final int NARGS = 2; |
| 304 | for (int mask = 0; mask < (1 << NARGS)-1; mask++) { |
| 305 | Object[] data = getNpeArgs(NARGS, mask); |
| 306 | try { |
| 307 | ttl = CONTROL.getTimeToLive((String) data[0], (Locale) data[1]); |
| 308 | error("getTimeToLive(%s, %s) doesn't throw NPE.%n", data[0], data[1]); |
| 309 | } catch (NullPointerException e) { |
| 310 | } |
| 311 | } |
| 312 | } |
| 313 | |
| 314 | // The functionality of needsReload is tested by |
| 315 | // ExpirationTest.sh. Only parameter checking is tested here. |
| 316 | private static void testNeedsReload() { |
| 317 | long loadTime = System.currentTimeMillis(); |
| 318 | |
| 319 | // NPE test |
| 320 | final int NARGS = 5; |
| 321 | for (int mask = 0; mask < (1 << NARGS)-1; mask++) { |
| 322 | Object[] data = getNpeArgs(NARGS, mask); |
| 323 | Locale loc = (Locale) data[1]; |
| 324 | try { |
| 325 | boolean b = CONTROL.needsReload((String) data[0], loc, |
| 326 | (String) data[2], (ClassLoader) data[3], |
| 327 | (ResourceBundle) data[4], loadTime); |
| 328 | error("needsReload(%s, %s, %s, %s, %s, loadTime) doesn't throw NPE.%n", |
| 329 | data[0], toString(loc), data[2], data[3], data[4]); |
| 330 | } catch (NullPointerException e) { |
| 331 | } |
| 332 | } |
| 333 | } |
| 334 | |
| 335 | private static void testToBundleName() { |
| 336 | final String name = "J2SE"; |
| 337 | Map<Locale, String> bundleNames = new HashMap<Locale, String>(); |
| 338 | bundleNames.put(new Locale("ja", "JP", "YOK"), |
| 339 | name + "_" + "ja" + "_" + "JP" + "_" + "YOK"); |
| 340 | bundleNames.put(new Locale("ja", "JP"), |
| 341 | name + "_" + "ja" + "_" + "JP"); |
| 342 | bundleNames.put(new Locale("ja"), |
| 343 | name + "_" + "ja"); |
| 344 | bundleNames.put(new Locale("ja", "", "YOK"), |
| 345 | name + "_" + "ja" + "_" + "" + "_" + "YOK"); |
| 346 | bundleNames.put(new Locale("", "JP", "YOK"), |
| 347 | name + "_" + "" + "_" + "JP" + "_" + "YOK"); |
| 348 | bundleNames.put(new Locale("", "", "YOK"), |
| 349 | name + "_" + "" + "_" + "" + "_" + "YOK"); |
| 350 | bundleNames.put(new Locale("", "JP"), |
| 351 | name + "_" + "" + "_" + "JP"); |
| 352 | bundleNames.put(new Locale(""), |
| 353 | name); |
| 354 | |
| 355 | for (Locale locale : bundleNames.keySet()) { |
| 356 | String bn = CONTROL.toBundleName(name, locale); |
| 357 | String expected = bundleNames.get(locale); |
| 358 | if (!bn.equals(expected)) { |
| 359 | error("toBundleName: got %s, expected %s%n", bn, expected); |
| 360 | } |
| 361 | } |
| 362 | |
| 363 | final int NARGS = 2; |
| 364 | for (int mask = 0; mask < (1 << NARGS)-1; mask++) { |
| 365 | Object[] data = getNpeArgs(NARGS, mask); |
| 366 | try { |
| 367 | String s = CONTROL.toBundleName((String) data[0], (Locale) data[1]); |
| 368 | error("toBundleName(%s, %s) doesn't throw NPE.%n", data[0], data[1]); |
| 369 | } catch (NullPointerException e) { |
| 370 | } |
| 371 | } |
| 372 | } |
| 373 | |
| 374 | private static void testToResourceName() { |
| 375 | String[][] names = { |
| 376 | // bundleName, suffix, expected result |
| 377 | { "com.sun.J2SE", "xml", "com/sun/J2SE.xml" }, |
| 378 | { ".J2SE", "xml", "/J2SE.xml" }, |
| 379 | { "J2SE", "xml", "J2SE.xml" }, |
| 380 | { "com/sun/J2SE", "xml", "com/sun/J2SE.xml" }, |
| 381 | { "com.sun.J2SE", "", "com/sun/J2SE." }, |
| 382 | { ".", "", "/." }, |
| 383 | { "", "", "." }, |
| 384 | |
| 385 | // data for NPE tests |
| 386 | { null, "any", null }, |
| 387 | { "any", null, null }, |
| 388 | { null, null, null }, |
| 389 | }; |
| 390 | |
| 391 | for (String[] data : names) { |
| 392 | String result = null; |
| 393 | boolean npeThrown = false; |
| 394 | try { |
| 395 | result = CONTROL.toResourceName(data[0], data[1]); |
| 396 | } catch (NullPointerException npe) { |
| 397 | npeThrown = true; |
| 398 | } |
| 399 | String expected = data[2]; |
| 400 | if (expected != null) { |
| 401 | if (!result.equals(expected)) { |
| 402 | error("toResourceName: got %s, expected %s%n", result, data[2]); |
| 403 | } |
| 404 | } else { |
| 405 | if (!npeThrown) { |
| 406 | error("toResourceName(%s, %s) doesn't throw NPE.%n", data[0], data[1]); |
| 407 | } |
| 408 | } |
| 409 | } |
| 410 | } |
| 411 | |
| 412 | /** |
| 413 | * Produces permutations argument data that contains at least one |
| 414 | * null. |
| 415 | */ |
| 416 | private static Object[] getNpeArgs(int length, int mask) { |
| 417 | Object[] data = new Object[length]; |
| 418 | for (int i = 0; i < length; i++) { |
| 419 | if ((mask & (1 << i)) == 0) { |
| 420 | data[i] = null; |
| 421 | } else { |
| 422 | data[i] = FULLARGS[i]; |
| 423 | } |
| 424 | } |
| 425 | return data; |
| 426 | } |
| 427 | |
| 428 | private static String toString(Locale loc) { |
| 429 | if (loc == null) |
| 430 | return "null"; |
| 431 | return "\"" + loc.getLanguage() + "_" + loc.getCountry() + "_" + loc.getVariant() + "\""; |
| 432 | } |
| 433 | |
| 434 | private static void error(String msg) { |
| 435 | System.out.println(msg); |
| 436 | errors++; |
| 437 | } |
| 438 | |
| 439 | private static void error(String fmt, Object... args) { |
| 440 | System.out.printf(fmt, args); |
| 441 | errors++; |
| 442 | } |
| 443 | } |