1 /*
2  * Copyright (c) 2007, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * 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 
main(String[] args)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 
checkConstants()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 
checkImmutableList(List<String> list)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 
testGetFormats()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 
testGetCandidateLocales()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 
testGetFallbackLocale()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 
testNewBundle()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 
testGetTimeToLive()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.
testNeedsReload()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 
testToBundleName()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 
testToResourceName()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      */
getNpeArgs(int length, int mask)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 
toString(Locale loc)428     private static String toString(Locale loc) {
429         if (loc == null)
430             return "null";
431         return "\"" + loc.getLanguage() + "_" + loc.getCountry() + "_" + loc.getVariant() + "\"";
432     }
433 
error(String msg)434     private static void error(String msg) {
435         System.out.println(msg);
436         errors++;
437     }
438 
error(String fmt, Object... args)439     private static void error(String fmt, Object... args) {
440         System.out.printf(fmt, args);
441         errors++;
442     }
443 }
444