1 /* 2 * Copyright (c) 2018, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* 27 * @test 28 * @bug 4397357 6565620 6959267 7070436 7198195 8032446 8072600 8221431 29 * @summary Confirm normal case mappings are handled correctly. 30 * @library /lib/testlibrary/java/lang 31 * @run main/timeout=200 UnicodeCasingTest 32 */ 33 34 import java.io.BufferedReader; 35 import java.io.IOException; 36 import java.nio.file.Files; 37 import java.nio.file.Paths; 38 import java.util.ArrayList; 39 import java.util.Locale; 40 import java.util.HashMap; 41 import java.util.List; 42 import java.util.Map; 43 44 public class UnicodeCasingTest { 45 46 private static boolean err = false; 47 48 // Locales which are used for testing 49 private static List<Locale> locales = new ArrayList<>(); 50 static { 51 locales.add(new Locale("az", "")); 52 locales.addAll(java.util.Arrays.asList(Locale.getAvailableLocales())); 53 } 54 55 // Default locale 56 private static String defaultLang; 57 58 // List for Unicode characters whose mappings are included in 59 // SpecialCasing.txt and mappings in UnicodeData.txt isn't applicable. 60 private static Map<String, String> excludeList = new HashMap<>(); 61 62 public static void main(String[] args) { 63 UnicodeCasingTest specialCasingTest = new UnicodeCasingTest(); 64 specialCasingTest.test(); 65 } 66 67 private void test() { 68 Locale defaultLocale = Locale.getDefault(); 69 BufferedReader in = null; 70 try { 71 // First, we create exlude lists of characters whose mappings exist 72 // in SpecialCasing.txt and mapping rules in UnicodeData.txt aren't 73 // applicable. 74 in = Files.newBufferedReader(UCDFiles.SPECIAL_CASING.toRealPath()); 75 String line; 76 while ((line = in.readLine()) != null) { 77 if (line.length() == 0 || line.charAt(0) == '#') { 78 continue; 79 } 80 updateExcludeList(line); 81 } 82 in.close(); 83 in = null; 84 int locale_num = locales.size(); 85 for (int l = 0; l < locale_num; l++) { 86 Locale locale = locales.get(l); 87 Locale.setDefault(locale); 88 defaultLang = locale.getLanguage(); 89 // System.out.println("Testing on " + locale + " locale...."); 90 System.err.println("Testing on " + locale + " locale...."); 91 in = Files.newBufferedReader(UCDFiles.UNICODE_DATA.toRealPath()); 92 while ((line = in.readLine()) != null) { 93 if (line.length() == 0 || line.charAt(0) == '#') { 94 continue; 95 } 96 test(line); 97 } 98 in.close(); 99 in = null; 100 } 101 } 102 catch (IOException e) { 103 err = true; 104 e.printStackTrace(); 105 } 106 finally { 107 if (in != null) { 108 try { 109 in.close(); 110 } 111 catch (IOException e) { 112 } 113 } 114 115 Locale.setDefault(defaultLocale); 116 117 if (err) { 118 throw new RuntimeException("UnicodeCasingTest failed."); 119 } else { 120 System.out.println("*** UnicodeCasingTest passed."); 121 } 122 } 123 } 124 125 private void updateExcludeList(String line) { 126 int index = line.indexOf('#'); 127 if (index != -1) { 128 line = line.substring(0, index); 129 } 130 131 String lang = null; 132 String condition = null; 133 String[] fields = line.split("; "); 134 135 // If the given character is mapped to multiple characters under the 136 // normal condition, add it to the exclude list. 137 if (fields.length == 4) { 138 excludeList.put(fields[0], "all"); 139 } else if (fields.length == 5) { 140 if (fields[4].length() == 2) { /// locale 141 if (excludeList.get(fields[0]) == null) { 142 excludeList.put(fields[0], fields[4]); 143 } 144 } 145 } 146 } 147 148 private void test(String line) { 149 String[] fields = line.split(";", 15); 150 String orig = convert(fields[0]); 151 152 String lang = excludeList.get(fields[0]); 153 if (!"all".equals(lang) && !defaultLang.equals(lang)) { 154 if (fields[12].length() == 0) { 155 testUpperCase(orig, convert(fields[0])); 156 } else { 157 testUpperCase(orig, convert(fields[12])); 158 } 159 160 if (fields[13].length() == 0) { 161 testLowerCase(orig, convert(fields[0])); 162 } else { 163 testLowerCase(orig, convert(fields[13])); 164 } 165 } 166 } 167 168 private void testUpperCase(String orig, String expected) { 169 String got = orig.toUpperCase(); 170 171 // Ugly workaround for special mappings for az and tr locales.... 172 if (orig.equals("\u0069") && 173 (defaultLang.equals("az") || defaultLang.equals("tr"))) { 174 expected = "\u0130"; 175 } 176 177 if (!expected.equals(got)) { 178 err = true; 179 System.err.println("toUpperCase(" + 180 ") failed.\n\tOriginal: " + toString(orig) + 181 "\n\tGot: " + toString(got) + 182 "\n\tExpected: " + toString(expected)); 183 } 184 } 185 186 private void testLowerCase(String orig, String expected) { 187 String got = orig.toLowerCase(); 188 // Ugly workaround for special mappings for az and tr locales.... 189 if (orig.equals("\u0049") && 190 (defaultLang.equals("az") || defaultLang.equals("tr"))) { 191 expected = "\u0131"; 192 } 193 194 if (!expected.equals(got)) { 195 err = true; 196 System.err.println("toLowerCase(" + 197 ") failed.\n\tOriginal: " + toString(orig) + 198 "\n\tGot: " + toString(got) + 199 "\n\tExpected: " + toString(expected)); 200 } 201 } 202 203 StringBuilder sb = new StringBuilder(); 204 205 private String convert(String str) { 206 sb.setLength(0); 207 208 String[] tokens = str.split(" "); 209 for (String token : tokens) { 210 int j = Integer.parseInt(token, 16); 211 if (j < Character.MIN_SUPPLEMENTARY_CODE_POINT) { 212 sb.append((char)j); 213 } else { 214 sb.append(Character.toChars(j)); 215 } 216 } 217 218 return sb.toString(); 219 } 220 221 private String toString(String str) { 222 sb.setLength(0); 223 224 int len = str.length(); 225 for (int i = 0; i < len; i++) { 226 sb.append("0x").append(Integer.toHexString(str.charAt(i)).toUpperCase()).append(" "); 227 } 228 229 return sb.toString(); 230 } 231 232 }