1 /*
   2  * Copyright (c) 2016, 2019, 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 /*
  25  * @test
  26  * @bug 8040211 8191404 8203872 8222980 8225435
  27  * @summary Checks the IANA language subtag registry data update
  28  *          (LSR Revision: 2019-09-16) with Locale and Locale.LanguageRange
  29  *          class methods.
  30  * @run main Bug8040211
  31  */
  32 
  33 import java.util.ArrayList;
  34 import java.util.Iterator;
  35 import java.util.Locale;
  36 import java.util.List;
  37 import java.util.Locale.LanguageRange;
  38 import java.util.Locale.FilteringMode;
  39 import static java.util.Locale.FilteringMode.EXTENDED_FILTERING;
  40 
  41 public class Bug8040211 {
  42 
  43     static boolean err = false;
  44 
  45     private static final String ACCEPT_LANGUAGE =
  46         "Accept-Language: aam, adp, aog, aue, bcg, cey, cqu, dif, ema,"
  47         + " en-gb-oed, gti, kdz, koj, kwq, kxe, lii, lmm, lsn, lsv, lvi, mtm,"
  48         + " ngv, nns, oyb, phr, pnd, pub, snz, suj, szy,taj, tjj, tjp, tvx,"
  49         + " uss, uth, wkr;q=0.9, ar-hyw;q=0.8, yug;q=0.5, gfx;q=0.4";
  50     private static final List<LanguageRange> EXPECTED_RANGE_LIST = List.of(
  51             new LanguageRange("aam", 1.0),
  52             new LanguageRange("aas", 1.0),
  53             new LanguageRange("adp", 1.0),
  54             new LanguageRange("dz", 1.0),
  55             new LanguageRange("aog", 1.0),
  56             new LanguageRange("myd", 1.0),
  57             new LanguageRange("aue", 1.0),
  58             new LanguageRange("ktz", 1.0),
  59             new LanguageRange("bcg", 1.0),
  60             new LanguageRange("bgm", 1.0),
  61             new LanguageRange("cey", 1.0),
  62             new LanguageRange("cqu", 1.0),
  63             new LanguageRange("quh", 1.0),
  64             new LanguageRange("dif", 1.0),
  65             new LanguageRange("dit", 1.0),
  66             new LanguageRange("ema", 1.0),
  67             new LanguageRange("uok", 1.0),
  68             new LanguageRange("en-gb-oed", 1.0),
  69             new LanguageRange("en-gb-oxendict", 1.0),
  70             new LanguageRange("gti", 1.0),
  71             new LanguageRange("nyc", 1.0),
  72             new LanguageRange("kdz", 1.0),
  73             new LanguageRange("ncp", 1.0),
  74             new LanguageRange("koj", 1.0),
  75             new LanguageRange("kwv", 1.0),
  76             new LanguageRange("kwq", 1.0),
  77             new LanguageRange("yam", 1.0),
  78             new LanguageRange("kxe", 1.0),
  79             new LanguageRange("tvd", 1.0),
  80             new LanguageRange("lii", 1.0),
  81             new LanguageRange("raq", 1.0),
  82             new LanguageRange("lmm", 1.0),
  83             new LanguageRange("rmx", 1.0),
  84             new LanguageRange("lsn", 1.0),
  85             new LanguageRange("lsv", 1.0),
  86             new LanguageRange("lvi", 1.0),
  87             new LanguageRange("mtm", 1.0),
  88             new LanguageRange("ymt", 1.0),
  89             new LanguageRange("ngv", 1.0),
  90             new LanguageRange("nnx", 1.0),
  91             new LanguageRange("nns", 1.0),
  92             new LanguageRange("nbr", 1.0),
  93             new LanguageRange("oyb", 1.0),
  94             new LanguageRange("thx", 1.0),
  95             new LanguageRange("skk", 1.0),
  96             new LanguageRange("jeg", 1.0),
  97             new LanguageRange("phr", 1.0),
  98             new LanguageRange("pmu", 1.0),
  99             new LanguageRange("pnd", 1.0),
 100             new LanguageRange("pub", 1.0),
 101             new LanguageRange("puz", 1.0),
 102             new LanguageRange("snz", 1.0),
 103             new LanguageRange("asd", 1.0),
 104             new LanguageRange("suj", 1.0),
 105             new LanguageRange("szy", 1.0),
 106             new LanguageRange("taj", 1.0),
 107             new LanguageRange("tsf", 1.0),
 108             new LanguageRange("tjj", 1.0),
 109             new LanguageRange("tjp", 1.0),
 110             new LanguageRange("tvx", 1.0),
 111             new LanguageRange("uss", 1.0),
 112             new LanguageRange("uth", 1.0),
 113             new LanguageRange("wkr", 0.9),
 114             new LanguageRange("ar-hyw", 0.8),
 115             new LanguageRange("yug", 0.5),
 116             new LanguageRange("yuu", 0.5),
 117             new LanguageRange("gfx", 0.4),
 118             new LanguageRange("oun", 0.4),
 119             new LanguageRange("mwj", 0.4),
 120             new LanguageRange("vaj", 0.4)
 121         );
 122 
 123     public static void main(String[] args) {
 124         testLanguageRange();
 125         testLocale();
 126 
 127         if (err) {
 128             throw new RuntimeException("Failed.");
 129         }
 130     }
 131 
 132     private static void testLanguageRange() {
 133         System.out.println("Test LanguageRange class parse method...");
 134         test_parse();
 135     }
 136 
 137     private static void testLocale() {
 138         System.out.println("Test Locale class methods...");
 139         test_filter();
 140         test_filterTags();
 141         test_lookup();
 142         test_lookupTag();
 143     }
 144 
 145     private static void test_parse() {
 146         boolean error = false;
 147         List<LanguageRange> got = LanguageRange.parse(ACCEPT_LANGUAGE);
 148         if (!areEqual(EXPECTED_RANGE_LIST, got)) {
 149             error = true;
 150             System.err.println("    language parse() test failed.");
 151         }
 152 
 153         if (error) {
 154             err = true;
 155             System.out.println("  test_parse() failed.");
 156         } else {
 157             System.out.println("  test_parse() passed.");
 158         }
 159 
 160     }
 161 
 162     private static boolean areEqual(List<LanguageRange> expected,
 163             List<LanguageRange> got) {
 164         boolean error = false;
 165 
 166         int expectedSize = expected.size();
 167         int actualSize = got.size();
 168 
 169         if (expectedSize != actualSize) {
 170             error = true;
 171 
 172             System.err.println("  Expected size=" + expectedSize);
 173             for (LanguageRange lr : expected) {
 174                 System.err.println("    range=" + lr.getRange()
 175                         + ", weight=" + lr.getWeight());
 176             }
 177 
 178             System.err.println("  Actual size=" + actualSize);
 179             for (LanguageRange lr : got) {
 180                 System.err.println("    range=" + lr.getRange()
 181                         + ", weight=" + lr.getWeight());
 182             }
 183         } else {
 184             for (int i = 0; i < expectedSize; i++) {
 185                 LanguageRange lr1 = expected.get(i);
 186                 LanguageRange lr2 = got.get(i);
 187 
 188                 if (!lr1.getRange().equals(lr2.getRange())
 189                         || lr1.getWeight() != lr2.getWeight()) {
 190                     error = true;
 191                     System.err.println("  " + i + ": Expected: range=" + lr1.getRange()
 192                             + ", weight=" + lr1.getWeight());
 193                     System.err.println("  " + i + ": Actual:   range=" + lr2.getRange()
 194                             + ", weight=" + lr2.getWeight());
 195                 }
 196             }
 197         }
 198 
 199         return !error;
 200     }
 201 
 202     private static void test_filter() {
 203         boolean error = false;
 204 
 205         String ranges = "mtm-RU, en-gb-oed, coy, ar-HY";
 206         String tags = "de-DE, en, mtm-RU, ymt-RU, en-gb-oxendict, ja-JP, pij, nts, ar-arevela";
 207         FilteringMode mode = EXTENDED_FILTERING;
 208 
 209         List<LanguageRange> priorityList = LanguageRange.parse(ranges);
 210         List<Locale> tagList = generateLocales(tags);
 211         String actualLocales
 212                 = showLocales(Locale.filter(priorityList, tagList, mode));
 213         String expectedLocales = "mtm-RU, ymt-RU, en-GB-oxendict, nts, pij";
 214 
 215         if (!expectedLocales.equals(actualLocales)) {
 216             error = true;
 217             showErrorMessage("#1 filter(" + mode + ")",
 218                     ranges, tags, expectedLocales, actualLocales);
 219         }
 220 
 221         ranges = "phr-*-IN, ja-JP";
 222         tags = "en, pmu-Guru-IN, ja-Latn-JP, iw";
 223         mode = EXTENDED_FILTERING;
 224 
 225         priorityList = LanguageRange.parse(ranges);
 226         tagList = generateLocales(tags);
 227         actualLocales = showLocales(Locale.filter(priorityList, tagList, mode));
 228         expectedLocales = "pmu-Guru-IN, ja-Latn-JP";
 229 
 230         if (!expectedLocales.equals(actualLocales)) {
 231             error = true;
 232             showErrorMessage("#2 filter(" + mode + ")",
 233                     ranges, tags, expectedLocales, actualLocales);
 234         }
 235 
 236         if (error) {
 237             err = true;
 238             System.out.println("  test_filter() failed.");
 239         } else {
 240             System.out.println("  test_filter() passed.");
 241         }
 242     }
 243 
 244     private static void test_filterTags() {
 245         boolean error = false;
 246 
 247         String ranges = "gti;q=0.2, gfx, kzj";
 248         String tags = "de-DE, gti, he, nyc, mwj, vaj, ktr, dtp";
 249 
 250         List<LanguageRange> priorityList = LanguageRange.parse(ranges);
 251         List<String> tagList = generateLanguageTags(tags);
 252         String actualTags
 253                 = showLanguageTags(Locale.filterTags(priorityList, tagList));
 254         String expectedTags = "mwj, vaj, ktr, dtp, gti, nyc";
 255 
 256         if (!expectedTags.equals(actualTags)) {
 257             error = true;
 258             showErrorMessage("filterTags()",
 259                     ranges, tags, expectedTags, actualTags);
 260         }
 261 
 262         if (error) {
 263             err = true;
 264             System.out.println("  test_filterTags() failed.");
 265         } else {
 266             System.out.println("  test_filterTags() passed.");
 267         }
 268     }
 269 
 270     private static void test_lookup() {
 271         boolean error = false;
 272 
 273         String ranges = "en;q=0.2, yam, rmx;q=0.9";
 274         String tags = "de-DE, en, kwq, lmm";
 275         List<LanguageRange> priorityList = LanguageRange.parse(ranges);
 276         List<Locale> localeList = generateLocales(tags);
 277         String actualLocale
 278                 = Locale.lookup(priorityList, localeList).toLanguageTag();
 279         String expectedLocale = "kwq";
 280 
 281         if (!expectedLocale.equals(actualLocale)) {
 282             error = true;
 283             showErrorMessage("lookup()", ranges, tags, expectedLocale, actualLocale);
 284         }
 285 
 286         if (error) {
 287             err = true;
 288             System.out.println("  test_lookup() failed.");
 289         } else {
 290             System.out.println("  test_lookup() passed.");
 291         }
 292     }
 293 
 294     private static void test_lookupTag() {
 295         boolean error = false;
 296 
 297         String ranges = "en, tsf;q=0.2";
 298         String tags = "es, ja-JP, taj";
 299         List<LanguageRange> priorityList = LanguageRange.parse(ranges);
 300         List<String> tagList = generateLanguageTags(tags);
 301         String actualTag = Locale.lookupTag(priorityList, tagList);
 302         String expectedTag = "taj";
 303 
 304         if (!expectedTag.equals(actualTag)) {
 305             error = true;
 306             showErrorMessage("lookupTag()", ranges, tags, expectedTag, actualTag);
 307         }
 308 
 309         if (error) {
 310             err = true;
 311             System.out.println("  test_lookupTag() failed.");
 312         } else {
 313             System.out.println("  test_lookupTag() passed.");
 314         }
 315     }
 316 
 317     private static List<Locale> generateLocales(String tags) {
 318         if (tags == null) {
 319             return null;
 320         }
 321 
 322         List<Locale> localeList = new ArrayList<>();
 323         if (tags.equals("")) {
 324             return localeList;
 325         }
 326         String[] t = tags.split(", ");
 327         for (String tag : t) {
 328             localeList.add(Locale.forLanguageTag(tag));
 329         }
 330         return localeList;
 331     }
 332 
 333     private static List<String> generateLanguageTags(String tags) {
 334         List<String> tagList = new ArrayList<>();
 335         String[] t = tags.split(", ");
 336         for (String tag : t) {
 337             tagList.add(tag);
 338         }
 339         return tagList;
 340     }
 341 
 342     private static String showLanguageTags(List<String> tags) {
 343         StringBuilder sb = new StringBuilder();
 344 
 345         Iterator<String> itr = tags.iterator();
 346         if (itr.hasNext()) {
 347             sb.append(itr.next());
 348         }
 349         while (itr.hasNext()) {
 350             sb.append(", ");
 351             sb.append(itr.next());
 352         }
 353 
 354         return sb.toString().trim();
 355     }
 356 
 357     private static String showLocales(List<Locale> locales) {
 358         StringBuilder sb = new StringBuilder();
 359 
 360         java.util.Iterator<Locale> itr = locales.iterator();
 361         if (itr.hasNext()) {
 362             sb.append(itr.next().toLanguageTag());
 363         }
 364         while (itr.hasNext()) {
 365             sb.append(", ");
 366             sb.append(itr.next().toLanguageTag());
 367         }
 368 
 369         return sb.toString().trim();
 370     }
 371 
 372     private static void showErrorMessage(String methodName,
 373             String priorityList,
 374             String tags,
 375             String expectedTags,
 376             String actualTags) {
 377         System.err.println("\nIncorrect " + methodName + " result.");
 378         System.err.println("  Priority list  :  " + priorityList);
 379         System.err.println("  Language tags  :  " + tags);
 380         System.err.println("  Expected value : " + expectedTags);
 381         System.err.println("  Actual value   : " + actualTags);
 382     }
 383 
 384 }
 385