1 /* 2 * Copyright (c) 2007, 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. 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 4830803 4886934 6565620 6959267 7070436 7198195 8032446 8072600 8202771 29 * @summary Check that the UnicodeBlock forName() method works as expected and block ranges are correct for all Unicode characters. 30 * @run main CheckBlocks 31 * @author John O'Conner 32 */ 33 34 import java.lang.Character.UnicodeBlock; 35 import java.lang.reflect.Field; 36 import java.io.BufferedReader; 37 import java.io.File; 38 import java.io.FileReader; 39 import java.util.HashSet; 40 import java.util.Locale; 41 42 public class CheckBlocks { 43 44 static boolean err = false; 45 static Class<?> clazzUnicodeBlock; 46 47 public static void main(String[] args) throws Exception { 48 generateBlockList(); 49 50 try { 51 clazzUnicodeBlock = Class.forName("java.lang.Character$UnicodeBlock"); 52 } catch (ClassNotFoundException e) { 53 throw new RuntimeException("Class.forName(\"java.lang.Character$UnicodeBlock\") failed."); 54 } 55 56 for (Block blk : blocks) { 57 test4830803_1(blk); 58 test4830803_2(); 59 test4886934(blk); 60 } 61 62 test8202771(); 63 64 if (err) { 65 throw new RuntimeException("Failed"); 66 } else { 67 System.out.println("Passed"); 68 } 69 } 70 71 /** 72 * Check that the UnicodeBlock forName() method works as expected. 73 */ 74 private static void test4830803_1(Block blk) throws Exception { 75 76 /* 77 * Try 3 forms of block name in the forName() method. Each form should 78 * produce the same expected block. 79 */ 80 String blkName = blk.getName(); 81 82 // For backward compatibility 83 switch (blkName) { 84 case "COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS": 85 blkName = "COMBINING_MARKS_FOR_SYMBOLS"; 86 System.out.println("*** COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS" 87 + " is replaced with COMBINING_MARKS_FOR_SYMBOLS" 88 + " for backward compatibility."); 89 break; 90 case "GREEK_AND_COPTIC": 91 blkName = "GREEK"; 92 System.out.println("*** GREEK_AND_COPTIC is replaced with GREEK" 93 + " for backward compatibility."); 94 break; 95 case "CYRILLIC_SUPPLEMENT": 96 blkName = "CYRILLIC_SUPPLEMENTARY"; 97 System.out.println("*** CYRILLIC_SUPPLEMENT is replaced with" 98 + " CYRILLIC_SUPPLEMENTARY for backward compatibility."); 99 break; 100 default: 101 break; 102 } 103 104 String expectedBlock = null; 105 try { 106 expectedBlock = clazzUnicodeBlock.getField(blkName).getName(); 107 } catch (NoSuchFieldException | SecurityException e) { 108 System.err.println("Error: " + blkName + " was not found."); 109 err = true; 110 return; 111 } 112 113 String canonicalBlockName = blk.getOriginalName(); 114 String idBlockName = expectedBlock; 115 String regexBlockName = toRegExString(canonicalBlockName); 116 117 if (regexBlockName == null) { 118 System.err.println("Error: Block name which was processed with regex was null."); 119 err = true; 120 return; 121 } 122 123 if (!expectedBlock.equals(UnicodeBlock.forName(canonicalBlockName).toString())) { 124 System.err.println("Error #1: UnicodeBlock.forName(\"" + 125 canonicalBlockName + "\") returned wrong value.\n\tGot: " + 126 UnicodeBlock.forName(canonicalBlockName) + 127 "\n\tExpected: " + expectedBlock); 128 err = true; 129 } 130 131 if (!expectedBlock.equals(UnicodeBlock.forName(idBlockName).toString())) { 132 System.err.println("Error #2: UnicodeBlock.forName(\"" + 133 idBlockName + "\") returned wrong value.\n\tGot: " + 134 UnicodeBlock.forName(idBlockName) + 135 "\n\tExpected: " + expectedBlock); 136 err = true; 137 } 138 139 if (!expectedBlock.equals(UnicodeBlock.forName(regexBlockName).toString())) { 140 System.err.println("Error #3: UnicodeBlock.forName(\"" + 141 regexBlockName + "\") returned wrong value.\n\tGot: " + 142 UnicodeBlock.forName(regexBlockName) + 143 "\n\tExpected: " + expectedBlock); 144 err = true; 145 } 146 } 147 148 /** 149 * now try a bad block name. This should produce an IAE. 150 */ 151 private static void test4830803_2() { 152 boolean threwExpected = false; 153 154 try { 155 UnicodeBlock block = UnicodeBlock.forName("notdefined"); 156 } 157 catch(IllegalArgumentException e) { 158 threwExpected = true; 159 } 160 161 if (threwExpected == false) { 162 System.err.println("Error: UnicodeBlock.forName(\"notdefined\") should throw IllegalArgumentException."); 163 err = true; 164 } 165 } 166 167 /** 168 * Convert the argument to a block name form used by the regex package. 169 * That is, remove all spaces. 170 */ 171 private static String toRegExString(String str) { 172 String[] tokens = null; 173 StringBuilder retStr = new StringBuilder(); 174 try { 175 tokens = str.split(" "); 176 } 177 catch(java.util.regex.PatternSyntaxException e) { 178 return null; 179 } 180 for(int x=0; x < tokens.length; ++x) { 181 retStr.append(tokens[x]); 182 } 183 return retStr.toString(); 184 } 185 186 private static void test4886934(Block blk) { 187 String blkName = blk.getName(); 188 String blkOrigName = blk.getOriginalName(); 189 UnicodeBlock block; 190 String blockName; 191 192 // For backward compatibility 193 switch (blkName) { 194 case "COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS": 195 blkName = "COMBINING_MARKS_FOR_SYMBOLS"; 196 System.out.println("*** COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS" 197 + " is replaced with COMBINING_MARKS_FOR_SYMBOLS" 198 + " for backward compatibility."); 199 break; 200 case "GREEK_AND_COPTIC": 201 blkName = "GREEK"; 202 System.out.println("*** GREEK_AND_COPTIC is replaced with GREEK" 203 + " for backward compatibility."); 204 break; 205 case "CYRILLIC_SUPPLEMENT": 206 blkName = "CYRILLIC_SUPPLEMENTARY"; 207 System.out.println("*** CYRILLIC_SUPPLEMENT is replaced with" 208 + " CYRILLIC_SUPPLEMENTARY for backward compatibility."); 209 break; 210 default: 211 break; 212 } 213 214 for (int ch = blk.getBegin(); ch <= blk.getEnd(); ch++) { 215 block = UnicodeBlock.of(ch); 216 if (block == null) { 217 System.err.println("Error: The block for " + blkName 218 + " is missing. Please check java.lang.Character.UnicodeBlock."); 219 err = true; 220 break; 221 } 222 blockName = block.toString(); 223 if (!blockName.equals(blkName)) { 224 System.err.println("Error: Character(0x" 225 + Integer.toHexString(ch).toUpperCase() 226 + ") should be in \"" + blkName + "\" block " 227 + "(Block name is \"" + blkOrigName + "\")" 228 + " but found in \"" + blockName + "\" block."); 229 err = true; 230 } 231 } 232 } 233 234 /** 235 * Check if every Field of Character.UnicodeBlock is a valid Unicode Block. 236 */ 237 private static void test8202771() { 238 Field[] fields = clazzUnicodeBlock.getFields(); 239 240 for (Field f : fields) { 241 // Handle Deprecated field "SURROGATES_AREA". 242 if (f.getAnnotation(Deprecated.class) != null) { 243 continue; 244 } 245 246 String blkName = f.getName(); 247 switch (blkName) { 248 case "COMBINING_MARKS_FOR_SYMBOLS": 249 validateBlock("COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS"); 250 break; 251 case "GREEK": 252 validateBlock("GREEK_AND_COPTIC"); 253 break; 254 case "CYRILLIC_SUPPLEMENTARY": 255 validateBlock("CYRILLIC_SUPPLEMENT"); 256 break; 257 default: 258 validateBlock(blkName); 259 break; 260 } 261 } 262 } 263 264 private static void validateBlock(String blkName) { 265 for (Block block : blocks) { 266 String blockName = block.getName(); 267 if (blockName.equals(blkName)) { 268 return; 269 } 270 } 271 err = true; 272 System.err.println(blkName + " is not a valid Unicode Block."); 273 } 274 275 // List of all Unicode blocks, their start, and end codepoints. 276 public static HashSet<Block> blocks = new HashSet<>(); 277 278 private static void generateBlockList() throws Exception { 279 File blockData = new File(System.getProperty("test.src", "."), 280 "Blocks.txt"); 281 try (BufferedReader f = new BufferedReader(new FileReader(blockData))) { 282 String line; 283 while ((line = f.readLine()) != null) { 284 if (line.length() == 0 || line.charAt(0) == '#') { 285 continue; 286 } 287 288 int index1 = line.indexOf('.'); 289 int begin = Integer.parseInt(line.substring(0, index1), 16); 290 int index2 = line.indexOf(';'); 291 int end = Integer.parseInt(line.substring(index1 + 2, index2), 16); 292 String name = line.substring(index2 + 1).trim(); 293 294 System.out.println(" Adding a Block(" + Integer.toHexString(begin) + ", " + Integer.toHexString(end) 295 + ", " + name + ")"); 296 blocks.add(new Block(begin, end, name)); 297 } 298 } 299 } 300 } 301 302 class Block { 303 304 public Block() { 305 blockBegin = 0; 306 blockEnd = 0; 307 blockName = null; 308 } 309 310 public Block(int begin, int end, String name) { 311 blockBegin = begin; 312 blockEnd = end; 313 blockName = name.replaceAll("[ -]", "_").toUpperCase(Locale.ENGLISH); 314 originalBlockName = name; 315 } 316 317 public int getBegin() { 318 return blockBegin; 319 } 320 321 public int getEnd() { 322 return blockEnd; 323 } 324 325 public String getName() { 326 return blockName; 327 } 328 329 public String getOriginalName() { 330 return originalBlockName; 331 } 332 333 @Override 334 public boolean equals(Object obj) { 335 if (obj == null) return false; 336 if (!(obj instanceof Block)) return false; 337 338 Block other = (Block)obj; 339 return other.blockBegin == blockBegin && 340 other.blockEnd == blockEnd && 341 other.blockName.equals(blockName) && 342 other.originalBlockName.equals(originalBlockName); 343 } 344 int blockBegin, blockEnd; 345 String blockName, originalBlockName; 346 }