blob: b2970bf0cac9b5940b1598873bcd1f3f442b6be8 [file] [log] [blame]
/*
**********************************************************************
* Copyright (c) 2009, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* Author: Alan Liu
* Created: January 14 2004
* Since: ICU 2.8
**********************************************************************
*/
package com.ibm.icu.dev.test.util;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Locale;
import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.text.Collator;
import com.ibm.icu.util.ULocale;
public class ULocaleCollationTest extends TestFmwk {
public static void main(String[] args) throws Exception {
new ULocaleCollationTest().run(args);
}
public void TestCollator() {
checkService("ja_JP_YOKOHAMA", new ServiceFacade() {
public Object create(ULocale req) {
return Collator.getInstance(req);
}
}, null, new Registrar() {
public Object register(ULocale loc, Object prototype) {
return Collator.registerInstance((Collator) prototype, loc);
}
public boolean unregister(Object key) {
return Collator.unregister(key);
}
});
}
/**
* Interface used by checkService defining a protocol to create an
* object, given a requested locale.
*/
interface ServiceFacade {
Object create(ULocale requestedLocale);
}
/**
* Interface used by checkService defining a protocol to get a
* contained subobject, given its parent object.
*/
interface Subobject {
Object get(Object parent);
}
/**
* Interface used by checkService defining a protocol to register
* and unregister a service object prototype.
*/
interface Registrar {
Object register(ULocale loc, Object prototype);
boolean unregister(Object key);
}
/**
* Compare two locale IDs. If they are equal, return 0. If `string'
* starts with `prefix' plus an additional element, that is, string ==
* prefix + '_' + x, then return 1. Otherwise return a value < 0.
*/
static int loccmp(String string, String prefix) {
int slen = string.length(),
plen = prefix.length();
/* 'root' is "less than" everything */
if (prefix.equals("root")) {
return string.equals("root") ? 0 : 1;
}
// ON JAVA (only -- not on C -- someone correct me if I'm wrong)
// consider "" to be an alternate name for "root".
if (plen == 0) {
return slen == 0 ? 0 : 1;
}
if (!string.startsWith(prefix)) return -1; /* mismatch */
if (slen == plen) return 0;
if (string.charAt(plen) == '_') return 1;
return -2; /* false match, e.g. "en_USX" cmp "en_US" */
}
/**
* Check the relationship between requested locales, and report problems.
* The caller specifies the expected relationships between requested
* and valid (expReqValid) and between valid and actual (expValidActual).
* Possible values are:
* "gt" strictly greater than, e.g., en_US > en
* "ge" greater or equal, e.g., en >= en
* "eq" equal, e.g., en == en
*/
void checklocs(String label,
String req,
Locale validLoc,
Locale actualLoc,
String expReqValid,
String expValidActual) {
String valid = validLoc.toString();
String actual = actualLoc.toString();
int reqValid = loccmp(req, valid);
int validActual = loccmp(valid, actual);
boolean reqOK = (expReqValid.equals("gt") && reqValid > 0) ||
(expReqValid.equals("ge") && reqValid >= 0) ||
(expReqValid.equals("eq") && reqValid == 0);
boolean valOK = (expValidActual.equals("gt") && validActual > 0) ||
(expValidActual.equals("ge") && validActual >= 0) ||
(expValidActual.equals("eq") && validActual == 0);
if (reqOK && valOK) {
logln("Ok: " + label + "; req=" + req + ", valid=" + valid +
", actual=" + actual);
} else {
errln("FAIL: " + label + "; req=" + req + ", valid=" + valid +
", actual=" + actual +
(reqOK ? "" : "\n req !" + expReqValid + " valid") +
(valOK ? "" : "\n val !" + expValidActual + " actual"));
}
}
/**
* Use reflection to call getLocale() on the given object to
* determine both the valid and the actual locale. Verify these
* for correctness.
*/
void checkObject(String requestedLocale, Object obj,
String expReqValid, String expValidActual) {
Class[] getLocaleParams = new Class[] { ULocale.Type.class };
try {
Class cls = obj.getClass();
Method getLocale = cls.getMethod("getLocale", getLocaleParams);
ULocale valid = (ULocale) getLocale.invoke(obj, new Object[] {
ULocale.VALID_LOCALE });
ULocale actual = (ULocale) getLocale.invoke(obj, new Object[] {
ULocale.ACTUAL_LOCALE });
checklocs(cls.getName(), requestedLocale,
valid.toLocale(), actual.toLocale(),
expReqValid, expValidActual);
}
// Make the following exceptions _specific_ -- do not
// catch(Exception), since that will catch the exception
// that errln throws.
catch(NoSuchMethodException e1) {
// no longer an error, Currency has no getLocale
// errln("FAIL: reflection failed: " + e1);
} catch(SecurityException e2) {
errln("FAIL: reflection failed: " + e2);
} catch(IllegalAccessException e3) {
errln("FAIL: reflection failed: " + e3);
} catch(IllegalArgumentException e4) {
errln("FAIL: reflection failed: " + e4);
} catch(InvocationTargetException e5) {
// no longer an error, Currency has no getLocale
// errln("FAIL: reflection failed: " + e5);
}
}
/**
* Verify the correct getLocale() behavior for the given service.
* @param requestedLocale the locale to request. This MUST BE
* FAKE. In other words, it should be something like
* en_US_FAKEVARIANT so this method can verify correct fallback
* behavior.
* @param svc a factory object that can create the object to be
* tested. This isn't necessary here (one could just pass in the
* object) but is required for the overload of this method that
* takes a Registrar.
*/
void checkService(String requestedLocale, ServiceFacade svc) {
checkService(requestedLocale, svc, null, null);
}
/**
* Verify the correct getLocale() behavior for the given service.
* @param requestedLocale the locale to request. This MUST BE
* FAKE. In other words, it should be something like
* en_US_FAKEVARIANT so this method can verify correct fallback
* behavior.
* @param svc a factory object that can create the object to be
* tested.
* @param sub an object that can be used to retrieve a subobject
* which should also be tested. May be null.
* @param reg an object that supplies the registration and
* unregistration functionality to be tested. May be null.
*/
void checkService(String requestedLocale, ServiceFacade svc,
Subobject sub, Registrar reg) {
ULocale req = new ULocale(requestedLocale);
Object obj = svc.create(req);
checkObject(requestedLocale, obj, "gt", "ge");
if (sub != null) {
Object subobj = sub.get(obj);
checkObject(requestedLocale, subobj, "gt", "ge");
}
if (reg != null) {
logln("Info: Registering service");
Object key = reg.register(req, obj);
Object objReg = svc.create(req);
checkObject(requestedLocale, objReg, "eq", "eq");
if (sub != null) {
Object subobj = sub.get(obj);
// Assume subobjects don't come from services, so
// their metadata should be structured normally.
checkObject(requestedLocale, subobj, "gt", "ge");
}
logln("Info: Unregistering service");
if (!reg.unregister(key)) {
errln("FAIL: unregister failed");
}
Object objUnreg = svc.create(req);
checkObject(requestedLocale, objUnreg, "gt", "ge");
}
}
}