blob: 9af35422729b4a2e311dbe1d3b9c25216cb381af [file] [log] [blame]
// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
/*
*******************************************************************************
* Copyright (C) 1996-2015, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*
*/
package com.ibm.icu.dev.test.serializable;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.junit.Test;
import org.junit.runner.RunWith;
import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.dev.test.serializable.SerializableTestUtility.Handler;
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
/**
* @author sgill
* @author emader
*/
@RunWith(JUnitParamsRunner.class)
public class CompatibilityTest extends TestFmwk
{
private static final class FileHolder {
String className;
String icuVersion;
byte[] b;
boolean skip;
FileHolder(String fileName, byte[] b) {
this.b = b;
// Replace '\' with '/' to normalize fileName before extracting
// substrings. This is required if serialization test data is
// loaded from Windows file system.
String tmpPath = fileName.replaceAll("\\\\", "/");
int fileBreak = tmpPath.lastIndexOf('/');
this.className = fileName.substring(fileBreak + 1, tmpPath.lastIndexOf('.'));
int finalDirBreak = tmpPath.lastIndexOf("/ICU");
this.icuVersion = tmpPath.substring(finalDirBreak + 1, fileBreak);
className = className.substring(className.lastIndexOf('/') + 1);
this.skip = skipFile(this.icuVersion, this.className);
}
private static boolean skipFile(String icuVersion, String className) {
for (int skip = 0; skip < SKIP_CASES.length; skip++) {
if (icuVersion.equals(SKIP_CASES[skip][0]) && className.equals(SKIP_CASES[skip][1])) {
return true;
}
}
return false;
}
@Override
public String toString() {
return icuVersion + "[" + className + "]";
}
}
@Test
@Parameters(method="generateClassList")
public void testCompatibility(FileHolder holder) throws ClassNotFoundException, IOException {
if (holder.skip) {
logln("Skipping File = " + holder);
return;
}
Object[] oldObjects = SerializableTestUtility.getSerializedObjects(holder.b);
Handler classHandler = SerializableTestUtility.getHandler(holder.className);
Object[] testObjects = classHandler.getTestObjects();
for (int i = 0; i < testObjects.length; i++) {
if (!classHandler.hasSameBehavior(oldObjects[i], testObjects[i])) {
errln("Input object " + i + " failed behavior test.");
}
}
}
@SuppressWarnings("unused")
private List<FileHolder> generateClassList() throws IOException {
URL dataURL = getClass().getResource("data");
String protocol = dataURL.getProtocol();
if (protocol.equals("jar")) {
return getJarList(dataURL);
} else if (protocol.equals("file")) {
return getFileList(dataURL);
} else {
errln("Don't know how to test " + dataURL);
return null;
}
}
private List<FileHolder> getFileList(URL dataURL) throws IOException {
List<FileHolder> classList = new ArrayList();
File topDir = new File(dataURL.getPath());
File dataDirs[] = topDir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.isDirectory();
}});
for (File dataDir : dataDirs) {
File files[] = dataDir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.isFile() && pathname.getName().endsWith(".dat");
}});
for (File file : files) {
FileInputStream fis = new FileInputStream(file);
byte[] fileBytes;
try {
fileBytes = SerializableTestUtility.copyStreamBytes(fis);
} finally {
fis.close();
}
classList.add(new FileHolder(file.getAbsolutePath(), fileBytes));
}
}
return classList;
}
private List<FileHolder> getJarList(URL jarURL) throws IOException {
List<FileHolder> classList = new ArrayList();
String prefix = jarURL.getPath();
int ix = prefix.indexOf("!/");
if (ix >= 0) {
prefix = prefix.substring(ix + 2);
}
JarFile jarFile = null;
try {
String urlAsString = jarURL.toExternalForm();
ix = urlAsString.indexOf("!/");
jarURL = new URL(urlAsString.substring(0, ix + 2));
JarURLConnection conn = (JarURLConnection) jarURL.openConnection();
jarFile = conn.getJarFile();
Enumeration entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = (JarEntry) entries.nextElement();
if (!entry.isDirectory()) {
String entryName = entry.getName();
if (entryName.startsWith(prefix) && entryName.endsWith(".dat")) {
FileHolder holder = new FileHolder(entryName,
SerializableTestUtility.copyStreamBytes(jarFile.getInputStream(entry)));
classList.add(holder);
}
}
}
} finally {
if (jarFile != null) {
jarFile.close();
}
}
return classList;
}
private static final String[][] SKIP_CASES = {
// ICU 52+ PluralRules/PluralFormat/CurrencyPluralInfo are not
// serialization-compatible with previous versions.
{"ICU_50.1", "com.ibm.icu.text.CurrencyPluralInfo"},
{"ICU_51.1", "com.ibm.icu.text.CurrencyPluralInfo"},
{"ICU_50.1", "com.ibm.icu.text.PluralFormat"},
{"ICU_51.1", "com.ibm.icu.text.PluralFormat"},
{"ICU_50.1", "com.ibm.icu.text.PluralRules"},
{"ICU_51.1", "com.ibm.icu.text.PluralRules"},
// GeneralMeasureFormat was in technical preview, but is going away after ICU 52.1.
{"ICU_52.1", "com.ibm.icu.text.GeneralMeasureFormat"},
// RuleBasedNumberFormat
{"ICU_3.6", "com.ibm.icu.text.RuleBasedNumberFormat"},
// ICU 4.8+ MessageFormat is not serialization-compatible with previous versions.
{"ICU_3.6", "com.ibm.icu.text.MessageFormat"},
};
}