Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.core;
     18 
     19 import junit.framework.Assert;
     20 import junit.framework.TestCase;
     21 
     22 import java.io.File;
     23 import java.io.InputStream;
     24 import java.io.ObjectInputStream;
     25 import java.lang.reflect.Field;
     26 import java.lang.reflect.Method;
     27 import java.security.KeyStore;
     28 import java.security.cert.Certificate;
     29 import java.util.Arrays;
     30 import java.util.ConcurrentModificationException;
     31 import java.util.Enumeration;
     32 import java.util.Iterator;
     33 import java.util.LinkedHashMap;
     34 import java.util.Random;
     35 import java.util.jar.JarEntry;
     36 import java.util.jar.JarFile;
     37 import java.util.logging.Logger;
     38 import java.util.zip.Deflater;
     39 import java.util.zip.Inflater;
     40 import java.util.zip.ZipEntry;
     41 import java.util.zip.ZipFile;
     42 import android.test.suitebuilder.annotation.MediumTest;
     43 import android.test.suitebuilder.annotation.SmallTest;
     44 import android.test.suitebuilder.annotation.LargeTest;
     45 
     46 public class MiscRegressionTest extends TestCase {
     47 
     48     // Regression test for #857840: want JKS key store
     49     @SmallTest
     50     public void testDefaultKeystore() {
     51         String type = KeyStore.getDefaultType();
     52         Assert.assertEquals("Default keystore type must be Bouncy Castle", "BKS", type);
     53 
     54         try {
     55             KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType());
     56             Assert.assertNotNull("Keystore must not be null", store);
     57         } catch (Exception ex) {
     58             throw new RuntimeException(ex);
     59         }
     60 
     61         try {
     62             KeyStore store = KeyStore.getInstance("BKS");
     63             Assert.assertNotNull("Keystore must not be null", store);
     64         } catch (Exception ex) {
     65             throw new RuntimeException(ex);
     66         }
     67     }
     68 
     69     // Regression test for #951285: Suitable LogHandler should be chosen
     70     // depending on the environment.
     71     @MediumTest
     72     public void testAndroidLogHandler() throws Exception {
     73         Logger.global.severe("This has logging Level.SEVERE, should become ERROR");
     74         Logger.global.warning("This has logging Level.WARNING, should become WARN");
     75         Logger.global.info("This has logging Level.INFO, should become INFO");
     76         Logger.global.config("This has logging Level.CONFIG, should become DEBUG");
     77         Logger.global.fine("This has logging Level.FINE, should become VERBOSE");
     78         Logger.global.finer("This has logging Level.FINER, should become VERBOSE");
     79         Logger.global.finest("This has logging Level.FINEST, should become VERBOSE");
     80     }
     81 
     82     // Regression test for Issue 5697:
     83     // getContextClassLoader returns a non-application classloader
     84     // http://code.google.com/p/android/issues/detail?id=5697
     85     //
     86     @MediumTest
     87     public void testJavaContextClassLoader() throws Exception {
     88         Assert.assertNotNull("Must hava a Java context ClassLoader",
     89                              Thread.currentThread().getContextClassLoader());
     90     }
     91 
     92     // Regression test for #1045939: Different output for Method.toString()
     93     @SmallTest
     94     public void testMethodToString() {
     95         try {
     96             Method m1 = Object.class.getMethod("notify", new Class[] { });
     97             Method m2 = Object.class.getMethod("toString", new Class[] { });
     98             Method m3 = Object.class.getMethod("wait", new Class[] { long.class, int.class });
     99             Method m4 = Object.class.getMethod("equals", new Class[] { Object.class });
    100             Method m5 = String.class.getMethod("valueOf", new Class[] { char[].class });
    101             Method m6 = Runtime.class.getMethod("exec", new Class[] { String[].class });
    102 
    103             assertEquals("Method.toString() must match expectations",
    104                     "public final native void java.lang.Object.notify()",
    105                     m1.toString());
    106 
    107             assertEquals("Method.toString() must match expectations",
    108                     "public java.lang.String java.lang.Object.toString()",
    109                     m2.toString());
    110 
    111             assertEquals("Method.toString() must match expectations",
    112                     "public final native void java.lang.Object.wait(long,int) throws java.lang.InterruptedException",
    113                     m3.toString());
    114 
    115             assertEquals("Method.toString() must match expectations",
    116                     "public boolean java.lang.Object.equals(java.lang.Object)",
    117                     m4.toString());
    118 
    119             assertEquals("Method.toString() must match expectations",
    120                     "public static java.lang.String java.lang.String.valueOf(char[])",
    121                     m5.toString());
    122 
    123             assertEquals("Method.toString() must match expectations",
    124                     "public java.lang.Process java.lang.Runtime.exec(java.lang.String[]) throws java.io.IOException",
    125                     m6.toString());
    126 
    127         } catch (Exception ex) {
    128             throw new RuntimeException(ex);
    129         }
    130 
    131     }
    132 
    133     // Regression test for #1062200: Enum fails to deserialize. Actual problem
    134     // was that Class.isEnum() erroneously returned true for indirect
    135     // descendants of Enum.
    136     enum TrafficLights {
    137         RED,
    138         YELLOW {},
    139         GREEN {
    140             @SuppressWarnings("unused")
    141             int i;
    142             @SuppressWarnings("unused")
    143             void foobar() {}
    144         };
    145     }
    146 
    147     @SmallTest
    148     public void testClassIsEnum() {
    149         Class<?> trafficClass = TrafficLights.class;
    150 
    151         Class<?> redClass = TrafficLights.RED.getClass();
    152         Class<?> yellowClass = TrafficLights.YELLOW.getClass();
    153         Class<?> greenClass = TrafficLights.GREEN.getClass();
    154 
    155         Assert.assertSame("Classes must be equal", trafficClass, redClass);
    156         Assert.assertNotSame("Classes must be different", trafficClass, yellowClass);
    157         Assert.assertNotSame("Classes must be different", trafficClass, greenClass);
    158         Assert.assertNotSame("Classes must be different", yellowClass, greenClass);
    159 
    160         Assert.assertTrue("Must be an enum", trafficClass.isEnum());
    161         Assert.assertTrue("Must be an enum", redClass.isEnum());
    162         Assert.assertFalse("Must not be an enum", yellowClass.isEnum());
    163         Assert.assertFalse("Must not be an enum", greenClass.isEnum());
    164 
    165         Assert.assertNotNull("Must have enum constants", trafficClass.getEnumConstants());
    166         Assert.assertNull("Must not have enum constants", yellowClass.getEnumConstants());
    167         Assert.assertNull("Must not have enum constants", greenClass.getEnumConstants());
    168     }
    169 
    170     // Regression test for #1046174: JarEntry.getCertificates() is really slow.
    171     public void checkJarCertificates(File file) {
    172         try {
    173             JarFile jarFile = new JarFile(file);
    174             JarEntry je = jarFile.getJarEntry("AndroidManifest.xml");
    175             byte[] readBuffer = new byte[1024];
    176 
    177             long t0 = System.currentTimeMillis();
    178 
    179             // We must read the stream for the JarEntry to retrieve
    180             // its certificates.
    181             InputStream is = jarFile.getInputStream(je);
    182             while (is.read(readBuffer, 0, readBuffer.length) != -1) {
    183                 // not using
    184             }
    185             is.close();
    186             Certificate[] certs = je != null ? je.getCertificates() : null;
    187 
    188             long t1 = System.currentTimeMillis();
    189             android.util.Log.d("TestHarness", "loadCertificates() took " + (t1 - t0) + " ms");
    190             if (certs == null) {
    191                 android.util.Log.d("TestHarness", "We have no certificates");
    192             } else {
    193                 android.util.Log.d("TestHarness", "We have " + certs.length + " certificates");
    194             }
    195         } catch (Exception ex) {
    196             throw new RuntimeException(ex);
    197         }
    198     }
    199 
    200     @LargeTest
    201     public void testJarCertificates() {
    202         File[] files = new File("/system/app").listFiles();
    203         for (int i = 0; i < files.length; i++) {
    204             checkJarCertificates(files[i]);
    205         }
    206     }
    207 
    208     // Regression test for #1120750: Reflection for static long fields is broken
    209     private static final long MY_LONG = 5073258162644648461L;
    210 
    211     @SmallTest
    212     public void testLongFieldReflection() {
    213         try {
    214             Field field = getClass().getDeclaredField("MY_LONG");
    215             assertEquals(5073258162644648461L, field.getLong(null));
    216         } catch (Exception ex) {
    217             throw new RuntimeException(ex);
    218         }
    219     }
    220 
    221     // Regression test for Harmony LinkedHashMap bug. Copied from core, just
    222     // to make sure it doesn't get lost.
    223     @SmallTest
    224     public void testLinkedHashMap() {
    225         // we want to test the LinkedHashMap in access ordering mode.
    226         LinkedHashMap map = new LinkedHashMap<String, String>(10, 0.75f, true);
    227 
    228         map.put("key1", "value1");
    229         map.put("key2", "value2");
    230         map.put("key3", "value3");
    231 
    232         Iterator iterator = map.keySet().iterator();
    233         String id = (String) iterator.next();
    234         map.get(id);
    235         try {
    236             iterator.next();
    237             // A LinkedHashMap is supposed to throw this Exception when a
    238             // iterator.next() Operation takes place after a get
    239             // Operation. This is because the get Operation is considered
    240             // a structural modification if the LinkedHashMap is in
    241             // access order mode.
    242             fail("expected ConcurrentModificationException was not thrown.");
    243         } catch(ConcurrentModificationException e) {
    244             // expected
    245         }
    246 
    247         LinkedHashMap mapClone = (LinkedHashMap) map.clone();
    248 
    249         iterator = map.keySet().iterator();
    250         id = (String) iterator.next();
    251         mapClone.get(id);
    252         try {
    253             iterator.next();
    254         } catch(ConcurrentModificationException e) {
    255             fail("expected ConcurrentModificationException was not thrown.");
    256         }
    257     }
    258 
    259     // Regression test for #1212257: Boot-time package scan is slow. Not
    260     // expected to fail. Please see log if you are interested in the results.
    261     @LargeTest
    262     public void testZipStressManifest() {
    263         android.util.Log.d("MiscRegressionTest", "ZIP stress test started");
    264 
    265         long time0 = System.currentTimeMillis();
    266 
    267         try {
    268             File[] files = new File("/system/app").listFiles();
    269 
    270             byte[] buffer = new byte[512];
    271 
    272             if (files != null) {
    273                 for (int i = 0; i < files.length; i++) {
    274                     android.util.Log.d("MiscRegressionTest",
    275                             "ZIP stress test processing " + files[i] + "...");
    276 
    277                     ZipFile zip = new ZipFile(files[i]);
    278 
    279                     ZipEntry entry = zip.getEntry("AndroidManifest.xml");
    280                     InputStream stream = zip.getInputStream(entry);
    281 
    282                     int j = stream.read(buffer);
    283                     while (j != -1) {
    284                         j = stream.read(buffer);
    285                     }
    286 
    287                     stream.close();
    288                 }
    289             }
    290         } catch (Exception ex) {
    291             throw new RuntimeException(ex);
    292         }
    293 
    294         long time1 = System.currentTimeMillis();
    295 
    296         android.util.Log.d("MiscRegressionTest", "ZIP stress test finished, " +
    297                 "time was " + (time1- time0) + "ms");
    298     }
    299 
    300     @LargeTest
    301     public void testZipStressAllFiles() {
    302         android.util.Log.d("MiscRegressionTest", "ZIP stress test started");
    303 
    304         long time0 = System.currentTimeMillis();
    305 
    306         try {
    307             File[] files = new File("/system/app").listFiles();
    308 
    309             byte[] buffer = new byte[512];
    310 
    311             if (files != null) {
    312                 for (int i = 0; i < files.length; i++) {
    313                     android.util.Log.d("MiscRegressionTest",
    314                             "ZIP stress test processing " + files[i] + "...");
    315 
    316                     ZipFile zip = new ZipFile(files[i]);
    317 
    318                     Enumeration<? extends ZipEntry> entries = zip.entries();
    319                     while (entries.hasMoreElements()) {
    320                         InputStream stream = zip.getInputStream(entries.nextElement());
    321 
    322                         int j = stream.read(buffer);
    323                         while (j != -1) {
    324                             j = stream.read(buffer);
    325                         }
    326 
    327                         stream.close();
    328                     }
    329                 }
    330             }
    331         } catch (Exception ex) {
    332             throw new RuntimeException(ex);
    333         }
    334 
    335         long time1 = System.currentTimeMillis();
    336 
    337         android.util.Log.d("MiscRegressionTest", "ZIP stress test finished, " +
    338                 "time was " + (time1- time0) + "ms");
    339     }
    340 
    341     @SmallTest
    342     public void testOsEncodingProperty() {
    343         long time0 = System.currentTimeMillis();
    344         String[] files = new File("/system/app").list();
    345         long time1 = System.currentTimeMillis();
    346         android.util.Log.d("MiscRegressionTest", "File.list() test finished, " +
    347                 "time was " + (time1- time0) + "ms");
    348     }
    349 
    350     // -------------------------------------------------------------------------
    351     // Regression test for #1185084: Native memory allocated by
    352     // java.util.zip.Deflater in system_server. The fix reduced some internal
    353     // ZLIB buffers in size, so this test is trying to execute a lot of
    354     // deflating to ensure that things are still working properly.
    355     private void assertEquals(byte[] a, byte[] b) {
    356         assertEquals("Arrays must have same length", a.length, b.length);
    357 
    358         for (int i = 0; i < a.length; i++) {
    359             assertEquals("Array elements #" + i + " must be equal", a[i], b[i]);
    360         }
    361     }
    362 
    363     @LargeTest
    364     public void testZipDeflateInflateStress() {
    365 
    366         final int DATA_SIZE = 16384;
    367 
    368         Random random = new Random(42); // Seed makes test reproducible
    369 
    370         try {
    371             // Outer loop selects "mode" of test.
    372             for (int j = 1; j <=2 ; j++) {
    373 
    374                 byte[] input = new byte[DATA_SIZE];
    375 
    376                 if (j == 1) {
    377                     // Totally random content
    378                     random.nextBytes(input);
    379                 } else {
    380                     // Random contents with longer repetitions
    381                     int pos = 0;
    382                     while (pos < input.length) {
    383                         byte what = (byte)random.nextInt(256);
    384                         int howMany = random.nextInt(32);
    385                         if (pos + howMany >= input.length) {
    386                             howMany = input.length - pos;
    387                         }
    388                         Arrays.fill(input, pos, pos + howMany, what);
    389                         pos += howMany;
    390                     }
    391                 }
    392 
    393                 // Inner loop tries all 9 compression levels.
    394                 for (int i = 1; i <= 9; i++) {
    395                     android.util.Log.d("MiscRegressionTest", "ZipDeflateInflateStress test (" + j + "," + i + ")...");
    396 
    397                     byte[] zipped = new byte[2 * DATA_SIZE]; // Just to make sure...
    398 
    399                     Deflater deflater = new Deflater(i);
    400                     deflater.setInput(input);
    401                     deflater.finish();
    402 
    403                     deflater.deflate(zipped);
    404 
    405                     byte[] output = new byte[DATA_SIZE];
    406 
    407                     Inflater inflater = new Inflater();
    408                     inflater.setInput(zipped);
    409                     inflater.finished();
    410 
    411                     inflater.inflate(output);
    412 
    413                     assertEquals(input, output);
    414                 }
    415             }
    416         } catch (Exception ex) {
    417             throw new RuntimeException(ex);
    418         }
    419     }
    420 
    421     // -------------------------------------------------------------------------
    422     // Regression test for #1252043: Thread.getStackTrace() is broken
    423     class MyThread extends Thread {
    424         public MyThread(String name) {
    425             super(name);
    426         }
    427 
    428         @Override
    429         public void run() {
    430             doSomething();
    431         }
    432 
    433         public void doSomething() {
    434             for (int i = 0; i < 20;) {
    435                 try {
    436                     Thread.sleep(100);
    437                 } catch (InterruptedException ex) {
    438                 }
    439             }
    440         }
    441     }
    442 
    443     class MyOtherThread extends Thread {
    444         public int visibleTraces;
    445 
    446         public MyOtherThread(ThreadGroup group, String name) {
    447             super(group, name);
    448         }
    449 
    450         @Override
    451         public void run() {
    452             visibleTraces = Thread.getAllStackTraces().size();
    453         }
    454     }
    455 
    456     @LargeTest
    457     public void testThreadGetStackTrace() {
    458         MyThread t1 = new MyThread("t1");
    459         t1.start();
    460 
    461         try {
    462             Thread.sleep(1000);
    463         } catch (InterruptedException ex) {
    464         }
    465 
    466         StackTraceElement[] traces = t1.getStackTrace();
    467         StackTraceElement trace = traces[traces.length - 2];
    468 
    469         // Expect to find MyThread.doSomething in the trace
    470         assertTrue("Must find MyThread.doSomething in trace",
    471                 trace.getClassName().endsWith("$MyThread") &&
    472                 trace.getMethodName().equals("doSomething"));
    473 
    474         ThreadGroup g1 = new ThreadGroup("1");
    475         MyOtherThread t2 = new MyOtherThread(g1, "t2");
    476         t2.start();
    477         try {
    478             t2.join();
    479         } catch (InterruptedException ex) {
    480         }
    481 
    482         // Expect to see the traces of all threads (not just t2)
    483         assertTrue("Must have traces for all threads", t2.visibleTraces > 1);
    484     }
    485 }
    486