1/* 2 ******************************************************************************* 3 * Copyright (C) 1996-2015, International Business Machines Corporation and 4 * others. All Rights Reserved. 5 ******************************************************************************* 6 * 7 */ 8 9package com.ibm.icu.dev.test.serializable; 10 11import java.io.ByteArrayInputStream; 12import java.io.ByteArrayOutputStream; 13import java.io.File; 14import java.io.FileInputStream; 15import java.io.FileNotFoundException; 16import java.io.IOException; 17import java.io.InputStream; 18import java.io.ObjectInputStream; 19import java.net.JarURLConnection; 20import java.net.URL; 21import java.util.Enumeration; 22import java.util.MissingResourceException; 23import java.util.jar.JarEntry; 24import java.util.jar.JarFile; 25 26import com.ibm.icu.dev.test.TestFmwk; 27 28/** 29 * @author emader 30 */ 31public class CompatibilityTest extends TestFmwk 32{ 33 public class FolderTarget extends Target 34 { 35 private Target head = new Target(null); 36 private Target tail = head; 37 38 public FolderTarget(String name) 39 { 40 super(name); 41 } 42 43 public void add(String className, InputStream is) 44 { 45 HandlerTarget newTarget = new HandlerTarget(className, is); 46 47 tail.setNext(newTarget); 48 tail = newTarget; 49 } 50 51 protected boolean validate() 52 { 53 return true; 54 } 55 56 protected void execute() throws Exception 57 { 58 params.indentLevel += 1; 59 60 for (Target target = head.getNext(); target != null; target = target.getNext()) 61 { 62 target.run(); 63 } 64 65 params.indentLevel -= 1; 66 } 67 } 68 69 public class HandlerTarget extends Target 70 { 71 protected SerializableTest.Handler handler = null; 72 protected InputStream inputStream = null; 73 74 public HandlerTarget(String name, InputStream is) 75 { 76 super(name); 77 inputStream = is; 78 } 79 80 protected boolean validate() 81 { 82 handler = SerializableTest.getHandler(name); 83 84 return handler != null; 85 } 86 87 protected void execute() throws Exception 88 { 89 try { 90 if (params.inDocMode()) { 91 // nothing to execute 92 } else if (!params.stack.included) { 93 ++params.invalidCount; 94 } else { 95 params.testCount += 1; 96 97 try { 98 ObjectInputStream in = new ObjectInputStream(inputStream); 99 Object inputObjects[] = (Object[]) in.readObject(); 100 Object testObjects[] = handler.getTestObjects(); 101 102 in.close(); 103 inputStream.close(); 104 105 // TODO: add equality test... 106 // The commented out code below does that, 107 // but some test objects don't define an equals() method, 108 // and the default method is the same as the "==" operator... 109 for (int i = 0; i < testObjects.length; i += 1) { 110 // if (! inputObjects[i].equals(testObjects[i])) { 111 // errln("Input object " + i + " failed equality test."); 112 // } 113 114 if (!handler.hasSameBehavior(inputObjects[i], testObjects[i])) { 115 warnln("Input object " + i + " failed behavior test."); 116 } 117 } 118 } catch (MissingResourceException e) { 119 warnln("Could not load the data. " + e.getMessage()); 120 } catch (Exception e) { 121 e.printStackTrace(); 122 errln("Exception: " + e.toString()); 123 } 124 } 125 } finally { 126 inputStream.close(); 127 inputStream = null; 128 } 129 } 130 } 131 132 private static final String[][] SKIP_CASES = { 133 // ICU 52+ PluralRules/PluralFormat/CurrencyPluralInfo are not 134 // serialization-compatible with previous versions. 135 {"ICU_50.1", "com.ibm.icu.text.CurrencyPluralInfo.dat"}, 136 {"ICU_51.1", "com.ibm.icu.text.CurrencyPluralInfo.dat"}, 137 138 {"ICU_50.1", "com.ibm.icu.text.PluralFormat.dat"}, 139 {"ICU_51.1", "com.ibm.icu.text.PluralFormat.dat"}, 140 141 {"ICU_50.1", "com.ibm.icu.text.PluralRules.dat"}, 142 {"ICU_51.1", "com.ibm.icu.text.PluralRules.dat"}, 143 144 // GeneralMeasureFormat was in technical preview, but is going away after ICU 52.1. 145 {"ICU_52.1", "com.ibm.icu.text.GeneralMeasureFormat.dat"}, 146 147 // RuleBasedNumberFormat 148 {"ICU_3.6", "com.ibm.icu.text.RuleBasedNumberFormat.dat"}, 149 150 // ICU 4.8+ MessageFormat is not serialization-compatible with previous versions. 151 {"ICU_3.6", "com.ibm.icu.text.MessageFormat.dat"}, 152 }; 153 154 private Target getFileTargets(URL fileURL) 155 { 156 File topDir = new File(fileURL.getPath()); 157 File dataDirs[] = topDir.listFiles(); 158 FolderTarget target = null; 159 160 for (int d = 0; d < dataDirs.length; d += 1) { 161 File dataDir = dataDirs[d]; 162 163 if (dataDir.isDirectory()) { 164 FolderTarget newTarget = new FolderTarget(dataDir.getName()); 165 File files[] = dataDir.listFiles(); 166 167 newTarget.setNext(target); 168 target = newTarget; 169 170 String dataDirName = dataDir.getName(); 171 172 element_loop: 173 for (int i = 0; i < files.length; i += 1) { 174 File file = files[i]; 175 String filename = file.getName(); 176 int ix = filename.indexOf(".dat"); 177 178 if (ix > 0) { 179 String className = filename.substring(0, ix); 180 181 // Skip some cases which do not work well 182 for (int j = 0; j < SKIP_CASES.length; j++) { 183 if (dataDirName.equals(SKIP_CASES[j][0]) && filename.equals(SKIP_CASES[j][1])) { 184 logln("Skipping test case - " + dataDirName + "/" + className); 185 continue element_loop; 186 } 187 } 188 189 try { 190 @SuppressWarnings("resource") // Closed by HandlerTarget.execute(). 191 InputStream is = new FileInputStream(file); 192 target.add(className, is); 193 } catch (FileNotFoundException e) { 194 errln("Exception: " + e.toString()); 195 } 196 197 } 198 } 199 } 200 } 201 202 return target; 203 } 204 205 private static InputStream copyInputStream(InputStream in) throws IOException { 206 try { 207 ByteArrayOutputStream out = new ByteArrayOutputStream(); 208 byte[] buf = new byte[1024]; 209 while (true) { 210 int r = in.read(buf); 211 if (r == -1) { 212 break; 213 } 214 out.write(buf, 0, r); 215 } 216 return new ByteArrayInputStream(out.toByteArray()); 217 } finally { 218 in.close(); 219 } 220 } 221 222 private Target getJarTargets(URL jarURL) 223 { 224 String prefix = jarURL.getPath(); 225 String currentDir = null; 226 int ix = prefix.indexOf("!/"); 227 FolderTarget target = null; 228 229 if (ix >= 0) { 230 prefix = prefix.substring(ix + 2); 231 } 232 233 try { 234 JarURLConnection conn = (JarURLConnection) jarURL.openConnection(); 235 JarFile jarFile = conn.getJarFile(); 236 try { 237 Enumeration entries = jarFile.entries(); 238element_loop: 239 while (entries.hasMoreElements()) { 240 JarEntry entry = (JarEntry) entries.nextElement(); 241 String name = entry.getName(); 242 243 if (name.startsWith(prefix)) { 244 name = name.substring(prefix.length()); 245 246 if (!entry.isDirectory()) { 247 int dx = name.lastIndexOf("/"); 248 String dirName = name.substring(1, dx); 249 String filename = name.substring(dx + 1); 250 251 if (!dirName.equals(currentDir)) { 252 currentDir = dirName; 253 254 FolderTarget newTarget = new FolderTarget(currentDir); 255 256 newTarget.setNext(target); 257 target = newTarget; 258 } 259 260 int xx = filename.indexOf(".dat"); 261 262 if (xx > 0) { 263 String className = filename.substring(0, xx); 264 265 // Skip some cases which do not work well 266 for (int i = 0; i < SKIP_CASES.length; i++) { 267 if (dirName.equals(SKIP_CASES[i][0]) && filename.equals(SKIP_CASES[i][1])) { 268 logln("Skipping test case - " + dirName + "/" + className); 269 continue element_loop; 270 } 271 } 272 273 // The InputStream object returned by JarFile.getInputStream() will 274 // no longer be useable after JarFile.close() has been called. It's 275 // therefore necessary to make a copy of it here. 276 target.add(className, copyInputStream(jarFile.getInputStream(entry))); 277 } 278 } 279 } 280 } 281 } finally { 282 jarFile.close(); 283 } 284 } catch (Exception e) { 285 errln("jar error: " + e.getMessage()); 286 } 287 288 return target; 289 } 290 291 protected Target getTargets(String targetName) 292 { 293 URL dataURL = getClass().getResource("data"); 294 String protocol = dataURL.getProtocol(); 295 296 if (protocol.equals("jar")) { 297 return getJarTargets(dataURL); 298 } else if (protocol.equals("file")) { 299 return getFileTargets(dataURL); 300 } else { 301 errln("Don't know how to test " + dataURL); 302 return null; 303 } 304 } 305 306 public static void main(String[] args) 307 { 308 CompatibilityTest test = new CompatibilityTest(); 309 310 test.run(args); 311 } 312} 313