1 /* 2 * Copyright (c) 2018, 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 8202771 27 * @summary Check j.l.Character.isDigit/isLetter/isLetterOrDigit/isSpaceChar 28 * /isWhitespace/isTitleCase/isISOControl/isIdentifierIgnorable 29 * /isJavaIdentifierStart/isJavaIdentifierPart/isUnicodeIdentifierStart 30 * /isUnicodeIdentifierPart 31 * @run main CharPropTest 32 */ 33 34 import java.nio.file.Files; 35 import java.nio.file.Path; 36 import java.nio.file.Paths; 37 import java.util.stream.Stream; 38 39 public class CharPropTest { 40 private static int diffs = 0; 41 private static int rangeStart = 0x0000; 42 private static boolean isRange = false; 43 main(String[] args)44 public static void main(String[] args) throws Exception { 45 Path path = Paths.get(System.getProperty("test.src", "."), 46 "UnicodeData.txt"); 47 try (Stream<String> lines = Files.lines(path)) { 48 lines.map(String::trim) 49 .filter(line -> line.length() != 0 && line.charAt(0) != '#') 50 .forEach(line -> handleOneLine(line)); 51 52 if (diffs != 0) { 53 throw new RuntimeException("Total differences: " + diffs); 54 } 55 } 56 } 57 handleOneLine(String line)58 private static void handleOneLine(String line) { 59 String[] fields = line.split(";"); 60 int currentCp = Integer.parseInt(fields[0], 16); 61 String name = fields[1]; 62 String category = fields[2]; 63 64 // Except single code point, also handle ranges like the following: 65 // 3400;<CJK Ideograph Extension A, First>;Lo;0;L;;;;;N;;;;; 66 // 4DB5;<CJK Ideograph Extension A, Last>;Lo;0;L;;;;;N;;;; 67 if (isRange) { 68 if (name.endsWith("Last>")) { 69 for (int cp = rangeStart; cp <= currentCp; cp++) { 70 testCodePoint(cp, category); 71 } 72 } else { 73 throw new RuntimeException("Not a valid range, first range <" 74 + Integer.toHexString(rangeStart) + "> without last."); 75 } 76 isRange = false; 77 } else { 78 if (name.endsWith("First>")) { 79 rangeStart = currentCp; 80 isRange = true; 81 } else { 82 testCodePoint(currentCp, category); 83 } 84 } 85 } 86 testCodePoint(int codePoint, String category)87 private static void testCodePoint(int codePoint, String category) { 88 isDigitTest(codePoint, category); 89 isLetterTest(codePoint, category); 90 isLetterOrDigitTest(codePoint, category); 91 92 isSpaceCharTest(codePoint, category); 93 isWhitespaceTest(codePoint, category); 94 95 isTitleCaseTest(codePoint, category); 96 97 isISOControlTest(codePoint); 98 99 isIdentifierIgnorableTest(codePoint, category); 100 isJavaIdentifierStartTest(codePoint, category); 101 isJavaIdentifierPartTest(codePoint, category); 102 isUnicodeIdentifierStartTest(codePoint, category); 103 isUnicodeIdentifierPartTest(codePoint, category); 104 } 105 isDigitTest(int codePoint, String category)106 private static void isDigitTest(int codePoint, String category) { 107 boolean actual = Character.isDigit(codePoint); 108 boolean expected = category.equals("Nd"); 109 if (actual != expected) { 110 printDiff(codePoint, "isDigit", actual, expected); 111 } 112 } 113 isLetterTest(int codePoint, String category)114 private static void isLetterTest(int codePoint, String category) { 115 boolean actual = Character.isLetter(codePoint); 116 boolean expected = isLetter(category); 117 if (actual != expected) { 118 printDiff(codePoint, "isLetter", actual, expected); 119 } 120 } 121 isLetterOrDigitTest(int codePoint, String category)122 private static void isLetterOrDigitTest(int codePoint, String category) { 123 boolean actual = Character.isLetterOrDigit(codePoint); 124 boolean expected = isLetter(category) || category.equals("Nd"); 125 if (actual != expected) { 126 printDiff(codePoint, "isLetterOrDigit", actual, expected); 127 } 128 } 129 isSpaceCharTest(int codePoint, String category)130 private static void isSpaceCharTest(int codePoint, String category) { 131 boolean actual = Character.isSpaceChar(codePoint); 132 boolean expected = isSpaceChar(category); 133 if (actual != expected) { 134 printDiff(codePoint, "isSpaceChar", actual, expected); 135 } 136 } 137 isWhitespaceTest(int codePoint, String category)138 private static void isWhitespaceTest(int codePoint, String category) { 139 boolean actual = Character.isWhitespace(codePoint); 140 boolean expected = isWhitespace(codePoint, category); 141 if (actual != expected) { 142 printDiff(codePoint, "isWhitespace", actual, expected); 143 } 144 } 145 isTitleCaseTest(int codePoint, String category)146 private static void isTitleCaseTest(int codePoint, String category) { 147 boolean actual = Character.isTitleCase(codePoint); 148 boolean expected = category.equals("Lt"); 149 if (actual != expected) { 150 printDiff(codePoint, "isTitleCase", actual, expected); 151 } 152 } 153 isISOControlTest(int codePoint)154 private static void isISOControlTest(int codePoint) { 155 boolean actual = Character.isISOControl(codePoint); 156 boolean expected = isISOControl(codePoint); 157 if (actual != expected) { 158 printDiff(codePoint, "isISOControl", actual, expected); 159 } 160 } 161 isIdentifierIgnorableTest(int codePoint, String category)162 private static void isIdentifierIgnorableTest(int codePoint, String category) { 163 boolean actual = Character.isIdentifierIgnorable(codePoint); 164 boolean expected = isIdentifierIgnorable(codePoint, category); 165 if (actual != expected) { 166 printDiff(codePoint, "isIdentifierIgnorable", actual, expected); 167 } 168 } 169 isJavaIdentifierStartTest(int codePoint, String category)170 private static void isJavaIdentifierStartTest(int codePoint, String category) { 171 boolean actual = Character.isJavaIdentifierStart(codePoint); 172 boolean expected = isJavaIdentifierStart(category); 173 if (actual != expected) { 174 printDiff(codePoint, "isJavaIdentifierStart", actual, expected); 175 } 176 } 177 isJavaIdentifierPartTest(int codePoint, String category)178 private static void isJavaIdentifierPartTest(int codePoint, String category) { 179 boolean actual = Character.isJavaIdentifierPart(codePoint); 180 boolean expected = isJavaIdentifierPart(codePoint, category); 181 if (actual != expected) { 182 printDiff(codePoint, "isJavaIdentifierPart", actual, expected); 183 } 184 } 185 isUnicodeIdentifierStartTest(int codePoint, String category)186 private static void isUnicodeIdentifierStartTest(int codePoint, String category) { 187 boolean actual = Character.isUnicodeIdentifierStart(codePoint); 188 boolean expected = isUnicodeIdentifierStart(category); 189 if (actual != expected) { 190 printDiff(codePoint, "isUnicodeIdentifierStart", actual, expected); 191 } 192 } 193 isUnicodeIdentifierPartTest(int codePoint, String category)194 private static void isUnicodeIdentifierPartTest(int codePoint, String category) { 195 boolean actual = Character.isUnicodeIdentifierPart(codePoint); 196 boolean expected = isUnicodeIdentifierPart(codePoint, category); 197 if (actual != expected) { 198 printDiff(codePoint, "isUnicodeIdentifierPart", actual, expected); 199 } 200 } 201 isLetter(String category)202 private static boolean isLetter(String category) { 203 return category.equals("Lu") || category.equals("Ll") 204 || category.equals("Lt") || category.equals("Lm") 205 || category.equals("Lo"); 206 } 207 isSpaceChar(String category)208 private static boolean isSpaceChar(String category) { 209 return category.equals("Zs") || category.equals("Zl") 210 || category.equals("Zp"); 211 } 212 isWhitespace(int codePoint, String category)213 private static boolean isWhitespace(int codePoint, String category) { 214 if (isSpaceChar(category) && codePoint != Integer.parseInt("00A0", 16) 215 && codePoint != Integer.parseInt("2007", 16) 216 && codePoint != Integer.parseInt("202F", 16)) { 217 return true; 218 } else { 219 if (codePoint == Integer.parseInt("0009", 16) 220 || codePoint == Integer.parseInt("000A", 16) 221 || codePoint == Integer.parseInt("000B", 16) 222 || codePoint == Integer.parseInt("000C", 16) 223 || codePoint == Integer.parseInt("000D", 16) 224 || codePoint == Integer.parseInt("001C", 16) 225 || codePoint == Integer.parseInt("001D", 16) 226 || codePoint == Integer.parseInt("001E", 16) 227 || codePoint == Integer.parseInt("001F", 16)) { 228 return true; 229 } 230 } 231 return false; 232 } 233 isISOControl(int codePoint)234 private static boolean isISOControl(int codePoint) { 235 return (codePoint > 0x00 && codePoint < 0x1f) 236 || (codePoint > 0x7f && codePoint < 0x9f) 237 || (codePoint == 0x00 || codePoint == 0x1f || codePoint == 0x7f || codePoint == 0x9f); 238 } 239 isIdentifierIgnorable(int codePoint, String category)240 private static boolean isIdentifierIgnorable(int codePoint, String category) { 241 if (category.equals("Cf")) { 242 return true; 243 } else { 244 int a1 = Integer.parseInt("0000", 16); 245 int a2 = Integer.parseInt("0008", 16); 246 int b1 = Integer.parseInt("000E", 16); 247 int b2 = Integer.parseInt("001B", 16); 248 int c1 = Integer.parseInt("007F", 16); 249 int c2 = Integer.parseInt("009F", 16); 250 251 if ((codePoint > a1 && codePoint < a2) || (codePoint > b1 && codePoint < b2) 252 || (codePoint > c1 && codePoint < c2) || (codePoint == a1 || codePoint == a2 253 || codePoint == b1 || codePoint == b2 || codePoint == c1 || codePoint == c2)) { 254 return true; 255 } 256 } 257 return false; 258 } 259 isJavaIdentifierStart(String category)260 private static boolean isJavaIdentifierStart(String category) { 261 return isLetter(category) || category.equals("Nl") || category.equals("Sc") 262 || category.equals("Pc"); 263 } 264 isJavaIdentifierPart(int codePoint, String category)265 private static boolean isJavaIdentifierPart(int codePoint, String category) { 266 return isLetter(category) || category.equals("Sc") || category.equals("Pc") 267 || category.equals("Nd") || category.equals("Nl") 268 || category.equals("Mc") || category.equals("Mn") 269 || isIdentifierIgnorable(codePoint, category); 270 } 271 isUnicodeIdentifierStart(String category)272 private static boolean isUnicodeIdentifierStart(String category) { 273 return isLetter(category) || category.equals("Nl"); 274 } 275 isUnicodeIdentifierPart(int codePoint, String category)276 private static boolean isUnicodeIdentifierPart(int codePoint, String category) { 277 return isLetter(category) || category.equals("Pc") || category.equals("Nd") 278 || category.equals("Nl") || category.equals("Mc") || category.equals("Mn") 279 || isIdentifierIgnorable(codePoint, category); 280 } 281 printDiff(int codePoint, String method, boolean actual, boolean expected)282 private static void printDiff(int codePoint, String method, boolean actual, boolean expected) { 283 System.out.println("Not equal at codePoint <" + Integer.toHexString(codePoint) 284 + ">, method: " + method 285 + ", actual: " + actual + ", expected: " + expected); 286 diffs++; 287 } 288 } 289