Home | History | Annotate | Download | only in serializable
      1 /* GENERATED SOURCE. DO NOT MODIFY. */
      2 //  2016 and later: Unicode, Inc. and others.
      3 // License & terms of use: http://www.unicode.org/copyright.html#License
      4 /*
      5  *******************************************************************************
      6  * Copyright (C) 1996-2016, International Business Machines Corporation and
      7  * others. All Rights Reserved.
      8  *******************************************************************************
      9  *
     10  */
     11 
     12 package android.icu.dev.test.serializable;
     13 
     14 import java.io.File;
     15 import java.io.FileFilter;
     16 import java.io.FileInputStream;
     17 import java.io.IOException;
     18 import java.net.JarURLConnection;
     19 import java.net.MalformedURLException;
     20 import java.net.URL;
     21 import java.util.ArrayList;
     22 import java.util.Enumeration;
     23 import java.util.List;
     24 import java.util.jar.JarEntry;
     25 import java.util.jar.JarFile;
     26 
     27 import org.junit.Test;
     28 import org.junit.runner.RunWith;
     29 
     30 import android.icu.dev.test.TestFmwk;
     31 import android.icu.dev.test.serializable.SerializableTestUtility.Handler;
     32 
     33 import junitparams.JUnitParamsRunner;
     34 import junitparams.Parameters;
     35 
     36 /**
     37  * @author sgill
     38  * @author emader
     39  */
     40 @RunWith(JUnitParamsRunner.class)
     41 public class CompatibilityTest extends TestFmwk
     42 {
     43     private static final class FileHolder {
     44         String className;
     45         String icuVersion;
     46         byte[] b;
     47         boolean skip;
     48 
     49         FileHolder(String fileName, byte[] b) {
     50             this.b = b;
     51 
     52             // Replace '\' with '/' to normalize fileName before extracting
     53             // substrings. This is required if serialization test data is
     54             // loaded from Windows file system.
     55             String tmpPath = fileName.replaceAll("\\\\", "/");
     56 
     57             int fileBreak = tmpPath.lastIndexOf('/');
     58             this.className = fileName.substring(fileBreak + 1, tmpPath.lastIndexOf('.'));
     59             int finalDirBreak = tmpPath.lastIndexOf("/ICU");
     60             this.icuVersion = tmpPath.substring(finalDirBreak + 1, fileBreak);
     61             className = className.substring(className.lastIndexOf('/') + 1);
     62 
     63             this.skip = skipFile(this.icuVersion, this.className);
     64         }
     65 
     66         private static boolean skipFile(String icuVersion, String className) {
     67             for (int skip = 0; skip < SKIP_CASES.length; skip++) {
     68                 if (icuVersion.equals(SKIP_CASES[skip][0]) && className.equals(SKIP_CASES[skip][1])) {
     69                     return true;
     70                 }
     71             }
     72             return false;
     73         }
     74 
     75         @Override
     76         public String toString() {
     77             return icuVersion + "[" + className + "]";
     78         }
     79     }
     80 
     81     @Test
     82     @Parameters(method="generateClassList")
     83     public void testCompatibility(FileHolder holder) throws ClassNotFoundException, IOException {
     84         if (holder.skip) {
     85             logln("Skipping File = " + holder);
     86             return;
     87         }
     88 
     89         Object[] oldObjects = SerializableTestUtility.getSerializedObjects(holder.b);
     90         Handler classHandler = SerializableTestUtility.getHandler(holder.className);
     91 
     92         Object[] testObjects = classHandler.getTestObjects();
     93         for (int i = 0; i < testObjects.length; i++) {
     94             if (!classHandler.hasSameBehavior(oldObjects[i], testObjects[i])) {
     95                 errln("Input object " + i + " failed behavior test.");
     96             }
     97         }
     98     }
     99 
    100     /**
    101      * The path to an actual data resource file in the JAR. This is needed because when the
    102      * code is packaged for Android the resulting archive does not have entries for directories
    103      * and so only actual resources can be found.
    104      */
    105     private static final String ACTUAL_RESOURCE = "/ICU_3.6/android.icu.impl.OlsonTimeZone.dat";
    106 
    107     @SuppressWarnings("unused")
    108     private List<FileHolder> generateClassList() throws IOException {
    109         // Get the URL to an actual resource and then compute the URL to the directory just in
    110         // case the resources are in a JAR file that doesn't have entries for directories.
    111         URL dataURL = getClass().getResource("data" + ACTUAL_RESOURCE);
    112         try {
    113             dataURL = new URL(dataURL.toExternalForm().replace(ACTUAL_RESOURCE, ""));
    114         } catch (MalformedURLException e) {
    115             throw new RuntimeException(e);
    116         }
    117         String protocol = dataURL.getProtocol();
    118 
    119         if (protocol.equals("jar")) {
    120             return getJarList(dataURL);
    121         } else if (protocol.equals("file")) {
    122             return getFileList(dataURL);
    123         } else {
    124             errln("Don't know how to test " + dataURL);
    125             return null;
    126         }
    127     }
    128 
    129     private List<FileHolder> getFileList(URL dataURL) throws IOException {
    130         List<FileHolder> classList = new ArrayList();
    131 
    132         File topDir = new File(dataURL.getPath());
    133         File dataDirs[] = topDir.listFiles(new FileFilter() {
    134             @Override
    135             public boolean accept(File pathname) {
    136                 return pathname.isDirectory();
    137             }});
    138 
    139         for (File dataDir : dataDirs) {
    140             File files[] = dataDir.listFiles(new FileFilter() {
    141                 @Override
    142                 public boolean accept(File pathname) {
    143                     return pathname.isFile() && pathname.getName().endsWith(".dat");
    144                 }});
    145 
    146                 for (File file : files) {
    147                     FileInputStream fis = new FileInputStream(file);
    148                     byte[] fileBytes;
    149                     try {
    150                         fileBytes = SerializableTestUtility.copyStreamBytes(fis);
    151                     } finally {
    152                         fis.close();
    153                     }
    154                     classList.add(new FileHolder(file.getAbsolutePath(), fileBytes));
    155                 }
    156         }
    157         return classList;
    158     }
    159 
    160     private List<FileHolder> getJarList(URL jarURL) throws IOException {
    161         List<FileHolder> classList = new ArrayList();
    162 
    163         String prefix = jarURL.getPath();
    164         int ix = prefix.indexOf("!/");
    165         if (ix >= 0) {
    166             prefix = prefix.substring(ix + 2);
    167         }
    168 
    169         JarFile jarFile = null;
    170         try {
    171             // Need to trim the directory off the JAR entry before opening the connection otherwise
    172             // it could fail as it will try and find the entry within the JAR which may not exist.
    173             String urlAsString = jarURL.toExternalForm();
    174             ix = urlAsString.indexOf("!/");
    175             jarURL = new URL(urlAsString.substring(0, ix + 2));
    176 
    177             JarURLConnection conn = (JarURLConnection) jarURL.openConnection();
    178             jarFile = conn.getJarFile();
    179             Enumeration entries = jarFile.entries();
    180             while (entries.hasMoreElements()) {
    181                 JarEntry entry = (JarEntry) entries.nextElement();
    182                 if (!entry.isDirectory()) {
    183                     String entryName = entry.getName();
    184 
    185                     if (entryName.startsWith(prefix) && entryName.endsWith(".dat")) {
    186                         FileHolder holder = new FileHolder(entryName,
    187                                 SerializableTestUtility.copyStreamBytes(jarFile.getInputStream(entry)));
    188                         classList.add(holder);
    189 
    190                     }
    191                 }
    192             }
    193         } finally {
    194             if (jarFile != null) {
    195                 jarFile.close();
    196             }
    197         }
    198         return classList;
    199     }
    200 
    201     private static final String[][] SKIP_CASES = {
    202             // ICU 52+ PluralRules/PluralFormat/CurrencyPluralInfo are not
    203             // serialization-compatible with previous versions.
    204             {"ICU_50.1", "android.icu.text.CurrencyPluralInfo"},
    205             {"ICU_51.1", "android.icu.text.CurrencyPluralInfo"},
    206 
    207             {"ICU_50.1", "android.icu.text.PluralFormat"},
    208             {"ICU_51.1", "android.icu.text.PluralFormat"},
    209 
    210             {"ICU_50.1", "android.icu.text.PluralRules"},
    211             {"ICU_51.1", "android.icu.text.PluralRules"},
    212 
    213             // GeneralMeasureFormat was in technical preview, but is going away after ICU 52.1.
    214             {"ICU_52.1", "android.icu.text.GeneralMeasureFormat"},
    215 
    216             // RuleBasedNumberFormat
    217             {"ICU_3.6",     "android.icu.text.RuleBasedNumberFormat"},
    218 
    219             // ICU 4.8+ MessageFormat is not serialization-compatible with previous versions.
    220             {"ICU_3.6",     "android.icu.text.MessageFormat"},
    221     };
    222 }
    223