2 **********************************************************************
\r
3 * Copyright (c) 2009, International Business Machines
\r
4 * Corporation and others. All Rights Reserved.
\r
5 **********************************************************************
\r
7 * Created: January 14 2004
\r
9 **********************************************************************
\r
11 package com.ibm.icu.dev.test.util;
\r
13 import java.lang.reflect.InvocationTargetException;
\r
14 import java.lang.reflect.Method;
\r
15 import java.util.Locale;
\r
17 import com.ibm.icu.dev.test.TestFmwk;
\r
18 import com.ibm.icu.text.Collator;
\r
19 import com.ibm.icu.util.ULocale;
\r
21 public class ULocaleCollationTest extends TestFmwk {
\r
23 public static void main(String[] args) throws Exception {
\r
24 new ULocaleCollationTest().run(args);
\r
27 public void TestCollator() {
\r
28 checkService("ja_JP_YOKOHAMA", new ServiceFacade() {
\r
29 public Object create(ULocale req) {
\r
30 return Collator.getInstance(req);
\r
32 }, null, new Registrar() {
\r
33 public Object register(ULocale loc, Object prototype) {
\r
34 return Collator.registerInstance((Collator) prototype, loc);
\r
36 public boolean unregister(Object key) {
\r
37 return Collator.unregister(key);
\r
44 * Interface used by checkService defining a protocol to create an
\r
45 * object, given a requested locale.
\r
47 interface ServiceFacade {
\r
48 Object create(ULocale requestedLocale);
\r
52 * Interface used by checkService defining a protocol to get a
\r
53 * contained subobject, given its parent object.
\r
55 interface Subobject {
\r
56 Object get(Object parent);
\r
60 * Interface used by checkService defining a protocol to register
\r
61 * and unregister a service object prototype.
\r
63 interface Registrar {
\r
64 Object register(ULocale loc, Object prototype);
\r
65 boolean unregister(Object key);
\r
71 * Compare two locale IDs. If they are equal, return 0. If `string'
\r
72 * starts with `prefix' plus an additional element, that is, string ==
\r
73 * prefix + '_' + x, then return 1. Otherwise return a value < 0.
\r
75 static int loccmp(String string, String prefix) {
\r
76 int slen = string.length(),
\r
77 plen = prefix.length();
\r
78 /* 'root' is "less than" everything */
\r
79 if (prefix.equals("root")) {
\r
80 return string.equals("root") ? 0 : 1;
\r
82 // ON JAVA (only -- not on C -- someone correct me if I'm wrong)
\r
83 // consider "" to be an alternate name for "root".
\r
85 return slen == 0 ? 0 : 1;
\r
87 if (!string.startsWith(prefix)) return -1; /* mismatch */
\r
88 if (slen == plen) return 0;
\r
89 if (string.charAt(plen) == '_') return 1;
\r
90 return -2; /* false match, e.g. "en_USX" cmp "en_US" */
\r
94 * Check the relationship between requested locales, and report problems.
\r
95 * The caller specifies the expected relationships between requested
\r
96 * and valid (expReqValid) and between valid and actual (expValidActual).
\r
97 * Possible values are:
\r
98 * "gt" strictly greater than, e.g., en_US > en
\r
99 * "ge" greater or equal, e.g., en >= en
\r
100 * "eq" equal, e.g., en == en
\r
102 void checklocs(String label,
\r
106 String expReqValid,
\r
107 String expValidActual) {
\r
108 String valid = validLoc.toString();
\r
109 String actual = actualLoc.toString();
\r
110 int reqValid = loccmp(req, valid);
\r
111 int validActual = loccmp(valid, actual);
\r
112 boolean reqOK = (expReqValid.equals("gt") && reqValid > 0) ||
\r
113 (expReqValid.equals("ge") && reqValid >= 0) ||
\r
114 (expReqValid.equals("eq") && reqValid == 0);
\r
115 boolean valOK = (expValidActual.equals("gt") && validActual > 0) ||
\r
116 (expValidActual.equals("ge") && validActual >= 0) ||
\r
117 (expValidActual.equals("eq") && validActual == 0);
\r
118 if (reqOK && valOK) {
\r
119 logln("Ok: " + label + "; req=" + req + ", valid=" + valid +
\r
120 ", actual=" + actual);
\r
122 errln("FAIL: " + label + "; req=" + req + ", valid=" + valid +
\r
123 ", actual=" + actual +
\r
124 (reqOK ? "" : "\n req !" + expReqValid + " valid") +
\r
125 (valOK ? "" : "\n val !" + expValidActual + " actual"));
\r
130 * Use reflection to call getLocale() on the given object to
\r
131 * determine both the valid and the actual locale. Verify these
\r
134 void checkObject(String requestedLocale, Object obj,
\r
135 String expReqValid, String expValidActual) {
\r
136 Class[] getLocaleParams = new Class[] { ULocale.Type.class };
\r
138 Class cls = obj.getClass();
\r
139 Method getLocale = cls.getMethod("getLocale", getLocaleParams);
\r
140 ULocale valid = (ULocale) getLocale.invoke(obj, new Object[] {
\r
141 ULocale.VALID_LOCALE });
\r
142 ULocale actual = (ULocale) getLocale.invoke(obj, new Object[] {
\r
143 ULocale.ACTUAL_LOCALE });
\r
144 checklocs(cls.getName(), requestedLocale,
\r
145 valid.toLocale(), actual.toLocale(),
\r
146 expReqValid, expValidActual);
\r
149 // Make the following exceptions _specific_ -- do not
\r
150 // catch(Exception), since that will catch the exception
\r
151 // that errln throws.
\r
152 catch(NoSuchMethodException e1) {
\r
153 // no longer an error, Currency has no getLocale
\r
154 // errln("FAIL: reflection failed: " + e1);
\r
155 } catch(SecurityException e2) {
\r
156 errln("FAIL: reflection failed: " + e2);
\r
157 } catch(IllegalAccessException e3) {
\r
158 errln("FAIL: reflection failed: " + e3);
\r
159 } catch(IllegalArgumentException e4) {
\r
160 errln("FAIL: reflection failed: " + e4);
\r
161 } catch(InvocationTargetException e5) {
\r
162 // no longer an error, Currency has no getLocale
\r
163 // errln("FAIL: reflection failed: " + e5);
\r
168 * Verify the correct getLocale() behavior for the given service.
\r
169 * @param requestedLocale the locale to request. This MUST BE
\r
170 * FAKE. In other words, it should be something like
\r
171 * en_US_FAKEVARIANT so this method can verify correct fallback
\r
173 * @param svc a factory object that can create the object to be
\r
174 * tested. This isn't necessary here (one could just pass in the
\r
175 * object) but is required for the overload of this method that
\r
176 * takes a Registrar.
\r
178 void checkService(String requestedLocale, ServiceFacade svc) {
\r
179 checkService(requestedLocale, svc, null, null);
\r
183 * Verify the correct getLocale() behavior for the given service.
\r
184 * @param requestedLocale the locale to request. This MUST BE
\r
185 * FAKE. In other words, it should be something like
\r
186 * en_US_FAKEVARIANT so this method can verify correct fallback
\r
188 * @param svc a factory object that can create the object to be
\r
190 * @param sub an object that can be used to retrieve a subobject
\r
191 * which should also be tested. May be null.
\r
192 * @param reg an object that supplies the registration and
\r
193 * unregistration functionality to be tested. May be null.
\r
195 void checkService(String requestedLocale, ServiceFacade svc,
\r
196 Subobject sub, Registrar reg) {
\r
197 ULocale req = new ULocale(requestedLocale);
\r
198 Object obj = svc.create(req);
\r
199 checkObject(requestedLocale, obj, "gt", "ge");
\r
201 Object subobj = sub.get(obj);
\r
202 checkObject(requestedLocale, subobj, "gt", "ge");
\r
205 logln("Info: Registering service");
\r
206 Object key = reg.register(req, obj);
\r
207 Object objReg = svc.create(req);
\r
208 checkObject(requestedLocale, objReg, "eq", "eq");
\r
210 Object subobj = sub.get(obj);
\r
211 // Assume subobjects don't come from services, so
\r
212 // their metadata should be structured normally.
\r
213 checkObject(requestedLocale, subobj, "gt", "ge");
\r
215 logln("Info: Unregistering service");
\r
216 if (!reg.unregister(key)) {
\r
217 errln("FAIL: unregister failed");
\r
219 Object objUnreg = svc.create(req);
\r
220 checkObject(requestedLocale, objUnreg, "gt", "ge");
\r