1 /* 2 * Copyright (c) 2000, 2016, 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 4018937 27 * @library /java/text/testlib 28 * @summary Tests the formatToCharacterIterator method of SimpleDateFormat, 29 * MessageFormat and DecimalFormat. 30 */ 31 32 import java.io.*; 33 import java.lang.reflect.*; 34 import java.text.*; 35 import java.util.*; 36 import java.util.concurrent.atomic.AtomicInteger; 37 import java.util.concurrent.atomic.AtomicLong; 38 39 /** 40 * FormatTester creates Formats, and tests the resulting FieldPositions 41 * and AttributedCharacterIterator based on a file. The file is a hierarchical 42 * set of key/value pairs, where each value can also be an array or map. The 43 * top map must contain a tests entry, which will be an array consisting 44 * of pairs of maps. The first map specifies the Format that 45 * should be created, and consists of: 46 * <pre> 47 * class = className 48 * args = (arg1 arg2 ...) 49 * valueClass = className 50 * valueArgs = (arg1 arg2 ...) 51 * </pre> 52 * The second map dictates what to test, and should consist of the following: 53 * <pre> 54 * length = lengthOfFormattedString 55 * text = Result of Formatting 56 * 0...lengthOfFormattedString = (arg1 arg2 ...) 57 * limits = ( range1 range2 ...) 58 * fieldPositions = ( fp1 fp2 ...) 59 * </pre> 60 * <code>lengthOfFormattedString</code> indicate the total length of formatted 61 * string. <code>text</code> indicates the resulting string. 62 * <code>0...x</code> where x == <code>lengthOfFormattedString - 1</code> is 63 * an array of the attributes that should exist at the particular 64 * location. <code>limits</code> is an array of maps, where each map 65 * can be used to test the bounds of a set of attributes. Each map will 66 * consist of: 67 * <pre> 68 * attributes = array of attributes 69 * begin = start location 70 * begin2 = second start location 71 * end = limit location 72 * end2 = second limit location 73 * </pre> 74 * These are tested by iterating from begin to end in the CharacterIterator 75 * and doing the following at each index: 76 * <pre> 77 * getRunStart() == begin 78 * getRunStart(attributes) == begin2 79 * getRunLimit() == end 80 * getRunLimit(attributes) == end2 81 * </pre> 82 * <code>fieldPositions</code> is used to test the results of invoking 83 * <code>format</code> with a <code>FieldPosition</code>. 84 * <code>fieldPositions</code> is an array of maps, where each map contains 85 * the following: 86 * <pre> 87 * field = Integer field reference (optional) 88 * fieldID = Object reference 89 * begin = begin index of FieldPosition after formatting 90 * end = end index of FieldPosition after formatting 91 * </pre> 92 */ 93 public class FormatIteratorTest extends IntlTest { 94 private static HashMap attrs; 95 private Format format; 96 private Object value; 97 private String text; 98 99 public static final Object ARG0_FIELD_ID = MessageFormat. 100 Field.ARGUMENT; 101 public static final Object ARG1_FIELD_ID = MessageFormat. 102 Field.ARGUMENT; 103 public static final Object ARG2_FIELD_ID = MessageFormat. 104 Field.ARGUMENT; 105 public static final Object ARG3_FIELD_ID = MessageFormat. 106 Field.ARGUMENT; 107 108 public static void main(String[] args) throws Exception { 109 Locale reservedLocale = Locale.getDefault(); 110 TimeZone reservedTimeZone = TimeZone.getDefault(); 111 try { 112 // The current tests are only appropriate for US. If tests are 113 // added for other locales are added, then a property should be 114 // added to each file (test) to be able to specify the locale. 115 Locale.setDefault(Locale.US); 116 TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); 117 new FormatIteratorTest().run(args); 118 } finally { 119 // restore the reserved locale and time zone 120 Locale.setDefault(reservedLocale); 121 TimeZone.setDefault(reservedTimeZone); 122 } 123 } 124 125 public FormatIteratorTest() { 126 } 127 128 public void testDecimalFormat() { 129 _test(new File(System.getProperty("test.src", "."), 130 "decimalFormat.props")); 131 } 132 133 public void testMessageFormat() { 134 _test(new File(System.getProperty("test.src", "."), 135 "messageFormat.props")); 136 } 137 138 public void testDateFormat() { 139 _test(new File(System.getProperty("test.src", "."), 140 "dateFormat.props")); 141 } 142 143 private void _test(File file) { 144 try { 145 attrs = new HashMap(); 146 logln("testing: " + file); 147 PParser parser = new PParser(); 148 Hashtable contents = parser.parse(new BufferedReader( 149 new FileReader(file))); 150 Vector test = (Vector)contents.get("tests"); 151 152 for (int counter = 0; counter < test.size(); counter++) { 153 logln("creating: " + (counter / 2)); 154 155 AttributedCharacterIterator iterator = 156 create((Hashtable)test.get(counter)); 157 158 logln("verifying: " + (counter / 2)); 159 verify(iterator, (Hashtable)test.get(++counter)); 160 } 161 } catch (IOException ioe) { 162 errln("Error reading: " + ioe); 163 } 164 } 165 166 public void verify(AttributedCharacterIterator iterator,Hashtable table) { 167 int length = Integer.parseInt((String)table.get("length")); 168 169 // Verify the text 170 if (!getText(iterator).equals( 171 escapeIfNecessary((String)table.get("text")))) { 172 String text = getText(iterator); 173 174 errln("text doesn't match, got: " + getText(iterator)); 175 } 176 if (iterator.getBeginIndex() != 0) { 177 errln("Bogus start: " + iterator.getBeginIndex()); 178 } 179 if (iterator.getEndIndex() != length) { 180 errln("Bogus end: " + iterator.getEndIndex()); 181 } 182 for (int counter = 0; counter < length; counter++) { 183 iterator.setIndex(counter); 184 if (!verifyAttributes(iterator.getAttributes().keySet(), 185 makeAttributes((Vector)table.get(Integer. 186 toString(counter))))) { 187 errln("Attributes don't match at " + counter + " expecting " + 188 makeAttributes((Vector)table.get(Integer.toString 189 (counter))) + " got " + 190 iterator.getAttributes().keySet()); 191 } 192 } 193 for (int counter = length - 1; counter >= 0; counter--) { 194 iterator.setIndex(counter); 195 if (!verifyAttributes(iterator.getAttributes().keySet(), 196 makeAttributes((Vector)table.get(Integer. 197 toString(counter))))) { 198 errln("Attributes don't match at " + counter + " expecting " + 199 makeAttributes((Vector)table.get(Integer.toString 200 (counter))) + " got " + 201 iterator.getAttributes().keySet()); 202 } 203 } 204 verifyLimits(iterator, table); 205 206 text = escapeIfNecessary((String)table.get("text")); 207 Vector fps = (Vector)table.get("fieldPositions"); 208 209 if (fps != null) { 210 for (int counter = 0; counter < fps.size(); counter++) { 211 verifyFieldPosition(counter, (Hashtable)fps.get(counter)); 212 } 213 } 214 } 215 216 private void verifyLimits(AttributedCharacterIterator iterator, 217 Hashtable table) { 218 Vector limits = (Vector)table.get("limits"); 219 220 if (limits != null) { 221 for (int counter = 0; counter < limits.size(); counter++) { 222 verifyLimit(iterator, (Hashtable)limits.get(counter)); 223 } 224 } 225 } 226 227 private void verifyLimit(AttributedCharacterIterator iterator, 228 Hashtable table) { 229 int begin = Integer.parseInt((String)table.get("begin")); 230 int end = Integer.parseInt((String)table.get("end")); 231 Set attrs = makeAttributes((Vector)table.get("attributes")); 232 String begin2S = (String)table.get("begin2"); 233 int begin2 = (begin2S != null) ? Integer.parseInt(begin2S) : begin; 234 String end2S = (String)table.get("end2"); 235 int end2 = (end2S != null) ? Integer.parseInt(end2S) : end; 236 237 for (int counter = begin; counter < end; counter++) { 238 iterator.setIndex(counter); 239 if (iterator.getRunStart() != begin) { 240 errln("Begin doesn't match want " + begin + " got " + 241 iterator.getRunStart() + " at " + counter + " attrs " + 242 attrs); 243 } 244 if (iterator.getRunStart(attrs) != begin2) { 245 errln("Begin2 doesn't match want " + begin2 + " got " + 246 iterator.getRunStart(attrs) + " at " + counter + 247 " attrs " + attrs); 248 } 249 if (iterator.getRunLimit() != end) { 250 errln("End doesn't match want " + end + " got " + 251 iterator.getRunLimit() + " at " + counter + " attrs " + 252 attrs); 253 } 254 if (iterator.getRunLimit(attrs) != end2) { 255 errln("End2 doesn't match want " + end2 + " got " + 256 iterator.getRunLimit(attrs) + " at " + counter + 257 " attrs " + attrs); 258 } 259 } 260 } 261 262 private boolean verifyAttributes(Set a, Set b) { 263 boolean aEmpty = (a.size() == 0); 264 boolean bEmpty = (b.size() == 0); 265 266 if (aEmpty && bEmpty) { 267 return true; 268 } 269 else if (aEmpty || bEmpty) { 270 return false; 271 } 272 return a.equals(b); 273 } 274 275 private String getText(AttributedCharacterIterator iterator) { 276 StringBuffer buffer = new StringBuffer(); 277 278 for (int counter = 0; counter < iterator.getEndIndex(); counter++) { 279 buffer.append(iterator.setIndex(counter)); 280 } 281 return buffer.toString(); 282 } 283 284 private void verifyFieldPosition(int index, Hashtable table) { 285 Object o = table.get("field"); 286 int begin = Integer.parseInt((String)table.get("begin")); 287 int end = Integer.parseInt((String)table.get("end")); 288 289 if (o != null) { 290 FieldPosition fp = new FieldPosition(((Integer) 291 lookupField((String)o)).intValue()); 292 293 verifyFieldPosition(fp, begin, end, index); 294 } 295 o = table.get("fieldID"); 296 if (o != null) { 297 FieldPosition fp = new FieldPosition((Format.Field) 298 lookupField((String)o)); 299 verifyFieldPosition(fp, begin, end, index); 300 } 301 } 302 303 private void verifyFieldPosition(FieldPosition fp, int begin, int end, 304 int index) { 305 StringBuffer buffer = new StringBuffer(); 306 307 format.format(value, buffer, fp); 308 if (fp.getBeginIndex() != begin) { 309 errln("bogus begin want " + begin + " got " + fp.getBeginIndex() + 310 " for " + fp + " at " + index); 311 } 312 if (fp.getEndIndex() != end) { 313 errln("bogus end want " + end + " got " + fp.getEndIndex() + 314 " for " + fp + " at " + index); 315 } 316 if (!buffer.toString().equals(text)) { 317 errln("Text does not match, want !" + buffer.toString() + 318 "! got !" + text + "!"); 319 } 320 } 321 322 public AttributedCharacterIterator create(Hashtable table) { 323 format = (Format)createInstance((String)table.get("class"), 324 ((Vector)table.get("args")).toArray()); 325 value = createInstance((String)table.get("valueClass"), 326 ((Vector)table.get("valueArgs")).toArray()); 327 328 logln("Created format: " + format + " value " + value); 329 AttributedCharacterIterator aci = format. 330 formatToCharacterIterator(value); 331 332 logln("Obtained Iterator: " + aci); 333 return aci; 334 } 335 336 public Format.Field makeAttribute(String name) { 337 return (Format.Field)lookupField(name); 338 } 339 340 private Object createInstance(String className, Object[] args) { 341 if (className.equals("java.lang.reflect.Array")) { 342 for (int counter = 0; counter < args.length; counter++) { 343 if (args[counter] instanceof Vector) { 344 Vector v = (Vector)args[counter]; 345 346 args[counter] = createInstance((String)v.get(0), 347 ((Vector)v.get(1)).toArray()); 348 } 349 } 350 return args; 351 } 352 for (int counter = 0; counter < args.length; counter++) { 353 args[counter] = escapeIfNecessary((String)args[counter]); 354 } 355 try { 356 if (className.equals("java.util.concurrent.atomic.AtomicInteger")) { 357 return new AtomicInteger(Integer.valueOf((String)args[0])); 358 } else if (className.equals("java.util.concurrent.atomic.AtomicLong")) { 359 return new AtomicLong(Long.valueOf((String)args[0])); 360 } else { 361 Class klass = lookupClass(className); 362 Constructor cons = klass.getConstructor( 363 new Class[] { String.class }); 364 Object value = cons.newInstance(args); 365 366 return value; 367 } 368 } catch (Throwable th) { 369 errln("Error creating instance " + th); 370 return null; 371 } 372 } 373 374 private Class lookupClass(String name) throws ClassNotFoundException { 375 try { 376 Class klass = Class.forName(name); 377 378 return klass; 379 } catch (ClassNotFoundException e1) {} 380 381 try { 382 Class klass = Class.forName("java.lang." + name); 383 384 return klass; 385 } catch (ClassNotFoundException e1) {} 386 387 Class klass = Class.forName("java.text." + name); 388 389 return klass; 390 } 391 392 private Object lookupField(String name) { 393 Throwable error = null; 394 395 try { 396 int dotIndex = name.indexOf('.'); 397 Class klass = lookupClass(name.substring(0, dotIndex)); 398 String fieldName = name.substring(dotIndex + 1); 399 Field[] fields = klass.getFields(); 400 401 for (int counter = fields.length - 1; counter >= 0; counter--) { 402 if (fields[counter].getName().equals(fieldName)) { 403 return fields[counter].get(null); 404 } 405 } 406 } catch (Throwable th) { 407 error = th; 408 } 409 errln("Could not lookup field " + name + " " + error); 410 return null; 411 } 412 413 protected String escapeIfNecessary(String string) { 414 if (string != null) { 415 int index; 416 417 if ((index = string.indexOf("\\u")) != -1) { 418 StringBuffer sb = new StringBuffer(string.substring(0, index)); 419 420 sb.append((char)Integer.parseInt( 421 string.substring(index + 2, index + 6), 16)); 422 sb.append(string.substring(index + 6)); 423 string = sb.toString(); 424 } 425 } 426 return string; 427 } 428 429 public Set makeAttributes(Vector names) { 430 HashSet set = new HashSet(Math.max(1, names.size())); 431 432 for (int counter = 0; counter < names.size(); counter++) { 433 set.add(makeAttribute((String)names.get(counter))); 434 } 435 return set; 436 } 437 }