blob: 773439770104f0d056879c4cf81d5c56725ba129 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
17package android.core;
18
19import junit.framework.Assert;
20import junit.framework.TestCase;
21
22import java.io.File;
23import java.io.InputStream;
24import java.io.ObjectInputStream;
25import java.lang.reflect.Field;
26import java.lang.reflect.Method;
27import java.security.KeyStore;
28import java.security.cert.Certificate;
29import java.util.Arrays;
30import java.util.ConcurrentModificationException;
31import java.util.Enumeration;
32import java.util.Iterator;
33import java.util.LinkedHashMap;
34import java.util.Random;
35import java.util.jar.JarEntry;
36import java.util.jar.JarFile;
37import java.util.logging.Logger;
38import java.util.zip.Deflater;
39import java.util.zip.Inflater;
40import java.util.zip.ZipEntry;
41import java.util.zip.ZipFile;
42import android.test.suitebuilder.annotation.MediumTest;
43import android.test.suitebuilder.annotation.SmallTest;
44import android.test.suitebuilder.annotation.LargeTest;
45
46public 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069 // 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
Brian Carlstrom778ce482010-02-09 11:23:40 -080082 // 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092 // 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}