Path: blob/master/test/jdk/java/util/Locale/LocaleProviders.java
41149 views
/*1* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/22import java.text.*;23import java.text.spi.*;24import java.time.LocalDate;25import java.time.ZoneId;26import java.time.ZonedDateTime;27import java.time.format.DateTimeFormatter;28import java.time.format.FormatStyle;29import java.time.temporal.WeekFields;30import java.util.*;31import java.util.concurrent.CopyOnWriteArrayList;32import java.util.logging.Level;33import java.util.logging.LogRecord;34import java.util.logging.StreamHandler;35import java.util.spi.*;36import java.util.stream.IntStream;37import sun.util.locale.provider.LocaleProviderAdapter;3839import static java.util.logging.LogManager.*;4041public class LocaleProviders {4243private static final boolean IS_WINDOWS = System.getProperty("os.name").startsWith("Windows");44private static final boolean IS_MAC = System.getProperty("os.name").startsWith("Mac");4546public static void main(String[] args) {47String methodName = args[0];4849switch (methodName) {50case "getPlatformLocale":51if (args[1].equals("format")) {52getPlatformLocale(Locale.Category.FORMAT);53} else {54getPlatformLocale(Locale.Category.DISPLAY);55}56break;5758case "adapterTest":59adapterTest(args[1], args[2], (args.length >= 4 ? args[3] : ""));60break;6162case "bug7198834Test":63bug7198834Test();64break;6566case "tzNameTest":67tzNameTest(args[1]);68break;6970case "bug8001440Test":71bug8001440Test();72break;7374case "bug8010666Test":75bug8010666Test();76break;7778case "bug8013086Test":79bug8013086Test(args[1], args[2]);80break;8182case "bug8013903Test":83bug8013903Test();84break;8586case "bug8027289Test":87bug8027289Test(args[1]);88break;8990case "bug8220227Test":91bug8220227Test();92break;9394case "bug8228465Test":95bug8228465Test();96break;9798case "bug8232871Test":99bug8232871Test();100break;101102case "bug8232860Test":103bug8232860Test();104break;105106case "bug8245241Test":107bug8245241Test(args[1]);108break;109110case "bug8248695Test":111bug8248695Test();112break;113114case "bug8257964Test":115bug8257964Test();116break;117118default:119throw new RuntimeException("Test method '"+methodName+"' not found.");120}121}122123static void getPlatformLocale(Locale.Category cat) {124Locale defloc = Locale.getDefault(cat);125System.out.printf("%s,%s\n", defloc.getLanguage(), defloc.getCountry());126}127128static void adapterTest(String expected, String lang, String ctry) {129Locale testLocale = new Locale(lang, ctry);130LocaleProviderAdapter ldaExpected =131LocaleProviderAdapter.forType(LocaleProviderAdapter.Type.valueOf(expected));132if (!ldaExpected.getDateFormatProvider().isSupportedLocale(testLocale)) {133System.out.println("test locale: "+testLocale+" is not supported by the expected provider: "+ldaExpected+". Ignoring the test.");134return;135}136String preference = System.getProperty("java.locale.providers", "");137LocaleProviderAdapter lda = LocaleProviderAdapter.getAdapter(DateFormatProvider.class, testLocale);138LocaleProviderAdapter.Type type = lda.getAdapterType();139System.out.printf("testLocale: %s, got: %s, expected: %s\n", testLocale, type, expected);140if (!type.toString().equals(expected)) {141throw new RuntimeException("Returned locale data adapter is not correct.");142}143}144145static void bug7198834Test() {146LocaleProviderAdapter lda = LocaleProviderAdapter.getAdapter(DateFormatProvider.class, Locale.US);147LocaleProviderAdapter.Type type = lda.getAdapterType();148if (type == LocaleProviderAdapter.Type.HOST && IS_WINDOWS) {149DateFormat df = DateFormat.getDateInstance(DateFormat.FULL, Locale.US);150String date = df.format(new Date());151if (date.charAt(date.length()-1) == ' ') {152throw new RuntimeException("Windows Host Locale Provider returns a trailing space.");153}154} else {155System.out.println("Windows HOST locale adapter not found. Ignoring this test.");156}157}158159static void tzNameTest(String id) {160TimeZone tz = TimeZone.getTimeZone(id);161String tzName = tz.getDisplayName(false, TimeZone.SHORT, Locale.US);162if (tzName.startsWith("GMT")) {163throw new RuntimeException("JRE's localized time zone name for "+id+" could not be retrieved. Returned name was: "+tzName);164}165}166167static void bug8001440Test() {168Locale locale = Locale.forLanguageTag("th-TH-u-nu-hoge");169NumberFormat nf = NumberFormat.getInstance(locale);170String nu = nf.format(1234560);171}172173// This test assumes Windows localized language/country display names.174static void bug8010666Test() {175if (IS_WINDOWS) {176NumberFormat nf = NumberFormat.getInstance(Locale.US);177try {178double ver = nf.parse(System.getProperty("os.version"))179.doubleValue();180System.out.printf("Windows version: %.1f\n", ver);181if (ver >= 6.0) {182LocaleProviderAdapter lda =183LocaleProviderAdapter.getAdapter(184LocaleNameProvider.class, Locale.ENGLISH);185LocaleProviderAdapter.Type type = lda.getAdapterType();186if (type == LocaleProviderAdapter.Type.HOST) {187LocaleNameProvider lnp = lda.getLocaleNameProvider();188Locale mkmk = Locale.forLanguageTag("mk-MK");189String result = mkmk.getDisplayLanguage(Locale.ENGLISH);190String hostResult =191lnp.getDisplayLanguage(mkmk.getLanguage(),192Locale.ENGLISH);193System.out.printf(" Display language name for" +194" (mk_MK): result(HOST): \"%s\", returned: \"%s\"\n",195hostResult, result);196if (result == null ||197hostResult != null &&198!result.equals(hostResult)) {199throw new RuntimeException("Display language name" +200" mismatch for \"mk\". Returned name was" +201" \"" + result + "\", result(HOST): \"" +202hostResult + "\"");203}204result = Locale.US.getDisplayLanguage(Locale.ENGLISH);205hostResult =206lnp.getDisplayLanguage(Locale.US.getLanguage(),207Locale.ENGLISH);208System.out.printf(" Display language name for" +209" (en_US): result(HOST): \"%s\", returned: \"%s\"\n",210hostResult, result);211if (result == null ||212hostResult != null &&213!result.equals(hostResult)) {214throw new RuntimeException("Display language name" +215" mismatch for \"en\". Returned name was" +216" \"" + result + "\", result(HOST): \"" +217hostResult + "\"");218}219if (ver >= 6.1) {220result = Locale.US.getDisplayCountry(Locale.ENGLISH);221hostResult = lnp.getDisplayCountry(222Locale.US.getCountry(), Locale.ENGLISH);223System.out.printf(" Display country name for" +224" (en_US): result(HOST): \"%s\", returned: \"%s\"\n",225hostResult, result);226if (result == null ||227hostResult != null &&228!result.equals(hostResult)) {229throw new RuntimeException("Display country name" +230" mismatch for \"US\". Returned name was" +231" \"" + result + "\", result(HOST): \"" +232hostResult + "\"");233}234}235} else {236throw new RuntimeException("Windows Host" +237" LocaleProviderAdapter was not selected for" +238" English locale.");239}240}241} catch (ParseException pe) {242throw new RuntimeException("Parsing Windows version failed: "+pe.toString());243}244}245}246247static void bug8013086Test(String lang, String ctry) {248try {249// Throws a NullPointerException if the test fails.250System.out.println(new SimpleDateFormat("z", new Locale(lang, ctry)).parse("UTC"));251} catch (ParseException pe) {252// ParseException is fine in this test, as it's not "UTC"253}254}255256static void bug8013903Test() {257if (IS_WINDOWS) {258Date sampleDate = new Date(0x10000000000L);259String expected = "\u5e73\u6210 16.11.03 (\u6c34) \u5348\u524d 11:53:47";260Locale l = new Locale("ja", "JP", "JP");261SimpleDateFormat sdf = new SimpleDateFormat("GGGG yyyy.MMM.dd '('E')' a hh:mm:ss", l);262sdf.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));263String result = sdf.format(sampleDate);264System.out.println(result);265if (LocaleProviderAdapter.getAdapterPreference()266.contains(LocaleProviderAdapter.Type.JRE)) {267if (!expected.equals(result)) {268throw new RuntimeException("Format failed. result: \"" +269result + "\", expected: \"" + expected);270}271} else {272// Windows display names. Subject to change if Windows changes its format.273if (!expected.equals(result)) {274throw new RuntimeException("Format failed. result: \"" +275result + "\", expected: \"" + expected);276}277}278}279}280281static void bug8027289Test(String expectedCodePoint) {282if (IS_WINDOWS) {283char[] expectedSymbol = Character.toChars(Integer.valueOf(expectedCodePoint, 16));284NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.CHINA);285char formatted = nf.format(7000).charAt(0);286System.out.println("returned: " + formatted + ", expected: " + expectedSymbol[0]);287if (formatted != expectedSymbol[0]) {288throw new RuntimeException(289"Unexpected Chinese currency symbol. returned: "290+ formatted + ", expected: " + expectedSymbol[0]);291}292}293}294295static void bug8220227Test() {296if (IS_WINDOWS) {297Locale l = new Locale("xx","XX");298String country = l.getDisplayCountry();299if (country.endsWith("(XX)")) {300throw new RuntimeException(301"Unexpected Region name: " + country);302}303}304}305306static void bug8228465Test() {307LocaleProviderAdapter lda = LocaleProviderAdapter.getAdapter(CalendarNameProvider.class, Locale.US);308LocaleProviderAdapter.Type type = lda.getAdapterType();309if (type == LocaleProviderAdapter.Type.HOST && IS_WINDOWS) {310var names = new GregorianCalendar()311.getDisplayNames(Calendar.ERA, Calendar.SHORT_FORMAT, Locale.US);312if (!names.keySet().contains("AD") ||313names.get("AD").intValue() != 1) {314throw new RuntimeException(315"Short Era name for 'AD' is missing or incorrect");316} else {317System.out.println("bug8228465Test succeeded.");318}319}320}321322static void bug8232871Test() {323LocaleProviderAdapter lda = LocaleProviderAdapter.getAdapter(CalendarNameProvider.class, Locale.US);324LocaleProviderAdapter.Type type = lda.getAdapterType();325var lang = Locale.getDefault().getLanguage();326var cal = Calendar.getInstance();327var calType = cal.getCalendarType();328var expected = "\u4ee4\u548c1\u5e745\u67081\u65e5 \u6c34\u66dc\u65e5 \u5348\u524d0:00:00 \u30a2\u30e1\u30ea\u30ab\u592a\u5e73\u6d0b\u590f\u6642\u9593";329330if (type == LocaleProviderAdapter.Type.HOST &&331IS_MAC &&332lang.equals("ja") &&333calType.equals("japanese")) {334cal.set(1, 4, 1, 0, 0, 0);335cal.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));336DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL,337Locale.JAPAN);338df.setCalendar(cal);339var result = df.format(cal.getTime());340if (result.equals(expected)) {341System.out.println("bug8232871Test succeeded.");342} else {343throw new RuntimeException(344"Japanese calendar names mismatch. result: " +345result +346", expected: " +347expected);348}349} else {350System.out.println("Test ignored. Either :-\n" +351"OS is not macOS, or\n" +352"provider is not HOST: " + type + ", or\n" +353"Language is not Japanese: " + lang + ", or\n" +354"native calendar is not JapaneseCalendar: " + calType);355}356}357358static void bug8232860Test() {359var inputList = List.of(123, 123.4);360var nfExpectedList = List.of("123", "123.4");361var ifExpectedList = List.of("123", "123");362363var defLoc = Locale.getDefault(Locale.Category.FORMAT);364var type = LocaleProviderAdapter.getAdapter(CalendarNameProvider.class, Locale.US)365.getAdapterType();366if (defLoc.equals(Locale.US) &&367type == LocaleProviderAdapter.Type.HOST &&368(IS_WINDOWS || IS_MAC)) {369final var numf = NumberFormat.getNumberInstance(Locale.US);370final var intf = NumberFormat.getIntegerInstance(Locale.US);371372IntStream.range(0, inputList.size())373.forEach(i -> {374var input = inputList.get(i);375var nfExpected = nfExpectedList.get(i);376var result = numf.format(input);377if (!result.equals(nfExpected)) {378throw new RuntimeException("Incorrect number format. " +379"input: " + input + ", expected: " +380nfExpected + ", result: " + result);381}382383var ifExpected = ifExpectedList.get(i);384result = intf.format(input);385if (!result.equals(ifExpected)) {386throw new RuntimeException("Incorrect integer format. " +387"input: " + input + ", expected: " +388ifExpected + ", result: " + result);389}390});391System.out.println("bug8232860Test succeeded.");392} else {393System.out.println("Test ignored. Either :-\n" +394"Default format locale is not Locale.US: " + defLoc + ", or\n" +395"OS is neither macOS/Windows, or\n" +396"provider is not HOST: " + type);397}398}399400static void bug8245241Test(String expected) {401// this will ensure LocaleProviderAdapter initialization402DateFormat.getDateInstance();403LogConfig.handler.flush();404405if (LogConfig.logRecordList.stream()406.noneMatch(r -> r.getLevel() == Level.INFO &&407r.getMessage().equals(expected))) {408throw new RuntimeException("Expected log was not emitted.");409}410}411412// Set the root logger on loading the logging class413public static class LogConfig {414final static CopyOnWriteArrayList<LogRecord> logRecordList = new CopyOnWriteArrayList<>();415final static StreamHandler handler = new StreamHandler() {416@Override417public void publish(LogRecord record) {418logRecordList.add(record);419System.out.println("LogRecord: " + record.getMessage());420}421};422static {423getLogManager().getLogger("").addHandler(handler);424}425}426427static void bug8248695Test() {428Locale l = Locale.getDefault(Locale.Category.FORMAT);429LocaleProviderAdapter lda = LocaleProviderAdapter.getAdapter(DateFormatProvider.class, l);430LocaleProviderAdapter.Type type = lda.getAdapterType();431if (type == LocaleProviderAdapter.Type.HOST) {432System.out.println("Locale: " + l);433var ld = LocalDate.now();434var zdt = ZonedDateTime.now(ZoneId.of("America/Los_Angeles"));435var df = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).withLocale(l);436var tf = DateTimeFormatter.ofLocalizedTime(FormatStyle.FULL).withLocale(l);437var dtf = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withLocale(l);438439// Checks there's no "unsupported temporal field" exception thrown, such as HourOfDay440System.out.println(df.format(ld));441System.out.println(tf.format(zdt));442443// Checks there's no "Too many pattern letters: aa" exception thrown, if444// underlying OS provides the "am/pm" pattern.445System.out.println(dtf.format(zdt));446}447}448449// Run only if the platform locale is en-GB450static void bug8257964Test() {451var defLoc = Locale.getDefault(Locale.Category.FORMAT);452var type = LocaleProviderAdapter.getAdapter(CalendarNameProvider.class, Locale.UK)453.getAdapterType();454if (defLoc.equals(Locale.UK) &&455type == LocaleProviderAdapter.Type.HOST &&456(IS_WINDOWS || IS_MAC)) {457Calendar instance = Calendar.getInstance(Locale.UK);458int result = instance.getMinimalDaysInFirstWeek();459if (result != 4) {460throw new RuntimeException("MinimalDaysInFirstWeek for Locale.UK is incorrect. " +461"returned: " + result);462}463464LocalDate date = LocalDate.of(2020,12,31);465result = date.get(WeekFields.of(Locale.UK).weekOfWeekBasedYear());466if (result != 53) {467throw new RuntimeException("weekNumber is incorrect. " +468"returned: " + result);469}470System.out.println("bug8257964Test succeeded.");471} else {472System.out.println("Test ignored. Either :-\n" +473"Default format locale is not Locale.UK: " + defLoc + ", or\n" +474"OS is neither macOS/Windows, or\n" +475"provider is not HOST: " + type);476}477}478}479480481