diff options
Diffstat (limited to 'luni/src/test')
76 files changed, 5485 insertions, 2027 deletions
diff --git a/luni/src/test/java/libcore/icu/ICUTest.java b/luni/src/test/java/libcore/icu/ICUTest.java index 9282167..a7e732c 100644 --- a/luni/src/test/java/libcore/icu/ICUTest.java +++ b/luni/src/test/java/libcore/icu/ICUTest.java @@ -53,4 +53,12 @@ public class ICUTest extends junit.framework.TestCase { assertEquals(new Locale("", "", "POSIX"), ICU.localeFromString("__POSIX")); assertEquals(new Locale("aa", "BB", "CC"), ICU.localeFromString("aa_BB_CC")); } + + public void test_getScript_addLikelySubtags() throws Exception { + assertEquals("Latn", ICU.getScript(ICU.addLikelySubtags("en_US"))); + assertEquals("Hebr", ICU.getScript(ICU.addLikelySubtags("he"))); + assertEquals("Hebr", ICU.getScript(ICU.addLikelySubtags("he_IL"))); + assertEquals("Hebr", ICU.getScript(ICU.addLikelySubtags("iw"))); + assertEquals("Hebr", ICU.getScript(ICU.addLikelySubtags("iw_IL"))); + } } diff --git a/luni/src/test/java/libcore/icu/LocaleDataTest.java b/luni/src/test/java/libcore/icu/LocaleDataTest.java new file mode 100644 index 0000000..e412a1d --- /dev/null +++ b/luni/src/test/java/libcore/icu/LocaleDataTest.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package libcore.icu; + +import java.util.Locale; + +public class LocaleDataTest extends junit.framework.TestCase { + public void testAll() throws Exception { + // Test that we can get the locale data for all known locales. + for (Locale l : Locale.getAvailableLocales()) { + LocaleData d = LocaleData.get(l); + System.err.println(l + " : " + d.yesterday + " " + d.today + " " + d.tomorrow); + } + } + + public void test_en_US() throws Exception { + LocaleData l = LocaleData.get(Locale.US); + assertEquals("AM", l.amPm[0]); + assertEquals("BC", l.eras[0]); + + assertEquals("January", l.longMonthNames[0]); + assertEquals("Jan", l.shortMonthNames[0]); + assertEquals("J", l.tinyMonthNames[0]); + + assertEquals("January", l.longStandAloneMonthNames[0]); + assertEquals("Jan", l.shortStandAloneMonthNames[0]); + assertEquals("J", l.tinyStandAloneMonthNames[0]); + + assertEquals("Sunday", l.longWeekdayNames[1]); + assertEquals("Sun", l.shortWeekdayNames[1]); + assertEquals("S", l.tinyWeekdayNames[1]); + + assertEquals("Sunday", l.longStandAloneWeekdayNames[1]); + assertEquals("Sun", l.shortStandAloneWeekdayNames[1]); + assertEquals("S", l.tinyStandAloneWeekdayNames[1]); + + assertEquals("Yesterday", l.yesterday); + assertEquals("Today", l.today); + assertEquals("Tomorrow", l.tomorrow); + } + + public void test_de_DE() throws Exception { + LocaleData l = LocaleData.get(new Locale("de", "DE")); + + assertEquals("Gestern", l.yesterday); + assertEquals("Heute", l.today); + assertEquals("Morgen", l.tomorrow); + } + + public void test_cs_CZ() throws Exception { + LocaleData l = LocaleData.get(new Locale("cs", "CZ")); + + assertEquals("ledna", l.longMonthNames[0]); + assertEquals("Led", l.shortMonthNames[0]); + assertEquals("1", l.tinyMonthNames[0]); + + assertEquals("leden", l.longStandAloneMonthNames[0]); + assertEquals("1.", l.shortStandAloneMonthNames[0]); + assertEquals("l", l.tinyStandAloneMonthNames[0]); + } + + public void test_ru_RU() throws Exception { + LocaleData l = LocaleData.get(new Locale("ru", "RU")); + + assertEquals("воскресенье", l.longWeekdayNames[1]); + assertEquals("вс", l.shortWeekdayNames[1]); + assertEquals("В", l.tinyWeekdayNames[1]); + + // Russian stand-alone weekday names get an initial capital. + assertEquals("Воскресенье", l.longStandAloneWeekdayNames[1]); + assertEquals("Вс", l.shortStandAloneWeekdayNames[1]); + assertEquals("В", l.tinyStandAloneWeekdayNames[1]); + } +} diff --git a/luni/src/test/java/libcore/io/DiskLruCacheTest.java b/luni/src/test/java/libcore/io/DiskLruCacheTest.java index 03a6932..2796b65 100644 --- a/luni/src/test/java/libcore/io/DiskLruCacheTest.java +++ b/luni/src/test/java/libcore/io/DiskLruCacheTest.java @@ -349,6 +349,28 @@ public final class DiskLruCacheTest extends TestCase { creator2.commit(); } + public void testCreateNewEntryWithMissingFileAborts() throws Exception { + DiskLruCache.Editor creator = cache.edit("k1"); + creator.set(0, "A"); + creator.set(1, "A"); + assertTrue(getDirtyFile("k1", 0).exists()); + assertTrue(getDirtyFile("k1", 1).exists()); + assertTrue(getDirtyFile("k1", 0).delete()); + assertFalse(getDirtyFile("k1", 0).exists()); + creator.commit(); // silently abort if file does not exist due to I/O issue + + assertFalse(getCleanFile("k1", 0).exists()); + assertFalse(getCleanFile("k1", 1).exists()); + assertFalse(getDirtyFile("k1", 0).exists()); + assertFalse(getDirtyFile("k1", 1).exists()); + assertNull(cache.get("k1")); + + DiskLruCache.Editor creator2 = cache.edit("k1"); + creator2.set(0, "B"); + creator2.set(1, "C"); + creator2.commit(); + } + public void testRevertWithTooFewValues() throws Exception { DiskLruCache.Editor creator = cache.edit("k1"); creator.set(1, "A"); @@ -805,4 +827,4 @@ public final class DiskLruCacheTest extends TestCase { assertTrue(getCleanFile(key, 1).exists()); snapshot.close(); } -}
\ No newline at end of file +} diff --git a/luni/src/test/java/libcore/io/MemoryTest.java b/luni/src/test/java/libcore/io/MemoryTest.java index a533f15..9a596fb 100644 --- a/luni/src/test/java/libcore/io/MemoryTest.java +++ b/luni/src/test/java/libcore/io/MemoryTest.java @@ -18,6 +18,7 @@ package libcore.io; import dalvik.system.VMRuntime; +import java.util.Arrays; import junit.framework.TestCase; public class MemoryTest extends TestCase { @@ -28,65 +29,116 @@ public class MemoryTest extends TestCase { swappedValues[i] = Integer.reverseBytes(values[i]); } - int scale = 4; + int scale = SizeOf.INT; VMRuntime runtime = VMRuntime.getRuntime(); - byte[] array = (byte[]) runtime.newNonMovableArray(byte.class, scale * values.length); - int ptr = (int) runtime.addressOf(array); + byte[] array = (byte[]) runtime.newNonMovableArray(byte.class, scale * values.length + 1); + int base_ptr = (int) runtime.addressOf(array); - // Regular copy. - Memory.pokeIntArray(ptr, values, 0, values.length, false); - assertIntsEqual(values, ptr, false); - assertIntsEqual(swappedValues, ptr, true); + for (int ptr_offset = 0; ptr_offset < 2; ++ptr_offset) { + int ptr = base_ptr + ptr_offset; // To test aligned and unaligned accesses. + Arrays.fill(array, (byte) 0); - // Swapped copy. - Memory.pokeIntArray(ptr, values, 0, values.length, true); - assertIntsEqual(values, ptr, true); - assertIntsEqual(swappedValues, ptr, false); + // Regular copy. + Memory.pokeIntArray(ptr, values, 0, values.length, false); + assertIntsEqual(values, ptr, false); + assertIntsEqual(swappedValues, ptr, true); - // Swapped copies of slices (to ensure we test non-zero offsets). - for (int i = 0; i < values.length; ++i) { - Memory.pokeIntArray(ptr + i * scale, values, i, 1, true); + // Swapped copy. + Memory.pokeIntArray(ptr, values, 0, values.length, true); + assertIntsEqual(values, ptr, true); + assertIntsEqual(swappedValues, ptr, false); + + // Swapped copies of slices (to ensure we test non-zero offsets). + for (int i = 0; i < values.length; ++i) { + Memory.pokeIntArray(ptr + i * scale, values, i, 1, true); + } + assertIntsEqual(values, ptr, true); + assertIntsEqual(swappedValues, ptr, false); } - assertIntsEqual(values, ptr, true); - assertIntsEqual(swappedValues, ptr, false); } private void assertIntsEqual(int[] expectedValues, int ptr, boolean swap) { for (int i = 0; i < expectedValues.length; ++i) { - assertEquals(expectedValues[i], Memory.peekInt(ptr + 4 * i, swap)); + assertEquals(expectedValues[i], Memory.peekInt(ptr + SizeOf.INT * i, swap)); } } + public void testSetLongArray() { + long[] values = { 0x1020304050607080L, 0xffeeddccbbaa9988L }; + long[] swappedValues = new long[values.length]; + for (int i = 0; i < values.length; ++i) { + swappedValues[i] = Long.reverseBytes(values[i]); + } + + int scale = SizeOf.LONG; + VMRuntime runtime = VMRuntime.getRuntime(); + byte[] array = (byte[]) runtime.newNonMovableArray(byte.class, scale * values.length + 1); + int base_ptr = (int) runtime.addressOf(array); + + for (int ptr_offset = 0; ptr_offset < 2; ++ptr_offset) { + int ptr = base_ptr + ptr_offset; // To test aligned and unaligned accesses. + Arrays.fill(array, (byte) 0); + + // Regular copy. + Memory.pokeLongArray(ptr, values, 0, values.length, false); + assertLongsEqual(values, ptr, false); + assertLongsEqual(swappedValues, ptr, true); + + // Swapped copy. + Memory.pokeLongArray(ptr, values, 0, values.length, true); + assertLongsEqual(values, ptr, true); + assertLongsEqual(swappedValues, ptr, false); + + // Swapped copies of slices (to ensure we test non-zero offsets). + for (int i = 0; i < values.length; ++i) { + Memory.pokeLongArray(ptr + i * scale, values, i, 1, true); + } + assertLongsEqual(values, ptr, true); + assertLongsEqual(swappedValues, ptr, false); + } + } + + private void assertLongsEqual(long[] expectedValues, int ptr, boolean swap) { + for (int i = 0; i < expectedValues.length; ++i) { + assertEquals(expectedValues[i], Memory.peekLong(ptr + SizeOf.LONG * i, swap)); + } + } + public void testSetShortArray() { short[] values = { 0x0001, 0x0020, 0x0300, 0x4000 }; short[] swappedValues = { 0x0100, 0x2000, 0x0003, 0x0040 }; - int scale = 2; + int scale = SizeOf.SHORT; VMRuntime runtime = VMRuntime.getRuntime(); - byte[] array = (byte[]) runtime.newNonMovableArray(byte.class, scale * values.length); - int ptr = (int) runtime.addressOf(array); + byte[] array = (byte[]) runtime.newNonMovableArray(byte.class, scale * values.length + 1); + int base_ptr = (int) runtime.addressOf(array); - // Regular copy. Memset first so we start from a known state. - Memory.pokeShortArray(ptr, values, 0, values.length, false); - assertShortsEqual(values, ptr, false); - assertShortsEqual(swappedValues, ptr, true); + for (int ptr_offset = 0; ptr_offset < 2; ++ptr_offset) { + int ptr = base_ptr + ptr_offset; // To test aligned and unaligned accesses. + Arrays.fill(array, (byte) 0); - // Swapped copy. - Memory.pokeShortArray(ptr, values, 0, values.length, true); - assertShortsEqual(values, ptr, true); - assertShortsEqual(swappedValues, ptr, false); + // Regular copy. + Memory.pokeShortArray(ptr, values, 0, values.length, false); + assertShortsEqual(values, ptr, false); + assertShortsEqual(swappedValues, ptr, true); - // Swapped copies of slices (to ensure we test non-zero offsets). - for (int i = 0; i < values.length; ++i) { - Memory.pokeShortArray(ptr + i * scale, values, i, 1, true); + // Swapped copy. + Memory.pokeShortArray(ptr, values, 0, values.length, true); + assertShortsEqual(values, ptr, true); + assertShortsEqual(swappedValues, ptr, false); + + // Swapped copies of slices (to ensure we test non-zero offsets). + for (int i = 0; i < values.length; ++i) { + Memory.pokeShortArray(ptr + i * scale, values, i, 1, true); + } + assertShortsEqual(values, ptr, true); + assertShortsEqual(swappedValues, ptr, false); } - assertShortsEqual(values, ptr, true); - assertShortsEqual(swappedValues, ptr, false); } private void assertShortsEqual(short[] expectedValues, int ptr, boolean swap) { for (int i = 0; i < expectedValues.length; ++i) { - assertEquals(expectedValues[i], Memory.peekShort(ptr + 2 * i, swap)); + assertEquals(expectedValues[i], Memory.peekShort(ptr + SizeOf.SHORT * i, swap)); } } } diff --git a/luni/src/test/java/libcore/java/io/FileTest.java b/luni/src/test/java/libcore/java/io/FileTest.java index 3cf621e..b2391ac 100644 --- a/luni/src/test/java/libcore/java/io/FileTest.java +++ b/luni/src/test/java/libcore/java/io/FileTest.java @@ -225,4 +225,45 @@ public class FileTest extends junit.framework.TestCase { assertTrue(new File("/").getTotalSpace() >= 0); assertTrue(new File("/").getUsableSpace() >= 0); } + + public void test_mkdirs() throws Exception { + // Set up a directory to test in. + File base = createTemporaryDirectory(); + + // mkdirs returns true only if it _creates_ a directory. + // So we get false for a directory that already exists... + assertTrue(base.exists()); + assertFalse(base.mkdirs()); + // But true if we had to create something. + File a = new File(base, "a"); + assertFalse(a.exists()); + assertTrue(a.mkdirs()); + assertTrue(a.exists()); + + // Test the recursive case where we need to create multiple parents. + File b = new File(a, "b"); + File c = new File(b, "c"); + File d = new File(c, "d"); + assertTrue(a.exists()); + assertFalse(b.exists()); + assertFalse(c.exists()); + assertFalse(d.exists()); + assertTrue(d.mkdirs()); + assertTrue(a.exists()); + assertTrue(b.exists()); + assertTrue(c.exists()); + assertTrue(d.exists()); + + // Test the case where the 'directory' exists as a file. + File existsAsFile = new File(base, "existsAsFile"); + existsAsFile.createNewFile(); + assertTrue(existsAsFile.exists()); + assertFalse(existsAsFile.mkdirs()); + + // Test the case where the parent exists as a file. + File badParent = new File(existsAsFile, "sub"); + assertTrue(existsAsFile.exists()); + assertFalse(badParent.exists()); + assertFalse(badParent.mkdirs()); + } } diff --git a/luni/src/test/java/libcore/java/io/InterruptedStreamTest.java b/luni/src/test/java/libcore/java/io/InterruptedStreamTest.java index e973b8f..e46df5d 100644..100755 --- a/luni/src/test/java/libcore/java/io/InterruptedStreamTest.java +++ b/luni/src/test/java/libcore/java/io/InterruptedStreamTest.java @@ -28,6 +28,7 @@ import java.net.InetSocketAddress; import java.net.Socket; import java.nio.ByteBuffer; import java.nio.channels.ClosedByInterruptException; +import java.nio.channels.ClosedChannelException; import java.nio.channels.Pipe; import java.nio.channels.ReadableByteChannel; import java.nio.channels.ServerSocketChannel; @@ -45,10 +46,16 @@ public final class InterruptedStreamTest extends TestCase { private Socket[] sockets; + @Override protected void setUp() throws Exception { + Thread.interrupted(); // clear interrupted bit + super.tearDown(); + } + @Override protected void tearDown() throws Exception { if (sockets != null) { sockets[0].close(); sockets[1].close(); + sockets = null; } Thread.interrupted(); // clear interrupted bit super.tearDown(); @@ -93,7 +100,7 @@ public final class InterruptedStreamTest extends TestCase { public void testInterruptWritableSocketChannel() throws Exception { sockets = newSocketChannelPair(); - testInterruptReadableChannel(sockets[0].getChannel()); + testInterruptWritableChannel(sockets[0].getChannel()); } /** @@ -110,71 +117,102 @@ public final class InterruptedStreamTest extends TestCase { } private void testInterruptInputStream(final InputStream in) throws Exception { - interruptMeLater(); + Thread thread = interruptMeLater(); try { in.read(); fail(); } catch (InterruptedIOException expected) { + } finally { + waitForInterrupt(thread); } } private void testInterruptReader(final PipedReader reader) throws Exception { - interruptMeLater(); + Thread thread = interruptMeLater(); try { reader.read(); fail(); } catch (InterruptedIOException expected) { + } finally { + waitForInterrupt(thread); } } private void testInterruptReadableChannel(final ReadableByteChannel channel) throws Exception { - interruptMeLater(); + Thread thread = interruptMeLater(); try { channel.read(ByteBuffer.allocate(BUFFER_SIZE)); fail(); } catch (ClosedByInterruptException expected) { + } finally { + waitForInterrupt(thread); } } private void testInterruptOutputStream(final OutputStream out) throws Exception { - interruptMeLater(); + Thread thread = interruptMeLater(); try { // this will block when the receiving buffer fills up while (true) { out.write(new byte[BUFFER_SIZE]); } } catch (InterruptedIOException expected) { + } finally { + waitForInterrupt(thread); } } private void testInterruptWriter(final PipedWriter writer) throws Exception { - interruptMeLater(); + Thread thread = interruptMeLater(); try { // this will block when the receiving buffer fills up while (true) { writer.write(new char[BUFFER_SIZE]); } } catch (InterruptedIOException expected) { + } finally { + waitForInterrupt(thread); } } private void testInterruptWritableChannel(final WritableByteChannel channel) throws Exception { - interruptMeLater(); + Thread thread = interruptMeLater(); try { // this will block when the receiving buffer fills up while (true) { channel.write(ByteBuffer.allocate(BUFFER_SIZE)); } } catch (ClosedByInterruptException expected) { + } catch (ClosedChannelException expected) { + } finally { + waitForInterrupt(thread); } } - private void interruptMeLater() throws Exception { + private Thread interruptMeLater() throws Exception { final Thread toInterrupt = Thread.currentThread(); - new Thread(new Runnable () { + Thread thread = new Thread(new Runnable () { @Override public void run() { + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + } toInterrupt.interrupt(); } - }).start(); + }); + thread.start(); + return thread; + } + + private static void waitForInterrupt(Thread thread) throws Exception { + try { + thread.join(); + } catch (InterruptedException ignore) { + // There is currently a race between Thread.interrupt in + // interruptMeLater and Thread.join here. Most of the time + // we won't get an InterruptedException, but occasionally + // we do, so for now ignore this exception. + // http://b/6951157 + } } } diff --git a/luni/src/test/java/libcore/java/io/SerializationTest.java b/luni/src/test/java/libcore/java/io/SerializationTest.java index 434dd56..d452c11 100644 --- a/luni/src/test/java/libcore/java/io/SerializationTest.java +++ b/luni/src/test/java/libcore/java/io/SerializationTest.java @@ -18,6 +18,8 @@ package libcore.java.io; import java.io.IOException; import java.io.InvalidClassException; +import java.io.ObjectStreamClass; +import java.io.ObjectStreamField; import java.io.Serializable; import junit.framework.TestCase; import libcore.util.SerializationTester; @@ -26,6 +28,13 @@ public final class SerializationTest extends TestCase { // http://b/4471249 public void testSerializeFieldMadeTransient() throws Exception { + // Does ObjectStreamClass have the right idea? + ObjectStreamClass osc = ObjectStreamClass.lookup(FieldMadeTransient.class); + ObjectStreamField[] fields = osc.getFields(); + assertEquals(1, fields.length); + assertEquals("nonTransientInt", fields[0].getName()); + assertEquals(int.class, fields[0].getType()); + // this was created by serializing a FieldMadeTransient with a non-0 transientInt String s = "aced0005737200346c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6e54657" + "374244669656c644d6164655472616e7369656e74000000000000000002000149000c7472616e736" @@ -37,6 +46,7 @@ public final class SerializationTest extends TestCase { static class FieldMadeTransient implements Serializable { private static final long serialVersionUID = 0L; private transient int transientInt; + private int nonTransientInt; } public void testSerialVersionUidChange() throws Exception { diff --git a/luni/src/test/java/libcore/java/lang/IntrinsicTest.java b/luni/src/test/java/libcore/java/lang/IntrinsicTest.java index 75a4e42..6425b85 100644 --- a/luni/src/test/java/libcore/java/lang/IntrinsicTest.java +++ b/luni/src/test/java/libcore/java/lang/IntrinsicTest.java @@ -18,6 +18,9 @@ package libcore.java.lang; import junit.framework.TestCase; +/** + * Tests that all intrinsic methods are still invokable via reflection. + */ public final class IntrinsicTest extends TestCase { public void testString_charAt() throws Exception { "hello".charAt(0); diff --git a/luni/src/test/java/libcore/java/lang/OldObjectTest.java b/luni/src/test/java/libcore/java/lang/OldObjectTest.java index 08471b2..3ab0327 100644 --- a/luni/src/test/java/libcore/java/lang/OldObjectTest.java +++ b/luni/src/test/java/libcore/java/lang/OldObjectTest.java @@ -16,8 +16,6 @@ */ package libcore.java.lang; -import dalvik.annotation.SideEffect; -import java.util.Vector; import junit.framework.TestCase; public class OldObjectTest extends TestCase { @@ -187,7 +185,36 @@ public class OldObjectTest extends TestCase { fail("InterruptedException was thrown."); } assertEquals(3, status); + } + + public void test_waitJI_invalid() throws Exception { + Object o = new Object(); + synchronized (o) { + try { + o.wait(-1, 0); + fail(); + } catch (IllegalArgumentException expected) { + } + + try { + o.wait(0, -1); + fail(); + } catch (IllegalArgumentException expected) { + } + try { + o.wait(-1, -1); + fail(); + } catch (IllegalArgumentException expected) { + } + + // The ms timeout must fit in 32 bits. + try { + o.wait(Integer.MAX_VALUE + 1, 0); + fail(); + } catch (IllegalArgumentException expected) { + } + } } public void test_waitJ() { diff --git a/luni/src/test/java/libcore/java/lang/StringTest.java b/luni/src/test/java/libcore/java/lang/StringTest.java index 42a7aad..99dba49 100644 --- a/luni/src/test/java/libcore/java/lang/StringTest.java +++ b/luni/src/test/java/libcore/java/lang/StringTest.java @@ -91,10 +91,24 @@ public class StringTest extends TestCase { } } - public void testStringFromCharset() { - Charset cs = Charset.forName("UTF-8"); - byte[] bytes = new byte[] {(byte) 'h', (byte) 'i'}; - assertEquals("hi", new String(bytes, cs)); + public void testString_BII() throws Exception { + byte[] bytes = "xa\u0666bx".getBytes("UTF-8"); + assertEquals("a\u0666b", new String(bytes, 1, bytes.length - 2)); + } + + public void testString_BIIString() throws Exception { + byte[] bytes = "xa\u0666bx".getBytes("UTF-8"); + assertEquals("a\u0666b", new String(bytes, 1, bytes.length - 2, "UTF-8")); + } + + public void testString_BIICharset() throws Exception { + byte[] bytes = "xa\u0666bx".getBytes("UTF-8"); + assertEquals("a\u0666b", new String(bytes, 1, bytes.length - 2, Charset.forName("UTF-8"))); + } + + public void testString_BCharset() throws Exception { + byte[] bytes = "a\u0666b".getBytes("UTF-8"); + assertEquals("a\u0666b", new String(bytes, Charset.forName("UTF-8"))); } public void testStringFromCharset_MaliciousCharset() { diff --git a/luni/src/test/java/libcore/java/lang/ref/FinalizeTest.java b/luni/src/test/java/libcore/java/lang/ref/FinalizeTest.java index 10a26fe..ef303bd 100644 --- a/luni/src/test/java/libcore/java/lang/ref/FinalizeTest.java +++ b/luni/src/test/java/libcore/java/lang/ref/FinalizeTest.java @@ -29,18 +29,42 @@ public final class FinalizeTest extends TestCase { FinalizationTester.induceFinalization(); if (!finalized.get()) { - fail(); + fail("object not yet finalized"); + } + } + + /** + * Test verifies that runFinalization() does not mess up objects + * that should be finalized later on. http://b/6907299 + */ + public void testInducedFinalization() throws Exception { + AtomicBoolean finalized1 = new AtomicBoolean(); + AtomicBoolean finalized2 = new AtomicBoolean(); + createFinalizableObject(finalized1); + createFinalizableObject(finalized2); + FinalizationTester.induceFinalization(); + if (!finalized1.get() || !finalized2.get()) { + fail("not yet finalized: " + finalized1.get() + " " + finalized2.get()); } } /** Do not inline this method; that could break non-precise GCs. See FinalizationTester. */ - private void createFinalizableObject(final AtomicBoolean finalized) { - new X() { + private X createFinalizableObject(final AtomicBoolean finalized) { + X result = new X() { @Override protected void finalize() throws Throwable { super.finalize(); finalized.set(true); } }; + FinalizationTester.induceFinalization(); + // Dance around a bit to discourage dx from realizing that 'result' is no longer live. + boolean wasFinalized = finalized.get(); + if (wasFinalized) { + fail("finalizer called early"); // ...because 'result' is still live until we return. + } + // But we don't actually want to return 'result' because then we'd have to worry about + // the caller accidentally keeping it live. + return wasFinalized ? result : null; } static class X {} diff --git a/luni/src/test/java/libcore/java/net/ConcurrentCloseTest.java b/luni/src/test/java/libcore/java/net/ConcurrentCloseTest.java index d33c5f3..99a479c2 100644 --- a/luni/src/test/java/libcore/java/net/ConcurrentCloseTest.java +++ b/luni/src/test/java/libcore/java/net/ConcurrentCloseTest.java @@ -16,11 +16,13 @@ package libcore.java.net; +import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; +import java.net.SocketAddress; import java.net.SocketException; import java.nio.channels.AsynchronousCloseException; import java.nio.channels.ClosedChannelException; @@ -36,25 +38,25 @@ import tests.net.StuckServer; */ public class ConcurrentCloseTest extends junit.framework.TestCase { public void test_accept() throws Exception { - ServerSocket s = new ServerSocket(0); - new Killer(s).start(); + ServerSocket ss = new ServerSocket(0); + new Killer(ss).start(); try { System.err.println("accept..."); - s.accept(); - fail("accept returned!"); + Socket s = ss.accept(); + fail("accept returned " + s + "!"); } catch (SocketException expected) { assertEquals("Socket closed", expected.getMessage()); } } public void test_connect() throws Exception { - StuckServer ss = new StuckServer(); + StuckServer ss = new StuckServer(false); Socket s = new Socket(); new Killer(s).start(); try { System.err.println("connect..."); s.connect(ss.getLocalSocketAddress()); - fail("connect returned!"); + fail("connect returned: " + s + "!"); } catch (SocketException expected) { assertEquals("Socket closed", expected.getMessage()); } finally { @@ -63,13 +65,13 @@ public class ConcurrentCloseTest extends junit.framework.TestCase { } public void test_connect_timeout() throws Exception { - StuckServer ss = new StuckServer(); + StuckServer ss = new StuckServer(false); Socket s = new Socket(); new Killer(s).start(); try { System.err.println("connect (with timeout)..."); s.connect(ss.getLocalSocketAddress(), 3600 * 1000); - fail("connect returned!"); + fail("connect returned: " + s + "!"); } catch (SocketException expected) { assertEquals("Socket closed", expected.getMessage()); } finally { @@ -78,7 +80,7 @@ public class ConcurrentCloseTest extends junit.framework.TestCase { } public void test_connect_nonBlocking() throws Exception { - StuckServer ss = new StuckServer(); + StuckServer ss = new StuckServer(false); SocketChannel s = SocketChannel.open(); new Killer(s.socket()).start(); try { @@ -88,7 +90,7 @@ public class ConcurrentCloseTest extends junit.framework.TestCase { while (!s.finishConnect()) { // Spin like a mad thing! } - fail("connect returned!"); + fail("connect returned: " + s + "!"); } catch (SocketException expected) { assertEquals("Socket closed", expected.getMessage()); } catch (AsynchronousCloseException alsoOkay) { @@ -102,23 +104,14 @@ public class ConcurrentCloseTest extends junit.framework.TestCase { } public void test_read() throws Exception { - final ServerSocket ss = new ServerSocket(0); - new Thread(new Runnable() { - public void run() { - try { - ss.accept(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - }).start(); + SilentServer ss = new SilentServer(); Socket s = new Socket(); s.connect(ss.getLocalSocketAddress()); new Killer(s).start(); try { System.err.println("read..."); int i = s.getInputStream().read(); - fail("read returned " + i); + fail("read returned: " + i); } catch (SocketException expected) { assertEquals("Socket closed", expected.getMessage()); } @@ -126,16 +119,7 @@ public class ConcurrentCloseTest extends junit.framework.TestCase { } public void test_read_multiple() throws Throwable { - final ServerSocket ss = new ServerSocket(0); - new Thread(new Runnable() { - public void run() { - try { - ss.accept(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - }).start(); + SilentServer ss = new SilentServer(); final Socket s = new Socket(); s.connect(ss.getLocalSocketAddress()); @@ -152,7 +136,7 @@ public class ConcurrentCloseTest extends junit.framework.TestCase { try { System.err.println("read..."); int i = s.getInputStream().read(); - fail("read returned " + i); + fail("read returned: " + i); } catch (SocketException expected) { assertEquals("Socket closed", expected.getMessage()); } @@ -173,6 +157,8 @@ public class ConcurrentCloseTest extends junit.framework.TestCase { for (Throwable exception : thrownExceptions) { throw exception; } + + ss.close(); } public void test_recv() throws Exception { @@ -190,21 +176,7 @@ public class ConcurrentCloseTest extends junit.framework.TestCase { } public void test_write() throws Exception { - final ServerSocket ss = new ServerSocket(0); - new Thread(new Runnable() { - public void run() { - try { - System.err.println("accepting..."); - - Socket client = ss.accept(); - System.err.println("accepted..."); - Thread.sleep(30 * 1000); - System.err.println("server exiting..."); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - }).start(); + final SilentServer ss = new SilentServer(); Socket s = new Socket(); s.connect(ss.getLocalSocketAddress()); new Killer(s).start(); @@ -224,6 +196,37 @@ public class ConcurrentCloseTest extends junit.framework.TestCase { ss.close(); } + // This server accepts connections, but doesn't read or write anything. + // It holds on to the Socket connecting to the client so it won't be GCed. + // Call "close" to close both the server socket and its client connection. + static class SilentServer { + private final ServerSocket ss; + private Socket client; + + public SilentServer() throws IOException { + ss = new ServerSocket(0); + new Thread(new Runnable() { + public void run() { + try { + client = ss.accept(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + }).start(); + } + + public SocketAddress getLocalSocketAddress() { + return ss.getLocalSocketAddress(); + } + + public void close() throws IOException { + client.close(); + ss.close(); + } + } + + // This thread calls the "close" method on the supplied T after 2s. static class Killer<T> extends Thread { private final T s; diff --git a/luni/src/test/java/libcore/java/net/OldDatagramPacketTest.java b/luni/src/test/java/libcore/java/net/OldDatagramPacketTest.java index a77a44d..8ca4067 100644 --- a/luni/src/test/java/libcore/java/net/OldDatagramPacketTest.java +++ b/luni/src/test/java/libcore/java/net/OldDatagramPacketTest.java @@ -21,71 +21,40 @@ import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; -import tests.support.Support_PortManager; public class OldDatagramPacketTest extends junit.framework.TestCase { - DatagramPacket dp; - - volatile boolean started = false; - - public void test_getPort() throws IOException { - dp = new DatagramPacket("Hello".getBytes(), 5, InetAddress.getLocalHost(), 1000); + public void test_getPort() throws Exception { + DatagramPacket dp = new DatagramPacket("Hello".getBytes(), 5, InetAddress.getLocalHost(), 1000); assertEquals("Incorrect port returned", 1000, dp.getPort()); - InetAddress localhost = InetAddress.getByName("localhost"); - - int[] ports = Support_PortManager.getNextPortsForUDP(2); - final int port = ports[0]; - final Object lock = new Object(); - + final DatagramSocket ss = new DatagramSocket(); Thread thread = new Thread(new Runnable() { public void run() { - DatagramSocket socket = null; try { - socket = new DatagramSocket(port); - synchronized (lock) { - started = true; - lock.notifyAll(); - } - socket.setSoTimeout(3000); - DatagramPacket packet = new DatagramPacket(new byte[256], - 256); - socket.receive(packet); - socket.send(packet); - socket.close(); + DatagramPacket packet = new DatagramPacket(new byte[256], 256); + ss.setSoTimeout(3000); + ss.receive(packet); + ss.send(packet); } catch (IOException e) { System.out.println("thread exception: " + e); - if (socket != null) - socket.close(); } } }); thread.start(); - DatagramSocket socket = null; + DatagramSocket cs = new DatagramSocket(); try { - socket = new DatagramSocket(ports[1]); - socket.setSoTimeout(3000); - DatagramPacket packet = new DatagramPacket(new byte[] { 1, 2, 3, 4, - 5, 6 }, 6, localhost, port); - synchronized (lock) { - try { - if (!started) - lock.wait(); - } catch (InterruptedException e) { - fail(e.toString()); - } - } - socket.send(packet); - socket.receive(packet); - socket.close(); - assertTrue("datagram received wrong port: " + packet.getPort(), - packet.getPort() == port); + byte[] bytes = new byte[] { 1, 2, 3, 4, 5, 6 }; + DatagramPacket packet = new DatagramPacket(bytes, 6, InetAddress.getByName("localhost"), ss.getLocalPort()); + cs.send(packet); + cs.setSoTimeout(3000); + cs.receive(packet); + cs.close(); + assertEquals(packet.getPort(), ss.getLocalPort()); } finally { - if (socket != null) { - socket.close(); - } + cs.close(); + ss.close(); } } @@ -104,7 +73,7 @@ public class OldDatagramPacketTest extends junit.framework.TestCase { } public void test_setData$BII() { - dp = new DatagramPacket("Hello".getBytes(), 5); + DatagramPacket dp = new DatagramPacket("Hello".getBytes(), 5); try { dp.setData(null, 2, 3); fail("NullPointerException was not thrown."); @@ -113,7 +82,7 @@ public class OldDatagramPacketTest extends junit.framework.TestCase { } public void test_setData$B() { - dp = new DatagramPacket("Hello".getBytes(), 5); + DatagramPacket dp = new DatagramPacket("Hello".getBytes(), 5); try { dp.setData(null); fail("NullPointerException was not thrown."); diff --git a/luni/src/test/java/libcore/java/net/OldServerSocketTest.java b/luni/src/test/java/libcore/java/net/OldServerSocketTest.java index cf35489..6518897 100644 --- a/luni/src/test/java/libcore/java/net/OldServerSocketTest.java +++ b/luni/src/test/java/libcore/java/net/OldServerSocketTest.java @@ -33,7 +33,6 @@ import java.nio.channels.IllegalBlockingModeException; import java.nio.channels.ServerSocketChannel; import java.security.Permission; import java.util.Properties; -import tests.support.Support_PortManager; public class OldServerSocketTest extends OldSocketTestCase { @@ -86,10 +85,9 @@ public class OldServerSocketTest extends OldSocketTestCase { } public void test_ConstructorII() throws IOException { - int freePortNumber = Support_PortManager.getNextPort(); - s = new ServerSocket(freePortNumber, 1); + s = new ServerSocket(0, 1); s.setSoTimeout(2000); - startClient(freePortNumber); + startClient(s.getLocalPort()); sconn = s.accept(); sconn.close(); s.close(); @@ -133,10 +131,9 @@ public class OldServerSocketTest extends OldSocketTestCase { } public void test_ConstructorI() throws Exception { - int portNumber = Support_PortManager.getNextPort(); - s = new ServerSocket(portNumber); + s = new ServerSocket(0); try { - new ServerSocket(portNumber); + new ServerSocket(s.getLocalPort()); fail("IOException was not thrown."); } catch(IOException ioe) { //expected @@ -162,11 +159,9 @@ public class OldServerSocketTest extends OldSocketTestCase { } public void test_ConstructorIILjava_net_InetAddress() throws IOException { - int freePortNumber = Support_PortManager.getNextPort(); - - ServerSocket ss = new ServerSocket(freePortNumber, 10, InetAddress.getLocalHost()); + ServerSocket ss = new ServerSocket(0, 10, InetAddress.getLocalHost()); try { - new ServerSocket(freePortNumber, 10, InetAddress.getLocalHost()); + new ServerSocket(ss.getLocalPort(), 10, InetAddress.getLocalHost()); fail("IOException was not thrown."); } catch(IOException expected) { } @@ -217,9 +212,7 @@ public class OldServerSocketTest extends OldSocketTestCase { } public void test_accept() throws IOException { - int portNumber = Support_PortManager.getNextPort(); - - ServerSocket newSocket = new ServerSocket(portNumber); + ServerSocket newSocket = new ServerSocket(0); newSocket.setSoTimeout(500); try { Socket accepted = newSocket.accept(); diff --git a/luni/src/test/java/libcore/java/net/OldSocketTest.java b/luni/src/test/java/libcore/java/net/OldSocketTest.java index fda9557..033a7bf 100644 --- a/luni/src/test/java/libcore/java/net/OldSocketTest.java +++ b/luni/src/test/java/libcore/java/net/OldSocketTest.java @@ -38,7 +38,6 @@ import java.nio.channels.IllegalBlockingModeException; import java.nio.channels.SocketChannel; import java.security.Permission; import tests.support.Support_Configuration; -import tests.support.Support_PortManager; public class OldSocketTest extends OldSocketTestCase { @@ -115,17 +114,15 @@ public class OldSocketTest extends OldSocketTestCase { public void test_ConstructorLjava_lang_StringILjava_net_InetAddressI1() throws IOException { int sport = startServer("Cons String,I,InetAddress,I"); - int portNumber = Support_PortManager.getNextPort(); s = new Socket(InetAddress.getLocalHost().getHostName(), sport, - InetAddress.getLocalHost(), portNumber); + InetAddress.getLocalHost(), 0); assertTrue("Failed to create socket", s.getPort() == sport); } public void test_ConstructorLjava_lang_StringILjava_net_InetAddressI2() throws IOException { - int testPort = Support_PortManager.getNextPort(); - Socket s1 = new Socket("www.google.com", 80, null, testPort); + Socket s1 = new Socket("www.google.com", 80, null, 0); try { - Socket s2 = new Socket("www.google.com", 80, null, testPort); + Socket s2 = new Socket("www.google.com", 80, null, s1.getLocalPort()); try { s2.close(); } catch (IOException ignored) { @@ -162,10 +159,8 @@ public class OldSocketTest extends OldSocketTestCase { // Test for method java.net.Socket(java.net.InetAddress, int, // java.net.InetAddress, int) int sport = startServer("Cons InetAddress,I,InetAddress,I"); - int portNumber = Support_PortManager.getNextPort(); s = new Socket(InetAddress.getLocalHost().getHostName(), sport, - InetAddress.getLocalHost(), portNumber); - assertTrue("Failed to create socket", s.getLocalPort() == portNumber); + InetAddress.getLocalHost(), 0); } public void test_ConstructorLjava_net_InetAddressIZ() throws IOException { @@ -180,8 +175,7 @@ public class OldSocketTest extends OldSocketTestCase { public void test_close() throws IOException { // Test for method void java.net.Socket.close() int sport = startServer("SServer close"); - int portNumber = Support_PortManager.getNextPort(); - s = new Socket(InetAddress.getLocalHost(), sport, null, portNumber); + s = new Socket(InetAddress.getLocalHost(), sport, null, 0); try { s.setSoLinger(false, 100); } catch (IOException e) { @@ -199,8 +193,7 @@ public class OldSocketTest extends OldSocketTestCase { public void test_getInetAddress() throws IOException { // Test for method java.net.InetAddress java.net.Socket.getInetAddress() int sport = startServer("SServer getInetAddress"); - int portNumber = Support_PortManager.getNextPort(); - s = new Socket(InetAddress.getLocalHost(), sport, null, portNumber); + s = new Socket(InetAddress.getLocalHost(), sport, null, 0); assertTrue("Returned incorrect InetAddress", s.getInetAddress().equals( InetAddress.getLocalHost())); @@ -220,9 +213,7 @@ public class OldSocketTest extends OldSocketTestCase { public void test_getKeepAlive() { try { int sport = startServer("SServer getKeepAlive"); - int portNumber = Support_PortManager.getNextPort(); - Socket theSocket = new Socket(InetAddress.getLocalHost(), sport, - null, portNumber); + Socket theSocket = new Socket(InetAddress.getLocalHost(), sport, null, 0); theSocket.setKeepAlive(true); assertTrue("getKeepAlive false when it should be true", theSocket .getKeepAlive()); @@ -254,8 +245,7 @@ public class OldSocketTest extends OldSocketTestCase { // Test for method java.net.InetAddress // java.net.Socket.getLocalAddress() int sport = startServer("SServer getLocAddress"); - int portNumber = Support_PortManager.getNextPort(); - s = new Socket(InetAddress.getLocalHost(), sport, null, portNumber); + s = new Socket(InetAddress.getLocalHost(), sport, null, 0); assertEquals("Returned incorrect InetAddress", InetAddress.getLocalHost(), s.getLocalAddress()); @@ -271,10 +261,10 @@ public class OldSocketTest extends OldSocketTestCase { public void test_getLocalPort() throws IOException { // Test for method int java.net.Socket.getLocalPort() int sport = startServer("SServer getLocalPort"); - int portNumber = Support_PortManager.getNextPort(); s = new Socket(InetAddress.getLocalHost().getHostName(), sport, - InetAddress.getLocalHost(), portNumber); - assertTrue("Returned incorrect port", s.getLocalPort() == portNumber); + InetAddress.getLocalHost(), 0); + // There's nothing we can usefully assert about the kernel-assigned port. + s.getLocalPort(); } @SuppressWarnings("deprecation") @@ -282,15 +272,13 @@ public class OldSocketTest extends OldSocketTestCase { // Test for method java.io.OutputStream // java.net.Socket.getOutputStream() int sport = startServer("SServer getOutputStream"); - int portNumber = Support_PortManager.getNextPort(); - s = new Socket(InetAddress.getLocalHost(), sport, null, portNumber); + s = new Socket(InetAddress.getLocalHost(), sport); java.io.OutputStream os = s.getOutputStream(); assertNotNull("Failed to get stream", os); os.write(1); s.close(); // Regression test for harmony-2934 - s = new Socket("127.0.0.1", Support_PortManager.getNextPort(), - false); + s = new Socket("127.0.0.1", sport, false); OutputStream o = s.getOutputStream(); o.write(1); try { @@ -301,8 +289,7 @@ public class OldSocketTest extends OldSocketTestCase { s.close(); // Regression test for harmony-2942 - s = new Socket("0.0.0.0", Support_PortManager.getNextPort(), - false); + s = new Socket("0.0.0.0", sport, false); o = s.getOutputStream(); o.write(1); try { @@ -316,18 +303,15 @@ public class OldSocketTest extends OldSocketTestCase { public void test_getPort() throws IOException { // Test for method int java.net.Socket.getPort() int sport = startServer("SServer getPort"); - int portNumber = Support_PortManager.getNextPort(); - s = new Socket(InetAddress.getLocalHost(), sport, null, portNumber); - assertTrue("Returned incorrect port" + s.getPort(), - s.getPort() == sport); + s = new Socket(InetAddress.getLocalHost(), sport, null, 0); + assertTrue("Returned incorrect port" + s.getPort(), s.getPort() == sport); } public void test_getSoLinger() { // Test for method int java.net.Socket.getSoLinger() int sport = startServer("SServer getSoLinger"); try { - int portNumber = Support_PortManager.getNextPort(); - s = new Socket(InetAddress.getLocalHost(), sport, null, portNumber); + s = new Socket(InetAddress.getLocalHost(), sport, null, 0); s.setSoLinger(true, 200); assertEquals("Returned incorrect linger", 200, s.getSoLinger()); ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_LINGER); @@ -337,8 +321,7 @@ public class OldSocketTest extends OldSocketTestCase { } try { - int portNumber = Support_PortManager.getNextPort(); - s = new Socket(InetAddress.getLocalHost(), sport, null, portNumber); + s = new Socket(InetAddress.getLocalHost(), sport, null, 0); s.close(); try { s.getSoLinger(); @@ -354,9 +337,7 @@ public class OldSocketTest extends OldSocketTestCase { public void test_getReceiveBufferSize() { try { int sport = startServer("SServer getReceiveBufferSize"); - int portNumber = Support_PortManager.getNextPort(); - s = new Socket(InetAddress.getLocalHost().getHostName(), sport, - null, portNumber); + s = new Socket(InetAddress.getLocalHost().getHostName(), sport, null, 0); s.setReceiveBufferSize(130); assertTrue("Incorrect buffer size", s.getReceiveBufferSize() >= 130); ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_RCVBUF); @@ -381,9 +362,7 @@ public class OldSocketTest extends OldSocketTestCase { public void test_getSendBufferSize() { int sport = startServer("SServer setSendBufferSize"); try { - int portNumber = Support_PortManager.getNextPort(); - s = new Socket(InetAddress.getLocalHost().getHostName(), sport, - null, portNumber); + s = new Socket(InetAddress.getLocalHost().getHostName(), sport, null, 0); s.setSendBufferSize(134); assertTrue("Incorrect buffer size", s.getSendBufferSize() >= 134); ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_SNDBUF); @@ -391,8 +370,7 @@ public class OldSocketTest extends OldSocketTestCase { handleException(e, SO_SNDBUF); } try { - int portNumber = Support_PortManager.getNextPort(); - s = new Socket(InetAddress.getLocalHost(), sport, null, portNumber); + s = new Socket(InetAddress.getLocalHost(), sport, null, 0); s.close(); try { s.getSendBufferSize(); @@ -430,8 +408,7 @@ public class OldSocketTest extends OldSocketTestCase { // Test for method boolean java.net.Socket.getTcpNoDelay() int sport = startServer("SServer getTcpNoDelay"); try { - int portNumber = Support_PortManager.getNextPort(); - s = new Socket(InetAddress.getLocalHost(), sport, null, portNumber); + s = new Socket(InetAddress.getLocalHost(), sport, null, 0); boolean bool = !s.getTcpNoDelay(); s.setTcpNoDelay(bool); assertTrue("Failed to get no delay setting: " + s.getTcpNoDelay(), @@ -442,8 +419,7 @@ public class OldSocketTest extends OldSocketTestCase { } try { - int portNumber = Support_PortManager.getNextPort(); - s = new Socket(InetAddress.getLocalHost(), sport, null, portNumber); + s = new Socket(InetAddress.getLocalHost(), sport, null, 0); s.close(); try { s.getTcpNoDelay(); @@ -461,9 +437,7 @@ public class OldSocketTest extends OldSocketTestCase { // crashed machines. Just make sure we can set it try { int sport = startServer("SServer setKeepAlive"); - int portNumber = Support_PortManager.getNextPort(); - Socket theSocket = new Socket(InetAddress.getLocalHost(), sport, - null, portNumber); + Socket theSocket = new Socket(InetAddress.getLocalHost(), sport, null, 0); theSocket.setKeepAlive(true); theSocket.setKeepAlive(false); ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_KEEPALIVE); @@ -509,8 +483,7 @@ public class OldSocketTest extends OldSocketTestCase { public void test_setSendBufferSizeI() { try { int sport = startServer("SServer setSendBufferSizeI"); - int portNumber = Support_PortManager.getNextPort(); - s = new Socket(InetAddress.getLocalHost(), sport, null, portNumber); + s = new Socket(InetAddress.getLocalHost(), sport, null, 0); s.setSendBufferSize(134); assertTrue("Incorrect buffer size", s.getSendBufferSize() >= 134); ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_SNDBUF); @@ -533,8 +506,7 @@ public class OldSocketTest extends OldSocketTestCase { public void test_setReceiveBufferSizeI() { try { int sport = startServer("SServer setReceiveBufferSizeI"); - int portNumber = Support_PortManager.getNextPort(); - s = new Socket(InetAddress.getLocalHost(), sport, null, portNumber); + s = new Socket(InetAddress.getLocalHost(), sport, null, 0); s.setReceiveBufferSize(130); assertTrue("Incorrect buffer size", s.getReceiveBufferSize() >= 130); ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_RCVBUF); @@ -558,8 +530,7 @@ public class OldSocketTest extends OldSocketTestCase { // Test for method void java.net.Socket.setSoLinger(boolean, int) try { int sport = startServer("SServer setSoLingerZI"); - int portNumber = Support_PortManager.getNextPort(); - s = new Socket(InetAddress.getLocalHost(), sport, null, portNumber); + s = new Socket(InetAddress.getLocalHost(), sport, null, 0); s.setSoLinger(true, 500); assertEquals("Set incorrect linger", 500, s.getSoLinger()); ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_LINGER); @@ -584,8 +555,7 @@ public class OldSocketTest extends OldSocketTestCase { // Test for method void java.net.Socket.setTcpNoDelay(boolean) try { int sport = startServer("SServer setTcpNoDelayZ"); - int portNumber = Support_PortManager.getNextPort(); - s = new Socket(InetAddress.getLocalHost(), sport, null, portNumber); + s = new Socket(InetAddress.getLocalHost(), sport, null, 0); boolean bool; s.setTcpNoDelay(bool = !s.getTcpNoDelay()); assertTrue("Failed to set no delay setting: " + s.getTcpNoDelay(), @@ -610,9 +580,8 @@ public class OldSocketTest extends OldSocketTestCase { public void test_toString() throws IOException { // Test for method java.lang.String java.net.Socket.toString() int sport = startServer("SServer toString"); - int portNumber = Support_PortManager.getNextPort(); s = new Socket(InetAddress.getLocalHost().getHostName(), sport, - InetAddress.getLocalHost(), portNumber); + InetAddress.getLocalHost(), 0); assertEquals("Socket[address=" + InetAddress.getLocalHost() + ",port=" + s.getPort() + ",localPort=" + s.getLocalPort() + "]", s.toString()); } @@ -620,9 +589,8 @@ public class OldSocketTest extends OldSocketTestCase { // AndroidOnly: RI returns wrong value for EOF public void test_shutdownInput() throws Exception { InetAddress addr = InetAddress.getLocalHost(); - int port = Support_PortManager.getNextPort(); - ServerSocket serverSocket = new ServerSocket(port, 5, addr); - Socket theSocket = new Socket(addr, port); + ServerSocket serverSocket = new ServerSocket(0, 5, addr); + Socket theSocket = new Socket(addr, serverSocket.getLocalPort()); Socket servSock = serverSocket.accept(); InputStream theInput = theSocket.getInputStream(); @@ -656,10 +624,8 @@ public class OldSocketTest extends OldSocketTestCase { } public void test_shutdownOutput() throws IOException { - InetAddress addr = InetAddress.getLocalHost(); - int port = Support_PortManager.getNextPort(); - ServerSocket serverSocket = new ServerSocket(port, 5, addr); - Socket theSocket = new Socket(addr, port); + ServerSocket serverSocket = new ServerSocket(0, 5); + Socket theSocket = new Socket(serverSocket.getInetAddress(), serverSocket.getLocalPort()); Socket servSock = serverSocket.accept(); InputStream theInput = theSocket.getInputStream(); @@ -692,17 +658,9 @@ public class OldSocketTest extends OldSocketTestCase { // set up server connect and then validate that we get the right // response for the local address int sport = startServer("SServer getLocSocketAddress"); - int portNumber = Support_PortManager.getNextPort(); - s = new Socket(InetAddress.getLocalHost(), sport, null, portNumber); - assertTrue( - "Returned incorrect InetSocketAddress(1):" - + s.getLocalSocketAddress().toString() - + "Expected: " - + (new InetSocketAddress(InetAddress.getLocalHost(), - portNumber)).toString(), s - .getLocalSocketAddress().equals( - new InetSocketAddress(InetAddress - .getLocalHost(), portNumber))); + s = new Socket(InetAddress.getLocalHost(), sport, null, 0); + assertEquals(new InetSocketAddress(InetAddress.getLocalHost(), s.getLocalPort()), + s.getLocalSocketAddress()); s.close(); // now create a socket that is not bound and validate we get the @@ -713,21 +671,12 @@ public class OldSocketTest extends OldSocketTestCase { theSocket.getLocalSocketAddress()); // now bind the socket and make sure we get the right answer - portNumber = Support_PortManager.getNextPort(); - theSocket.bind(new InetSocketAddress(InetAddress.getLocalHost(), - portNumber)); - assertTrue( - "Returned incorrect InetSocketAddress(2):" - + theSocket.getLocalSocketAddress().toString() - + "Expected: " - + (new InetSocketAddress(InetAddress.getLocalHost(), - portNumber)).toString(), theSocket - .getLocalSocketAddress().equals( - new InetSocketAddress(InetAddress - .getLocalHost(), portNumber))); + theSocket.bind(new InetSocketAddress(InetAddress.getLocalHost(), 0)); + assertEquals(new InetSocketAddress(InetAddress.getLocalHost(), theSocket.getLocalPort()), + theSocket.getLocalSocketAddress()); theSocket.close(); - // now validate that behaviour when the any address is returned + // now validate that behavior when the any address is returned s = new Socket(); s.bind(new InetSocketAddress(InetAddress.getByName("0.0.0.0"), 0)); @@ -747,8 +696,7 @@ public class OldSocketTest extends OldSocketTestCase { // set up server connect and then validate that we get the right // response for the remote address int sport = startServer("SServer getLocRemoteAddress"); - int portNumber = Support_PortManager.getNextPort(); - s = new Socket(InetAddress.getLocalHost(), sport, null, portNumber); + s = new Socket(InetAddress.getLocalHost(), sport, null, 0); assertTrue("Returned incorrect InetSocketAddress(1):" + s.getLocalSocketAddress().toString(), s.getRemoteSocketAddress() @@ -760,9 +708,7 @@ public class OldSocketTest extends OldSocketTestCase { // now create one that is not connect and validate that we get the // right answer Socket theSocket = new Socket(); - portNumber = Support_PortManager.getNextPort(); - theSocket.bind(new InetSocketAddress(InetAddress.getLocalHost(), - portNumber)); + theSocket.bind(new InetSocketAddress(InetAddress.getLocalHost(), 0)); assertNull("Returned incorrect InetSocketAddress -unconnected socket:" + "Expected: NULL", theSocket.getRemoteSocketAddress()); @@ -781,10 +727,8 @@ public class OldSocketTest extends OldSocketTestCase { } public void test_isBound() throws IOException { - InetAddress addr = InetAddress.getLocalHost(); - int port = Support_PortManager.getNextPort(); - ServerSocket serverSocket = new ServerSocket(port, 5, addr); - Socket theSocket = new Socket(addr, port); + ServerSocket serverSocket = new ServerSocket(0, 5); + Socket theSocket = new Socket(serverSocket.getInetAddress(), serverSocket.getLocalPort()); Socket servSock = serverSocket.accept(); assertTrue("Socket indicated not bound when it should be (1)", theSocket.isBound()); @@ -793,14 +737,11 @@ public class OldSocketTest extends OldSocketTestCase { // now do it with the new constructors and revalidate. Connect causes // the socket to be bound - InetSocketAddress theAddress = new InetSocketAddress(InetAddress - .getLocalHost(), Support_PortManager.getNextPort()); theSocket = new Socket(); assertFalse("Socket indicated bound when it was not (2)", theSocket .isBound()); - serverSocket = new ServerSocket(); - serverSocket.bind(theAddress); - theSocket.connect(theAddress); + serverSocket = new ServerSocket(0, 5); + theSocket.connect(serverSocket.getLocalSocketAddress()); servSock = serverSocket.accept(); assertTrue("Socket indicated not bound when it should be (2)", theSocket.isBound()); @@ -808,12 +749,10 @@ public class OldSocketTest extends OldSocketTestCase { serverSocket.close(); // now test when we bind explicitly - InetSocketAddress theLocalAddress = new InetSocketAddress(InetAddress - .getLocalHost(), Support_PortManager.getNextPort()); theSocket = new Socket(); assertFalse("Socket indicated bound when it was not (3)", theSocket .isBound()); - theSocket.bind(theLocalAddress); + theSocket.bind(null); assertTrue("Socket indicated not bound when it should be (3a)", theSocket.isBound()); theSocket.close(); @@ -822,10 +761,8 @@ public class OldSocketTest extends OldSocketTestCase { } public void test_isConnected() throws IOException { - InetAddress addr = InetAddress.getLocalHost(); - int port = Support_PortManager.getNextPort(); - ServerSocket serverSocket = new ServerSocket(port, 5, addr); - Socket theSocket = new Socket(addr, port); + ServerSocket serverSocket = new ServerSocket(0, 5); + Socket theSocket = new Socket(serverSocket.getInetAddress(), serverSocket.getLocalPort()); Socket servSock = serverSocket.accept(); assertTrue("Socket indicated not connected when it should be", theSocket.isConnected()); @@ -833,14 +770,11 @@ public class OldSocketTest extends OldSocketTestCase { serverSocket.close(); // now do it with the new constructors and revalidate - InetSocketAddress theAddress = new InetSocketAddress(InetAddress - .getLocalHost(), Support_PortManager.getNextPort()); theSocket = new Socket(); assertFalse("Socket indicated connected when it was not", theSocket .isConnected()); - serverSocket = new ServerSocket(); - serverSocket.bind(theAddress); - theSocket.connect(theAddress); + serverSocket = new ServerSocket(0, 5); + theSocket.connect(serverSocket.getLocalSocketAddress()); servSock = serverSocket.accept(); assertTrue("Socket indicated not connected when it should be", theSocket.isConnected()); @@ -849,10 +783,8 @@ public class OldSocketTest extends OldSocketTestCase { } public void test_isClosed() throws IOException { - InetAddress addr = InetAddress.getLocalHost(); - int port = Support_PortManager.getNextPort(); - ServerSocket serverSocket = new ServerSocket(port, 5, addr); - Socket theSocket = new Socket(addr, port); + ServerSocket serverSocket = new ServerSocket(0, 5); + Socket theSocket = new Socket(serverSocket.getInetAddress(), serverSocket.getLocalPort()); Socket servSock = serverSocket.accept(); // validate isClosed returns expected values @@ -862,7 +794,7 @@ public class OldSocketTest extends OldSocketTestCase { assertTrue("Socket should indicate it is closed(1):", theSocket .isClosed()); - theSocket = new Socket(addr, port); + theSocket = new Socket(serverSocket.getInetAddress(), serverSocket.getLocalPort()); assertFalse("Socket should indicate it is not closed(2):", theSocket .isClosed()); theSocket.close(); @@ -891,7 +823,7 @@ public class OldSocketTest extends OldSocketTestCase { try { theSocket.bind(new InetSocketAddress(InetAddress .getByAddress(Support_Configuration.nonLocalAddressBytes), - Support_PortManager.getNextPort())); + 80)); fail("No exception when binding to bad address:" + theSocket.getLocalSocketAddress().toString()); } catch (IOException ex) { @@ -900,39 +832,21 @@ public class OldSocketTest extends OldSocketTestCase { // now create a socket that is not bound and then bind it theSocket = new Socket(); - int portNumber = Support_PortManager.getNextPort(); theSocket.bind(new InetSocketAddress(InetAddress.getLocalHost(), - portNumber)); + 0)); // validate that the localSocketAddress reflects the address we // bound to - assertTrue( - "Local address not correct after bind:" - + theSocket.getLocalSocketAddress().toString() - + " Expected: " - + (new InetSocketAddress(InetAddress.getLocalHost(), - portNumber)).toString(), theSocket - .getLocalSocketAddress().equals( - new InetSocketAddress(InetAddress - .getLocalHost(), portNumber))); + assertEquals(new InetSocketAddress(InetAddress.getLocalHost(), theSocket.getLocalPort()), + theSocket.getLocalSocketAddress()); // make sure we can now connect and that connections appear to come // from the address we bound to. - InetSocketAddress theAddress = new InetSocketAddress(InetAddress - .getLocalHost(), Support_PortManager.getNextPort()); - ServerSocket serverSocket = new ServerSocket(); - serverSocket.bind(theAddress); - theSocket.connect(theAddress); + ServerSocket serverSocket = new ServerSocket(0, 5); + theSocket.connect(serverSocket.getLocalSocketAddress()); Socket servSock = serverSocket.accept(); - assertTrue( - "Returned Remote address from server connected to does not match expected local address:" - + servSock.getRemoteSocketAddress().toString() - + " Expected: " - + (new InetSocketAddress(InetAddress.getLocalHost(), - portNumber)).toString(), servSock - .getRemoteSocketAddress().equals( - new InetSocketAddress(InetAddress - .getLocalHost(), portNumber))); + assertEquals(new InetSocketAddress(InetAddress.getLocalHost(), theSocket.getLocalPort()), + servSock.getRemoteSocketAddress()); theSocket.close(); servSock.close(); serverSocket.close(); @@ -951,10 +865,8 @@ public class OldSocketTest extends OldSocketTestCase { theSocket = new Socket(); Socket theSocket2 = new Socket(); try { - theAddress = new InetSocketAddress(InetAddress.getLocalHost(), - Support_PortManager.getNextPort()); - theSocket.bind(theAddress); - theSocket2.bind(theAddress); + theSocket.bind(null); + theSocket2.bind(theSocket.getLocalSocketAddress()); fail("No exception binding to address that is not available"); } catch (IOException ex) { } @@ -1020,7 +932,7 @@ public class OldSocketTest extends OldSocketTestCase { } // start by validating the error checks - int portNumber = Support_PortManager.getNextPort(); + int portNumber = 0; Socket theSocket = null; ServerSocket serverSocket = null; SocketAddress theAddress = null; @@ -1084,17 +996,8 @@ public class OldSocketTest extends OldSocketTestCase { // now validate that we can actually connect when somebody is listening theSocket = new Socket(); - serverSocket = new ServerSocket(); - serverSocket.bind(theAddress); - theSocket.connect(theAddress); - theSocket.close(); - serverSocket.close(); - - // now validate that we can actually connect when somebody is listening - theSocket = new Socket(); - serverSocket = new ServerSocket(); - serverSocket.bind(theAddress); - theSocket.connect(theAddress); + serverSocket = new ServerSocket(0, 5); + theSocket.connect(serverSocket.getLocalSocketAddress()); // validate that when a socket is connected that it answers // correctly to related queries @@ -1119,10 +1022,9 @@ public class OldSocketTest extends OldSocketTestCase { // are already connected try { theSocket = new Socket(); - serverSocket = new ServerSocket(); - serverSocket.bind(theAddress); - theSocket.connect(theAddress); - theSocket.connect(theAddress); + serverSocket = new ServerSocket(0, 5); + theSocket.connect(serverSocket.getLocalSocketAddress()); + theSocket.connect(serverSocket.getLocalSocketAddress()); theSocket.close(); serverSocket.close(); fail("No exception when we try to connect on a connected socket: "); @@ -1145,9 +1047,8 @@ public class OldSocketTest extends OldSocketTestCase { // now validate that connected socket can be used to read/write theSocket = new Socket(); - serverSocket = new ServerSocket(); - serverSocket.bind(theAddress); - theSocket.connect(theAddress); + serverSocket = new ServerSocket(0, 5); + theSocket.connect(serverSocket.getLocalSocketAddress()); Socket servSock = serverSocket.accept(); InputStream theInput = theSocket.getInputStream(); OutputStream theOutput = servSock.getOutputStream(); @@ -1197,10 +1098,8 @@ public class OldSocketTest extends OldSocketTestCase { SocketChannel channel = SocketChannel.open(); channel.configureBlocking(false); Socket socket = channel.socket(); - int port = Support_PortManager.getNextPort(); try { - socket.connect( new InetSocketAddress(InetAddress.getLocalHost(), - Support_PortManager.getNextPort())); + socket.connect(serverSocket.getLocalSocketAddress()); fail("IllegalBlockingModeException was not thrown."); } catch (IllegalBlockingModeException expected) { } @@ -1263,28 +1162,14 @@ public class OldSocketTest extends OldSocketTestCase { } // start by validating the error checks - int portNumber = Support_PortManager.getNextPort(); - Socket theSocket = null; - ServerSocket serverSocket = null; - SocketAddress theAddress = null; - SocketAddress nonConnectableAddress = null; - SocketAddress nonReachableAddress = null; - SocketAddress nonListeningAddress = null; - SocketAddress invalidType = null; byte[] theBytes = { 0, 0, 0, 0 }; + SocketAddress theAddress = new InetSocketAddress(InetAddress.getLocalHost(), 0); + SocketAddress nonConnectableAddress = new InetSocketAddress(InetAddress.getByAddress(theBytes), 0); + SocketAddress nonReachableAddress = new InetSocketAddress(InetAddress.getByName(Support_Configuration.ResolvedNotExistingHost), 0); + SocketAddress invalidType = new mySocketAddress(); - theAddress = new InetSocketAddress(InetAddress.getLocalHost(), - portNumber); - nonConnectableAddress = new InetSocketAddress(InetAddress - .getByAddress(theBytes), portNumber); - nonReachableAddress = new InetSocketAddress(InetAddress - .getByName(Support_Configuration.ResolvedNotExistingHost), - portNumber); - // make sure we get another port - Thread.sleep(7000); - nonListeningAddress = new InetSocketAddress(InetAddress.getLocalHost(), - Support_PortManager.getNextPort()); - invalidType = new mySocketAddress(); + Socket theSocket = null; + ServerSocket serverSocket = null; try { theSocket = new Socket(); @@ -1340,9 +1225,8 @@ public class OldSocketTest extends OldSocketTestCase { // now validate that we can actually connect when somebody is listening theSocket = new Socket(); - serverSocket = new ServerSocket(); - serverSocket.bind(theAddress); - theSocket.connect(theAddress, 0); + serverSocket = new ServerSocket(0, 5); + theSocket.connect(serverSocket.getLocalSocketAddress()); theSocket.close(); serverSocket.close(); @@ -1350,7 +1234,7 @@ public class OldSocketTest extends OldSocketTestCase { // an address on which nobody is listening try { theSocket = new Socket(); - theSocket.connect(nonListeningAddress, 100000); + theSocket.connect(new InetSocketAddress(InetAddress.getLocalHost(), 80), 100000); theSocket.close(); fail("No exception when connecting to address nobody listening on: "); } catch (Exception e) { @@ -1390,12 +1274,9 @@ public class OldSocketTest extends OldSocketTestCase { } // now validate that we can actually connect when somebody is listening - new InetSocketAddress(InetAddress.getLocalHost(), Support_PortManager - .getNextPort()); theSocket = new Socket(); - serverSocket = new ServerSocket(); - serverSocket.bind(theAddress); - theSocket.connect(theAddress, 100000); + serverSocket = new ServerSocket(0, 5); + theSocket.connect(serverSocket.getLocalSocketAddress()); // validate that when a socket is connected that it answers // correctly to related queries @@ -1419,8 +1300,6 @@ public class OldSocketTest extends OldSocketTestCase { // now validate that we get the right exception if we connect when we // are already connected try { - new InetSocketAddress(InetAddress.getLocalHost(), - Support_PortManager.getNextPort()); theSocket = new Socket(); serverSocket = new ServerSocket(); serverSocket.bind(theAddress); @@ -1447,12 +1326,9 @@ public class OldSocketTest extends OldSocketTestCase { } // now validate that connected socket can be used to read/write - new InetSocketAddress(InetAddress.getLocalHost(), Support_PortManager - .getNextPort()); theSocket = new Socket(); - serverSocket = new ServerSocket(); - serverSocket.bind(theAddress); - theSocket.connect(theAddress, 100000); + serverSocket = new ServerSocket(0, 5); + theSocket.connect(serverSocket.getLocalSocketAddress()); Socket servSock = serverSocket.accept(); InputStream theInput = theSocket.getInputStream(); OutputStream theOutput = servSock.getOutputStream(); @@ -1515,10 +1391,8 @@ public class OldSocketTest extends OldSocketTestCase { SocketChannel channel = SocketChannel.open(); channel.configureBlocking(false); Socket socket = channel.socket(); - int port = Support_PortManager.getNextPort(); try { - socket.connect( new InetSocketAddress(InetAddress.getLocalHost(), - Support_PortManager.getNextPort()), port); + socket.connect(serverSocket.getLocalSocketAddress()); fail("IllegalBlockingModeException was not thrown."); } catch (IllegalBlockingModeException expected) { } @@ -1526,12 +1400,9 @@ public class OldSocketTest extends OldSocketTestCase { } public void test_isInputShutdown() throws IOException { - InetSocketAddress theAddress = new InetSocketAddress(InetAddress - .getLocalHost(), Support_PortManager.getNextPort()); Socket theSocket = new Socket(); - ServerSocket serverSocket = new ServerSocket(); - serverSocket.bind(theAddress); - theSocket.connect(theAddress); + ServerSocket serverSocket = new ServerSocket(0, 5); + theSocket.connect(serverSocket.getLocalSocketAddress()); Socket servSock = serverSocket.accept(); InputStream theInput = theSocket.getInputStream(); OutputStream theOutput = servSock.getOutputStream(); @@ -1559,12 +1430,9 @@ public class OldSocketTest extends OldSocketTestCase { } public void test_isOutputShutdown() throws IOException { - InetSocketAddress theAddress = new InetSocketAddress(InetAddress - .getLocalHost(), Support_PortManager.getNextPort()); Socket theSocket = new Socket(); - ServerSocket serverSocket = new ServerSocket(); - serverSocket.bind(theAddress); - theSocket.connect(theAddress); + ServerSocket serverSocket = new ServerSocket(0, 5); + theSocket.connect(serverSocket.getLocalSocketAddress()); Socket servSock = serverSocket.accept(); InputStream theInput = theSocket.getInputStream(); OutputStream theOutput = servSock.getOutputStream(); @@ -1591,18 +1459,14 @@ public class OldSocketTest extends OldSocketTestCase { } - public void test_setReuseAddressZ() { + public void test_setReuseAddressZ() throws Exception { try { InetAddress allAddresses[] = InetAddress.getAllByName(InetAddress .getLocalHost().getHostName()); if (allAddresses.length > 1) { - InetSocketAddress theAddress = new InetSocketAddress( - InetAddress.getLocalHost(), Support_PortManager - .getNextPort()); - ServerSocket serverSocket = new ServerSocket(); - serverSocket.bind(theAddress); + ServerSocket serverSocket = new ServerSocket(0, 5); // try to bind to port address that is already in use with // reuseAddress = false. @@ -1612,17 +1476,15 @@ public class OldSocketTest extends OldSocketTestCase { // what the expected result is. It seems that on linux // platforms we also don't get an exception. InetSocketAddress theLocalAddress = new InetSocketAddress( - (InetAddress) allAddresses[1], Support_PortManager - .getNextPort()); + (InetAddress) allAddresses[1], 0); InetSocketAddress theOtherLocalAddress = new InetSocketAddress( - (InetAddress) allAddresses[0], theLocalAddress - .getPort()); + (InetAddress) allAddresses[0], theLocalAddress.getPort()); Socket theSocket = new Socket(); theSocket.setReuseAddress(false); theSocket.bind(theLocalAddress); Socket theSocket2 = null; String platform = System.getProperty("os.name"); - try { + theSocket2 = new Socket(); theSocket2.setReuseAddress(false); theSocket2.bind(theOtherLocalAddress); @@ -1639,69 +1501,34 @@ public class OldSocketTest extends OldSocketTestCase { + ":" + theOtherLocalAddress.toString()); } - } catch (IOException ex) { - if ((platform.startsWith("Linux")) - || ((platform.startsWith("Windows")) && ((((InetAddress) allAddresses[0]) instanceof Inet4Address) && (((InetAddress) allAddresses[1]) instanceof Inet4Address)))) { - fail("Got unexpected exception when binding with setReuseAddress false on windows platform:" - + theAddress.toString() + ":" + ex.toString()); - } - } theSocket.close(); theSocket2.close(); // try to bind to port that is already in use with reuseAddress // = true - theLocalAddress = new InetSocketAddress( - (InetAddress) allAddresses[0], Support_PortManager - .getNextPort()); - theOtherLocalAddress = new InetSocketAddress( - (InetAddress) allAddresses[1], theLocalAddress - .getPort()); + theLocalAddress = new InetSocketAddress((InetAddress) allAddresses[0], 0); theSocket = new Socket(); theSocket.setReuseAddress(true); theSocket.bind(theLocalAddress); - try { - theSocket2 = new Socket(); - theSocket2.setReuseAddress(true); - theSocket2.bind(theOtherLocalAddress); - theSocket2.close(); - } catch (IOException ex) { - fail("IOException when setReuseAddress is true and we bind :" - + ex.toString()); - } + theSocket2 = new Socket(); + theSocket2.setReuseAddress(true); + theOtherLocalAddress = new InetSocketAddress((InetAddress) allAddresses[1], theSocket.getLocalPort()); + theSocket2.bind(theOtherLocalAddress); + theSocket2.close(); theSocket.close(); serverSocket.close(); // try with default behavior which should be the same on all // platforms - theLocalAddress = new InetSocketAddress( - (InetAddress) allAddresses[0], Support_PortManager - .getNextPort()); - theOtherLocalAddress = new InetSocketAddress( - (InetAddress) allAddresses[1], theLocalAddress - .getPort()); + theLocalAddress = new InetSocketAddress((InetAddress) allAddresses[0], 0); theSocket = new Socket(); theSocket.bind(theLocalAddress); - try { - theSocket2 = new Socket(); - theSocket2.bind(theOtherLocalAddress); - theSocket2.close(); - if ((!platform.startsWith("Linux")) - && ((!platform.startsWith("Windows")) || !((((InetAddress) allAddresses[0]) instanceof Inet4Address) && (((InetAddress) allAddresses[1]) instanceof Inet4Address)))) { - fail("No exception when setReuseAddress is default and we bind:" - + theLocalAddress.toString() - + ":" - + theOtherLocalAddress.toString()); - } - } catch (IOException ex) { - if ((platform.startsWith("Linux")) - || ((platform.startsWith("Windows")) && ((((InetAddress) allAddresses[0]) instanceof Inet4Address) && (((InetAddress) allAddresses[1]) instanceof Inet4Address)))) { - fail("Got unexpected exception when binding with setReuseAddress default on windows platform:" - + theAddress.toString() + ":" + ex.toString()); - } - } + theSocket2 = new Socket(); + theOtherLocalAddress = new InetSocketAddress((InetAddress) allAddresses[1], theSocket.getLocalPort()); + theSocket2.bind(theOtherLocalAddress); + theSocket2.close(); theSocket.close(); serverSocket.close(); @@ -1754,8 +1581,6 @@ public class OldSocketTest extends OldSocketTestCase { public void test_setOOBInlineZ() { // mostly tested in getOOBInline. Just set to make sure call works ok try { - new InetSocketAddress(InetAddress.getLocalHost(), - Support_PortManager.getNextPort()); Socket theSocket = new Socket(); theSocket.setOOBInline(true); assertTrue("expected OOBIline to be true", theSocket.getOOBInline()); @@ -1779,8 +1604,6 @@ public class OldSocketTest extends OldSocketTestCase { public void test_getOOBInline() { try { - new InetSocketAddress(InetAddress.getLocalHost(), - Support_PortManager.getNextPort()); Socket theSocket = new Socket(); // validate that value reflects what we set it to true after true, @@ -1812,8 +1635,6 @@ public class OldSocketTest extends OldSocketTestCase { int IPTOS_LOWCOST = 0x2; int IPTOS_THROUGHPUT = 0x8; - new InetSocketAddress(InetAddress.getLocalHost(), - Support_PortManager.getNextPort()); Socket theSocket = new Socket(); // validate that value set must be between 0 and 255 @@ -1851,8 +1672,6 @@ public class OldSocketTest extends OldSocketTestCase { public void test_getTrafficClass() { try { - new InetSocketAddress(InetAddress.getLocalHost(), - Support_PortManager.getNextPort()); Socket theSocket = new Socket(); /* @@ -1888,13 +1707,9 @@ public class OldSocketTest extends OldSocketTestCase { // is silently ignored String urgentData = "U"; try { - InetSocketAddress theAddress = new InetSocketAddress( - InetAddress.getLocalHost(), Support_PortManager - .getNextPort()); Socket theSocket = new Socket(); - ServerSocket serverSocket = new ServerSocket(); - serverSocket.bind(theAddress); - theSocket.connect(theAddress); + ServerSocket serverSocket = new ServerSocket(0, 5); + theSocket.connect(serverSocket.getLocalSocketAddress()); Socket servSock = serverSocket.accept(); InputStream theInput = theSocket.getInputStream(); OutputStream theOutput = servSock.getOutputStream(); @@ -1931,12 +1746,9 @@ public class OldSocketTest extends OldSocketTestCase { // now validate that urgent data is received as expected. Expect // that it should be between the two writes. - theAddress = new InetSocketAddress(InetAddress.getLocalHost(), - Support_PortManager.getNextPort()); theSocket = new Socket(); - serverSocket = new ServerSocket(); - serverSocket.bind(theAddress); - theSocket.connect(theAddress); + serverSocket = new ServerSocket(0, 5); + theSocket.connect(serverSocket.getLocalSocketAddress()); servSock = serverSocket.accept(); theInput = theSocket.getInputStream(); theOutput = servSock.getOutputStream(); @@ -1973,12 +1785,9 @@ public class OldSocketTest extends OldSocketTestCase { serverSocket.close(); // now test case where we try to send two urgent bytes. - theAddress = new InetSocketAddress(InetAddress.getLocalHost(), - Support_PortManager.getNextPort()); theSocket = new Socket(); - serverSocket = new ServerSocket(); - serverSocket.bind(theAddress); - theSocket.connect(theAddress); + serverSocket = new ServerSocket(0, 5); + theSocket.connect(serverSocket.getLocalSocketAddress()); servSock = serverSocket.accept(); theInput = theSocket.getInputStream(); theOutput = servSock.getOutputStream(); @@ -2022,12 +1831,9 @@ public class OldSocketTest extends OldSocketTestCase { */ if (!platform.startsWith("Windows")) { // now test the case were we send turn the OOBInline on/off - theAddress = new InetSocketAddress(InetAddress - .getLocalHost(), Support_PortManager.getNextPort()); theSocket = new Socket(); - serverSocket = new ServerSocket(); - serverSocket.bind(theAddress); - theSocket.connect(theAddress); + serverSocket = new ServerSocket(0, 5); + theSocket.connect(serverSocket.getLocalSocketAddress()); servSock = serverSocket.accept(); theInput = theSocket.getInputStream(); theOutput = servSock.getOutputStream(); @@ -2139,12 +1945,9 @@ public class OldSocketTest extends OldSocketTestCase { } // now test the case where there is only urgent data - theAddress = new InetSocketAddress(InetAddress.getLocalHost(), - Support_PortManager.getNextPort()); theSocket = new Socket(); - serverSocket = new ServerSocket(); - serverSocket.bind(theAddress); - theSocket.connect(theAddress); + serverSocket = new ServerSocket(0, 5); + theSocket.connect(serverSocket.getLocalSocketAddress()); servSock = serverSocket.accept(); theInput = theSocket.getInputStream(); theOutput = servSock.getOutputStream(); @@ -2370,13 +2173,9 @@ public class OldSocketTest extends OldSocketTestCase { } - /** - * - */ protected int startServer(String name) { - int portNumber = Support_PortManager.getNextPort(); try { - ss = new ServerSocket(portNumber, 5); + ss = new ServerSocket(0, 5); } catch (IOException e) { fail(name + ": " + e); } diff --git a/luni/src/test/java/libcore/java/net/OldURLClassLoaderTest.java b/luni/src/test/java/libcore/java/net/OldURLClassLoaderTest.java index 2646f98..3a5608c 100644 --- a/luni/src/test/java/libcore/java/net/OldURLClassLoaderTest.java +++ b/luni/src/test/java/libcore/java/net/OldURLClassLoaderTest.java @@ -35,7 +35,6 @@ import java.util.List; import java.util.jar.Manifest; import org.apache.harmony.security.tests.support.TestCertUtils; import tests.support.Support_Configuration; -import tests.support.Support_PortManager; import tests.support.Support_TestWebData; import tests.support.Support_TestWebServer; import tests.support.resource.Support_Resources; @@ -210,13 +209,12 @@ public class OldURLClassLoaderTest extends junit.framework.TestCase { @SideEffect("Support_TestWebServer requires isolation.") public void test_findResourceLjava_lang_String() throws Exception { - int port = Support_PortManager.getNextPort(); File tmp = File.createTempFile("test", ".txt"); Support_TestWebServer server = new Support_TestWebServer(); try { - server.initServer(port, tmp.getAbsolutePath(), "text/html"); + int port = server.initServer(tmp.getAbsolutePath(), "text/html"); URL[] urls = { new URL("http://localhost:" + port + "/") }; ucl = new URLClassLoader(urls); @@ -244,9 +242,8 @@ public class OldURLClassLoaderTest extends junit.framework.TestCase { tempFile2.deleteOnExit(); Support_TestWebServer server = new Support_TestWebServer(); - int port = Support_PortManager.getNextPort(); try { - server.initServer(port, false); + int port = server.initServer(); String tempPath1 = tempFile1.getParentFile().getAbsolutePath() + "/"; InputStream is = getClass().getResourceAsStream( diff --git a/luni/src/test/java/libcore/java/net/URITest.java b/luni/src/test/java/libcore/java/net/URITest.java index b37358c..04a7d2e 100644 --- a/luni/src/test/java/libcore/java/net/URITest.java +++ b/luni/src/test/java/libcore/java/net/URITest.java @@ -659,5 +659,13 @@ public final class URITest extends TestCase { } } + // http://code.google.com/p/android/issues/detail?id=37577 + public void testUnderscore() throws Exception { + URI uri = new URI("http://a_b.c.d.net/"); + assertEquals("a_b.c.d.net", uri.getAuthority()); + // The RFC's don't permit underscores in hostnames, and neither does URI (unlike URL). + assertNull(uri.getHost()); + } + // Adding a new test? Consider adding an equivalent test to URLTest.java } diff --git a/luni/src/test/java/libcore/java/net/URLConnectionTest.java b/luni/src/test/java/libcore/java/net/URLConnectionTest.java index 347242a..1f2ebf9 100644 --- a/luni/src/test/java/libcore/java/net/URLConnectionTest.java +++ b/luni/src/test/java/libcore/java/net/URLConnectionTest.java @@ -24,7 +24,9 @@ import static com.google.mockwebserver.SocketPolicy.DISCONNECT_AT_END; import static com.google.mockwebserver.SocketPolicy.DISCONNECT_AT_START; import static com.google.mockwebserver.SocketPolicy.SHUTDOWN_INPUT_AT_END; import static com.google.mockwebserver.SocketPolicy.SHUTDOWN_OUTPUT_AT_END; +import dalvik.system.CloseGuard; import java.io.ByteArrayOutputStream; +import java.io.Closeable; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -76,6 +78,7 @@ import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import junit.framework.TestCase; +import libcore.java.lang.ref.FinalizationTester; import libcore.java.security.TestKeyStore; import libcore.javax.net.ssl.TestSSLContext; import libcore.net.http.HttpResponseCache; @@ -792,6 +795,27 @@ public final class URLConnectionTest extends TestCase { assertContainsNoneMatching(get.getHeaders(), "Proxy\\-Authorization.*"); } + // Don't disconnect after building a tunnel with CONNECT + // http://code.google.com/p/android/issues/detail?id=37221 + public void testProxyWithConnectionClose() throws IOException { + TestSSLContext testSSLContext = TestSSLContext.create(); + server.useHttps(testSSLContext.serverContext.getSocketFactory(), true); + server.enqueue(new MockResponse() + .setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END) + .clearHeaders()); + server.enqueue(new MockResponse().setBody("this response comes via a proxy")); + server.play(); + + URL url = new URL("https://android.com/foo"); + HttpsURLConnection connection = (HttpsURLConnection) url.openConnection( + server.toProxyAddress()); + connection.setRequestProperty("Connection", "close"); + connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory()); + connection.setHostnameVerifier(new RecordingHostnameVerifier()); + + assertContent("this response comes via a proxy", connection); + } + public void testDisconnectedConnection() throws IOException { server.enqueue(new MockResponse().setBody("ABCDEFGHIJKLMNOPQR")); server.play(); @@ -818,6 +842,50 @@ public final class URLConnectionTest extends TestCase { assertEquals(200, connection.getResponseCode()); } + public void testDisconnectAfterOnlyResponseCodeCausesNoCloseGuardWarning() throws IOException { + CloseGuardGuard guard = new CloseGuardGuard(); + try { + server.enqueue(new MockResponse() + .setBody(gzip("ABCABCABC".getBytes("UTF-8"))) + .addHeader("Content-Encoding: gzip")); + server.play(); + + HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); + assertEquals(200, connection.getResponseCode()); + connection.disconnect(); + connection = null; + assertFalse(guard.wasCloseGuardCalled()); + } finally { + guard.close(); + } + } + + public static class CloseGuardGuard implements Closeable, CloseGuard.Reporter { + private final CloseGuard.Reporter oldReporter = CloseGuard.getReporter(); + + private AtomicBoolean closeGuardCalled = new AtomicBoolean(); + + public CloseGuardGuard() { + CloseGuard.setReporter(this); + } + + @Override public void report(String message, Throwable allocationSite) { + oldReporter.report(message, allocationSite); + closeGuardCalled.set(true); + } + + public boolean wasCloseGuardCalled() { + FinalizationTester.induceFinalization(); + close(); + return closeGuardCalled.get(); + } + + @Override public void close() { + CloseGuard.setReporter(oldReporter); + } + + } + public void testDefaultRequestProperty() throws Exception { URLConnection.setDefaultRequestProperty("X-testSetDefaultRequestProperty", "A"); assertNull(URLConnection.getDefaultRequestProperty("X-setDefaultRequestProperty")); @@ -942,21 +1010,25 @@ public final class URLConnectionTest extends TestCase { URLConnection connection = server.getUrl("/").openConnection(); assertEquals("ABCABCABC", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); assertNull(connection.getContentEncoding()); + assertEquals(-1, connection.getContentLength()); RecordedRequest request = server.takeRequest(); assertContains(request.getHeaders(), "Accept-Encoding: gzip"); } public void testClientConfiguredGzipContentEncoding() throws Exception { + byte[] bodyBytes = gzip("ABCDEFGHIJKLMNOPQRSTUVWXYZ".getBytes("UTF-8")); server.enqueue(new MockResponse() - .setBody(gzip("ABCDEFGHIJKLMNOPQRSTUVWXYZ".getBytes("UTF-8"))) - .addHeader("Content-Encoding: gzip")); + .setBody(bodyBytes) + .addHeader("Content-Encoding: gzip") + .addHeader("Content-Length: " + bodyBytes.length)); server.play(); URLConnection connection = server.getUrl("/").openConnection(); connection.addRequestProperty("Accept-Encoding", "gzip"); InputStream gunzippedIn = new GZIPInputStream(connection.getInputStream()); assertEquals("ABCDEFGHIJKLMNOPQRSTUVWXYZ", readAscii(gunzippedIn, Integer.MAX_VALUE)); + assertEquals(bodyBytes.length, connection.getContentLength()); RecordedRequest request = server.takeRequest(); assertContains(request.getHeaders(), "Accept-Encoding: gzip"); @@ -1573,7 +1645,7 @@ public final class URLConnectionTest extends TestCase { * addresses. This is typically one IPv4 address and one IPv6 address. */ public void testConnectTimeouts() throws IOException { - StuckServer ss = new StuckServer(); + StuckServer ss = new StuckServer(false); int serverPort = ss.getLocalPort(); URLConnection urlConnection = new URL("http://localhost:" + serverPort).openConnection(); int timeout = 1000; diff --git a/luni/src/test/java/libcore/java/net/URLTest.java b/luni/src/test/java/libcore/java/net/URLTest.java index ced8314..962088e 100644 --- a/luni/src/test/java/libcore/java/net/URLTest.java +++ b/luni/src/test/java/libcore/java/net/URLTest.java @@ -686,5 +686,13 @@ public final class URLTest extends TestCase { assertEquals("re f", new URL("http://host/file?query#re f").getRef()); } + // http://code.google.com/p/android/issues/detail?id=37577 + public void testUnderscore() throws Exception { + URL url = new URL("http://a_b.c.d.net/"); + assertEquals("a_b.c.d.net", url.getAuthority()); + // The RFC's don't permit underscores in hostnames, but URL accepts them (unlike URI). + assertEquals("a_b.c.d.net", url.getHost()); + } + // Adding a new test? Consider adding an equivalent test to URITest.java } diff --git a/luni/src/test/java/libcore/java/nio/BufferTest.java b/luni/src/test/java/libcore/java/nio/BufferTest.java index 06a8e94..2a895fc 100644 --- a/luni/src/test/java/libcore/java/nio/BufferTest.java +++ b/luni/src/test/java/libcore/java/nio/BufferTest.java @@ -675,4 +675,80 @@ public class BufferTest extends TestCase { } assertFalse(bb.hasArray()); } + + public void testBug6085292() { + ByteBuffer b = ByteBuffer.allocateDirect(1); + + try { + b.asCharBuffer().get(); + fail(); + } catch (BufferUnderflowException expected) { + } + try { + b.asCharBuffer().get(0); + fail(); + } catch (IndexOutOfBoundsException expected) { + assertTrue(expected.getMessage().contains("limit=0")); + } + + try { + b.asDoubleBuffer().get(); + fail(); + } catch (BufferUnderflowException expected) { + } + try { + b.asDoubleBuffer().get(0); + fail(); + } catch (IndexOutOfBoundsException expected) { + assertTrue(expected.getMessage().contains("limit=0")); + } + + try { + b.asFloatBuffer().get(); + fail(); + } catch (BufferUnderflowException expected) { + } + try { + b.asFloatBuffer().get(0); + fail(); + } catch (IndexOutOfBoundsException expected) { + assertTrue(expected.getMessage().contains("limit=0")); + } + + try { + b.asIntBuffer().get(); + fail(); + } catch (BufferUnderflowException expected) { + } + try { + b.asIntBuffer().get(0); + fail(); + } catch (IndexOutOfBoundsException expected) { + assertTrue(expected.getMessage().contains("limit=0")); + } + + try { + b.asLongBuffer().get(); + fail(); + } catch (BufferUnderflowException expected) { + } + try { + b.asLongBuffer().get(0); + fail(); + } catch (IndexOutOfBoundsException expected) { + assertTrue(expected.getMessage().contains("limit=0")); + } + + try { + b.asShortBuffer().get(); + fail(); + } catch (BufferUnderflowException expected) { + } + try { + b.asShortBuffer().get(0); + fail(); + } catch (IndexOutOfBoundsException expected) { + assertTrue(expected.getMessage().contains("limit=0")); + } + } } diff --git a/luni/src/test/java/libcore/java/nio/channels/OldServerSocketChannelTest.java b/luni/src/test/java/libcore/java/nio/channels/OldServerSocketChannelTest.java index fb63512..51f288a 100644 --- a/luni/src/test/java/libcore/java/nio/channels/OldServerSocketChannelTest.java +++ b/luni/src/test/java/libcore/java/nio/channels/OldServerSocketChannelTest.java @@ -25,26 +25,17 @@ import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.channels.spi.SelectorProvider; import junit.framework.TestCase; -import tests.support.Support_PortManager; -/* - * test for ServerSocketChannel - */ public class OldServerSocketChannelTest extends TestCase { private static final int TIME_UNIT = 200; - private InetSocketAddress localAddr1; - private ServerSocketChannel serverChannel; private SocketChannel clientChannel; protected void setUp() throws Exception { super.setUp(); - this.localAddr1 = new InetSocketAddress( - "127.0.0.1", Support_PortManager - .getNextPort()); this.serverChannel = ServerSocketChannel.open(); this.clientChannel = SocketChannel.open(); } @@ -87,7 +78,7 @@ public class OldServerSocketChannelTest extends TestCase { public void test_accept_Block_NoConnect_interrupt() throws IOException { assertTrue(this.serverChannel.isBlocking()); ServerSocket gotSocket = this.serverChannel.socket(); - gotSocket.bind(localAddr1); + gotSocket.bind(null); class MyThread extends Thread { public String errMsg = null; diff --git a/luni/src/test/java/libcore/java/nio/channels/OldSocketChannelTest.java b/luni/src/test/java/libcore/java/nio/channels/OldSocketChannelTest.java index f182375..6560a7b 100644 --- a/luni/src/test/java/libcore/java/nio/channels/OldSocketChannelTest.java +++ b/luni/src/test/java/libcore/java/nio/channels/OldSocketChannelTest.java @@ -35,11 +35,7 @@ import java.nio.channels.UnresolvedAddressException; import java.nio.channels.UnsupportedAddressTypeException; import java.nio.channels.spi.SelectorProvider; import junit.framework.TestCase; -import tests.support.Support_PortManager; -/** - * Tests for SocketChannel and its default implementation. - */ public class OldSocketChannelTest extends TestCase { private static final int CAPACITY_NORMAL = 200; @@ -58,11 +54,10 @@ public class OldSocketChannelTest extends TestCase { protected void setUp() throws Exception { super.setUp(); - this.localAddr1 = new InetSocketAddress("127.0.0.1", - Support_PortManager.getNextPort()); this.channel1 = SocketChannel.open(); this.channel2 = SocketChannel.open(); - this.server1 = new ServerSocket(localAddr1.getPort()); + this.server1 = new ServerSocket(0); + this.localAddr1 = (InetSocketAddress) server1.getLocalSocketAddress(); } protected void tearDown() throws Exception { @@ -287,17 +282,27 @@ public class OldSocketChannelTest extends TestCase { } public void test_socketChannel_read_DirectByteBuffer() throws InterruptedException, IOException { - - ServerThread server = new ServerThread(); + final ServerSocketChannel ssc = ServerSocketChannel.open(); + ssc.socket().bind(null, 0); + + Thread server = new Thread() { + @Override public void run() { + try { + for (int i = 0; i < 2; ++i) { + ByteBuffer buf = ByteBuffer.allocate(10); + buf.put(data); + buf.rewind(); + ssc.accept().write(buf); + } + } catch (Exception ignored) { + } + } + }; server.start(); - Thread.currentThread().sleep(1000); - - InetSocketAddress address = new InetSocketAddress(InetAddress - .getByName("localhost"), port); // First test with array based byte buffer SocketChannel sc = SocketChannel.open(); - sc.connect(address); + sc.connect(ssc.socket().getLocalSocketAddress()); ByteBuffer buf = ByteBuffer.allocate(data.length); buf.limit(data.length / 2); @@ -313,7 +318,7 @@ public class OldSocketChannelTest extends TestCase { // Now test with direct byte buffer sc = SocketChannel.open(); - sc.connect(address); + sc.connect(ssc.socket().getLocalSocketAddress()); buf = ByteBuffer.allocateDirect(data.length); buf.limit(data.length / 2); @@ -339,32 +344,8 @@ public class OldSocketChannelTest extends TestCase { } public static boolean done = false; - public static int port = Support_PortManager.getNextPort(); public static byte[] data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - static class ServerThread extends Thread { - @Override - public void run() { - try { - ServerSocketChannel ssc = ServerSocketChannel.open(); - InetSocketAddress addr = new InetSocketAddress(InetAddress - .getByAddress(new byte[] {0, 0, 0, 0}), port); - ssc.socket().bind(addr, 0); - - ByteBuffer buf = ByteBuffer.allocate(10); - buf.put(data); - - while (!done) { - SocketChannel sc = ssc.accept(); - buf.rewind(); - sc.write(buf); - } - } catch (Exception e) { - // ignore - } - } - } - class MockSocketChannel extends SocketChannel { private boolean isConstructorCalled = false; diff --git a/luni/src/test/java/libcore/java/nio/channels/SelectorTest.java b/luni/src/test/java/libcore/java/nio/channels/SelectorTest.java index f73b6d5..4fc70c4 100644 --- a/luni/src/test/java/libcore/java/nio/channels/SelectorTest.java +++ b/luni/src/test/java/libcore/java/nio/channels/SelectorTest.java @@ -55,11 +55,10 @@ public class SelectorTest extends TestCase { public void testNonBlockingConnect_slow() throws Exception { // Test the case where we have to wait for the connection. Selector selector = Selector.open(); - StuckServer ss = new StuckServer(); + StuckServer ss = new StuckServer(true); try { SocketChannel sc = SocketChannel.open(); sc.configureBlocking(false); - ss.unblockAfterMs(2000); sc.connect(ss.getLocalSocketAddress()); SelectionKey key = sc.register(selector, SelectionKey.OP_CONNECT); assertEquals(1, selector.select()); diff --git a/luni/src/test/java/libcore/java/security/KeyStoreTest.java b/luni/src/test/java/libcore/java/security/KeyStoreTest.java index 14d0987..ddee6ce 100644 --- a/luni/src/test/java/libcore/java/security/KeyStoreTest.java +++ b/luni/src/test/java/libcore/java/security/KeyStoreTest.java @@ -21,6 +21,7 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.Key; @@ -44,13 +45,13 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; +import java.util.Enumeration; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import junit.framework.TestCase; -import libcore.io.IoUtils; public class KeyStoreTest extends TestCase { @@ -65,10 +66,12 @@ public class KeyStoreTest extends TestCase { private static final String ALIAS_SECRET = "secret"; private static final String ALIAS_ALT_CASE_PRIVATE = "pRiVaTe"; + private static final String ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE = "PrIvAtE-no-password"; private static final String ALIAS_ALT_CASE_CERTIFICATE = "cErTiFiCaTe"; private static final String ALIAS_ALT_CASE_SECRET = "sEcRet"; private static final String ALIAS_UNICODE_PRIVATE = "\u6400\u7902\u3101\u8c02\u5002\u8702\udd01"; + private static final String ALIAS_UNICODE_NO_PASSWORD_PRIVATE = "\u926c\u0967\uc65b\ubc78"; private static final String ALIAS_UNICODE_CERTIFICATE = "\u5402\udd01\u7902\u8702\u3101\u5f02\u3101\u5402\u5002\u8702\udd01"; private static final String ALIAS_UNICODE_SECRET = "\ue224\ud424\ud224\ue124\ud424\ue324"; @@ -146,7 +149,8 @@ public class KeyStoreTest extends TestCase { // JKS key stores cannot store secret keys, neither can the RI's PKCS12 return (!(ks.getType().equals("JKS") || ks.getType().equals("CaseExactJKS") - || (ks.getType().equals("PKCS12")))); + || (ks.getType().equals("PKCS12")) + || (ks.getType().equals("AndroidKeyStore")))); } private static boolean isCertificateEnabled(KeyStore ks) { @@ -157,13 +161,16 @@ public class KeyStoreTest extends TestCase { private static boolean isCaseSensitive(KeyStore ks) { return (ks.getType().equals("CaseExactJKS") || ks.getType().equals("BKS") - || ks.getType().equals("BouncyCastle")); + || ks.getType().equals("BouncyCastle") + || ks.getType().equals("AndroidKeyStore")); } private static boolean isUnsupported(KeyStore ks) { // Don't bother testing BC on RI - return (StandardNames.IS_RI && ks.getProvider().getName().equals("BC")); + // TODO enable AndroidKeyStore when CTS can set up the keystore + return (StandardNames.IS_RI && ks.getProvider().getName().equals("BC")) + || "AndroidKeyStore".equalsIgnoreCase(ks.getType()); } private static boolean isNullPasswordAllowed(KeyStore ks) { @@ -172,7 +179,9 @@ public class KeyStoreTest extends TestCase { || ks.getType().equals("JCEKS") || ks.getType().equals("PKCS12"))); } - + private static boolean isKeyPasswordSupported(KeyStore ks) { + return !ks.getType().equals("AndroidKeyStore"); + } private static boolean isKeyPasswordIgnored(KeyStore ks) { // BouncyCastle's PKCS12 ignores the key password unlike the RI which requires it return (ks.getType().equals("PKCS12") && ks.getProvider().getName().equals("BC")); @@ -183,6 +192,14 @@ public class KeyStoreTest extends TestCase { return (ks.getType().equals("PKCS12") && ks.getProvider().getName().equals("BC")); } + private static boolean isPersistentStorage(KeyStore ks) { + return ks.getType().equalsIgnoreCase("AndroidKeyStore"); + } + + private static boolean isLoadStoreUnsupported(KeyStore ks) { + return ks.getType().equalsIgnoreCase("AndroidKeyStore"); + } + private static boolean isSetKeyByteArrayUnimplemented(KeyStore ks) { // All of BouncyCastle's // KeyStore.setKeyEntry(String,byte[],char[]) implementations @@ -203,16 +220,13 @@ public class KeyStoreTest extends TestCase { } public static void populate(KeyStore ks) throws Exception { - ks.load(null, null); - if (isReadOnly(ks)) { - try { - setPrivateKey(ks); - fail(); - } catch (UnsupportedOperationException e) { - } + boolean readOnly = clearKeyStore(ks); + if (readOnly) { return; } - setPrivateKey(ks); + if (isKeyPasswordSupported(ks)) { + setPrivateKey(ks); + } if (isNullPasswordAllowed(ks)) { ks.setKeyEntry(ALIAS_NO_PASSWORD_PRIVATE, getPrivateKey().getPrivateKey(), @@ -234,6 +248,30 @@ public class KeyStoreTest extends TestCase { } } + private static boolean clearKeyStore(KeyStore ks) throws Exception { + ks.load(null, null); + if (isReadOnly(ks)) { + try { + setPrivateKey(ks); + fail(ks.toString()); + } catch (UnsupportedOperationException e) { + } + return true; + } + if (isPersistentStorage(ks)) { + Enumeration<String> aliases = ks.aliases(); + while (aliases.hasMoreElements()) { + String alias = aliases.nextElement(); + ks.deleteEntry(alias); + } + } + return false; + } + + public static void setPrivateKeyNoPassword(KeyStore ks, String alias, PrivateKeyEntry privateKey) + throws Exception { + ks.setKeyEntry(alias, privateKey.getPrivateKey(), null, privateKey.getCertificateChain()); + } public static void setPrivateKey(KeyStore ks) throws Exception { setPrivateKey(ks, ALIAS_PRIVATE); } @@ -377,7 +415,7 @@ public class KeyStoreTest extends TestCase { String type = KeyStore.getDefaultType(); try { KeyStore.getInstance(null); - fail(); + fail(type); } catch (NullPointerException expected) { } @@ -386,12 +424,12 @@ public class KeyStoreTest extends TestCase { String providerName = StandardNames.SECURITY_PROVIDER_NAME; try { KeyStore.getInstance(null, (String)null); - fail(); + fail(type); } catch (IllegalArgumentException expected) { } try { KeyStore.getInstance(null, providerName); - fail(); + fail(type); } catch (Exception e) { if (e.getClass() != NullPointerException.class && e.getClass() != KeyStoreException.class) { @@ -400,7 +438,7 @@ public class KeyStoreTest extends TestCase { } try { KeyStore.getInstance(type, (String)null); - fail(); + fail(type); } catch (IllegalArgumentException expected) { } assertNotNull(KeyStore.getInstance(type, providerName)); @@ -408,17 +446,17 @@ public class KeyStoreTest extends TestCase { Provider provider = Security.getProvider(providerName); try { KeyStore.getInstance(null, (Provider)null); - fail(); + fail(type); } catch (IllegalArgumentException expected) { } try { KeyStore.getInstance(null, provider); - fail(); + fail(type); } catch (NullPointerException expected) { } try { KeyStore.getInstance(type, (Provider)null); - fail(); + fail(type); } catch (IllegalArgumentException expected) { } assertNotNull(KeyStore.getInstance(type, provider)); @@ -457,7 +495,7 @@ public class KeyStoreTest extends TestCase { for (KeyStore keyStore : keyStores()) { try { keyStore.getKey(null, null); - fail(); + fail(keyStore.getType()); } catch (KeyStoreException expected) { } } @@ -468,7 +506,7 @@ public class KeyStoreTest extends TestCase { // test odd inputs try { keyStore.getKey(null, null); - fail(); + fail(keyStore.getType()); } catch (Exception e) { if (e.getClass() != NullPointerException.class && e.getClass() != IllegalArgumentException.class) { @@ -477,7 +515,7 @@ public class KeyStoreTest extends TestCase { } try { keyStore.getKey(null, PASSWORD_KEY); - fail(); + fail(keyStore.getType()); } catch (Exception e) { if (e.getClass() != NullPointerException.class && e.getClass() != IllegalArgumentException.class @@ -492,7 +530,12 @@ public class KeyStoreTest extends TestCase { if (isReadOnly(keyStore)) { assertNull(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); } else { - assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + if (isKeyPasswordSupported(keyStore)) { + assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + } + if (isNullPasswordAllowed(keyStore)) { + assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null)); + } if (isSecretKeyEnabled(keyStore)) { assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY)); } else { @@ -503,24 +546,30 @@ public class KeyStoreTest extends TestCase { // test case insensitive if (isCaseSensitive(keyStore) || isReadOnly(keyStore)) { assertNull(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY)); + assertNull(keyStore.getKey(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, PASSWORD_KEY)); assertNull(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY)); } else { - assertPrivateKey(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY)); + if (isKeyPasswordSupported(keyStore)) { + assertPrivateKey(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY)); + } + if (isNullPasswordAllowed(keyStore)) { + assertPrivateKey(keyStore.getKey(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, null)); + } if (isSecretKeyEnabled(keyStore)) { assertSecretKey(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY)); } } // test with null passwords - if (isKeyPasswordIgnored(keyStore)) { + if (isKeyPasswordSupported(keyStore) && isKeyPasswordIgnored(keyStore)) { assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, null)); } else { if (isReadOnly(keyStore)) { assertNull(keyStore.getKey(ALIAS_PRIVATE, null)); - } else { + } else if (isKeyPasswordSupported(keyStore)) { try { keyStore.getKey(ALIAS_PRIVATE, null); - fail(); + fail(keyStore.getType()); } catch (Exception e) { if (e.getClass() != UnrecoverableKeyException.class && e.getClass() != IllegalArgumentException.class) { @@ -534,7 +583,7 @@ public class KeyStoreTest extends TestCase { } else if (isSecretKeyEnabled(keyStore)) { try { keyStore.getKey(ALIAS_SECRET, null); - fail(); + fail(keyStore.getType()); } catch (Exception e) { if (e.getClass() != UnrecoverableKeyException.class && e.getClass() != IllegalArgumentException.class) { @@ -546,12 +595,12 @@ public class KeyStoreTest extends TestCase { // test with bad passwords if (isReadOnly(keyStore)) { assertNull(keyStore.getKey(ALIAS_PRIVATE, null)); - } else if (isKeyPasswordIgnored(keyStore)) { + } else if (isKeyPasswordSupported(keyStore) && isKeyPasswordIgnored(keyStore)) { assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, null)); - } else { + } else if (isKeyPasswordSupported(keyStore)) { try { keyStore.getKey(ALIAS_PRIVATE, PASSWORD_BAD); - fail(); + fail(keyStore.getType()); } catch (UnrecoverableKeyException expected) { } } @@ -560,7 +609,7 @@ public class KeyStoreTest extends TestCase { } else if (isSecretKeyEnabled(keyStore)) { try { keyStore.getKey(ALIAS_SECRET, PASSWORD_BAD); - fail(); + fail(keyStore.getType()); } catch (UnrecoverableKeyException expected) { } } @@ -571,7 +620,7 @@ public class KeyStoreTest extends TestCase { for (KeyStore keyStore : keyStores()) { try { keyStore.getCertificateChain(null); - fail(); + fail(keyStore.getType()); } catch (KeyStoreException expected) { } } @@ -581,7 +630,7 @@ public class KeyStoreTest extends TestCase { // test odd inputs try { keyStore.getCertificateChain(null); - fail(); + fail(keyStore.getType()); } catch (Exception e) { if (e.getClass() != NullPointerException.class && e.getClass() != IllegalArgumentException.class) { @@ -593,8 +642,10 @@ public class KeyStoreTest extends TestCase { // test case sensitive if (isReadOnly(keyStore)) { assertNull(keyStore.getCertificateChain(ALIAS_PRIVATE)); - } else { + } else if (isKeyPasswordSupported(keyStore)) { assertCertificateChain(keyStore.getCertificateChain(ALIAS_PRIVATE)); + } else if (isNullPasswordAllowed(keyStore)) { + assertCertificateChain(keyStore.getCertificateChain(ALIAS_NO_PASSWORD_PRIVATE)); } // test case insensitive @@ -610,7 +661,7 @@ public class KeyStoreTest extends TestCase { for (KeyStore keyStore : keyStores()) { try { keyStore.getCertificate(null); - fail(); + fail(keyStore.getType()); } catch (KeyStoreException expected) { } } @@ -620,7 +671,7 @@ public class KeyStoreTest extends TestCase { // test odd inputs try { keyStore.getCertificate(null); - fail(); + fail(keyStore.getType()); } catch (Exception e) { if (e.getClass() != NullPointerException.class && e.getClass() != IllegalArgumentException.class) { @@ -651,20 +702,21 @@ public class KeyStoreTest extends TestCase { for (KeyStore keyStore : keyStores()) { try { keyStore.getCreationDate(null); - fail(); + fail(keyStore.getType()); } catch (KeyStoreException expected) { } } long before = System.currentTimeMillis(); for (KeyStore keyStore : keyStores()) { + populate(keyStore); + // add 1000 since some key stores round of time to nearest second long after = System.currentTimeMillis() + 1000; - populate(keyStore); // test odd inputs try { keyStore.getCreationDate(null); - fail(); + fail(keyStore.getType()); } catch (NullPointerException expected) { } assertNull(keyStore.getCreationDate("")); @@ -673,8 +725,10 @@ public class KeyStoreTest extends TestCase { if (!isReadOnly(keyStore) && isCertificateEnabled(keyStore)) { Date date = keyStore.getCreationDate(ALIAS_CERTIFICATE); assertNotNull(date); - assertTrue(before <= date.getTime()); - assertTrue(date.getTime() <= after); + assertTrue("date should be after start time: " + date.getTime() + " >= " + before, + before <= date.getTime()); + assertTrue("date should be before expiry time: " + date.getTime() + " <= " + after, + date.getTime() <= after); } else { assertNull(keyStore.getCreationDate(ALIAS_CERTIFICATE)); } @@ -696,7 +750,7 @@ public class KeyStoreTest extends TestCase { for (KeyStore keyStore : keyStores()) { try { keyStore.setKeyEntry(null, null, null, null); - fail(); + fail(keyStore.getType()); } catch (KeyStoreException expected) { } } @@ -706,7 +760,7 @@ public class KeyStoreTest extends TestCase { if (isReadOnly(keyStore)) { try { keyStore.setKeyEntry(null, null, null, null); - fail(); + fail(keyStore.getType()); } catch (UnsupportedOperationException expected) { } continue; @@ -715,7 +769,7 @@ public class KeyStoreTest extends TestCase { // test odd inputs try { keyStore.setKeyEntry(null, null, null, null); - fail(); + fail(keyStore.getType()); } catch (Exception e) { if (e.getClass() != NullPointerException.class && e.getClass() != KeyStoreException.class) { @@ -724,7 +778,7 @@ public class KeyStoreTest extends TestCase { } try { keyStore.setKeyEntry(null, null, PASSWORD_KEY, null); - fail(); + fail(keyStore.getType()); } catch (Exception e) { if (e.getClass() != NullPointerException.class && e.getClass() != KeyStoreException.class) { @@ -736,27 +790,43 @@ public class KeyStoreTest extends TestCase { getPrivateKey().getPrivateKey(), PASSWORD_KEY, null); - fail(); - } catch (IllegalArgumentException expected) { + fail(keyStore.getType()); + } catch (Exception e) { + if (e.getClass() != IllegalArgumentException.class + && e.getClass() != KeyStoreException.class) { + throw e; + } } } for (KeyStore keyStore : keyStores()) { - keyStore.load(null, null); + clearKeyStore(keyStore); // test case sensitive - assertNull(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + if (isKeyPasswordSupported(keyStore)) { + assertNull(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + } + if (isNullPasswordAllowed(keyStore)) { + assertNull(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null)); + } if (isReadOnly(keyStore)) { try { keyStore.setKeyEntry(ALIAS_SECRET, getSecretKey(), PASSWORD_KEY, null); - fail(); + fail(keyStore.getType()); } catch (UnsupportedOperationException expected) { } continue; } - setPrivateKey(keyStore); - assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); - assertCertificateChain(keyStore.getCertificateChain(ALIAS_PRIVATE)); + if (isKeyPasswordSupported(keyStore)) { + setPrivateKey(keyStore); + assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + assertCertificateChain(keyStore.getCertificateChain(ALIAS_PRIVATE)); + } + if (isNullPasswordAllowed(keyStore)) { + setPrivateKeyNoPassword(keyStore, ALIAS_NO_PASSWORD_PRIVATE, getPrivateKey()); + assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null)); + assertCertificateChain(keyStore.getCertificateChain(ALIAS_NO_PASSWORD_PRIVATE)); + } if (isSecretKeyEnabled(keyStore)) { assertNull(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY)); setSecretKey(keyStore); @@ -764,7 +834,7 @@ public class KeyStoreTest extends TestCase { } else { try { keyStore.setKeyEntry(ALIAS_SECRET, getSecretKey(), PASSWORD_KEY, null); - fail(); + fail(keyStore.getType()); } catch (Exception e) { if (e.getClass() != KeyStoreException.class && e.getClass() != NullPointerException.class) { @@ -783,11 +853,22 @@ public class KeyStoreTest extends TestCase { assertNull(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY)); assertNull(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY)); } else if (isCaseSensitive(keyStore)) { - assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); - assertNull(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY)); - setPrivateKey(keyStore, ALIAS_ALT_CASE_PRIVATE, getPrivateKey2()); - assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); - assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY)); + if (isKeyPasswordSupported(keyStore)) { + assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + assertNull(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY)); + setPrivateKey(keyStore, ALIAS_ALT_CASE_PRIVATE, getPrivateKey2()); + assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY)); + } + + if (isNullPasswordAllowed(keyStore)) { + assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null)); + assertNull(keyStore.getKey(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, null)); + setPrivateKeyNoPassword(keyStore, ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, + getPrivateKey2()); + assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null)); + assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, null)); + } if (isSecretKeyEnabled(keyStore)) { assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY)); @@ -797,11 +878,22 @@ public class KeyStoreTest extends TestCase { assertSecretKey2(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY)); } } else { - assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); - assertPrivateKey(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY)); - setPrivateKey(keyStore, ALIAS_ALT_CASE_PRIVATE, getPrivateKey2()); - assertPrivateKey2(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); - assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY)); + if (isKeyPasswordSupported(keyStore)) { + assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + assertPrivateKey(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY)); + setPrivateKey(keyStore, ALIAS_ALT_CASE_PRIVATE, getPrivateKey2()); + assertPrivateKey2(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY)); + } + + if (isNullPasswordAllowed(keyStore)) { + assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, null)); + assertPrivateKey(keyStore.getKey(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, null)); + setPrivateKey(keyStore, ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, getPrivateKey2()); + assertPrivateKey2(keyStore.getKey(ALIAS_PRIVATE, null)); + assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, null)); + } + if (isSecretKeyEnabled(keyStore)) { assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY)); assertSecretKey(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY)); @@ -820,7 +912,7 @@ public class KeyStoreTest extends TestCase { getPrivateKey().getPrivateKey(), null, getPrivateKey().getCertificateChain()); - fail(); + fail(keyStore.getType()); } catch (UnsupportedOperationException expected) { } continue; @@ -839,7 +931,7 @@ public class KeyStoreTest extends TestCase { getPrivateKey().getPrivateKey(), null, getPrivateKey().getCertificateChain()); - fail(); + fail(keyStore.getType()); } catch (Exception e) { if (e.getClass() != UnrecoverableKeyException.class && e.getClass() != IllegalArgumentException.class @@ -855,7 +947,7 @@ public class KeyStoreTest extends TestCase { } else { try { keyStore.setKeyEntry(ALIAS_SECRET, getSecretKey(), null, null); - fail(); + fail(keyStore.getType()); } catch (Exception e) { if (e.getClass() != UnrecoverableKeyException.class && e.getClass() != IllegalArgumentException.class @@ -872,7 +964,7 @@ public class KeyStoreTest extends TestCase { for (KeyStore keyStore : keyStores()) { try { keyStore.setKeyEntry(null, null, null); - fail(); + fail(keyStore.getType()); } catch (KeyStoreException expected) { } } @@ -883,7 +975,7 @@ public class KeyStoreTest extends TestCase { if (isReadOnly(keyStore)) { try { keyStore.setKeyEntry(null, null, null); - fail(); + fail(keyStore.getType()); } catch (UnsupportedOperationException expected) { } continue; @@ -892,7 +984,7 @@ public class KeyStoreTest extends TestCase { // test odd inputs try { keyStore.setKeyEntry(null, null, null); - fail(); + fail(keyStore.getType()); } catch (Exception e) { if (e.getClass() != NullPointerException.class && e.getClass() != IllegalArgumentException.class @@ -913,21 +1005,33 @@ public class KeyStoreTest extends TestCase { continue; } - keyStore.load(null, null); + clearKeyStore(keyStore); // test case sensitive - assertNull(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + if (isKeyPasswordSupported(keyStore)) { + assertNull(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + } + if (isNullPasswordAllowed(keyStore)) { + assertNull(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null)); + } if (isReadOnly(keyStore)) { try { setPrivateKeyBytes(keyStore); - fail(); + fail(keyStore.getType()); } catch (UnsupportedOperationException expected) { } continue; } - setPrivateKeyBytes(keyStore); - assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); - assertCertificateChain(keyStore.getCertificateChain(ALIAS_PRIVATE)); + if (isKeyPasswordSupported(keyStore)) { + setPrivateKeyBytes(keyStore); + assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + assertCertificateChain(keyStore.getCertificateChain(ALIAS_PRIVATE)); + } + if (isNullPasswordAllowed(keyStore)) { + setPrivateKeyNoPassword(keyStore, ALIAS_NO_PASSWORD_PRIVATE, getPrivateKey()); + assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null)); + assertCertificateChain(keyStore.getCertificateChain(ALIAS_NO_PASSWORD_PRIVATE)); + } if (isSecretKeyEnabled(keyStore)) { assertNull(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY)); setSecretKeyBytes(keyStore); @@ -935,7 +1039,7 @@ public class KeyStoreTest extends TestCase { } else { try { keyStore.setKeyEntry(ALIAS_SECRET, getSecretKey().getEncoded(), null); - fail(); + fail(keyStore.getType()); } catch (KeyStoreException expected) { } } @@ -959,11 +1063,21 @@ public class KeyStoreTest extends TestCase { assertNull(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY)); assertNull(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY)); } else if (isCaseSensitive(keyStore)) { - assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); - assertNull(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY)); - setPrivateKeyBytes(keyStore, ALIAS_ALT_CASE_PRIVATE, getPrivateKey2()); - assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); - assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY)); + if (isKeyPasswordSupported(keyStore)) { + assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + assertNull(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY)); + setPrivateKeyBytes(keyStore, ALIAS_ALT_CASE_PRIVATE, getPrivateKey2()); + assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY)); + } + if (isNullPasswordAllowed(keyStore)) { + assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null)); + assertNull(keyStore.getKey(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, null)); + setPrivateKeyNoPassword(keyStore, ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, + getPrivateKey2()); + assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null)); + assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, null)); + } if (isSecretKeyEnabled(keyStore)) { assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY)); @@ -973,11 +1087,21 @@ public class KeyStoreTest extends TestCase { assertSecretKey2(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY)); } } else { - assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); - assertPrivateKey(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY)); - setPrivateKeyBytes(keyStore, ALIAS_ALT_CASE_PRIVATE, getPrivateKey2()); - assertPrivateKey2(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); - assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY)); + if (isKeyPasswordSupported(keyStore)) { + assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + assertPrivateKey(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY)); + setPrivateKeyBytes(keyStore, ALIAS_ALT_CASE_PRIVATE, getPrivateKey2()); + assertPrivateKey2(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY)); + } + if (isNullPasswordAllowed(keyStore)) { + assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null)); + assertPrivateKey(keyStore.getKey(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, null)); + setPrivateKeyNoPassword(keyStore, ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, + getPrivateKey2()); + assertPrivateKey2(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null)); + assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, null)); + } if (isSecretKeyEnabled(keyStore)) { assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY)); @@ -994,7 +1118,7 @@ public class KeyStoreTest extends TestCase { for (KeyStore keyStore : keyStores()) { try { keyStore.setCertificateEntry(null, null); - fail(); + fail(keyStore.getType()); } catch (KeyStoreException expected) { } } @@ -1005,7 +1129,7 @@ public class KeyStoreTest extends TestCase { // test odd inputs try { keyStore.setCertificateEntry(null, null); - fail(); + fail(keyStore.getType()); } catch (Exception e) { if (e.getClass() != NullPointerException.class && e.getClass() != KeyStoreException.class) { @@ -1017,7 +1141,7 @@ public class KeyStoreTest extends TestCase { try { assertNull(keyStore.getCertificate(ALIAS_CERTIFICATE)); keyStore.setCertificateEntry(ALIAS_CERTIFICATE, null); - fail(); + fail(keyStore.getType()); } catch (UnsupportedOperationException expected) { } continue; @@ -1031,18 +1155,22 @@ public class KeyStoreTest extends TestCase { try { int size = keyStore.size(); keyStore.setCertificateEntry(ALIAS_CERTIFICATE, null); - assertNull(keyStore.getCertificate(ALIAS_CERTIFICATE)); - assertEquals(size, keyStore.size()); - assertTrue(keyStore.isCertificateEntry(ALIAS_CERTIFICATE)); - assertTrue(Collections.list(keyStore.aliases()).contains(ALIAS_CERTIFICATE)); + assertNull(keyStore.getType(), keyStore.getCertificate(ALIAS_CERTIFICATE)); + assertEquals(keyStore.getType(), size, keyStore.size()); + assertTrue(keyStore.getType(), keyStore.isCertificateEntry(ALIAS_CERTIFICATE)); + assertTrue(keyStore.getType(), + Collections.list(keyStore.aliases()).contains(ALIAS_CERTIFICATE)); } catch (NullPointerException expectedSometimes) { - assertEquals("PKCS12", keyStore.getType()); - assertEquals("BC", keyStore.getProvider().getName()); + if (!("PKCS12".equalsIgnoreCase(keyStore.getType()) && + "BC".equalsIgnoreCase(keyStore.getProvider().getName())) + && !"AndroidKeyStore".equalsIgnoreCase(keyStore.getType())) { + throw expectedSometimes; + } } } else { try { keyStore.setCertificateEntry(ALIAS_CERTIFICATE, null); - fail(); + fail(keyStore.getType()); } catch (KeyStoreException expected) { } } @@ -1053,14 +1181,13 @@ public class KeyStoreTest extends TestCase { continue; } - keyStore.load(null, null); + clearKeyStore(keyStore); - // test case sensitive assertNull(keyStore.getCertificate(ALIAS_CERTIFICATE)); if (isReadOnly(keyStore)) { try { setCertificate(keyStore); - fail(); + fail(keyStore.getType()); } catch (UnsupportedOperationException expected) { } continue; @@ -1077,10 +1204,8 @@ public class KeyStoreTest extends TestCase { populate(keyStore); if (isReadOnly(keyStore)) { - assertNull(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); - assertNull(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY)); - assertNull(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY)); - assertNull(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY)); + assertNull(keyStore.getCertificate(ALIAS_CERTIFICATE)); + assertNull(keyStore.getCertificate(ALIAS_ALT_CASE_CERTIFICATE)); } else if (isCaseSensitive(keyStore)) { assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE)); assertNull(keyStore.getCertificate(ALIAS_ALT_CASE_CERTIFICATE)); @@ -1104,7 +1229,7 @@ public class KeyStoreTest extends TestCase { for (KeyStore keyStore : keyStores()) { try { keyStore.deleteEntry(null); - fail(); + fail(keyStore.getType()); } catch (KeyStoreException expected) { } } @@ -1115,7 +1240,7 @@ public class KeyStoreTest extends TestCase { if (isReadOnly(keyStore)) { try { keyStore.deleteEntry(null); - fail(); + fail(keyStore.getType()); } catch (UnsupportedOperationException expected) { } continue; @@ -1124,7 +1249,7 @@ public class KeyStoreTest extends TestCase { // test odd inputs try { keyStore.deleteEntry(null); - fail(); + fail(keyStore.getType()); } catch (Exception e) { if (e.getClass() != NullPointerException.class && e.getClass() != KeyStoreException.class) { @@ -1146,10 +1271,18 @@ public class KeyStoreTest extends TestCase { } // test case sensitive - assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); - assertCertificateChain(keyStore.getCertificateChain(ALIAS_PRIVATE)); - keyStore.deleteEntry(ALIAS_PRIVATE); - assertNull(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + if (isKeyPasswordSupported(keyStore)) { + assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + assertCertificateChain(keyStore.getCertificateChain(ALIAS_PRIVATE)); + keyStore.deleteEntry(ALIAS_PRIVATE); + assertNull(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + } + if (isNullPasswordAllowed(keyStore)) { + assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null)); + assertCertificateChain(keyStore.getCertificateChain(ALIAS_NO_PASSWORD_PRIVATE)); + keyStore.deleteEntry(ALIAS_NO_PASSWORD_PRIVATE); + assertNull(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null)); + } if (isSecretKeyEnabled(keyStore)) { assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY)); @@ -1174,9 +1307,16 @@ public class KeyStoreTest extends TestCase { // test case insensitive if (isCaseSensitive(keyStore)) { - assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); - keyStore.deleteEntry(ALIAS_ALT_CASE_PRIVATE); - assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + if (isKeyPasswordSupported(keyStore)) { + assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + keyStore.deleteEntry(ALIAS_ALT_CASE_PRIVATE); + assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + } + if (isNullPasswordAllowed(keyStore)) { + assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null)); + keyStore.deleteEntry(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE); + assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null)); + } if (isSecretKeyEnabled(keyStore)) { assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY)); @@ -1201,17 +1341,21 @@ public class KeyStoreTest extends TestCase { for (KeyStore keyStore : keyStores()) { try { keyStore.aliases(); - fail(); + fail(keyStore.getType()); } catch (KeyStoreException expected) { } } for (KeyStore keyStore : keyStores()) { keyStore.load(null, null); - if (hasDefaultContents(keyStore)) { - assertTrue(keyStore.aliases().hasMoreElements()); + if (isPersistentStorage(keyStore)) { + assertNotNull("Should be able to query size: " + keyStore.getType(), + keyStore.aliases()); + } else if (hasDefaultContents(keyStore)) { + assertTrue("Should have more than one alias already: " + keyStore.getType(), + keyStore.aliases().hasMoreElements()); } else { - assertEquals(Collections.EMPTY_SET, + assertEquals("Should have no aliases:" + keyStore.getType(), Collections.EMPTY_SET, new HashSet(Collections.list(keyStore.aliases()))); } } @@ -1220,7 +1364,9 @@ public class KeyStoreTest extends TestCase { populate(keyStore); Set<String> expected = new HashSet<String>(); - expected.add(ALIAS_PRIVATE); + if (isKeyPasswordSupported(keyStore)) { + expected.add(ALIAS_PRIVATE); + } if (isNullPasswordAllowed(keyStore)) { expected.add(ALIAS_NO_PASSWORD_PRIVATE); } @@ -1233,7 +1379,10 @@ public class KeyStoreTest extends TestCase { if (isCertificateEnabled(keyStore)) { expected.add(ALIAS_CERTIFICATE); } - if (hasDefaultContents(keyStore)) { + if (isPersistentStorage(keyStore)) { + assertNotNull("Should be able to query size: " + keyStore.getType(), + keyStore.aliases()); + } else if (hasDefaultContents(keyStore)) { assertTrue(keyStore.aliases().hasMoreElements()); } else { assertEquals(expected, new HashSet<String>(Collections.list(keyStore.aliases()))); @@ -1245,7 +1394,7 @@ public class KeyStoreTest extends TestCase { for (KeyStore keyStore : keyStores()) { try { keyStore.containsAlias(null); - fail(); + fail(keyStore.getType()); } catch (KeyStoreException expected) { } } @@ -1255,7 +1404,7 @@ public class KeyStoreTest extends TestCase { try { keyStore.containsAlias(null); - fail(); + fail(keyStore.getType()); } catch (NullPointerException expected) { } @@ -1271,7 +1420,11 @@ public class KeyStoreTest extends TestCase { assertFalse(keyStore.containsAlias(ALIAS_PRIVATE)); continue; } - assertTrue(keyStore.containsAlias(ALIAS_PRIVATE)); + if (isKeyPasswordSupported(keyStore)) { + assertTrue(keyStore.containsAlias(ALIAS_PRIVATE)); + } else if (isNullPasswordAllowed(keyStore)) { + assertTrue(keyStore.containsAlias(ALIAS_NO_PASSWORD_PRIVATE)); + } assertEquals(isSecretKeyEnabled(keyStore), keyStore.containsAlias(ALIAS_SECRET)); assertEquals(isCertificateEnabled(keyStore), keyStore.containsAlias(ALIAS_CERTIFICATE)); @@ -1288,28 +1441,36 @@ public class KeyStoreTest extends TestCase { for (KeyStore keyStore : keyStores()) { try { keyStore.aliases(); - fail(); + fail(keyStore.getType()); } catch (KeyStoreException expected) { } } for (KeyStore keyStore : keyStores()) { keyStore.load(null, null); - if (hasDefaultContents(keyStore)) { - assertTrue(keyStore.size() > 0); + if (isPersistentStorage(keyStore)) { + assertTrue("Should successfully query size: " + keyStore.getType(), + keyStore.size() >= 0); + } else if (hasDefaultContents(keyStore)) { + assertTrue("Should have non-empty store: " + keyStore.getType(), + keyStore.size() > 0); } else { - assertEquals(0, keyStore.size()); + assertEquals("Should have empty store: " + keyStore.getType(), 0, keyStore.size()); } } for (KeyStore keyStore : keyStores()) { populate(keyStore); if (hasDefaultContents(keyStore)) { - assertTrue(keyStore.size() > 0); + assertTrue("Should have non-empty store: " + keyStore.getType(), + keyStore.size() > 0); continue; } - int expected = 1; + int expected = 0; + if (isKeyPasswordSupported(keyStore)) { + expected++; + } if (isNullPasswordAllowed(keyStore)) { expected++; } @@ -1330,7 +1491,7 @@ public class KeyStoreTest extends TestCase { for (KeyStore keyStore : keyStores()) { try { keyStore.isKeyEntry(null); - fail(); + fail(keyStore.getType()); } catch (KeyStoreException expected) { } } @@ -1340,7 +1501,7 @@ public class KeyStoreTest extends TestCase { try { keyStore.isKeyEntry(null); - fail(); + fail(keyStore.getType()); } catch (NullPointerException expected) { } @@ -1355,7 +1516,12 @@ public class KeyStoreTest extends TestCase { assertFalse(keyStore.isKeyEntry(ALIAS_PRIVATE)); continue; } - assertTrue(keyStore.isKeyEntry(ALIAS_PRIVATE)); + if (isKeyPasswordSupported(keyStore)) { + assertTrue(keyStore.isKeyEntry(ALIAS_PRIVATE)); + } + if (isNullPasswordAllowed(keyStore)) { + assertTrue(keyStore.isKeyEntry(ALIAS_NO_PASSWORD_PRIVATE)); + } assertEquals(isSecretKeyEnabled(keyStore), keyStore.isKeyEntry(ALIAS_SECRET)); assertFalse(keyStore.isKeyEntry(ALIAS_CERTIFICATE)); @@ -1371,7 +1537,7 @@ public class KeyStoreTest extends TestCase { for (KeyStore keyStore : keyStores()) { try { keyStore.isCertificateEntry(null); - fail(); + fail(keyStore.getType()); } catch (KeyStoreException expected) { } } @@ -1382,7 +1548,7 @@ public class KeyStoreTest extends TestCase { if (isCertificateEnabled(keyStore)) { try { keyStore.isCertificateEntry(null); - fail(); + fail(keyStore.getType()); } catch (NullPointerException expected) { } } else { @@ -1397,7 +1563,12 @@ public class KeyStoreTest extends TestCase { assertFalse(keyStore.isCertificateEntry("")); - assertFalse(keyStore.isCertificateEntry(ALIAS_PRIVATE)); + if (isKeyPasswordSupported(keyStore)) { + assertFalse(keyStore.isCertificateEntry(ALIAS_PRIVATE)); + } + if (isNullPasswordAllowed(keyStore)) { + assertFalse(keyStore.isCertificateEntry(ALIAS_NO_PASSWORD_PRIVATE)); + } assertFalse(keyStore.isCertificateEntry(ALIAS_SECRET)); assertEquals(isCertificateEnabled(keyStore) && !isReadOnly(keyStore), keyStore.isCertificateEntry(ALIAS_CERTIFICATE)); @@ -1415,7 +1586,7 @@ public class KeyStoreTest extends TestCase { for (KeyStore keyStore : keyStores()) { try { keyStore.getCertificateAlias(null); - fail(); + fail(keyStore.getType()); } catch (KeyStoreException expected) { } } @@ -1429,7 +1600,9 @@ public class KeyStoreTest extends TestCase { populate(keyStore); Set<String> expected = new HashSet<String>(); - expected.add(ALIAS_PRIVATE); + if (isKeyPasswordSupported(keyStore)) { + expected.add(ALIAS_PRIVATE); + } if (isNullPasswordAllowed(keyStore)) { expected.add(ALIAS_NO_PASSWORD_PRIVATE); } @@ -1479,7 +1652,7 @@ public class KeyStoreTest extends TestCase { for (KeyStore keyStore : keyStores()) { try { keyStore.store(null, null); - fail(); + fail(keyStore.getType()); } catch (KeyStoreException expected) { } } @@ -1487,10 +1660,10 @@ public class KeyStoreTest extends TestCase { for (KeyStore keyStore : keyStores()) { keyStore.load(null, null); ByteArrayOutputStream out = new ByteArrayOutputStream(); - if (isReadOnly(keyStore)) { + if (isLoadStoreUnsupported(keyStore) || isReadOnly(keyStore)) { try { keyStore.store(out, null); - fail(); + fail(keyStore.getType()); } catch (UnsupportedOperationException expected) { } continue; @@ -1504,7 +1677,7 @@ public class KeyStoreTest extends TestCase { try { keyStore.store(out, null); - fail(); + fail(keyStore.getType()); } catch (Exception e) { if (e.getClass() != IllegalArgumentException.class && e.getClass() != NullPointerException.class) { @@ -1517,11 +1690,11 @@ public class KeyStoreTest extends TestCase { populate(keyStore); ByteArrayOutputStream out = new ByteArrayOutputStream(); - if (isReadOnly(keyStore)) { + if (isLoadStoreUnsupported(keyStore) || isReadOnly(keyStore)) { try { keyStore.store(out, null); - fail(); - } catch (UnsupportedOperationException e) { + fail(keyStore.getType()); + } catch (UnsupportedOperationException expected) { } } else if (isNullPasswordAllowed(keyStore)) { keyStore.store(out, null); @@ -1529,7 +1702,7 @@ public class KeyStoreTest extends TestCase { } else { try { keyStore.store(out, null); - fail(); + fail(keyStore.getType()); } catch (Exception e) { if (e.getClass() != IllegalArgumentException.class && e.getClass() != NullPointerException.class) { @@ -1542,10 +1715,10 @@ public class KeyStoreTest extends TestCase { for (KeyStore keyStore : keyStores()) { keyStore.load(null, null); ByteArrayOutputStream out = new ByteArrayOutputStream(); - if (isReadOnly(keyStore)) { + if (isLoadStoreUnsupported(keyStore) || isReadOnly(keyStore)) { try { keyStore.store(out, PASSWORD_STORE); - fail(); + fail(keyStore.getType()); } catch (UnsupportedOperationException e) { } continue; @@ -1557,10 +1730,10 @@ public class KeyStoreTest extends TestCase { for (KeyStore keyStore : keyStores()) { populate(keyStore); ByteArrayOutputStream out = new ByteArrayOutputStream(); - if (isReadOnly(keyStore)) { + if (isLoadStoreUnsupported(keyStore) || isReadOnly(keyStore)) { try { keyStore.store(out, PASSWORD_STORE); - fail(); + fail(keyStore.getType()); } catch (UnsupportedOperationException e) { } continue; @@ -1574,7 +1747,7 @@ public class KeyStoreTest extends TestCase { for (KeyStore keyStore : keyStores()) { try { keyStore.store(null); - fail(); + fail(keyStore.getType()); } catch (KeyStoreException expected) { } } @@ -1583,7 +1756,7 @@ public class KeyStoreTest extends TestCase { keyStore.load(null, null); try { keyStore.store(null); - fail(); + fail(keyStore.getType()); } catch (UnsupportedOperationException expected) { assertFalse(isLoadStoreParameterSupported(keyStore)); } catch (IllegalArgumentException expected) { @@ -1596,19 +1769,30 @@ public class KeyStoreTest extends TestCase { public void test_KeyStore_load_InputStream() throws Exception { for (KeyStore keyStore : keyStores()) { keyStore.load(null, null); - if (hasDefaultContents(keyStore)) { - assertTrue(keyStore.size() > 0); + if (isPersistentStorage(keyStore)) { + assertTrue("Should be able to query size: " + keyStore.getType(), + keyStore.size() >= 0); + } else if (hasDefaultContents(keyStore)) { + assertTrue("Should have non-empty store: " + keyStore.getType(), + keyStore.size() > 0); } else { - assertEquals(0, keyStore.size()); + assertEquals("Should have empty store: " + keyStore.getType(), 0, keyStore.size()); } } for (KeyStore keyStore : keyStores()) { + if (isLoadStoreUnsupported(keyStore)) { + continue; + } keyStore.load(null, PASSWORD_STORE); - if (hasDefaultContents(keyStore)) { - assertTrue(keyStore.size() > 0); + if (isPersistentStorage(keyStore)) { + assertTrue("Should be able to query size: " + keyStore.getType(), + keyStore.size() >= 0); + } else if (hasDefaultContents(keyStore)) { + assertTrue("Should have non-empty store: " + keyStore.getType(), + keyStore.size() > 0); } else { - assertEquals(0, keyStore.size()); + assertEquals("Should have empty store: " + keyStore.getType(), 0, keyStore.size()); } } @@ -1618,10 +1802,14 @@ public class KeyStoreTest extends TestCase { public void test_KeyStore_load_LoadStoreParameter() throws Exception { for (KeyStore keyStore : keyStores()) { keyStore.load(null); - if (hasDefaultContents(keyStore)) { - assertTrue(keyStore.size() > 0); + if (isPersistentStorage(keyStore)) { + assertTrue("Should be able to query size: " + keyStore.getType(), + keyStore.size() >= 0); + } else if (hasDefaultContents(keyStore)) { + assertTrue("Should have non-empty store: " + keyStore.getType(), + keyStore.size() > 0); } else { - assertEquals(0, keyStore.size()); + assertEquals("Should have empty store: " + keyStore.getType(), 0, keyStore.size()); } } @@ -1632,7 +1820,7 @@ public class KeyStoreTest extends TestCase { return null; } }); - fail(); + fail(keyStore.getType()); } catch (UnsupportedOperationException expected) { } } @@ -1642,7 +1830,7 @@ public class KeyStoreTest extends TestCase { for (KeyStore keyStore : keyStores()) { try { keyStore.getEntry(null, null); - fail(); + fail(keyStore.getType()); } catch (NullPointerException expected) { } } @@ -1653,12 +1841,12 @@ public class KeyStoreTest extends TestCase { // test odd inputs try { keyStore.getEntry(null, null); - fail(); + fail(keyStore.getType()); } catch (NullPointerException expected) { } try { keyStore.getEntry(null, PARAM_KEY); - fail(); + fail(keyStore.getType()); } catch (NullPointerException expected) { } assertNull(keyStore.getEntry("", null)); @@ -1668,7 +1856,11 @@ public class KeyStoreTest extends TestCase { if (isReadOnly(keyStore)) { assertNull(keyStore.getEntry(ALIAS_PRIVATE, PARAM_KEY)); } else { - assertPrivateKey(keyStore.getEntry(ALIAS_PRIVATE, PARAM_KEY)); + if (isKeyPasswordSupported(keyStore)) { + assertPrivateKey(keyStore.getEntry(ALIAS_PRIVATE, PARAM_KEY)); + } else if (isNullPasswordAllowed(keyStore)) { + assertPrivateKey(keyStore.getEntry(ALIAS_NO_PASSWORD_PRIVATE, null)); + } if (isSecretKeyEnabled(keyStore)) { assertSecretKey(keyStore.getEntry(ALIAS_SECRET, PARAM_KEY)); } else { @@ -1704,12 +1896,12 @@ public class KeyStoreTest extends TestCase { assertNull(keyStore.getEntry(ALIAS_NO_PASSWORD_PRIVATE, null)); } else if (isNullPasswordAllowed(keyStore)) { assertPrivateKey(keyStore.getEntry(ALIAS_NO_PASSWORD_PRIVATE, null)); - } else if (isKeyPasswordIgnored(keyStore)) { + } else if (isKeyPasswordSupported(keyStore) && isKeyPasswordIgnored(keyStore)) { assertPrivateKey(keyStore.getEntry(ALIAS_PRIVATE, null)); - } else { + } else if (isKeyPasswordIgnored(keyStore)) { try { keyStore.getEntry(ALIAS_PRIVATE, null); - fail(); + fail(keyStore.getType()); } catch (Exception e) { if (e.getClass() != UnrecoverableKeyException.class && e.getClass() != IllegalArgumentException.class) { @@ -1722,7 +1914,7 @@ public class KeyStoreTest extends TestCase { } else if (isSecretKeyEnabled(keyStore)) { try { keyStore.getEntry(ALIAS_SECRET, null); - fail(); + fail(keyStore.getType()); } catch (Exception e) { if (e.getClass() != UnrecoverableKeyException.class && e.getClass() != IllegalArgumentException.class) { @@ -1734,12 +1926,12 @@ public class KeyStoreTest extends TestCase { // test with bad passwords if (isReadOnly(keyStore)) { assertNull(keyStore.getEntry(ALIAS_PRIVATE, PARAM_BAD)); - } else if (isKeyPasswordIgnored(keyStore)) { + } else if (isKeyPasswordSupported(keyStore) && isKeyPasswordIgnored(keyStore)) { assertPrivateKey(keyStore.getEntry(ALIAS_PRIVATE, PARAM_BAD)); - } else { + } else if (isKeyPasswordSupported(keyStore)) { try { keyStore.getEntry(ALIAS_PRIVATE, PARAM_BAD); - fail(); + fail(keyStore.getType()); } catch (UnrecoverableKeyException expected) { } } @@ -1748,19 +1940,22 @@ public class KeyStoreTest extends TestCase { } else if (isSecretKeyEnabled(keyStore)) { try { keyStore.getEntry(ALIAS_SECRET, PARAM_BAD); - fail(); + fail(keyStore.getType()); } catch (UnrecoverableKeyException expected) { } } } } + public static class FakeProtectionParameter implements ProtectionParameter { + } + public void test_KeyStore_setEntry() throws Exception { for (KeyStore keyStore : keyStores()) { keyStore.load(null, null); try { keyStore.setEntry(null, null, null); - fail(); + fail(keyStore.getType()); } catch (NullPointerException expected) { } } @@ -1768,10 +1963,20 @@ public class KeyStoreTest extends TestCase { for (KeyStore keyStore : keyStores()) { keyStore.load(null, null); + try { + keyStore.setEntry(ALIAS_PRIVATE, getPrivateKey(), new FakeProtectionParameter()); + fail("Should not accept unknown ProtectionParameter: " + keyStore.getProvider()); + } catch (KeyStoreException expected) { + } + } + + for (KeyStore keyStore : keyStores()) { + keyStore.load(null, null); + // test odd inputs try { keyStore.setEntry(null, null, null); - fail(); + fail(keyStore.getType()); } catch (Exception e) { if (e.getClass() != NullPointerException.class && e.getClass() != KeyStoreException.class) { @@ -1780,7 +1985,7 @@ public class KeyStoreTest extends TestCase { } try { keyStore.setEntry(null, null, PARAM_KEY); - fail(); + fail(keyStore.getType()); } catch (Exception e) { if (e.getClass() != NullPointerException.class && e.getClass() != KeyStoreException.class) { @@ -1789,27 +1994,34 @@ public class KeyStoreTest extends TestCase { } try { keyStore.setEntry("", null, PARAM_KEY); - fail(); + fail(keyStore.getType()); } catch (NullPointerException expected) { } } for (KeyStore keyStore : keyStores()) { - keyStore.load(null, null); + clearKeyStore(keyStore); // test case sensitive assertNull(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); if (isReadOnly(keyStore)) { try { keyStore.setEntry(ALIAS_PRIVATE, getPrivateKey(), PARAM_KEY); - fail(); + fail(keyStore.getType()); } catch (UnsupportedOperationException expected) { } continue; } - keyStore.setEntry(ALIAS_PRIVATE, getPrivateKey(), PARAM_KEY); - assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); - assertCertificateChain(keyStore.getCertificateChain(ALIAS_PRIVATE)); + if (isKeyPasswordSupported(keyStore)) { + keyStore.setEntry(ALIAS_PRIVATE, getPrivateKey(), PARAM_KEY); + assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + assertCertificateChain(keyStore.getCertificateChain(ALIAS_PRIVATE)); + } + if (isNullPasswordAllowed(keyStore)) { + keyStore.setEntry(ALIAS_NO_PASSWORD_PRIVATE, getPrivateKey(), null); + assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null)); + assertCertificateChain(keyStore.getCertificateChain(ALIAS_NO_PASSWORD_PRIVATE)); + } if (isSecretKeyEnabled(keyStore)) { assertNull(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY)); keyStore.setEntry(ALIAS_SECRET, new SecretKeyEntry(getSecretKey()), PARAM_KEY); @@ -1817,7 +2029,7 @@ public class KeyStoreTest extends TestCase { } else { try { keyStore.setKeyEntry(ALIAS_SECRET, getSecretKey(), PASSWORD_KEY, null); - fail(); + fail(keyStore.getType()); } catch (KeyStoreException expected) { } } @@ -1832,13 +2044,21 @@ public class KeyStoreTest extends TestCase { keyStore.setEntry(ALIAS_CERTIFICATE, new TrustedCertificateEntry(getPrivateKey().getCertificate()), null); - fail(); + fail(keyStore.getType()); } catch (KeyStoreException expected) { } } - keyStore.setEntry(ALIAS_UNICODE_PRIVATE, getPrivateKey(), PARAM_KEY); - assertPrivateKey(keyStore.getKey(ALIAS_UNICODE_PRIVATE, PASSWORD_KEY)); - assertCertificateChain(keyStore.getCertificateChain(ALIAS_UNICODE_PRIVATE)); + if (isKeyPasswordSupported(keyStore)) { + keyStore.setEntry(ALIAS_UNICODE_PRIVATE, getPrivateKey(), PARAM_KEY); + assertPrivateKey(keyStore.getKey(ALIAS_UNICODE_PRIVATE, PASSWORD_KEY)); + assertCertificateChain(keyStore.getCertificateChain(ALIAS_UNICODE_PRIVATE)); + } + if (isNullPasswordAllowed(keyStore)) { + keyStore.setEntry(ALIAS_UNICODE_NO_PASSWORD_PRIVATE, getPrivateKey(), null); + assertPrivateKey(keyStore.getKey(ALIAS_UNICODE_NO_PASSWORD_PRIVATE, null)); + assertCertificateChain(keyStore + .getCertificateChain(ALIAS_UNICODE_NO_PASSWORD_PRIVATE)); + } if (isSecretKeyEnabled(keyStore)) { assertNull(keyStore.getKey(ALIAS_UNICODE_SECRET, PASSWORD_KEY)); keyStore.setEntry(ALIAS_UNICODE_SECRET, new SecretKeyEntry(getSecretKey()), PARAM_KEY); @@ -1846,7 +2066,7 @@ public class KeyStoreTest extends TestCase { } else { try { keyStore.setKeyEntry(ALIAS_UNICODE_SECRET, getSecretKey(), PASSWORD_KEY, null); - fail(); + fail(keyStore.getType()); } catch (KeyStoreException expected) { } } @@ -1861,11 +2081,21 @@ public class KeyStoreTest extends TestCase { assertNull(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY)); assertNull(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY)); } else if (isCaseSensitive(keyStore)) { - assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); - assertNull(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY)); - keyStore.setEntry(ALIAS_ALT_CASE_PRIVATE, getPrivateKey2(), PARAM_KEY); - assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); - assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY)); + if (isKeyPasswordSupported(keyStore)) { + assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + assertNull(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY)); + keyStore.setEntry(ALIAS_ALT_CASE_PRIVATE, getPrivateKey2(), PARAM_KEY); + assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY)); + assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY)); + } + + if (isNullPasswordAllowed(keyStore)) { + assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null)); + assertNull(keyStore.getKey(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, null)); + keyStore.setEntry(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, getPrivateKey2(), null); + assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null)); + assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, null)); + } if (isSecretKeyEnabled(keyStore)) { assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY)); @@ -1931,20 +2161,33 @@ public class KeyStoreTest extends TestCase { keyStore.load(null, null); // test with null/non-null passwords - try { - keyStore.setEntry(ALIAS_PRIVATE, getPrivateKey(), null); - fail(); - } catch (Exception e) { - if (e.getClass() != UnrecoverableKeyException.class - && e.getClass() != IllegalArgumentException.class - && e.getClass() != KeyStoreException.class) { - throw e; + if (isReadOnly(keyStore)) { + try { + keyStore.setEntry(ALIAS_PRIVATE, getPrivateKey(), null); + fail(keyStore.getType()); + } catch (UnsupportedOperationException expected) { } - } - if (isSecretKeyEnabled(keyStore)) { try { keyStore.setEntry(ALIAS_SECRET, new SecretKeyEntry(getSecretKey()), null); - fail(); + fail(keyStore.getType()); + } catch (UnsupportedOperationException expected) { + } + try { + keyStore.setEntry(ALIAS_CERTIFICATE, + new TrustedCertificateEntry(getPrivateKey().getCertificate()), + null); + fail(keyStore.getType()); + } catch (UnsupportedOperationException expected) { + } + continue; + } + if (isNullPasswordAllowed(keyStore) || isKeyPasswordIgnored(keyStore)) { + keyStore.setEntry(ALIAS_PRIVATE, getPrivateKey(), null); + assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, null)); + } else { + try { + keyStore.setEntry(ALIAS_PRIVATE, getPrivateKey(), null); + fail(keyStore.getType()); } catch (Exception e) { if (e.getClass() != UnrecoverableKeyException.class && e.getClass() != IllegalArgumentException.class @@ -1953,15 +2196,22 @@ public class KeyStoreTest extends TestCase { } } } - if (isReadOnly(keyStore)) { - try { - keyStore.setEntry(ALIAS_CERTIFICATE, - new TrustedCertificateEntry(getPrivateKey().getCertificate()), - PARAM_KEY); - fail(); - } catch (UnsupportedOperationException expected) { + if (isSecretKeyEnabled(keyStore)) { + if (isNullPasswordAllowed(keyStore) || isKeyPasswordIgnored(keyStore)) { + keyStore.setEntry(ALIAS_SECRET, new SecretKeyEntry(getSecretKey()), null); + assertSecretKey(keyStore.getKey(ALIAS_SECRET, null)); + } else { + try { + keyStore.setEntry(ALIAS_SECRET, new SecretKeyEntry(getSecretKey()), null); + fail(keyStore.getType()); + } catch (Exception e) { + if (e.getClass() != UnrecoverableKeyException.class + && e.getClass() != IllegalArgumentException.class + && e.getClass() != KeyStoreException.class) { + throw e; + } + } } - continue; } if (isCertificateEnabled(keyStore)) { if (isNullPasswordAllowed(keyStore) || isKeyPasswordIgnored(keyStore)) { @@ -1975,7 +2225,7 @@ public class KeyStoreTest extends TestCase { new TrustedCertificateEntry( getPrivateKey().getCertificate()), PARAM_KEY); - fail(); + fail(keyStore.getType()); } catch (KeyStoreException expected) { } } @@ -1987,7 +2237,7 @@ public class KeyStoreTest extends TestCase { for (KeyStore keyStore : keyStores()) { try { keyStore.entryInstanceOf(null, null); - fail(); + fail(keyStore.getType()); } catch (NullPointerException expected) { } } @@ -1997,17 +2247,17 @@ public class KeyStoreTest extends TestCase { try { keyStore.entryInstanceOf(null, null); - fail(); + fail(keyStore.getType()); } catch (NullPointerException expected) { } try { keyStore.entryInstanceOf(null, Entry.class); - fail(); + fail(keyStore.getType()); } catch (NullPointerException expected) { } try { keyStore.entryInstanceOf("", null); - fail(); + fail(keyStore.getType()); } catch (NullPointerException expected) { } @@ -2040,10 +2290,17 @@ public class KeyStoreTest extends TestCase { } // test case sensitive - assertTrue(keyStore.entryInstanceOf(ALIAS_PRIVATE, PrivateKeyEntry.class)); + assertEquals(isKeyPasswordSupported(keyStore), + keyStore.entryInstanceOf(ALIAS_PRIVATE, PrivateKeyEntry.class)); assertFalse(keyStore.entryInstanceOf(ALIAS_PRIVATE, SecretKeyEntry.class)); assertFalse(keyStore.entryInstanceOf(ALIAS_PRIVATE, TrustedCertificateEntry.class)); + assertEquals(isNullPasswordAllowed(keyStore), + keyStore.entryInstanceOf(ALIAS_NO_PASSWORD_PRIVATE, PrivateKeyEntry.class)); + assertFalse(keyStore.entryInstanceOf(ALIAS_NO_PASSWORD_PRIVATE, SecretKeyEntry.class)); + assertFalse(keyStore.entryInstanceOf(ALIAS_NO_PASSWORD_PRIVATE, + TrustedCertificateEntry.class)); + assertEquals(isSecretKeyEnabled(keyStore), keyStore.entryInstanceOf(ALIAS_SECRET, SecretKeyEntry.class)); assertFalse(keyStore.entryInstanceOf(ALIAS_SECRET, PrivateKeyEntry.class)); @@ -2082,7 +2339,7 @@ public class KeyStoreTest extends TestCase { keyStore.load(null, null); try { Builder.newInstance(keyStore, null); - fail(); + fail(keyStore.getType()); } catch (NullPointerException expected) { } } @@ -2092,7 +2349,7 @@ public class KeyStoreTest extends TestCase { Builder.newInstance(keyStore.getType(), keyStore.getProvider(), null); - fail(); + fail(keyStore.getType()); } catch (NullPointerException expected) { } } @@ -2103,7 +2360,7 @@ public class KeyStoreTest extends TestCase { null, null, null); - fail(); + fail(keyStore.getType()); } catch (NullPointerException expected) { } try { @@ -2111,7 +2368,7 @@ public class KeyStoreTest extends TestCase { keyStore.getProvider(), null, null); - fail(); + fail(keyStore.getType()); } catch (NullPointerException expected) { } } @@ -2121,13 +2378,13 @@ public class KeyStoreTest extends TestCase { Builder builder = Builder.newInstance(keyStore, PARAM_STORE); try { builder.getProtectionParameter(null); - fail(); + fail(keyStore.getType()); } catch (NullPointerException expected) { } assertEquals(keyStore, builder.getKeyStore()); try { builder.getProtectionParameter(null); - fail(); + fail(keyStore.getType()); } catch (NullPointerException expected) { } assertEquals(PARAM_STORE, builder.getProtectionParameter("")); @@ -2140,10 +2397,10 @@ public class KeyStoreTest extends TestCase { OutputStream os = null; try { os = new FileOutputStream(file); - if (isReadOnly(keyStore)) { + if (isLoadStoreUnsupported(keyStore) || isReadOnly(keyStore)) { try { keyStore.store(os, PASSWORD_STORE); - fail(); + fail(keyStore.getType()); } catch (UnsupportedOperationException expected) { } continue; @@ -2160,12 +2417,20 @@ public class KeyStoreTest extends TestCase { assertEquals(PARAM_STORE, builder.getProtectionParameter("")); assertEqualsKeyStores(file, PASSWORD_STORE, keyStore); } finally { - IoUtils.closeQuietly(os); + try { + if (os != null) { + os.close(); + } + } catch (IOException ignored) { + } file.delete(); } } for (KeyStore keyStore : keyStores()) { + if (isLoadStoreUnsupported(keyStore)) { + continue; + } Builder builder = Builder.newInstance(keyStore.getType(), keyStore.getProvider(), PARAM_STORE); @@ -2215,7 +2480,7 @@ public class KeyStoreTest extends TestCase { // http://b/857840: want JKS key store public void testDefaultKeystore() { String type = KeyStore.getDefaultType(); - assertEquals("Default keystore type must be Bouncy Castle", "BKS", type); + assertEquals(StandardNames.KEY_STORE_ALGORITHM, type); try { KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType()); @@ -2225,7 +2490,7 @@ public class KeyStoreTest extends TestCase { } try { - KeyStore store = KeyStore.getInstance("BKS"); + KeyStore store = KeyStore.getInstance(StandardNames.KEY_STORE_ALGORITHM); assertNotNull("Keystore must not be null", store); } catch (Exception ex) { throw new RuntimeException(ex); diff --git a/luni/src/test/java/libcore/java/security/ProviderTest.java b/luni/src/test/java/libcore/java/security/ProviderTest.java index 695908b..78608d0 100644 --- a/luni/src/test/java/libcore/java/security/ProviderTest.java +++ b/luni/src/test/java/libcore/java/security/ProviderTest.java @@ -17,14 +17,20 @@ package libcore.java.security; import java.security.Provider; +import java.security.SecureRandom; +import java.security.SecureRandomSpi; +import java.security.Security; +import java.security.Provider; +import java.security.SecureRandom; +import java.security.SecureRandomSpi; import java.security.Security; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Map.Entry; +import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -195,4 +201,48 @@ public class ProviderTest extends TestCase { } } } + + /** + * http://code.google.com/p/android/issues/detail?id=21449 + */ + public void testSecureRandomImplementationOrder() { + Provider srp = new SRProvider(); + try { + int position = Security.insertProviderAt(srp, 1); // first is one, not zero + assertEquals(1, position); + SecureRandom sr = new SecureRandom(); + if (!sr.getAlgorithm().equals("SecureRandom1")) { + throw new IllegalStateException("Expected SecureRandom1"); + } + } finally { + Security.removeProvider(srp.getName()); + } + } + + public static class SRProvider extends Provider { + + SRProvider() { + super("SRProvider", 1.42, "SecureRandom Provider"); + put("SecureRandom.SecureRandom1", SecureRandom1.class.getName()); + put("SecureRandom.SecureRandom2", SecureRandom2.class.getName()); + put("SecureRandom.SecureRandom3", SecureRandom3.class.getName()); + } + } + + public static abstract class AbstractSecureRandom extends SecureRandomSpi { + protected void engineSetSeed(byte[] seed) { + throw new UnsupportedOperationException(); + } + protected void engineNextBytes(byte[] bytes) { + throw new UnsupportedOperationException(); + } + protected byte[] engineGenerateSeed(int numBytes) { + throw new UnsupportedOperationException(); + } + } + + public static class SecureRandom1 extends AbstractSecureRandom {} + public static class SecureRandom2 extends AbstractSecureRandom {} + public static class SecureRandom3 extends AbstractSecureRandom {} + } diff --git a/luni/src/test/java/libcore/java/security/SecureRandomTest.java b/luni/src/test/java/libcore/java/security/SecureRandomTest.java new file mode 100644 index 0000000..8199120 --- /dev/null +++ b/luni/src/test/java/libcore/java/security/SecureRandomTest.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package libcore.java.security; + +import org.apache.harmony.xnet.provider.jsse.OpenSSLProvider; + +import java.security.Provider; +import java.security.SecureRandom; +import java.security.Security; +import java.util.Arrays; +import java.util.Set; + +import junit.framework.TestCase; + +public class SecureRandomTest extends TestCase { + private static final Class<? extends Provider> EXPECTED_PROVIDER = OpenSSLProvider.class; + + private static final byte[] STATIC_SEED_BYTES = new byte[] { + 0x0A, (byte) 0xA0, 0x01, 0x10, (byte) 0xFF, (byte) 0xF0, 0x0F + }; + + private static final long STATIC_SEED_LONG = 8506210602917522860L; + + public void test_getInstance() throws Exception { + Provider[] providers = Security.getProviders(); + for (Provider provider : providers) { + Set<Provider.Service> services = provider.getServices(); + for (Provider.Service service : services) { + String type = service.getType(); + if (!type.equals("SecureRandom")) { + continue; + } + + String algorithm = service.getAlgorithm(); + try { + SecureRandom sr1 = SecureRandom.getInstance(algorithm); + assertEquals(algorithm, sr1.getAlgorithm()); + test_SecureRandom(sr1); + + // SecureRandom.getInstance(String, Provider) + SecureRandom sr2 = SecureRandom.getInstance(algorithm, provider); + assertEquals(algorithm, sr2.getAlgorithm()); + assertEquals(provider, sr2.getProvider()); + test_SecureRandom(sr2); + + // SecureRandom.getInstance(String, String) + SecureRandom sr3 = SecureRandom.getInstance(algorithm, provider.getName()); + assertEquals(algorithm, sr3.getAlgorithm()); + assertEquals(provider, sr3.getProvider()); + test_SecureRandom(sr3); + + System.out.println("SecureRandomTest " + algorithm + " and provider " + + provider.getName()); + } catch (Exception e) { + throw new Exception("Problem testing SecureRandom." + algorithm + + ", provider: " + provider.getName(), e); + } + } + } + } + + private void test_SecureRandom(SecureRandom sr) throws Exception { + byte[] out1 = new byte[20]; + byte[] out2 = new byte[20]; + + sr.nextBytes(out1); + sr.nextBytes(out2); + assertFalse(Arrays.equals(out1, out2)); + + byte[] seed1 = sr.generateSeed(20); + byte[] seed2 = sr.generateSeed(20); + assertFalse(Arrays.equals(seed1, seed2)); + + sr.setSeed(STATIC_SEED_BYTES); + sr.nextBytes(out1); + sr.nextBytes(out2); + assertFalse(Arrays.equals(out1, out2)); + + sr.setSeed(STATIC_SEED_LONG); + sr.nextBytes(out1); + sr.nextBytes(out2); + assertFalse(Arrays.equals(out1, out2)); + } + + public void testGetCommonInstances_Success() throws Exception { + SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); + assertNotNull(sr); + assertEquals(EXPECTED_PROVIDER, sr.getProvider().getClass()); + } + + public void testNewConstructors_Success() throws Exception { + SecureRandom sr1 = new SecureRandom(); + assertEquals(EXPECTED_PROVIDER, sr1.getProvider().getClass()); + test_SecureRandom(sr1); + + SecureRandom sr2 = new SecureRandom(STATIC_SEED_BYTES); + assertEquals(EXPECTED_PROVIDER, sr2.getProvider().getClass()); + test_SecureRandom(sr2); + } +} diff --git a/luni/src/test/java/libcore/java/security/SignatureTest.java b/luni/src/test/java/libcore/java/security/SignatureTest.java index 2cd9982..63daa88 100644 --- a/luni/src/test/java/libcore/java/security/SignatureTest.java +++ b/luni/src/test/java/libcore/java/security/SignatureTest.java @@ -26,6 +26,7 @@ import java.security.Provider; import java.security.PublicKey; import java.security.Security; import java.security.Signature; +import java.security.SignatureException; import java.security.spec.DSAPrivateKeySpec; import java.security.spec.DSAPublicKeySpec; import java.security.spec.InvalidKeySpecException; @@ -123,9 +124,21 @@ public class SignatureTest extends TestCase { sig.update(DATA); assertTrue(sig.getAlgorithm(), sig.verify(signature)); - // Calling Signature.verify a second time should not throw - // http://code.google.com/p/android/issues/detail?id=34933 - sig.verify(signature); + /* + * The RI appears to clear out the input data in RawDSA while calling + * verify a second time. + */ + if (StandardNames.IS_RI && "NONEwithDSA".equalsIgnoreCase(sig.getAlgorithm())) { + try { + sig.verify(signature); + fail("Expected RI to have a NONEwithDSA bug"); + } catch (SignatureException bug) { + } + } else { + // Calling Signature.verify a second time should not throw + // http://code.google.com/p/android/issues/detail?id=34933 + sig.verify(signature); + } } private static final byte[] PK_BYTES = hexToBytes( @@ -326,6 +339,7 @@ public class SignatureTest extends TestCase { (byte) 0x39, }); + /* Test data is: "Android.\n" */ private static final byte[] Vector1Data = new byte[] { (byte) 0x41, (byte) 0x6e, (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x2e, (byte) 0x0a, @@ -550,11 +564,61 @@ public class SignatureTest extends TestCase { (byte) 0x02, (byte) 0xaf, (byte) 0x8f, (byte) 0x59, (byte) 0xe5, (byte) 0x67, (byte) 0x25, (byte) 0x00, }; + /* + * openssl rsautl -raw -sign -inkey rsa.key | recode ../x1 | sed 's/0x/(byte) 0x/g' + */ + private static final byte[] NONEwithRSA_Vector1Signature = new byte[] { + (byte) 0x35, (byte) 0x43, (byte) 0x38, (byte) 0x44, (byte) 0xAD, (byte) 0x3F, + (byte) 0x97, (byte) 0x02, (byte) 0xFB, (byte) 0x59, (byte) 0x1F, (byte) 0x4A, + (byte) 0x2B, (byte) 0xB9, (byte) 0x06, (byte) 0xEC, (byte) 0x66, (byte) 0xE6, + (byte) 0xD2, (byte) 0xC5, (byte) 0x8B, (byte) 0x7B, (byte) 0xE3, (byte) 0x18, + (byte) 0xBF, (byte) 0x07, (byte) 0xD6, (byte) 0x01, (byte) 0xF9, (byte) 0xD9, + (byte) 0x89, (byte) 0xC4, (byte) 0xDB, (byte) 0x00, (byte) 0x68, (byte) 0xFF, + (byte) 0x9B, (byte) 0x43, (byte) 0x90, (byte) 0xF2, (byte) 0xDB, (byte) 0x83, + (byte) 0xF4, (byte) 0x7E, (byte) 0xC6, (byte) 0x81, (byte) 0x01, (byte) 0x3A, + (byte) 0x0B, (byte) 0xE5, (byte) 0xED, (byte) 0x08, (byte) 0x73, (byte) 0x3E, + (byte) 0xE1, (byte) 0x3F, (byte) 0xDF, (byte) 0x1F, (byte) 0x07, (byte) 0x6D, + (byte) 0x22, (byte) 0x8D, (byte) 0xCC, (byte) 0x4E, (byte) 0xE3, (byte) 0x9A, + (byte) 0xBC, (byte) 0xCC, (byte) 0x8F, (byte) 0x9E, (byte) 0x9B, (byte) 0x02, + (byte) 0x48, (byte) 0x00, (byte) 0xAC, (byte) 0x9F, (byte) 0xA4, (byte) 0x8F, + (byte) 0x87, (byte) 0xA1, (byte) 0xA8, (byte) 0xE6, (byte) 0x9D, (byte) 0xCD, + (byte) 0x8B, (byte) 0x05, (byte) 0xE9, (byte) 0xD2, (byte) 0x05, (byte) 0x8D, + (byte) 0xC9, (byte) 0x95, (byte) 0x16, (byte) 0xD0, (byte) 0xCD, (byte) 0x43, + (byte) 0x25, (byte) 0x8A, (byte) 0x11, (byte) 0x46, (byte) 0xD7, (byte) 0x74, + (byte) 0x4C, (byte) 0xCF, (byte) 0x58, (byte) 0xF9, (byte) 0xA1, (byte) 0x30, + (byte) 0x84, (byte) 0x52, (byte) 0xC9, (byte) 0x01, (byte) 0x5F, (byte) 0x24, + (byte) 0x4C, (byte) 0xB1, (byte) 0x9F, (byte) 0x7D, (byte) 0x12, (byte) 0x38, + (byte) 0x27, (byte) 0x0F, (byte) 0x5E, (byte) 0xFF, (byte) 0xE0, (byte) 0x55, + (byte) 0x8B, (byte) 0xA3, (byte) 0xAD, (byte) 0x60, (byte) 0x35, (byte) 0x83, + (byte) 0x58, (byte) 0xAF, (byte) 0x99, (byte) 0xDE, (byte) 0x3F, (byte) 0x5D, + (byte) 0x80, (byte) 0x80, (byte) 0xFF, (byte) 0x9B, (byte) 0xDE, (byte) 0x5C, + (byte) 0xAB, (byte) 0x97, (byte) 0x43, (byte) 0x64, (byte) 0xD9, (byte) 0x9F, + (byte) 0xFB, (byte) 0x67, (byte) 0x65, (byte) 0xA5, (byte) 0x99, (byte) 0xE7, + (byte) 0xE6, (byte) 0xEB, (byte) 0x05, (byte) 0x95, (byte) 0xFC, (byte) 0x46, + (byte) 0x28, (byte) 0x4B, (byte) 0xD8, (byte) 0x8C, (byte) 0xF5, (byte) 0x0A, + (byte) 0xEB, (byte) 0x1F, (byte) 0x30, (byte) 0xEA, (byte) 0xE7, (byte) 0x67, + (byte) 0x11, (byte) 0x25, (byte) 0xF0, (byte) 0x44, (byte) 0x75, (byte) 0x74, + (byte) 0x94, (byte) 0x06, (byte) 0x78, (byte) 0xD0, (byte) 0x21, (byte) 0xF4, + (byte) 0x3F, (byte) 0xC8, (byte) 0xC4, (byte) 0x4A, (byte) 0x57, (byte) 0xBE, + (byte) 0x02, (byte) 0x3C, (byte) 0x93, (byte) 0xF6, (byte) 0x95, (byte) 0xFB, + (byte) 0xD1, (byte) 0x77, (byte) 0x8B, (byte) 0x43, (byte) 0xF0, (byte) 0xB9, + (byte) 0x7D, (byte) 0xE0, (byte) 0x32, (byte) 0xE1, (byte) 0x72, (byte) 0xB5, + (byte) 0x62, (byte) 0x3F, (byte) 0x86, (byte) 0xC3, (byte) 0xD4, (byte) 0x5F, + (byte) 0x5E, (byte) 0x54, (byte) 0x1B, (byte) 0x5B, (byte) 0xE6, (byte) 0x74, + (byte) 0xA1, (byte) 0x0B, (byte) 0xE5, (byte) 0x18, (byte) 0xD2, (byte) 0x4F, + (byte) 0x93, (byte) 0xF3, (byte) 0x09, (byte) 0x58, (byte) 0xCE, (byte) 0xF0, + (byte) 0xA3, (byte) 0x61, (byte) 0xE4, (byte) 0x6E, (byte) 0x46, (byte) 0x45, + (byte) 0x89, (byte) 0x50, (byte) 0xBD, (byte) 0x03, (byte) 0x3F, (byte) 0x38, + (byte) 0xDA, (byte) 0x5D, (byte) 0xD0, (byte) 0x1B, (byte) 0x1F, (byte) 0xB1, + (byte) 0xEE, (byte) 0x89, (byte) 0x59, (byte) 0xC5, + }; + public void testGetCommonInstances_Success() throws Exception { assertNotNull(Signature.getInstance("SHA1withRSA")); assertNotNull(Signature.getInstance("SHA256withRSA")); assertNotNull(Signature.getInstance("SHA384withRSA")); assertNotNull(Signature.getInstance("SHA512withRSA")); + assertNotNull(Signature.getInstance("NONEwithRSA")); assertNotNull(Signature.getInstance("MD5withRSA")); assertNotNull(Signature.getInstance("SHA1withDSA")); } @@ -732,8 +796,7 @@ public class SignatureTest extends TestCase { try { sig.initSign(privKey); fail("Should throw error when private exponent is not available"); - } catch (InvalidKeyException e) { - // success + } catch (InvalidKeyException expected) { } } @@ -757,8 +820,7 @@ public class SignatureTest extends TestCase { try { sig.initSign(privKey); fail("Should throw error when modulus is not available"); - } catch (InvalidKeyException e) { - // success + } catch (InvalidKeyException expected) { } } @@ -781,8 +843,7 @@ public class SignatureTest extends TestCase { try { sig.initSign(privKey); fail("Should throw error when key is empty"); - } catch (InvalidKeyException e) { - // success + } catch (InvalidKeyException expected) { } } @@ -902,6 +963,165 @@ public class SignatureTest extends TestCase { assertTrue("Signature must verify correctly", sig.verify(signature)); } + public void testSign_NONEwithRSA_Key_Success() throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus, + RSA_2048_privateExponent); + PrivateKey privKey = kf.generatePrivate(keySpec); + + Signature sig = Signature.getInstance("NONEwithRSA"); + sig.initSign(privKey); + sig.update(Vector1Data); + + byte[] signature = sig.sign(); + assertNotNull("Signature must not be null", signature); + assertTrue("Signature should match expected", + Arrays.equals(signature, NONEwithRSA_Vector1Signature)); + + RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(RSA_2048_modulus, + RSA_2048_publicExponent); + PublicKey pubKey = kf.generatePublic(pubKeySpec); + sig.initVerify(pubKey); + sig.update(Vector1Data); + assertTrue("Signature must verify correctly", sig.verify(signature)); + } + + public void testVerify_NONEwithRSA_Key_WrongSignature_Failure() throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + + RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(RSA_2048_modulus, + RSA_2048_publicExponent); + PublicKey pubKey = kf.generatePublic(pubKeySpec); + + Signature sig = Signature.getInstance("NONEwithRSA"); + sig.initVerify(pubKey); + sig.update(Vector1Data); + assertFalse("Invalid signature must not verify", sig.verify("Invalid".getBytes())); + } + + public void testSign_NONEwithRSA_Key_DataTooLarge_Failure() throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus, + RSA_2048_privateExponent); + PrivateKey privKey = kf.generatePrivate(keySpec); + + Signature sig = Signature.getInstance("NONEwithRSA"); + sig.initSign(privKey); + + final int oneTooBig = RSA_2048_modulus.bitLength() - 10; + for (int i = 0; i < oneTooBig; i++) { + sig.update((byte) i); + } + + try { + sig.sign(); + fail("Should throw exception when data is too large"); + } catch (SignatureException expected) { + } + } + + public void testSign_NONEwithRSA_Key_DataTooLarge_SingleByte_Failure() throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus, + RSA_2048_privateExponent); + PrivateKey privKey = kf.generatePrivate(keySpec); + + Signature sig = Signature.getInstance("NONEwithRSA"); + sig.initSign(privKey); + + // This should make it two bytes too big. + final int oneTooBig = RSA_2048_modulus.bitLength() - 10; + for (int i = 0; i < oneTooBig; i++) { + sig.update((byte) i); + } + + try { + sig.sign(); + fail("Should throw exception when data is too large"); + } catch (SignatureException expected) { + } + } + + public void testVerify_NONEwithRSA_Key_DataTooLarge_Failure() throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + + RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(RSA_2048_modulus, + RSA_2048_publicExponent); + PublicKey pubKey = kf.generatePublic(pubKeySpec); + + Signature sig = Signature.getInstance("NONEwithRSA"); + sig.initVerify(pubKey); + + // This should make it one bytes too big. + final int oneTooBig = RSA_2048_modulus.bitLength() + 1; + final byte[] vector = new byte[oneTooBig]; + for (int i = 0; i < oneTooBig; i++) { + vector[i] = (byte) Vector1Data[i % Vector1Data.length]; + } + sig.update(vector); + + assertFalse("Should not verify when signature is too large", + sig.verify(NONEwithRSA_Vector1Signature)); + } + + public void testVerify_NONEwithRSA_Key_DataTooLarge_SingleByte_Failure() throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + + RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(RSA_2048_modulus, + RSA_2048_publicExponent); + PublicKey pubKey = kf.generatePublic(pubKeySpec); + + Signature sig = Signature.getInstance("NONEwithRSA"); + sig.initVerify(pubKey); + + // This should make it twice as big as it should be. + final int tooBig = RSA_2048_modulus.bitLength() * 2; + for (int i = 0; i < tooBig; i++) { + sig.update((byte) Vector1Data[i % Vector1Data.length]); + } + + assertFalse("Should not verify when signature is too large", + sig.verify(NONEwithRSA_Vector1Signature)); + } + + public void testVerify_NONEwithRSA_Key_SignatureTooSmall_Failure() throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + + RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(RSA_2048_modulus, + RSA_2048_publicExponent); + PublicKey pubKey = kf.generatePublic(pubKeySpec); + + Signature sig = Signature.getInstance("NONEwithRSA"); + sig.initVerify(pubKey); + sig.update(Vector1Data); + + assertFalse("Invalid signature should not verify", sig.verify("Invalid sig".getBytes())); + } + + public void testVerify_NONEwithRSA_Key_SignatureTooLarge_Failure() throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + + RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(RSA_2048_modulus, + RSA_2048_publicExponent); + PublicKey pubKey = kf.generatePublic(pubKeySpec); + + Signature sig = Signature.getInstance("NONEwithRSA"); + sig.initVerify(pubKey); + sig.update(Vector1Data); + + byte[] invalidSignature = new byte[NONEwithRSA_Vector1Signature.length * 2]; + System.arraycopy(NONEwithRSA_Vector1Signature, 0, invalidSignature, 0, + NONEwithRSA_Vector1Signature.length); + System.arraycopy(NONEwithRSA_Vector1Signature, 0, invalidSignature, + NONEwithRSA_Vector1Signature.length, NONEwithRSA_Vector1Signature.length); + + try { + sig.verify(invalidSignature); + fail("Should throw exception when signature is too large"); + } catch (SignatureException expected) { + } + } + /* * These tests were generated with this DSA private key: * @@ -1033,4 +1253,23 @@ public class SignatureTest extends TestCase { sig.update(Vector2Data); assertTrue("Signature must verify correctly", sig.verify(SHA1withDSA_Vector2Signature)); } + + // NetscapeCertRequest looks up Signature algorithms by OID from + // BC but BC version 1.47 had registration bugs and MD5withRSA was + // overlooked. http://b/7453821 + public void testGetInstanceFromOID() throws Exception { + assertBouncyCastleSignatureFromOID("1.2.840.113549.1.1.4"); // MD5withRSA + assertBouncyCastleSignatureFromOID("1.2.840.113549.1.1.5"); // SHA1withRSA + assertBouncyCastleSignatureFromOID("1.3.14.3.2.29"); // SHA1withRSA + assertBouncyCastleSignatureFromOID("1.2.840.113549.1.1.11"); // SHA256withRSA + assertBouncyCastleSignatureFromOID("1.2.840.113549.1.1.12"); // SHA384withRSA + assertBouncyCastleSignatureFromOID("1.2.840.113549.1.1.13"); // SHA512withRSA + assertBouncyCastleSignatureFromOID("1.2.840.10040.4.3"); // SHA1withDSA + } + + private void assertBouncyCastleSignatureFromOID(String oid) throws Exception { + Signature signature = Signature.getInstance(oid, "BC"); + assertNotNull(oid, signature); + assertEquals(oid, signature.getAlgorithm()); + } } diff --git a/luni/src/test/java/libcore/java/text/OldDateFormatTest.java b/luni/src/test/java/libcore/java/text/OldDateFormatTest.java index f614d6f..df388d3 100644 --- a/luni/src/test/java/libcore/java/text/OldDateFormatTest.java +++ b/luni/src/test/java/libcore/java/text/OldDateFormatTest.java @@ -90,7 +90,7 @@ public class OldDateFormatTest extends junit.framework.TestCase { DateFormat.SHORT, DateFormat.SHORT, Locale.US); Date current = new Date(); String dtf = format.format(current); - SimpleDateFormat sdf = new SimpleDateFormat("M/d/yy h:mm a"); + SimpleDateFormat sdf = new SimpleDateFormat("M/d/yy h:mm a", Locale.US); assertTrue("Incorrect date format", sdf.format(current).equals(dtf)); } catch (Exception e) { fail("Unexpected exception " + e.toString()); @@ -110,7 +110,7 @@ public class OldDateFormatTest extends junit.framework.TestCase { StringBuffer toAppend = new StringBuffer(); FieldPosition fp = new FieldPosition(DateFormat.YEAR_FIELD); StringBuffer sb = format.format(current, toAppend, fp); - SimpleDateFormat sdf = new SimpleDateFormat("M/d/yy h:mm a"); + SimpleDateFormat sdf = new SimpleDateFormat("M/d/yy h:mm a", Locale.US); assertTrue("Incorrect date format", sdf.format(current).equals( sb.toString())); assertTrue("Incorrect beginIndex of filed position", fp @@ -203,7 +203,7 @@ public class OldDateFormatTest extends junit.framework.TestCase { /** * java.text.DateFormat#parse(String) */ - public void test_parseLString() { + public void test_parseLString() throws Exception { DateFormat format = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.US); try { @@ -338,35 +338,29 @@ public class OldDateFormatTest extends junit.framework.TestCase { try { format.parse("January 31 1970 7:52:34 AM PST"); fail("ParseException was not thrown."); - } catch(ParseException pe) { - //expected + } catch (ParseException expected) { } try { format.parse("January 31 1970"); fail("ParseException was not thrown."); - } catch(ParseException pe) { - //expected + } catch (ParseException expected) { } format = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, Locale.US); - try { - Date date = format.parse(format.format(current).toString()); - assertEquals(current.getDate(), date.getDate()); - assertEquals(current.getDay(), date.getDay()); - assertEquals(current.getMonth(), date.getMonth()); - assertEquals(current.getYear(), date.getYear()); - assertEquals(current.getHours(), date.getHours()); - assertEquals(current.getMinutes(), date.getMinutes()); - } catch(ParseException pe) { - fail("ParseException was thrown for current Date."); + String formatPattern = ((SimpleDateFormat) format).toPattern(); + String formattedCurrent = format.format(current); + Date date = format.parse(formattedCurrent); + // Date has millisecond accuracy, but humans don't use time formats that precise. + if (date.getTime() / 1000 != current.getTime() / 1000) { + fail(date.getTime() + " != " + current.getTime() + + "; " + formatPattern + "; " + formattedCurrent); } try { format.parse("January 16, 1970 8:03:52 PM CET"); fail("ParseException was not thrown."); - } catch(ParseException pe) { - //expected + } catch (ParseException expected) { } } diff --git a/luni/src/test/java/libcore/java/text/OldSimpleDateFormatTest.java b/luni/src/test/java/libcore/java/text/OldSimpleDateFormatTest.java index 01506df..ff24bb6 100644 --- a/luni/src/test/java/libcore/java/text/OldSimpleDateFormatTest.java +++ b/luni/src/test/java/libcore/java/text/OldSimpleDateFormatTest.java @@ -30,9 +30,21 @@ import java.util.TimeZone; public class OldSimpleDateFormatTest extends junit.framework.TestCase { - SimpleDateFormat format = new SimpleDateFormat("", Locale.ENGLISH); + SimpleDateFormat format = null; + SimpleDateFormat pFormat = null; + + @Override + protected void setUp() throws Exception { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + format = new SimpleDateFormat("", Locale.ENGLISH); + pFormat = new SimpleDateFormat("", Locale.ENGLISH); + } - SimpleDateFormat pFormat = new SimpleDateFormat("", Locale.ENGLISH); + @Override + protected void tearDown() throws Exception { + format = null; + pFormat = null; + } class FormatTester { boolean testsFailed = false; diff --git a/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java b/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java index c6296ff..cd54d1e 100644 --- a/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java +++ b/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java @@ -51,6 +51,7 @@ public class SimpleDateFormatTest extends junit.framework.TestCase { // The RI fails this test because this is an ICU-compatible Android extension. // Necessary for correct localization in various languages (http://b/2633414). public void testStandAloneNames() throws Exception { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); Locale en = Locale.ENGLISH; Locale pl = new Locale("pl"); Locale ru = new Locale("ru"); @@ -77,7 +78,7 @@ public class SimpleDateFormatTest extends junit.framework.TestCase { } public void test2038() { - SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy"); + SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy", Locale.US); format.setTimeZone(TimeZone.getTimeZone("UTC")); assertEquals("Sun Nov 24 17:31:44 1833", @@ -175,14 +176,14 @@ public class SimpleDateFormatTest extends junit.framework.TestCase { * longer use their DST zone but we should continue to parse it properly. */ public void testObsoleteDstZoneName() throws Exception { - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm zzzz"); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm zzzz", Locale.US); Date normal = format.parse("1970-01-01T00:00 EET"); Date dst = format.parse("1970-01-01T00:00 EEST"); assertEquals(60 * 60 * 1000, normal.getTime() - dst.getTime()); } public void testDstZoneNameWithNonDstTimestamp() throws Exception { - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm zzzz"); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm zzzz", Locale.US); Calendar calendar = new GregorianCalendar(AMERICA_LOS_ANGELES); calendar.setTime(format.parse("2011-06-21T10:00 Pacific Standard Time")); // 18:00 GMT-8 assertEquals(11, calendar.get(Calendar.HOUR_OF_DAY)); // 18:00 GMT-7 @@ -190,7 +191,7 @@ public class SimpleDateFormatTest extends junit.framework.TestCase { } public void testNonDstZoneNameWithDstTimestamp() throws Exception { - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm zzzz"); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm zzzz", Locale.US); Calendar calendar = new GregorianCalendar(AMERICA_LOS_ANGELES); calendar.setTime(format.parse("2010-12-21T10:00 Pacific Daylight Time")); // 17:00 GMT-7 assertEquals(9, calendar.get(Calendar.HOUR_OF_DAY)); // 17:00 GMT-8 @@ -199,7 +200,7 @@ public class SimpleDateFormatTest extends junit.framework.TestCase { // http://b/4723412 public void testDstZoneWithNonDstTimestampForNonHourDstZone() throws Exception { - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm zzzz"); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm zzzz", Locale.US); Calendar calendar = new GregorianCalendar(AUSTRALIA_LORD_HOWE); calendar.setTime(format.parse("2011-06-21T20:00 Lord Howe Daylight Time")); // 9:00 GMT+11 assertEquals(19, calendar.get(Calendar.HOUR_OF_DAY)); // 9:00 GMT+10:30 @@ -207,7 +208,7 @@ public class SimpleDateFormatTest extends junit.framework.TestCase { } public void testNonDstZoneWithDstTimestampForNonHourDstZone() throws Exception { - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm zzzz"); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm zzzz", Locale.US); Calendar calendar = new GregorianCalendar(AUSTRALIA_LORD_HOWE); calendar.setTime(format.parse("2010-12-21T19:30 Lord Howe Standard Time")); //9:00 GMT+10:30 assertEquals(20, calendar.get(Calendar.HOUR_OF_DAY)); // 9:00 GMT+11:00 @@ -227,4 +228,23 @@ public class SimpleDateFormatTest extends junit.framework.TestCase { new SimpleDateFormat("z", Locale.FRANCE).parse("UTC"); new SimpleDateFormat("z", Locale.US).parse("UTC"); } + + // http://code.google.com/p/android/issues/detail?id=36689 + public void testParseArabic() throws Exception { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", new Locale("ar", "EG")); + sdf.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles")); + + // Can we parse an ASCII-formatted date in an Arabic locale? + Date d = sdf.parse("2012-08-29 10:02:45"); + assertEquals(1346259765000L, d.getTime()); + + // Can we format a date correctly in an Arabic locale? + String formatted = sdf.format(d); + assertEquals("٢٠١٢-٠٨-٢٩ ١٠:٠٢:٤٥", formatted); + + // Can we parse the Arabic-formatted date in an Arabic locale, and get the same date + // we started with? + Date d2 = sdf.parse(formatted); + assertEquals(d, d2); + } } diff --git a/luni/src/test/java/libcore/java/util/LocaleTest.java b/luni/src/test/java/libcore/java/util/LocaleTest.java index 541dd66..b146b1a 100644 --- a/luni/src/test/java/libcore/java/util/LocaleTest.java +++ b/luni/src/test/java/libcore/java/util/LocaleTest.java @@ -46,6 +46,16 @@ public class LocaleTest extends junit.framework.TestCase { assertEquals("Deutsch", Locale.GERMAN.getDisplayLanguage(Locale.GERMAN)); } + // http://b/7291355; Locale.getDisplayLanguage fails for tl in tl in ICU 4.9. + public void test_tl() throws Exception { + Locale tl = new Locale("tl"); + Locale tl_PH = new Locale("tl", "PH"); + assertEquals("Filipino", tl.getDisplayLanguage(Locale.ENGLISH)); + assertEquals("Filipino", tl_PH.getDisplayLanguage(Locale.ENGLISH)); + assertEquals("Filipino", tl.getDisplayLanguage(tl)); + assertEquals("Filipino", tl_PH.getDisplayLanguage(tl_PH)); + } + // http://b/3452611; Locale.getDisplayLanguage fails for the obsolete language codes. public void test_getDisplayName_obsolete() throws Exception { // he (new) -> iw (obsolete) diff --git a/luni/src/test/java/libcore/java/util/OldAndroidLocaleTest.java b/luni/src/test/java/libcore/java/util/OldAndroidLocaleTest.java index 547b70a..8fbe5ff 100644 --- a/luni/src/test/java/libcore/java/util/OldAndroidLocaleTest.java +++ b/luni/src/test/java/libcore/java/util/OldAndroidLocaleTest.java @@ -31,7 +31,6 @@ import junit.framework.TestCase; * resource bundles. */ public class OldAndroidLocaleTest extends TestCase { - // Test basic Locale infrastructure. public void testLocale() throws Exception { Locale locale = new Locale("en"); @@ -47,49 +46,6 @@ public class OldAndroidLocaleTest extends TestCase { assertEquals("en_US_POSIX", locale.toString()); } - /* - * Tests some must-have locales. TODO: Add back "de". See discussion - * immediately below this method. - */ - public void testResourceBundles() throws Exception { - Locale eng = new Locale("en", "US"); - DateFormatSymbols engSymbols = new DateFormatSymbols(eng); - - //Locale deu = new Locale("de", "DE"); - //DateFormatSymbols deuSymbols = new DateFormatSymbols(deu); - - TimeZone berlin = TimeZone.getTimeZone("Europe/Berlin"); - - assertEquals("January", engSymbols.getMonths()[0]); - //assertEquals("Januar", deuSymbols.getMonths()[0]); - - assertEquals("Sunday", engSymbols.getWeekdays()[Calendar.SUNDAY]); - //assertEquals("Sonntag", deuSymbols.getWeekdays()[Calendar.SUNDAY]); - - assertEquals("Central European Time", - berlin.getDisplayName(false, TimeZone.LONG, eng)); - assertEquals("Central European Summer Time", - berlin.getDisplayName(true, TimeZone.LONG, eng)); - - //assertEquals("Mitteleurop\u00E4ische Zeit", - // berlin.getDisplayName(false, TimeZone.LONG, deu)); - //assertEquals("Mitteleurop\u00E4ische Sommerzeit", - // berlin.getDisplayName(true, TimeZone.LONG, deu)); - - assertTrue(engSymbols.getZoneStrings().length > 100); - } - - /* - * Disabled version of the above test. The version above omits - * checks for stuff in the "de" locale, because we stripped that - * out as part of the flash reduction effort (so that we could - * still ship on Dream). We expect to have a baseline target that - * includes a large enough system partition to include "de" - * immediately after the last official release for Dream (whenever - * that may be). - * - // Test some must-have locales. - @LargeTest public void testResourceBundles() throws Exception { Locale eng = new Locale("en", "US"); DateFormatSymbols engSymbols = new DateFormatSymbols(eng); @@ -117,7 +73,6 @@ public class OldAndroidLocaleTest extends TestCase { assertTrue(engSymbols.getZoneStrings().length > 100); } - */ // This one makes sure we have all necessary locales installed. // Suppress this flaky test for now. diff --git a/luni/src/test/java/libcore/java/util/OldScannerTest.java b/luni/src/test/java/libcore/java/util/OldScannerTest.java index b51cfbc..9bac1f4 100644 --- a/luni/src/test/java/libcore/java/util/OldScannerTest.java +++ b/luni/src/test/java/libcore/java/util/OldScannerTest.java @@ -28,7 +28,6 @@ import java.util.Scanner; import java.util.regex.MatchResult; import java.util.regex.Pattern; import junit.framework.TestCase; -import tests.support.Support_PortManager; public final class OldScannerTest extends TestCase { @@ -492,15 +491,12 @@ public final class OldScannerTest extends TestCase { assertEquals(102400, matchResult.end()); } - public void test_Constructor_LReadableByteChannel() - throws IOException { - InetSocketAddress localAddr = new InetSocketAddress("127.0.0.1", - Support_PortManager.getNextPort()); + public void test_Constructor_LReadableByteChannel() throws IOException { ServerSocketChannel ssc = ServerSocketChannel.open(); - ssc.socket().bind(localAddr); + ssc.socket().bind(null); SocketChannel sc = SocketChannel.open(); - sc.connect(localAddr); + sc.connect(ssc.socket().getLocalSocketAddress()); sc.configureBlocking(false); assertFalse(sc.isBlocking()); diff --git a/luni/src/test/java/libcore/java/util/OldTimeZoneTest.java b/luni/src/test/java/libcore/java/util/OldTimeZoneTest.java index 240403e..4ed89de 100644 --- a/luni/src/test/java/libcore/java/util/OldTimeZoneTest.java +++ b/luni/src/test/java/libcore/java/util/OldTimeZoneTest.java @@ -83,6 +83,7 @@ public class OldTimeZoneTest extends TestCase { } public void test_getDisplayName() { + Locale.setDefault(Locale.US); TimeZone tz = TimeZone.getTimeZone("GMT-6"); assertEquals("GMT-06:00", tz.getDisplayName()); tz = TimeZone.getTimeZone("America/Los_Angeles"); @@ -99,6 +100,7 @@ public class OldTimeZoneTest extends TestCase { } public void test_getDisplayNameZI() { + Locale.setDefault(Locale.US); TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles"); assertEquals("PST", tz.getDisplayName(false, 0)); assertEquals("Pacific Daylight Time", tz.getDisplayName(true, 1)); @@ -150,15 +152,4 @@ public class OldTimeZoneTest extends TestCase { tz.setID("New ID for GMT-6"); assertEquals("New ID for GMT-6", tz.getID()); } - - Locale loc = null; - - protected void setUp() { - loc = Locale.getDefault(); - Locale.setDefault(Locale.US); - } - - protected void tearDown() { - Locale.setDefault(loc); - } } diff --git a/luni/src/test/java/libcore/java/util/TimeZoneTest.java b/luni/src/test/java/libcore/java/util/TimeZoneTest.java index d94b017..6e8b8d8 100644 --- a/luni/src/test/java/libcore/java/util/TimeZoneTest.java +++ b/luni/src/test/java/libcore/java/util/TimeZoneTest.java @@ -17,12 +17,14 @@ package libcore.java.util; import java.text.SimpleDateFormat; +import java.util.Calendar; import java.util.Date; import java.util.Locale; -import java.util.TimeZone; import java.util.SimpleTimeZone; +import java.util.TimeZone; +import junit.framework.TestCase; -public class TimeZoneTest extends junit.framework.TestCase { +public class TimeZoneTest extends TestCase { // http://code.google.com/p/android/issues/detail?id=877 public void test_useDaylightTime_Taiwan() { TimeZone asiaTaipei = TimeZone.getTimeZone("Asia/Taipei"); @@ -144,8 +146,8 @@ public class TimeZoneTest extends junit.framework.TestCase { // http://code.google.com/p/android/issues/detail?id=11918 public void testHasSameRules() throws Exception { - TimeZone denver = TimeZone.getTimeZone ("America/Denver") ; - TimeZone phoenix = TimeZone.getTimeZone ("America/Phoenix") ; + TimeZone denver = TimeZone.getTimeZone("America/Denver"); + TimeZone phoenix = TimeZone.getTimeZone("America/Phoenix"); assertFalse(denver.hasSameRules(phoenix)); } @@ -157,4 +159,56 @@ public class TimeZoneTest extends junit.framework.TestCase { } catch (NullPointerException expected) { } } + + // http://b.corp.google.com/issue?id=6556561 + public void testCustomZoneIds() throws Exception { + // These are all okay (and equivalent). + assertEquals("GMT+05:00", TimeZone.getTimeZone("GMT+05:00").getID()); + assertEquals("GMT+05:00", TimeZone.getTimeZone("GMT+5:00").getID()); + assertEquals("GMT+05:00", TimeZone.getTimeZone("GMT+0500").getID()); + assertEquals("GMT+05:00", TimeZone.getTimeZone("GMT+500").getID()); + assertEquals("GMT+05:00", TimeZone.getTimeZone("GMT+5").getID()); + // These aren't. + assertEquals("GMT", TimeZone.getTimeZone("GMT+5.5").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+5:5").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+5:0").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+5:005").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+5:000").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+005:00").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+05:99").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+28:00").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+05:00.00").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+05:00:00").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+5:").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+junk").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+5junk").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+5:junk").getID()); + assertEquals("GMT", TimeZone.getTimeZone("GMT+5:00junk").getID()); + assertEquals("GMT", TimeZone.getTimeZone("junkGMT+5:00").getID()); + assertEquals("GMT", TimeZone.getTimeZone("junk").getID()); + assertEquals("GMT", TimeZone.getTimeZone("gmt+5:00").getID()); + } + + public void test_getDSTSavings() throws Exception { + assertEquals(0, TimeZone.getTimeZone("UTC").getDSTSavings()); + assertEquals(3600000, TimeZone.getTimeZone("America/Los_Angeles").getDSTSavings()); + assertEquals(1800000, TimeZone.getTimeZone("Australia/Lord_Howe").getDSTSavings()); + } + + public void testSimpleTimeZoneDoesNotCallOverrideableMethodsFromConstructor() { + new SimpleTimeZone(0, "X", Calendar.MARCH, 1, 1, 1, Calendar.SEPTEMBER, 1, 1, 1) { + @Override public void setStartRule(int m, int d, int dow, int time) { + fail(); + } + @Override public void setStartRule(int m, int d, int dow, int time, boolean after) { + fail(); + } + @Override public void setEndRule(int m, int d, int dow, int time) { + fail(); + } + @Override public void setEndRule(int m, int d, int dow, int time, boolean after) { + fail(); + } + }; + } } diff --git a/luni/src/test/java/libcore/java/util/prefs/OldPreferencesTest.java b/luni/src/test/java/libcore/java/util/prefs/OldPreferencesTest.java index aa5f088..f8a8154 100644 --- a/luni/src/test/java/libcore/java/util/prefs/OldPreferencesTest.java +++ b/luni/src/test/java/libcore/java/util/prefs/OldPreferencesTest.java @@ -29,8 +29,10 @@ import junit.framework.TestCase; public final class OldPreferencesTest extends TestCase { - final static String longKey; - final static String longValue; + private static final boolean ENCOURAGE_RACES = false; + + private static final String longKey; + private static final String longValue; static { StringBuilder key = new StringBuilder(Preferences.MAX_KEY_LENGTH); @@ -316,8 +318,7 @@ public final class OldPreferencesTest extends TestCase { String longName = name.toString(); Preferences root = Preferences.userRoot(); - Preferences parent = Preferences - .userNodeForPackage(Preferences.class); + Preferences parent = Preferences.userNodeForPackage(Preferences.class); Preferences pref = parent.node("mock"); try { @@ -352,8 +353,7 @@ public final class OldPreferencesTest extends TestCase { public void testNodeExists() throws BackingStoreException { - Preferences parent = Preferences - .userNodeForPackage(Preferences.class); + Preferences parent = Preferences.userNodeForPackage(Preferences.class); Preferences pref = parent.node("mock"); try { @@ -393,16 +393,14 @@ public final class OldPreferencesTest extends TestCase { } public void testParent() { - Preferences parent = Preferences - .userNodeForPackage(Preferences.class); + Preferences parent = Preferences.userNodeForPackage(Preferences.class); Preferences pref = parent.node("mock"); assertSame(parent, pref.parent()); } public void testPut() throws BackingStoreException { - Preferences pref = Preferences - .userNodeForPackage(Preferences.class); + Preferences pref = Preferences.userNodeForPackage(Preferences.class); pref.put("", "emptyvalue"); assertEquals("emptyvalue", pref.get("", null)); pref.put("testPutkey", "value1"); @@ -468,8 +466,7 @@ public final class OldPreferencesTest extends TestCase { } public void testPutDouble() { - Preferences pref = Preferences - .userNodeForPackage(Preferences.class); + Preferences pref = Preferences.userNodeForPackage(Preferences.class); try { pref.putDouble(null, 3); fail(); @@ -580,8 +577,7 @@ public final class OldPreferencesTest extends TestCase { } public void testRemove() throws BackingStoreException { - Preferences pref = Preferences - .userNodeForPackage(Preferences.class); + Preferences pref = Preferences.userNodeForPackage(Preferences.class); pref.remove("key"); pref.put("key", "value"); @@ -606,8 +602,7 @@ public final class OldPreferencesTest extends TestCase { } public void testRemoveNode() throws BackingStoreException { - Preferences pref = Preferences - .userNodeForPackage(Preferences.class); + Preferences pref = Preferences.userNodeForPackage(Preferences.class); Preferences child = pref.node("child"); Preferences child1 = pref.node("child1"); Preferences grandchild = child.node("grandchild"); @@ -636,11 +631,12 @@ public final class OldPreferencesTest extends TestCase { nl = new MockNodeChangeListener(); pref.addNodeChangeListener(nl); child1 = pref.node("mock1"); - nl.waitForEvent(); + nl.waitForEvent(1); assertEquals(1, nl.getAdded()); nl.reset(); pref.node("mock1"); - nl.waitForEvent(); + // There shouldn't be an event, but wait in case one arrives... + try { Thread.sleep(1000); } catch (InterruptedException ignored) {} assertEquals(0, nl.getAdded()); nl.reset(); } finally { @@ -653,7 +649,7 @@ public final class OldPreferencesTest extends TestCase { pref.addNodeChangeListener(nl); pref.addNodeChangeListener(nl); child1 = pref.node("mock2"); - nl.waitForEvent(); + nl.waitForEvent(2); assertEquals(2, nl.getAdded()); nl.reset(); } finally { @@ -667,7 +663,7 @@ public final class OldPreferencesTest extends TestCase { pref.addNodeChangeListener(nl); child1 = pref.node("mock3"); child1.removeNode(); - nl.waitForEvent(); + nl.waitForEvent(2); assertEquals(1, nl.getRemoved()); nl.reset(); } finally { @@ -680,7 +676,7 @@ public final class OldPreferencesTest extends TestCase { pref.addNodeChangeListener(nl); child1 = pref.node("mock6"); child1.removeNode(); - nl.waitForEvent(); + nl.waitForEvent(4); assertEquals(2, nl.getRemoved()); nl.reset(); } finally { @@ -695,27 +691,29 @@ public final class OldPreferencesTest extends TestCase { child1 = pref.node("mock4"); child1.addNodeChangeListener(nl); pref.node("mock4/mock5"); - nl.waitForEvent(); + nl.waitForEvent(1); assertEquals(1, nl.getAdded()); nl.reset(); child3 = pref.node("mock4/mock5/mock6"); - nl.waitForEvent(); + // There shouldn't be an event, but wait in case one arrives... + try { Thread.sleep(1000); } catch (InterruptedException ignored) {} assertEquals(0, nl.getAdded()); nl.reset(); child3.removeNode(); - nl.waitForEvent(); + // There shouldn't be an event, but wait in case one arrives... + try { Thread.sleep(1000); } catch (InterruptedException ignored) {} assertEquals(0, nl.getRemoved()); nl.reset(); pref.node("mock4/mock7"); - nl.waitForEvent(); + nl.waitForEvent(1); assertEquals(1, nl.getAdded()); nl.reset(); child1.removeNode(); - nl.waitForEvent(); - assertEquals(2, nl.getRemoved()); // fail 1 + nl.waitForEvent(2); + assertEquals(2, nl.getRemoved()); nl.reset(); } finally { try { @@ -749,7 +747,7 @@ public final class OldPreferencesTest extends TestCase { try { pref.clear(); pl.waitForEvent(2); - assertEquals(2, pl.getChanged()); // fail 1 + assertEquals(2, pl.getChanged()); } catch(BackingStoreException bse) { pl.reset(); fail("BackingStoreException is thrown"); @@ -784,7 +782,7 @@ public final class OldPreferencesTest extends TestCase { try { pref.clear(); pl.waitForEvent(3); - assertEquals(3, pl.getChanged()); // fails + assertEquals(3, pl.getChanged()); } catch(BackingStoreException bse) { fail("BackingStoreException is thrown"); } @@ -868,25 +866,38 @@ public final class OldPreferencesTest extends TestCase { static class MockNodeChangeListener implements NodeChangeListener { private int added = 0; private int removed = 0; + private int eventCount = 0; - public synchronized void waitForEvent() { - try { - wait(500); - } catch (InterruptedException ignored) { + public void waitForEvent(int count) { + synchronized (this) { + while (eventCount < count) { + try { + wait(); + } catch (InterruptedException ignored) { + } + } } } - public synchronized void childAdded(NodeChangeEvent e) { - ++added; - notifyAll(); + public void childAdded(NodeChangeEvent e) { + if (ENCOURAGE_RACES) try { Thread.sleep(1000); } catch (InterruptedException ignored) { } + synchronized (this) { + ++eventCount; + ++added; + notifyAll(); + } } - public synchronized void childRemoved(NodeChangeEvent e) { - removed++; - notifyAll(); + public void childRemoved(NodeChangeEvent e) { + if (ENCOURAGE_RACES) try { Thread.sleep(1000); } catch (InterruptedException ignored) { } + synchronized (this) { + ++eventCount; + ++removed; + notifyAll(); + } } - public synchronized int getAdded() { + public synchronized int getAdded() { return added; } @@ -894,7 +905,8 @@ public final class OldPreferencesTest extends TestCase { return removed; } - public void reset() { + public synchronized void reset() { + eventCount = 0; added = 0; removed = 0; } @@ -902,47 +914,35 @@ public final class OldPreferencesTest extends TestCase { private static class MockPreferenceChangeListener implements PreferenceChangeListener { private int changed = 0; - private boolean addDispatched = false; - private boolean result = false; + private int eventCount = 0; public void waitForEvent(int count) { - for (int i = 0; i < count; i++) { - try { - synchronized (this) { - wait(500); + synchronized (this) { + while (eventCount < count) { + try { + wait(); + } catch (InterruptedException ignored) { } - } catch (InterruptedException ignored) { } } } - public synchronized void preferenceChange(PreferenceChangeEvent pce) { - changed++; - addDispatched = true; - notifyAll(); - } - - public boolean getResult() throws InterruptedException { - if (!addDispatched) { - // TODO: don't know why must add limitation - wait(100); + public void preferenceChange(PreferenceChangeEvent pce) { + if (ENCOURAGE_RACES) try { Thread.sleep(1000); } catch (InterruptedException ignored) { } + synchronized (this) { + ++eventCount; + ++changed; + notifyAll(); } - addDispatched = false; - return result; } - public synchronized int getChanged() throws InterruptedException { - if (!addDispatched) { - // TODO: don't know why must add limitation - wait(1000); - } - addDispatched = false; + public synchronized int getChanged() { return changed; } - public void reset() { + public synchronized void reset() { + eventCount = 0; changed = 0; - result = false; } } diff --git a/luni/src/test/java/libcore/java/util/regex/OldMatcherTest.java b/luni/src/test/java/libcore/java/util/regex/OldMatcherTest.java index 450b8d9..07d99e9 100644 --- a/luni/src/test/java/libcore/java/util/regex/OldMatcherTest.java +++ b/luni/src/test/java/libcore/java/util/regex/OldMatcherTest.java @@ -247,19 +247,36 @@ public class OldMatcherTest extends TestCase { } } - // Starting index out of region + String string3 = "Brave new world"; Pattern pat3 = Pattern.compile("new"); - Matcher mat3 = pat3.matcher("Brave new world"); + Matcher mat3 = pat3.matcher(string3); + + // find(int) throws for out of range indexes. + try { + mat3.find(-1); + fail(); + } catch (IndexOutOfBoundsException expected) { + } + assertFalse(mat3.find(string3.length())); + try { + mat3.find(string3.length() + 1); + fail(); + } catch (IndexOutOfBoundsException expected) { + } - assertTrue(mat3.find(-1)); assertTrue(mat3.find(6)); assertFalse(mat3.find(7)); mat3.region(7, 10); + assertFalse(mat3.find()); // No "new" in the region. - assertFalse(mat3.find(3)); - assertFalse(mat3.find(6)); - assertFalse(mat3.find(7)); + assertTrue(mat3.find(3)); // find(int) ignores the region. + assertTrue(mat3.find(6)); // find(int) ignores the region. + assertFalse(mat3.find(7)); // No "new" >= 7. + + mat3.region(1, 4); + assertFalse(mat3.find()); // No "new" in the region. + assertTrue(mat3.find(5)); // find(int) ignores the region. } public void testSEOLsymbols() { @@ -579,4 +596,14 @@ public class OldMatcherTest extends TestCase { assertTrue(pattern.matcher("14pt").matches()); } + public void testUnicodeCharacterClasses() throws Exception { + // http://code.google.com/p/android/issues/detail?id=21176 + // We use the Unicode TR-18 definitions: http://www.unicode.org/reports/tr18/#Compatibility_Properties + assertTrue("\u0666".matches("\\d")); // ARABIC-INDIC DIGIT SIX + assertFalse("\u0666".matches("\\D")); // ARABIC-INDIC DIGIT SIX + assertTrue("\u1680".matches("\\s")); // OGHAM SPACE MARK + assertFalse("\u1680".matches("\\S")); // OGHAM SPACE MARK + assertTrue("\u00ea".matches("\\w")); // LATIN SMALL LETTER E WITH CIRCUMFLEX + assertFalse("\u00ea".matches("\\W")); // LATIN SMALL LETTER E WITH CIRCUMFLEX + } } diff --git a/luni/src/test/java/libcore/javax/crypto/CipherTest.java b/luni/src/test/java/libcore/javax/crypto/CipherTest.java index 7919b35..68a46f3 100644 --- a/luni/src/test/java/libcore/javax/crypto/CipherTest.java +++ b/luni/src/test/java/libcore/javax/crypto/CipherTest.java @@ -17,14 +17,788 @@ package libcore.javax.crypto; import com.android.org.bouncycastle.asn1.x509.KeyUsage; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.math.BigInteger; +import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; +import java.security.Key; +import java.security.KeyFactory; +import java.security.PrivateKey; +import java.security.Provider; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.Security; import java.security.cert.Certificate; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.RSAPrivateKeySpec; +import java.security.spec.RSAPublicKeySpec; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import javax.crypto.BadPaddingException; import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.ShortBufferException; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.PBEParameterSpec; +import javax.crypto.spec.SecretKeySpec; import junit.framework.TestCase; +import libcore.java.security.StandardNames; import libcore.java.security.TestKeyStore; public final class CipherTest extends TestCase { + private static final String[] RSA_PROVIDERS = ((StandardNames.IS_RI) + ? new String[] { "SunJCE" } + : new String[] { "BC" , "AndroidOpenSSL" }); + + private static final String[] AES_PROVIDERS = ((StandardNames.IS_RI) + ? new String[] { "SunJCE" } + : new String[] { "BC" }); // TOOD: , "AndroidOpenSSL" + + private static final boolean IS_UNLIMITED; + static { + boolean is_unlimited; + if (StandardNames.IS_RI) { + try { + String algorithm = "PBEWITHMD5ANDTRIPLEDES"; + Cipher.getInstance(algorithm).init(getEncryptMode(algorithm), + getEncryptKey(algorithm), + getAlgorithmParameterSpec(algorithm)); + is_unlimited = true; + } catch (Exception e) { + is_unlimited = false; + System.out.println("WARNING: Some tests disabled due to lack of " + + "'Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files'"); + } + } else { + is_unlimited = true; + } + IS_UNLIMITED = is_unlimited; + } + + private static boolean isUnsupported(String algorithm) { + if (algorithm.equals("RC2")) { + return true; + } + if (algorithm.equals("PBEWITHMD5ANDRC2")) { + return true; + } + if (algorithm.startsWith("PBEWITHSHA1ANDRC2")) { + return true; + } + if (algorithm.equals("PBEWITHSHAAND40BITRC2-CBC")) { + return true; + } + if (algorithm.equals("PBEWITHSHAAND128BITRC2-CBC")) { + return true; + } + if (algorithm.equals("PBEWITHSHAANDTWOFISH-CBC")) { + return true; + } + if (!IS_UNLIMITED) { + if (algorithm.equals("PBEWITHMD5ANDTRIPLEDES")) { + return true; + } + } + return false; + } + + private synchronized static int getEncryptMode(String algorithm) throws Exception { + if (isWrap(algorithm)) { + return Cipher.WRAP_MODE; + } + return Cipher.ENCRYPT_MODE; + } + + private synchronized static int getDecryptMode(String algorithm) throws Exception { + if (isWrap(algorithm)) { + return Cipher.UNWRAP_MODE; + } + return Cipher.DECRYPT_MODE; + } + + private static String getBaseAlgorithm(String algorithm) { + if (algorithm.equals("AESWRAP")) { + return "AES"; + } + if (algorithm.startsWith("AES/")) { + return "AES"; + } + if (algorithm.equals("PBEWITHMD5AND128BITAES-CBC-OPENSSL")) { + return "AES"; + } + if (algorithm.equals("PBEWITHMD5AND192BITAES-CBC-OPENSSL")) { + return "AES"; + } + if (algorithm.equals("PBEWITHMD5AND256BITAES-CBC-OPENSSL")) { + return "AES"; + } + if (algorithm.equals("PBEWITHSHA256AND128BITAES-CBC-BC")) { + return "AES"; + } + if (algorithm.equals("PBEWITHSHA256AND192BITAES-CBC-BC")) { + return "AES"; + } + if (algorithm.equals("PBEWITHSHA256AND256BITAES-CBC-BC")) { + return "AES"; + } + if (algorithm.equals("PBEWITHSHAAND128BITAES-CBC-BC")) { + return "AES"; + } + if (algorithm.equals("PBEWITHSHAAND192BITAES-CBC-BC")) { + return "AES"; + } + if (algorithm.equals("PBEWITHSHAAND256BITAES-CBC-BC")) { + return "AES"; + } + if (algorithm.equals("PBEWITHMD5ANDDES")) { + return "DES"; + } + if (algorithm.equals("PBEWITHSHA1ANDDES")) { + return "DES"; + } + if (algorithm.equals("DESEDEWRAP")) { + return "DESEDE"; + } + if (algorithm.equals("PBEWITHSHAAND2-KEYTRIPLEDES-CBC")) { + return "DESEDE"; + } + if (algorithm.equals("PBEWITHSHAAND3-KEYTRIPLEDES-CBC")) { + return "DESEDE"; + } + if (algorithm.equals("PBEWITHMD5ANDTRIPLEDES")) { + return "DESEDE"; + } + if (algorithm.equals("PBEWITHSHA1ANDDESEDE")) { + return "DESEDE"; + } + if (algorithm.equals("RSA/ECB/NOPADDING")) { + return "RSA"; + } + if (algorithm.equals("RSA/ECB/PKCS1PADDING")) { + return "RSA"; + } + if (algorithm.equals("PBEWITHSHAAND40BITRC4")) { + return "ARC4"; + } + if (algorithm.equals("PBEWITHSHAAND128BITRC4")) { + return "ARC4"; + } + return algorithm; + } + + private static boolean isAsymmetric(String algorithm) { + return getBaseAlgorithm(algorithm).equals("RSA"); + } + + private static boolean isWrap(String algorithm) { + return algorithm.endsWith("WRAP"); + } + + private static boolean isPBE(String algorithm) { + return algorithm.startsWith("PBE"); + } + + private static Map<String, Key> ENCRYPT_KEYS = new HashMap<String, Key>(); + private synchronized static Key getEncryptKey(String algorithm) throws Exception { + Key key = ENCRYPT_KEYS.get(algorithm); + if (key != null) { + return key; + } + if (algorithm.startsWith("RSA")) { + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus, + RSA_2048_privateExponent); + key = kf.generatePrivate(keySpec); + } else if (isPBE(algorithm)) { + SecretKeyFactory skf = SecretKeyFactory.getInstance(algorithm); + key = skf.generateSecret(new PBEKeySpec("secret".toCharArray())); + } else { + KeyGenerator kg = KeyGenerator.getInstance(getBaseAlgorithm(algorithm)); + if (StandardNames.IS_RI && algorithm.equals("AES")) { + kg.init(128); + } + key = kg.generateKey(); + } + ENCRYPT_KEYS.put(algorithm, key); + return key; + } + + private static Map<String, Key> DECRYPT_KEYS = new HashMap<String, Key>(); + private synchronized static Key getDecryptKey(String algorithm) throws Exception { + Key key = DECRYPT_KEYS.get(algorithm); + if (key != null) { + return key; + } + if (algorithm.startsWith("RSA")) { + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPublicKeySpec keySpec = new RSAPublicKeySpec(RSA_2048_modulus, + RSA_2048_publicExponent); + key = kf.generatePublic(keySpec); + } else { + assertFalse(algorithm, isAsymmetric(algorithm)); + key = getEncryptKey(algorithm); + } + DECRYPT_KEYS.put(algorithm, key); + return key; + } + + private static Map<String, Integer> EXPECTED_BLOCK_SIZE = new HashMap<String, Integer>(); + static { + setExpectedBlockSize("AES", 16); + setExpectedBlockSize("PBEWITHMD5AND128BITAES-CBC-OPENSSL", 16); + setExpectedBlockSize("PBEWITHMD5AND192BITAES-CBC-OPENSSL", 16); + setExpectedBlockSize("PBEWITHMD5AND256BITAES-CBC-OPENSSL", 16); + setExpectedBlockSize("PBEWITHSHA256AND128BITAES-CBC-BC", 16); + setExpectedBlockSize("PBEWITHSHA256AND192BITAES-CBC-BC", 16); + setExpectedBlockSize("PBEWITHSHA256AND256BITAES-CBC-BC", 16); + setExpectedBlockSize("PBEWITHSHAAND128BITAES-CBC-BC", 16); + setExpectedBlockSize("PBEWITHSHAAND192BITAES-CBC-BC", 16); + setExpectedBlockSize("PBEWITHSHAAND256BITAES-CBC-BC", 16); + + if (StandardNames.IS_RI) { + setExpectedBlockSize("AESWRAP", 16); + } else { + setExpectedBlockSize("AESWRAP", 0); + } + + setExpectedBlockSize("ARC4", 0); + setExpectedBlockSize("ARCFOUR", 0); + setExpectedBlockSize("PBEWITHSHAAND40BITRC4", 0); + setExpectedBlockSize("PBEWITHSHAAND128BITRC4", 0); + + setExpectedBlockSize("BLOWFISH", 8); + + setExpectedBlockSize("DES", 8); + setExpectedBlockSize("PBEWITHMD5ANDDES", 8); + setExpectedBlockSize("PBEWITHSHA1ANDDES", 8); + + setExpectedBlockSize("DESEDE", 8); + setExpectedBlockSize("PBEWITHSHAAND2-KEYTRIPLEDES-CBC", 8); + setExpectedBlockSize("PBEWITHSHAAND3-KEYTRIPLEDES-CBC", 8); + setExpectedBlockSize("PBEWITHMD5ANDTRIPLEDES", 8); + setExpectedBlockSize("PBEWITHSHA1ANDDESEDE", 8); + + + if (StandardNames.IS_RI) { + setExpectedBlockSize("DESEDEWRAP", 8); + } else { + setExpectedBlockSize("DESEDEWRAP", 0); + } + + if (StandardNames.IS_RI) { + setExpectedBlockSize("RSA", 0); + setExpectedBlockSize("RSA/ECB/NoPadding", 0); + setExpectedBlockSize("RSA/ECB/PKCS1Padding", 0); + } else { + setExpectedBlockSize("RSA", Cipher.ENCRYPT_MODE, 256); + setExpectedBlockSize("RSA/ECB/NoPadding", Cipher.ENCRYPT_MODE, 256); + setExpectedBlockSize("RSA/ECB/PKCS1Padding", Cipher.ENCRYPT_MODE, 245); + + // BC strips the leading 0 for us even when NoPadding is specified + setExpectedBlockSize("RSA", Cipher.ENCRYPT_MODE, "BC", 255); + setExpectedBlockSize("RSA/ECB/NoPadding", Cipher.ENCRYPT_MODE, "BC", 255); + + setExpectedBlockSize("RSA", Cipher.DECRYPT_MODE, 256); + setExpectedBlockSize("RSA/ECB/NoPadding", Cipher.DECRYPT_MODE, 256); + setExpectedBlockSize("RSA/ECB/PKCS1Padding", Cipher.DECRYPT_MODE, 256); + } + } + + private static String modeKey(String algorithm, int mode) { + return algorithm + ":" + mode; + } + + private static String modeProviderKey(String algorithm, int mode, String provider) { + return algorithm + ":" + mode + ":" + provider; + } + + private static void setExpectedSize(Map<String, Integer> map, + String algorithm, int value) { + algorithm = algorithm.toUpperCase(Locale.US); + map.put(algorithm, value); + } + + private static void setExpectedSize(Map<String, Integer> map, + String algorithm, int mode, int value) { + setExpectedSize(map, modeKey(algorithm, mode), value); + } + + private static void setExpectedSize(Map<String, Integer> map, + String algorithm, int mode, String provider, int value) { + setExpectedSize(map, modeProviderKey(algorithm, mode, provider), value); + } + + private static int getExpectedSize(Map<String, Integer> map, String algorithm, int mode, String provider) { + Integer expected = map.get(modeProviderKey(algorithm, mode, provider)); + if (expected != null) { + return expected; + } + expected = map.get(modeKey(algorithm, mode)); + if (expected != null) { + return expected; + } + expected = map.get(algorithm); + assertNotNull("Algorithm " + algorithm + " not found in " + map, expected); + return expected; + } + + private static void setExpectedBlockSize(String algorithm, int value) { + setExpectedSize(EXPECTED_BLOCK_SIZE, algorithm, value); + } + + private static void setExpectedBlockSize(String algorithm, int mode, int value) { + setExpectedSize(EXPECTED_BLOCK_SIZE, algorithm, mode, value); + } + + private static void setExpectedBlockSize(String algorithm, int mode, String provider, int value) { + setExpectedSize(EXPECTED_BLOCK_SIZE, algorithm, mode, provider, value); + } + + private static int getExpectedBlockSize(String algorithm, int mode, String provider) { + return getExpectedSize(EXPECTED_BLOCK_SIZE, algorithm, mode, provider); + } + + private static Map<String, Integer> EXPECTED_OUTPUT_SIZE = new HashMap<String, Integer>(); + static { + setExpectedOutputSize("AES", Cipher.ENCRYPT_MODE, 16); + setExpectedOutputSize("PBEWITHMD5AND128BITAES-CBC-OPENSSL", 16); + setExpectedOutputSize("PBEWITHMD5AND192BITAES-CBC-OPENSSL", 16); + setExpectedOutputSize("PBEWITHMD5AND256BITAES-CBC-OPENSSL", 16); + setExpectedOutputSize("PBEWITHSHA256AND128BITAES-CBC-BC", 16); + setExpectedOutputSize("PBEWITHSHA256AND192BITAES-CBC-BC", 16); + setExpectedOutputSize("PBEWITHSHA256AND256BITAES-CBC-BC", 16); + setExpectedOutputSize("PBEWITHSHAAND128BITAES-CBC-BC", 16); + setExpectedOutputSize("PBEWITHSHAAND192BITAES-CBC-BC", 16); + setExpectedOutputSize("PBEWITHSHAAND256BITAES-CBC-BC", 16); + + setExpectedOutputSize("AES", Cipher.DECRYPT_MODE, 0); + setExpectedOutputSize("PBEWITHMD5AND128BITAES-CBC-OPENSSL", Cipher.DECRYPT_MODE, 0); + setExpectedOutputSize("PBEWITHMD5AND192BITAES-CBC-OPENSSL", Cipher.DECRYPT_MODE, 0); + setExpectedOutputSize("PBEWITHMD5AND256BITAES-CBC-OPENSSL", Cipher.DECRYPT_MODE, 0); + setExpectedOutputSize("PBEWITHSHA256AND128BITAES-CBC-BC", Cipher.DECRYPT_MODE, 0); + setExpectedOutputSize("PBEWITHSHA256AND192BITAES-CBC-BC", Cipher.DECRYPT_MODE, 0); + setExpectedOutputSize("PBEWITHSHA256AND256BITAES-CBC-BC", Cipher.DECRYPT_MODE, 0); + setExpectedOutputSize("PBEWITHSHAAND128BITAES-CBC-BC", Cipher.DECRYPT_MODE, 0); + setExpectedOutputSize("PBEWITHSHAAND192BITAES-CBC-BC", Cipher.DECRYPT_MODE, 0); + setExpectedOutputSize("PBEWITHSHAAND256BITAES-CBC-BC", Cipher.DECRYPT_MODE, 0); + + if (StandardNames.IS_RI) { + setExpectedOutputSize("AESWRAP", Cipher.WRAP_MODE, 8); + setExpectedOutputSize("AESWRAP", Cipher.UNWRAP_MODE, 0); + } else { + setExpectedOutputSize("AESWRAP", -1); + } + + setExpectedOutputSize("ARC4", 0); + setExpectedOutputSize("ARCFOUR", 0); + setExpectedOutputSize("PBEWITHSHAAND40BITRC4", 0); + setExpectedOutputSize("PBEWITHSHAAND128BITRC4", 0); + + setExpectedOutputSize("BLOWFISH", Cipher.ENCRYPT_MODE, 8); + setExpectedOutputSize("BLOWFISH", Cipher.DECRYPT_MODE, 0); + + setExpectedOutputSize("DES", Cipher.ENCRYPT_MODE, 8); + setExpectedOutputSize("PBEWITHMD5ANDDES", Cipher.ENCRYPT_MODE, 8); + setExpectedOutputSize("PBEWITHSHA1ANDDES", Cipher.ENCRYPT_MODE, 8); + + setExpectedOutputSize("DES", Cipher.DECRYPT_MODE, 0); + setExpectedOutputSize("PBEWITHMD5ANDDES", Cipher.DECRYPT_MODE, 0); + setExpectedOutputSize("PBEWITHSHA1ANDDES", Cipher.DECRYPT_MODE, 0); + + setExpectedOutputSize("DESEDE", Cipher.ENCRYPT_MODE, 8); + setExpectedOutputSize("PBEWITHSHAAND2-KEYTRIPLEDES-CBC", Cipher.ENCRYPT_MODE, 8); + setExpectedOutputSize("PBEWITHSHAAND3-KEYTRIPLEDES-CBC", Cipher.ENCRYPT_MODE, 8); + setExpectedOutputSize("PBEWITHMD5ANDTRIPLEDES", Cipher.ENCRYPT_MODE, 8); + setExpectedOutputSize("PBEWITHSHA1ANDDESEDE", Cipher.ENCRYPT_MODE, 8); + + setExpectedOutputSize("DESEDE", Cipher.DECRYPT_MODE, 0); + setExpectedOutputSize("PBEWITHSHAAND2-KEYTRIPLEDES-CBC", Cipher.DECRYPT_MODE, 0); + setExpectedOutputSize("PBEWITHSHAAND3-KEYTRIPLEDES-CBC", Cipher.DECRYPT_MODE, 0); + setExpectedOutputSize("PBEWITHMD5ANDTRIPLEDES", Cipher.DECRYPT_MODE, 0); + setExpectedOutputSize("PBEWITHSHA1ANDDESEDE", Cipher.DECRYPT_MODE, 0); + + if (StandardNames.IS_RI) { + setExpectedOutputSize("DESEDEWRAP", Cipher.WRAP_MODE, 16); + setExpectedOutputSize("DESEDEWRAP", Cipher.UNWRAP_MODE, 0); + } else { + setExpectedOutputSize("DESEDEWRAP", -1); + } + + setExpectedOutputSize("RSA", Cipher.ENCRYPT_MODE, 256); + setExpectedOutputSize("RSA/ECB/NoPadding", Cipher.ENCRYPT_MODE, 256); + setExpectedOutputSize("RSA/ECB/PKCS1Padding", Cipher.ENCRYPT_MODE, 256); + + setExpectedOutputSize("RSA", Cipher.DECRYPT_MODE, 256); + setExpectedOutputSize("RSA/ECB/NoPadding", Cipher.DECRYPT_MODE, 256); + setExpectedOutputSize("RSA/ECB/PKCS1Padding", Cipher.DECRYPT_MODE, 245); + + // BC strips the leading 0 for us even when NoPadding is specified + setExpectedOutputSize("RSA", Cipher.DECRYPT_MODE, "BC", 255); + setExpectedOutputSize("RSA/ECB/NoPadding", Cipher.DECRYPT_MODE, "BC", 255); + } + + private static void setExpectedOutputSize(String algorithm, int value) { + setExpectedSize(EXPECTED_OUTPUT_SIZE, algorithm, value); + } + + private static void setExpectedOutputSize(String algorithm, int mode, int value) { + setExpectedSize(EXPECTED_OUTPUT_SIZE, algorithm, mode, value); + } + + private static void setExpectedOutputSize(String algorithm, int mode, String provider, int value) { + setExpectedSize(EXPECTED_OUTPUT_SIZE, algorithm, mode, provider, value); + } + + private static int getExpectedOutputSize(String algorithm, int mode, String provider) { + return getExpectedSize(EXPECTED_OUTPUT_SIZE, algorithm, mode, provider); + } + + private static byte[] ORIGINAL_PLAIN_TEXT = new byte[] { 0x0a, 0x0b, 0x0c }; + private static byte[] PKCS1_BLOCK_TYPE_00_PADDED_PLAIN_TEXT = new byte[] { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0a, 0x0b, 0x0c + }; + private static byte[] PKCS1_BLOCK_TYPE_01_PADDED_PLAIN_TEXT = new byte[] { + (byte) 0x00, (byte) 0x01, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0x0a, (byte) 0x0b, (byte) 0x0c + }; + private static byte[] PKCS1_BLOCK_TYPE_02_PADDED_PLAIN_TEXT = new byte[] { + (byte) 0x00, (byte) 0x02, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0x0a, (byte) 0x0b, (byte) 0x0c + }; + + private static byte[] getExpectedPlainText(String algorithm) { + if (algorithm.equals("RSA/ECB/NOPADDING")) { + return PKCS1_BLOCK_TYPE_00_PADDED_PLAIN_TEXT; + } + return ORIGINAL_PLAIN_TEXT; + } + + private static AlgorithmParameterSpec getAlgorithmParameterSpec(String algorithm) { + if (!isPBE(algorithm)) { + return null; + } + final byte[] salt = new byte[8]; + new SecureRandom().nextBytes(salt); + return new PBEParameterSpec(salt, 1024); + } + + public void test_getInstance() throws Exception { + final ByteArrayOutputStream errBuffer = new ByteArrayOutputStream(); + PrintStream out = new PrintStream(errBuffer); + + Set<String> seenBaseCipherNames = new HashSet<String>(); + Set<String> seenCiphersWithModeAndPadding = new HashSet<String>(); + + Provider[] providers = Security.getProviders(); + for (Provider provider : providers) { + Set<Provider.Service> services = provider.getServices(); + for (Provider.Service service : services) { + String type = service.getType(); + if (!type.equals("Cipher")) { + continue; + } + + String algorithm = service.getAlgorithm(); + + /* + * Any specific modes and paddings aren't tested directly here, + * but we need to make sure we see the bare algorithm from some + * provider. We will test each mode specifically when we get the + * base cipher. + */ + final int firstSlash = algorithm.indexOf('/'); + if (firstSlash == -1) { + seenBaseCipherNames.add(algorithm); + } else { + final String baseCipherName = algorithm.substring(0, firstSlash); + if (!seenBaseCipherNames.contains(baseCipherName)) { + seenCiphersWithModeAndPadding.add(baseCipherName); + } + continue; + } + + try { + test_Cipher_Algorithm(provider, algorithm); + } catch (Throwable e) { + out.append("Error encountered checking " + algorithm + + " with provider " + provider.getName() + "\n"); + e.printStackTrace(out); + } + + Set<String> modes = StandardNames.getModesForCipher(algorithm); + if (modes != null) { + for (String mode : modes) { + Set<String> paddings = StandardNames.getPaddingsForCipher(algorithm); + if (paddings != null) { + for (String padding : paddings) { + final String algorithmName = algorithm + "/" + mode + "/" + padding; + try { + test_Cipher_Algorithm(provider, algorithmName); + } catch (Throwable e) { + out.append("Error encountered checking " + algorithmName + + " with provider " + provider.getName() + "\n"); + e.printStackTrace(out); + } + } + } + } + } + } + } + + seenCiphersWithModeAndPadding.removeAll(seenBaseCipherNames); + assertEquals("Ciphers seen with mode and padding but not base cipher", + Collections.EMPTY_SET, seenCiphersWithModeAndPadding); + + out.flush(); + if (errBuffer.size() > 0) { + throw new Exception("Errors encountered:\n\n" + errBuffer.toString() + "\n\n"); + } + } + + private void test_Cipher_Algorithm(Provider provider, String algorithm) throws Exception { + // Cipher.getInstance(String) + Cipher c1 = Cipher.getInstance(algorithm); + assertEquals(algorithm, c1.getAlgorithm()); + test_Cipher(c1); + + // Cipher.getInstance(String, Provider) + Cipher c2 = Cipher.getInstance(algorithm, provider); + assertEquals(algorithm, c2.getAlgorithm()); + assertEquals(provider, c2.getProvider()); + test_Cipher(c2); + + // KeyGenerator.getInstance(String, String) + Cipher c3 = Cipher.getInstance(algorithm, provider.getName()); + assertEquals(algorithm, c3.getAlgorithm()); + assertEquals(provider, c3.getProvider()); + test_Cipher(c3); + } + + private void test_Cipher(Cipher c) throws Exception { + String algorithm = c.getAlgorithm().toUpperCase(Locale.US); + if (isUnsupported(algorithm)) { + return; + } + String providerName = c.getProvider().getName(); + String cipherID = algorithm + ":" + providerName; + + try { + c.getOutputSize(0); + } catch (IllegalStateException expected) { + } + + // TODO: test keys from different factories (e.g. OpenSSLRSAPrivateKey vs JCERSAPrivateKey) + Key encryptKey = getEncryptKey(algorithm); + + final AlgorithmParameterSpec spec = getAlgorithmParameterSpec(algorithm); + + int encryptMode = getEncryptMode(algorithm); + c.init(encryptMode, encryptKey, spec); + assertEquals(cipherID, getExpectedBlockSize(algorithm, encryptMode, providerName), c.getBlockSize()); + assertEquals(cipherID, getExpectedOutputSize(algorithm, encryptMode, providerName), c.getOutputSize(0)); + int decryptMode = getDecryptMode(algorithm); + c.init(decryptMode, encryptKey, spec); + assertEquals(cipherID, getExpectedBlockSize(algorithm, decryptMode, providerName), c.getBlockSize()); + assertEquals(cipherID, getExpectedOutputSize(algorithm, decryptMode, providerName), c.getOutputSize(0)); + + // TODO: test Cipher.getIV() + + // TODO: test Cipher.getParameters() + + assertNull(cipherID, c.getExemptionMechanism()); + + c.init(getEncryptMode(algorithm), encryptKey, spec); + if (isWrap(algorithm)) { + byte[] cipherText = c.wrap(encryptKey); + c.init(getDecryptMode(algorithm), getDecryptKey(algorithm), spec); + int keyType = (isAsymmetric(algorithm)) ? Cipher.PRIVATE_KEY : Cipher.SECRET_KEY; + Key decryptedKey = c.unwrap(cipherText, encryptKey.getAlgorithm(), keyType); + assertEquals("encryptKey.getAlgorithm()=" + encryptKey.getAlgorithm() + + " decryptedKey.getAlgorithm()=" + decryptedKey.getAlgorithm() + + " encryptKey.getEncoded()=" + Arrays.toString(encryptKey.getEncoded()) + + " decryptedKey.getEncoded()=" + Arrays.toString(decryptedKey.getEncoded()), + encryptKey, decryptedKey); + } else { + byte[] cipherText = c.doFinal(ORIGINAL_PLAIN_TEXT); + c.init(getDecryptMode(algorithm), getDecryptKey(algorithm), spec); + byte[] decryptedPlainText = c.doFinal(cipherText); + assertEquals(cipherID, + Arrays.toString(getExpectedPlainText(algorithm)), + Arrays.toString(decryptedPlainText)); + } + } + + public void testInputPKCS1Padding() throws Exception { + for (String provider : RSA_PROVIDERS) { + testInputPKCS1Padding(provider); + } + } + + private void testInputPKCS1Padding(String provider) throws Exception { + testInputPKCS1Padding(provider, PKCS1_BLOCK_TYPE_01_PADDED_PLAIN_TEXT, getEncryptKey("RSA"), getDecryptKey("RSA")); + try { + testInputPKCS1Padding(provider, PKCS1_BLOCK_TYPE_02_PADDED_PLAIN_TEXT, getEncryptKey("RSA"), getDecryptKey("RSA")); + fail(); + } catch (BadPaddingException expected) { + } + try { + testInputPKCS1Padding(provider, PKCS1_BLOCK_TYPE_01_PADDED_PLAIN_TEXT, getDecryptKey("RSA"), getEncryptKey("RSA")); + fail(); + } catch (BadPaddingException expected) { + } + testInputPKCS1Padding(provider, PKCS1_BLOCK_TYPE_02_PADDED_PLAIN_TEXT, getDecryptKey("RSA"), getEncryptKey("RSA")); + } + + private void testInputPKCS1Padding(String provider, byte[] prePaddedPlainText, Key encryptKey, Key decryptKey) throws Exception { + Cipher encryptCipher = Cipher.getInstance("RSA/ECB/NoPadding", provider); + encryptCipher.init(Cipher.ENCRYPT_MODE, encryptKey); + byte[] cipherText = encryptCipher.doFinal(prePaddedPlainText); + Cipher decryptCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider); + decryptCipher.init(Cipher.DECRYPT_MODE, decryptKey); + byte[] plainText = decryptCipher.doFinal(cipherText); + assertEquals(Arrays.toString(ORIGINAL_PLAIN_TEXT), + Arrays.toString(plainText)); + } + + public void testOutputPKCS1Padding() throws Exception { + for (String provider : RSA_PROVIDERS) { + testOutputPKCS1Padding(provider); + } + } + + private void testOutputPKCS1Padding(String provider) throws Exception { + testOutputPKCS1Padding(provider, (byte) 1, getEncryptKey("RSA"), getDecryptKey("RSA")); + testOutputPKCS1Padding(provider, (byte) 2, getDecryptKey("RSA"), getEncryptKey("RSA")); + } + + private void testOutputPKCS1Padding(String provider, byte expectedBlockType, Key encryptKey, Key decryptKey) throws Exception { + Cipher encryptCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider); + encryptCipher.init(Cipher.ENCRYPT_MODE, encryptKey); + byte[] cipherText = encryptCipher.doFinal(ORIGINAL_PLAIN_TEXT); + Cipher decryptCipher = Cipher.getInstance("RSA/ECB/NoPadding", provider); + decryptCipher.init(Cipher.DECRYPT_MODE, decryptKey); + byte[] plainText = decryptCipher.doFinal(cipherText); + assertPadding(provider, expectedBlockType, ORIGINAL_PLAIN_TEXT, plainText); + } + + private void assertPadding(String provider, byte expectedBlockType, byte[] expectedData, byte[] actualDataWithPadding) { + assertNotNull(provider, actualDataWithPadding); + int expectedOutputSize = getExpectedOutputSize("RSA", Cipher.DECRYPT_MODE, provider); + assertEquals(provider, expectedOutputSize, actualDataWithPadding.length); + int expectedBlockTypeOffset; + if (provider.equals("BC")) { + // BC strips the leading 0 for us on decrypt even when NoPadding is specified... + expectedBlockTypeOffset = 0; + } else { + expectedBlockTypeOffset = 1; + assertEquals(provider, 0, actualDataWithPadding[0]); + } + byte actualBlockType = actualDataWithPadding[expectedBlockTypeOffset]; + assertEquals(provider, expectedBlockType, actualBlockType); + int actualDataOffset = actualDataWithPadding.length - expectedData.length; + if (actualBlockType == 1) { + int expectedDataOffset = expectedBlockTypeOffset + 1; + for (int i = expectedDataOffset; i < actualDataOffset - 1; i++) { + assertEquals(provider, (byte) 0xFF, actualDataWithPadding[i]); + } + } + assertEquals(provider, 0x00, actualDataWithPadding[actualDataOffset-1]); + byte[] actualData = new byte[expectedData.length]; + System.arraycopy(actualDataWithPadding, actualDataOffset, actualData, 0, actualData.length); + assertEquals(provider, Arrays.toString(expectedData), Arrays.toString(actualData)); + } + public void testCipherInitWithCertificate () throws Exception { // no key usage specified, everything is fine assertCipherInitWithKeyUsage(0, true, true, true, true); @@ -108,4 +882,1287 @@ public final class CipherTest extends TestCase { .build() .getPrivateKey("RSA", "RSA").getCertificate(); } + + /* + * Test vectors generated with this private key: + * + * -----BEGIN RSA PRIVATE KEY----- + * MIIEpAIBAAKCAQEA4Ec+irjyKE/rnnQv+XSPoRjtmGM8kvUq63ouvg075gMpvnZq + * 0Q62pRXQ0s/ZvqeTDwwwZTeJn3lYzT6FsB+IGFJNMSWEqUslHjYltUFB7b/uGYgI + * 4buX/Hy0m56qr2jpyY19DtxTu8D6ADQ1bWMF+7zDxwAUBThqu8hzyw8+90JfPTPf + * ezFa4DbSoLZq/UdQOxab8247UWJRW3Ff2oPeryxYrrmr+zCXw8yd2dvl7ylsF2E5 + * Ao6KZx5jBW1F9AGI0sQTNJCEXeUsJTTpxrJHjAe9rpKII7YtBmx3cPn2Pz26JH9T + * CER0e+eqqF2FO4vSRKzsPePImrRkU6tNJMOsaQIDAQABAoIBADd4R3al8XaY9ayW + * DfuDobZ1ZOZIvQWXz4q4CHGG8macJ6nsvdSA8Bl6gNBzCebGqW+SUzHlf4tKxvTU + * XtpFojJpwJ/EKMB6Tm7fc4oV3sl/q9Lyu0ehTyDqcvz+TDbgGtp3vRN82NTaELsW + * LpSkZilx8XX5hfoYjwVsuX7igW9Dq503R2Ekhs2owWGWwwgYqZXshdOEZ3kSZ7O/ + * IfJzcQppJYYldoQcW2cSwS1L0govMpmtt8E12l6VFavadufK8qO+gFUdBzt4vxFi + * xIrSt/R0OgI47k0lL31efmUzzK5kzLOTYAdaL9HgNOw65c6cQIzL8OJeQRQCFoez + * 3UdUroECgYEA9UGIS8Nzeyki1BGe9F4t7izUy7dfRVBaFXqlAJ+Zxzot8HJKxGAk + * MGMy6omBd2NFRl3G3x4KbxQK/ztzluaomUrF2qloc0cv43dJ0U6z4HXmKdvrNYMz + * im82SdCiZUp6Qv2atr+krE1IHTkLsimwZL3DEcwb4bYxidp8QM3s8rECgYEA6hp0 + * LduIHO23KIyH442GjdekCdFaQ/RF1Td6C1cx3b/KLa8oqOE81cCvzsM0fXSjniNa + * PNljPydN4rlPkt9DgzkR2enxz1jyfeLgj/RZZMcg0+whOdx8r8kSlTzeyy81Wi4s + * NaUPrXVMs7IxZkJLo7bjESoriYw4xcFe2yOGkzkCgYBRgo8exv2ZYCmQG68dfjN7 + * pfCvJ+mE6tiVrOYr199O5FoiQInyzBUa880XP84EdLywTzhqLNzA4ANrokGfVFeS + * YtRxAL6TGYSj76Bb7PFBV03AebOpXEqD5sQ/MhTW3zLVEt4ZgIXlMeYWuD/X3Z0f + * TiYHwzM9B8VdEH0dOJNYcQKBgQDbT7UPUN6O21P/NMgJMYigUShn2izKBIl3WeWH + * wkQBDa+GZNWegIPRbBZHiTAfZ6nweAYNg0oq29NnV1toqKhCwrAqibPzH8zsiiL+ + * OVeVxcbHQitOXXSh6ajzDndZufwtY5wfFWc+hOk6XvFQb0MVODw41Fy9GxQEj0ch + * 3IIyYQKBgQDYEUWTr0FfthLb8ZI3ENVNB0hiBadqO0MZSWjA3/HxHvD2GkozfV/T + * dBu8lkDkR7i2tsR8OsEgQ1fTsMVbqShr2nP2KSlvX6kUbYl2NX08dR51FIaWpAt0 + * aFyCzjCQLWOdck/yTV4ulAfuNO3tLjtN9lqpvP623yjQe6aQPxZXaA== + * -----END RSA PRIVATE KEY----- + * + */ + + private static final BigInteger RSA_2048_modulus = new BigInteger(new byte[] { + (byte) 0x00, (byte) 0xe0, (byte) 0x47, (byte) 0x3e, (byte) 0x8a, (byte) 0xb8, (byte) 0xf2, (byte) 0x28, + (byte) 0x4f, (byte) 0xeb, (byte) 0x9e, (byte) 0x74, (byte) 0x2f, (byte) 0xf9, (byte) 0x74, (byte) 0x8f, + (byte) 0xa1, (byte) 0x18, (byte) 0xed, (byte) 0x98, (byte) 0x63, (byte) 0x3c, (byte) 0x92, (byte) 0xf5, + (byte) 0x2a, (byte) 0xeb, (byte) 0x7a, (byte) 0x2e, (byte) 0xbe, (byte) 0x0d, (byte) 0x3b, (byte) 0xe6, + (byte) 0x03, (byte) 0x29, (byte) 0xbe, (byte) 0x76, (byte) 0x6a, (byte) 0xd1, (byte) 0x0e, (byte) 0xb6, + (byte) 0xa5, (byte) 0x15, (byte) 0xd0, (byte) 0xd2, (byte) 0xcf, (byte) 0xd9, (byte) 0xbe, (byte) 0xa7, + (byte) 0x93, (byte) 0x0f, (byte) 0x0c, (byte) 0x30, (byte) 0x65, (byte) 0x37, (byte) 0x89, (byte) 0x9f, + (byte) 0x79, (byte) 0x58, (byte) 0xcd, (byte) 0x3e, (byte) 0x85, (byte) 0xb0, (byte) 0x1f, (byte) 0x88, + (byte) 0x18, (byte) 0x52, (byte) 0x4d, (byte) 0x31, (byte) 0x25, (byte) 0x84, (byte) 0xa9, (byte) 0x4b, + (byte) 0x25, (byte) 0x1e, (byte) 0x36, (byte) 0x25, (byte) 0xb5, (byte) 0x41, (byte) 0x41, (byte) 0xed, + (byte) 0xbf, (byte) 0xee, (byte) 0x19, (byte) 0x88, (byte) 0x08, (byte) 0xe1, (byte) 0xbb, (byte) 0x97, + (byte) 0xfc, (byte) 0x7c, (byte) 0xb4, (byte) 0x9b, (byte) 0x9e, (byte) 0xaa, (byte) 0xaf, (byte) 0x68, + (byte) 0xe9, (byte) 0xc9, (byte) 0x8d, (byte) 0x7d, (byte) 0x0e, (byte) 0xdc, (byte) 0x53, (byte) 0xbb, + (byte) 0xc0, (byte) 0xfa, (byte) 0x00, (byte) 0x34, (byte) 0x35, (byte) 0x6d, (byte) 0x63, (byte) 0x05, + (byte) 0xfb, (byte) 0xbc, (byte) 0xc3, (byte) 0xc7, (byte) 0x00, (byte) 0x14, (byte) 0x05, (byte) 0x38, + (byte) 0x6a, (byte) 0xbb, (byte) 0xc8, (byte) 0x73, (byte) 0xcb, (byte) 0x0f, (byte) 0x3e, (byte) 0xf7, + (byte) 0x42, (byte) 0x5f, (byte) 0x3d, (byte) 0x33, (byte) 0xdf, (byte) 0x7b, (byte) 0x31, (byte) 0x5a, + (byte) 0xe0, (byte) 0x36, (byte) 0xd2, (byte) 0xa0, (byte) 0xb6, (byte) 0x6a, (byte) 0xfd, (byte) 0x47, + (byte) 0x50, (byte) 0x3b, (byte) 0x16, (byte) 0x9b, (byte) 0xf3, (byte) 0x6e, (byte) 0x3b, (byte) 0x51, + (byte) 0x62, (byte) 0x51, (byte) 0x5b, (byte) 0x71, (byte) 0x5f, (byte) 0xda, (byte) 0x83, (byte) 0xde, + (byte) 0xaf, (byte) 0x2c, (byte) 0x58, (byte) 0xae, (byte) 0xb9, (byte) 0xab, (byte) 0xfb, (byte) 0x30, + (byte) 0x97, (byte) 0xc3, (byte) 0xcc, (byte) 0x9d, (byte) 0xd9, (byte) 0xdb, (byte) 0xe5, (byte) 0xef, + (byte) 0x29, (byte) 0x6c, (byte) 0x17, (byte) 0x61, (byte) 0x39, (byte) 0x02, (byte) 0x8e, (byte) 0x8a, + (byte) 0x67, (byte) 0x1e, (byte) 0x63, (byte) 0x05, (byte) 0x6d, (byte) 0x45, (byte) 0xf4, (byte) 0x01, + (byte) 0x88, (byte) 0xd2, (byte) 0xc4, (byte) 0x13, (byte) 0x34, (byte) 0x90, (byte) 0x84, (byte) 0x5d, + (byte) 0xe5, (byte) 0x2c, (byte) 0x25, (byte) 0x34, (byte) 0xe9, (byte) 0xc6, (byte) 0xb2, (byte) 0x47, + (byte) 0x8c, (byte) 0x07, (byte) 0xbd, (byte) 0xae, (byte) 0x92, (byte) 0x88, (byte) 0x23, (byte) 0xb6, + (byte) 0x2d, (byte) 0x06, (byte) 0x6c, (byte) 0x77, (byte) 0x70, (byte) 0xf9, (byte) 0xf6, (byte) 0x3f, + (byte) 0x3d, (byte) 0xba, (byte) 0x24, (byte) 0x7f, (byte) 0x53, (byte) 0x08, (byte) 0x44, (byte) 0x74, + (byte) 0x7b, (byte) 0xe7, (byte) 0xaa, (byte) 0xa8, (byte) 0x5d, (byte) 0x85, (byte) 0x3b, (byte) 0x8b, + (byte) 0xd2, (byte) 0x44, (byte) 0xac, (byte) 0xec, (byte) 0x3d, (byte) 0xe3, (byte) 0xc8, (byte) 0x9a, + (byte) 0xb4, (byte) 0x64, (byte) 0x53, (byte) 0xab, (byte) 0x4d, (byte) 0x24, (byte) 0xc3, (byte) 0xac, + (byte) 0x69, + }); + + private static final BigInteger RSA_2048_privateExponent = new BigInteger(new byte[] { + (byte) 0x37, (byte) 0x78, (byte) 0x47, (byte) 0x76, (byte) 0xa5, (byte) 0xf1, (byte) 0x76, (byte) 0x98, + (byte) 0xf5, (byte) 0xac, (byte) 0x96, (byte) 0x0d, (byte) 0xfb, (byte) 0x83, (byte) 0xa1, (byte) 0xb6, + (byte) 0x75, (byte) 0x64, (byte) 0xe6, (byte) 0x48, (byte) 0xbd, (byte) 0x05, (byte) 0x97, (byte) 0xcf, + (byte) 0x8a, (byte) 0xb8, (byte) 0x08, (byte) 0x71, (byte) 0x86, (byte) 0xf2, (byte) 0x66, (byte) 0x9c, + (byte) 0x27, (byte) 0xa9, (byte) 0xec, (byte) 0xbd, (byte) 0xd4, (byte) 0x80, (byte) 0xf0, (byte) 0x19, + (byte) 0x7a, (byte) 0x80, (byte) 0xd0, (byte) 0x73, (byte) 0x09, (byte) 0xe6, (byte) 0xc6, (byte) 0xa9, + (byte) 0x6f, (byte) 0x92, (byte) 0x53, (byte) 0x31, (byte) 0xe5, (byte) 0x7f, (byte) 0x8b, (byte) 0x4a, + (byte) 0xc6, (byte) 0xf4, (byte) 0xd4, (byte) 0x5e, (byte) 0xda, (byte) 0x45, (byte) 0xa2, (byte) 0x32, + (byte) 0x69, (byte) 0xc0, (byte) 0x9f, (byte) 0xc4, (byte) 0x28, (byte) 0xc0, (byte) 0x7a, (byte) 0x4e, + (byte) 0x6e, (byte) 0xdf, (byte) 0x73, (byte) 0x8a, (byte) 0x15, (byte) 0xde, (byte) 0xc9, (byte) 0x7f, + (byte) 0xab, (byte) 0xd2, (byte) 0xf2, (byte) 0xbb, (byte) 0x47, (byte) 0xa1, (byte) 0x4f, (byte) 0x20, + (byte) 0xea, (byte) 0x72, (byte) 0xfc, (byte) 0xfe, (byte) 0x4c, (byte) 0x36, (byte) 0xe0, (byte) 0x1a, + (byte) 0xda, (byte) 0x77, (byte) 0xbd, (byte) 0x13, (byte) 0x7c, (byte) 0xd8, (byte) 0xd4, (byte) 0xda, + (byte) 0x10, (byte) 0xbb, (byte) 0x16, (byte) 0x2e, (byte) 0x94, (byte) 0xa4, (byte) 0x66, (byte) 0x29, + (byte) 0x71, (byte) 0xf1, (byte) 0x75, (byte) 0xf9, (byte) 0x85, (byte) 0xfa, (byte) 0x18, (byte) 0x8f, + (byte) 0x05, (byte) 0x6c, (byte) 0xb9, (byte) 0x7e, (byte) 0xe2, (byte) 0x81, (byte) 0x6f, (byte) 0x43, + (byte) 0xab, (byte) 0x9d, (byte) 0x37, (byte) 0x47, (byte) 0x61, (byte) 0x24, (byte) 0x86, (byte) 0xcd, + (byte) 0xa8, (byte) 0xc1, (byte) 0x61, (byte) 0x96, (byte) 0xc3, (byte) 0x08, (byte) 0x18, (byte) 0xa9, + (byte) 0x95, (byte) 0xec, (byte) 0x85, (byte) 0xd3, (byte) 0x84, (byte) 0x67, (byte) 0x79, (byte) 0x12, + (byte) 0x67, (byte) 0xb3, (byte) 0xbf, (byte) 0x21, (byte) 0xf2, (byte) 0x73, (byte) 0x71, (byte) 0x0a, + (byte) 0x69, (byte) 0x25, (byte) 0x86, (byte) 0x25, (byte) 0x76, (byte) 0x84, (byte) 0x1c, (byte) 0x5b, + (byte) 0x67, (byte) 0x12, (byte) 0xc1, (byte) 0x2d, (byte) 0x4b, (byte) 0xd2, (byte) 0x0a, (byte) 0x2f, + (byte) 0x32, (byte) 0x99, (byte) 0xad, (byte) 0xb7, (byte) 0xc1, (byte) 0x35, (byte) 0xda, (byte) 0x5e, + (byte) 0x95, (byte) 0x15, (byte) 0xab, (byte) 0xda, (byte) 0x76, (byte) 0xe7, (byte) 0xca, (byte) 0xf2, + (byte) 0xa3, (byte) 0xbe, (byte) 0x80, (byte) 0x55, (byte) 0x1d, (byte) 0x07, (byte) 0x3b, (byte) 0x78, + (byte) 0xbf, (byte) 0x11, (byte) 0x62, (byte) 0xc4, (byte) 0x8a, (byte) 0xd2, (byte) 0xb7, (byte) 0xf4, + (byte) 0x74, (byte) 0x3a, (byte) 0x02, (byte) 0x38, (byte) 0xee, (byte) 0x4d, (byte) 0x25, (byte) 0x2f, + (byte) 0x7d, (byte) 0x5e, (byte) 0x7e, (byte) 0x65, (byte) 0x33, (byte) 0xcc, (byte) 0xae, (byte) 0x64, + (byte) 0xcc, (byte) 0xb3, (byte) 0x93, (byte) 0x60, (byte) 0x07, (byte) 0x5a, (byte) 0x2f, (byte) 0xd1, + (byte) 0xe0, (byte) 0x34, (byte) 0xec, (byte) 0x3a, (byte) 0xe5, (byte) 0xce, (byte) 0x9c, (byte) 0x40, + (byte) 0x8c, (byte) 0xcb, (byte) 0xf0, (byte) 0xe2, (byte) 0x5e, (byte) 0x41, (byte) 0x14, (byte) 0x02, + (byte) 0x16, (byte) 0x87, (byte) 0xb3, (byte) 0xdd, (byte) 0x47, (byte) 0x54, (byte) 0xae, (byte) 0x81, + }); + + private static final BigInteger RSA_2048_publicExponent = new BigInteger(new byte[] { + (byte) 0x01, (byte) 0x00, (byte) 0x01, + }); + + private static final BigInteger RSA_2048_primeP = new BigInteger(new byte[] { + (byte) 0x00, (byte) 0xf5, (byte) 0x41, (byte) 0x88, (byte) 0x4b, (byte) 0xc3, (byte) 0x73, (byte) 0x7b, + (byte) 0x29, (byte) 0x22, (byte) 0xd4, (byte) 0x11, (byte) 0x9e, (byte) 0xf4, (byte) 0x5e, (byte) 0x2d, + (byte) 0xee, (byte) 0x2c, (byte) 0xd4, (byte) 0xcb, (byte) 0xb7, (byte) 0x5f, (byte) 0x45, (byte) 0x50, + (byte) 0x5a, (byte) 0x15, (byte) 0x7a, (byte) 0xa5, (byte) 0x00, (byte) 0x9f, (byte) 0x99, (byte) 0xc7, + (byte) 0x3a, (byte) 0x2d, (byte) 0xf0, (byte) 0x72, (byte) 0x4a, (byte) 0xc4, (byte) 0x60, (byte) 0x24, + (byte) 0x30, (byte) 0x63, (byte) 0x32, (byte) 0xea, (byte) 0x89, (byte) 0x81, (byte) 0x77, (byte) 0x63, + (byte) 0x45, (byte) 0x46, (byte) 0x5d, (byte) 0xc6, (byte) 0xdf, (byte) 0x1e, (byte) 0x0a, (byte) 0x6f, + (byte) 0x14, (byte) 0x0a, (byte) 0xff, (byte) 0x3b, (byte) 0x73, (byte) 0x96, (byte) 0xe6, (byte) 0xa8, + (byte) 0x99, (byte) 0x4a, (byte) 0xc5, (byte) 0xda, (byte) 0xa9, (byte) 0x68, (byte) 0x73, (byte) 0x47, + (byte) 0x2f, (byte) 0xe3, (byte) 0x77, (byte) 0x49, (byte) 0xd1, (byte) 0x4e, (byte) 0xb3, (byte) 0xe0, + (byte) 0x75, (byte) 0xe6, (byte) 0x29, (byte) 0xdb, (byte) 0xeb, (byte) 0x35, (byte) 0x83, (byte) 0x33, + (byte) 0x8a, (byte) 0x6f, (byte) 0x36, (byte) 0x49, (byte) 0xd0, (byte) 0xa2, (byte) 0x65, (byte) 0x4a, + (byte) 0x7a, (byte) 0x42, (byte) 0xfd, (byte) 0x9a, (byte) 0xb6, (byte) 0xbf, (byte) 0xa4, (byte) 0xac, + (byte) 0x4d, (byte) 0x48, (byte) 0x1d, (byte) 0x39, (byte) 0x0b, (byte) 0xb2, (byte) 0x29, (byte) 0xb0, + (byte) 0x64, (byte) 0xbd, (byte) 0xc3, (byte) 0x11, (byte) 0xcc, (byte) 0x1b, (byte) 0xe1, (byte) 0xb6, + (byte) 0x31, (byte) 0x89, (byte) 0xda, (byte) 0x7c, (byte) 0x40, (byte) 0xcd, (byte) 0xec, (byte) 0xf2, + (byte) 0xb1, + }); + + private static final BigInteger RSA_2048_primeQ = new BigInteger(new byte[] { + (byte) 0x00, (byte) 0xea, (byte) 0x1a, (byte) 0x74, (byte) 0x2d, (byte) 0xdb, (byte) 0x88, (byte) 0x1c, + (byte) 0xed, (byte) 0xb7, (byte) 0x28, (byte) 0x8c, (byte) 0x87, (byte) 0xe3, (byte) 0x8d, (byte) 0x86, + (byte) 0x8d, (byte) 0xd7, (byte) 0xa4, (byte) 0x09, (byte) 0xd1, (byte) 0x5a, (byte) 0x43, (byte) 0xf4, + (byte) 0x45, (byte) 0xd5, (byte) 0x37, (byte) 0x7a, (byte) 0x0b, (byte) 0x57, (byte) 0x31, (byte) 0xdd, + (byte) 0xbf, (byte) 0xca, (byte) 0x2d, (byte) 0xaf, (byte) 0x28, (byte) 0xa8, (byte) 0xe1, (byte) 0x3c, + (byte) 0xd5, (byte) 0xc0, (byte) 0xaf, (byte) 0xce, (byte) 0xc3, (byte) 0x34, (byte) 0x7d, (byte) 0x74, + (byte) 0xa3, (byte) 0x9e, (byte) 0x23, (byte) 0x5a, (byte) 0x3c, (byte) 0xd9, (byte) 0x63, (byte) 0x3f, + (byte) 0x27, (byte) 0x4d, (byte) 0xe2, (byte) 0xb9, (byte) 0x4f, (byte) 0x92, (byte) 0xdf, (byte) 0x43, + (byte) 0x83, (byte) 0x39, (byte) 0x11, (byte) 0xd9, (byte) 0xe9, (byte) 0xf1, (byte) 0xcf, (byte) 0x58, + (byte) 0xf2, (byte) 0x7d, (byte) 0xe2, (byte) 0xe0, (byte) 0x8f, (byte) 0xf4, (byte) 0x59, (byte) 0x64, + (byte) 0xc7, (byte) 0x20, (byte) 0xd3, (byte) 0xec, (byte) 0x21, (byte) 0x39, (byte) 0xdc, (byte) 0x7c, + (byte) 0xaf, (byte) 0xc9, (byte) 0x12, (byte) 0x95, (byte) 0x3c, (byte) 0xde, (byte) 0xcb, (byte) 0x2f, + (byte) 0x35, (byte) 0x5a, (byte) 0x2e, (byte) 0x2c, (byte) 0x35, (byte) 0xa5, (byte) 0x0f, (byte) 0xad, + (byte) 0x75, (byte) 0x4c, (byte) 0xb3, (byte) 0xb2, (byte) 0x31, (byte) 0x66, (byte) 0x42, (byte) 0x4b, + (byte) 0xa3, (byte) 0xb6, (byte) 0xe3, (byte) 0x11, (byte) 0x2a, (byte) 0x2b, (byte) 0x89, (byte) 0x8c, + (byte) 0x38, (byte) 0xc5, (byte) 0xc1, (byte) 0x5e, (byte) 0xdb, (byte) 0x23, (byte) 0x86, (byte) 0x93, + (byte) 0x39, + }); + + /** + * Test data is PKCS#1 padded "Android.\n" which can be generated by: + * echo "Android." | openssl rsautl -inkey rsa.key -sign | openssl rsautl -inkey rsa.key -raw -verify | recode ../x1 + */ + private static final byte[] RSA_2048_Vector1 = new byte[] { + (byte) 0x00, (byte) 0x01, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0x00, (byte) 0x41, (byte) 0x6E, (byte) 0x64, (byte) 0x72, (byte) 0x6F, + (byte) 0x69, (byte) 0x64, (byte) 0x2E, (byte) 0x0A, + }; + + /** + * This vector is simply "Android.\n" which is too short. + */ + private static final byte[] TooShort_Vector = new byte[] { + (byte) 0x41, (byte) 0x6E, (byte) 0x64, (byte) 0x72, (byte) 0x6F, (byte) 0x69, + (byte) 0x64, (byte) 0x2E, (byte) 0x0A, + }; + + /** + * This vector is simply "Android.\n" padded with zeros. + */ + private static final byte[] TooShort_Vector_Zero_Padded = new byte[] { + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x41, (byte) 0x6e, (byte) 0x64, (byte) 0x72, (byte) 0x6f, + (byte) 0x69, (byte) 0x64, (byte) 0x2e, (byte) 0x0a, + }; + + /** + * openssl rsautl -raw -sign -inkey rsa.key | recode ../x1 | sed 's/0x/(byte) 0x/g' + */ + private static final byte[] RSA_Vector1_Encrypt_Private = new byte[] { + (byte) 0x35, (byte) 0x43, (byte) 0x38, (byte) 0x44, (byte) 0xAD, (byte) 0x3F, + (byte) 0x97, (byte) 0x02, (byte) 0xFB, (byte) 0x59, (byte) 0x1F, (byte) 0x4A, + (byte) 0x2B, (byte) 0xB9, (byte) 0x06, (byte) 0xEC, (byte) 0x66, (byte) 0xE6, + (byte) 0xD2, (byte) 0xC5, (byte) 0x8B, (byte) 0x7B, (byte) 0xE3, (byte) 0x18, + (byte) 0xBF, (byte) 0x07, (byte) 0xD6, (byte) 0x01, (byte) 0xF9, (byte) 0xD9, + (byte) 0x89, (byte) 0xC4, (byte) 0xDB, (byte) 0x00, (byte) 0x68, (byte) 0xFF, + (byte) 0x9B, (byte) 0x43, (byte) 0x90, (byte) 0xF2, (byte) 0xDB, (byte) 0x83, + (byte) 0xF4, (byte) 0x7E, (byte) 0xC6, (byte) 0x81, (byte) 0x01, (byte) 0x3A, + (byte) 0x0B, (byte) 0xE5, (byte) 0xED, (byte) 0x08, (byte) 0x73, (byte) 0x3E, + (byte) 0xE1, (byte) 0x3F, (byte) 0xDF, (byte) 0x1F, (byte) 0x07, (byte) 0x6D, + (byte) 0x22, (byte) 0x8D, (byte) 0xCC, (byte) 0x4E, (byte) 0xE3, (byte) 0x9A, + (byte) 0xBC, (byte) 0xCC, (byte) 0x8F, (byte) 0x9E, (byte) 0x9B, (byte) 0x02, + (byte) 0x48, (byte) 0x00, (byte) 0xAC, (byte) 0x9F, (byte) 0xA4, (byte) 0x8F, + (byte) 0x87, (byte) 0xA1, (byte) 0xA8, (byte) 0xE6, (byte) 0x9D, (byte) 0xCD, + (byte) 0x8B, (byte) 0x05, (byte) 0xE9, (byte) 0xD2, (byte) 0x05, (byte) 0x8D, + (byte) 0xC9, (byte) 0x95, (byte) 0x16, (byte) 0xD0, (byte) 0xCD, (byte) 0x43, + (byte) 0x25, (byte) 0x8A, (byte) 0x11, (byte) 0x46, (byte) 0xD7, (byte) 0x74, + (byte) 0x4C, (byte) 0xCF, (byte) 0x58, (byte) 0xF9, (byte) 0xA1, (byte) 0x30, + (byte) 0x84, (byte) 0x52, (byte) 0xC9, (byte) 0x01, (byte) 0x5F, (byte) 0x24, + (byte) 0x4C, (byte) 0xB1, (byte) 0x9F, (byte) 0x7D, (byte) 0x12, (byte) 0x38, + (byte) 0x27, (byte) 0x0F, (byte) 0x5E, (byte) 0xFF, (byte) 0xE0, (byte) 0x55, + (byte) 0x8B, (byte) 0xA3, (byte) 0xAD, (byte) 0x60, (byte) 0x35, (byte) 0x83, + (byte) 0x58, (byte) 0xAF, (byte) 0x99, (byte) 0xDE, (byte) 0x3F, (byte) 0x5D, + (byte) 0x80, (byte) 0x80, (byte) 0xFF, (byte) 0x9B, (byte) 0xDE, (byte) 0x5C, + (byte) 0xAB, (byte) 0x97, (byte) 0x43, (byte) 0x64, (byte) 0xD9, (byte) 0x9F, + (byte) 0xFB, (byte) 0x67, (byte) 0x65, (byte) 0xA5, (byte) 0x99, (byte) 0xE7, + (byte) 0xE6, (byte) 0xEB, (byte) 0x05, (byte) 0x95, (byte) 0xFC, (byte) 0x46, + (byte) 0x28, (byte) 0x4B, (byte) 0xD8, (byte) 0x8C, (byte) 0xF5, (byte) 0x0A, + (byte) 0xEB, (byte) 0x1F, (byte) 0x30, (byte) 0xEA, (byte) 0xE7, (byte) 0x67, + (byte) 0x11, (byte) 0x25, (byte) 0xF0, (byte) 0x44, (byte) 0x75, (byte) 0x74, + (byte) 0x94, (byte) 0x06, (byte) 0x78, (byte) 0xD0, (byte) 0x21, (byte) 0xF4, + (byte) 0x3F, (byte) 0xC8, (byte) 0xC4, (byte) 0x4A, (byte) 0x57, (byte) 0xBE, + (byte) 0x02, (byte) 0x3C, (byte) 0x93, (byte) 0xF6, (byte) 0x95, (byte) 0xFB, + (byte) 0xD1, (byte) 0x77, (byte) 0x8B, (byte) 0x43, (byte) 0xF0, (byte) 0xB9, + (byte) 0x7D, (byte) 0xE0, (byte) 0x32, (byte) 0xE1, (byte) 0x72, (byte) 0xB5, + (byte) 0x62, (byte) 0x3F, (byte) 0x86, (byte) 0xC3, (byte) 0xD4, (byte) 0x5F, + (byte) 0x5E, (byte) 0x54, (byte) 0x1B, (byte) 0x5B, (byte) 0xE6, (byte) 0x74, + (byte) 0xA1, (byte) 0x0B, (byte) 0xE5, (byte) 0x18, (byte) 0xD2, (byte) 0x4F, + (byte) 0x93, (byte) 0xF3, (byte) 0x09, (byte) 0x58, (byte) 0xCE, (byte) 0xF0, + (byte) 0xA3, (byte) 0x61, (byte) 0xE4, (byte) 0x6E, (byte) 0x46, (byte) 0x45, + (byte) 0x89, (byte) 0x50, (byte) 0xBD, (byte) 0x03, (byte) 0x3F, (byte) 0x38, + (byte) 0xDA, (byte) 0x5D, (byte) 0xD0, (byte) 0x1B, (byte) 0x1F, (byte) 0xB1, + (byte) 0xEE, (byte) 0x89, (byte) 0x59, (byte) 0xC5, + }; + + private static final byte[] RSA_Vector1_ZeroPadded_Encrypted = new byte[] { + (byte) 0x60, (byte) 0x4a, (byte) 0x12, (byte) 0xa3, (byte) 0xa7, (byte) 0x4a, + (byte) 0xa4, (byte) 0xbf, (byte) 0x6c, (byte) 0x36, (byte) 0xad, (byte) 0x66, + (byte) 0xdf, (byte) 0xce, (byte) 0xf1, (byte) 0xe4, (byte) 0x0f, (byte) 0xd4, + (byte) 0x54, (byte) 0x5f, (byte) 0x03, (byte) 0x15, (byte) 0x4b, (byte) 0x9e, + (byte) 0xeb, (byte) 0xfe, (byte) 0x9e, (byte) 0x24, (byte) 0xce, (byte) 0x8e, + (byte) 0xc3, (byte) 0x36, (byte) 0xa5, (byte) 0x76, (byte) 0xf6, (byte) 0x54, + (byte) 0xb7, (byte) 0x84, (byte) 0x48, (byte) 0x2f, (byte) 0xd4, (byte) 0x45, + (byte) 0x74, (byte) 0x48, (byte) 0x5f, (byte) 0x08, (byte) 0x4e, (byte) 0x9c, + (byte) 0x89, (byte) 0xcc, (byte) 0x34, (byte) 0x40, (byte) 0xb1, (byte) 0x5f, + (byte) 0xa7, (byte) 0x0e, (byte) 0x11, (byte) 0x4b, (byte) 0xb5, (byte) 0x94, + (byte) 0xbe, (byte) 0x14, (byte) 0xaa, (byte) 0xaa, (byte) 0xe0, (byte) 0x38, + (byte) 0x1c, (byte) 0xce, (byte) 0x40, (byte) 0x61, (byte) 0xfc, (byte) 0x08, + (byte) 0xcb, (byte) 0x14, (byte) 0x2b, (byte) 0xa6, (byte) 0x54, (byte) 0xdf, + (byte) 0x05, (byte) 0x5c, (byte) 0x9b, (byte) 0x4f, (byte) 0x14, (byte) 0x93, + (byte) 0xb0, (byte) 0x70, (byte) 0xd9, (byte) 0x32, (byte) 0xdc, (byte) 0x24, + (byte) 0xe0, (byte) 0xae, (byte) 0x48, (byte) 0xfc, (byte) 0x53, (byte) 0xee, + (byte) 0x7c, (byte) 0x9f, (byte) 0x69, (byte) 0x34, (byte) 0xf4, (byte) 0x76, + (byte) 0xee, (byte) 0x67, (byte) 0xb2, (byte) 0xa7, (byte) 0x33, (byte) 0x1c, + (byte) 0x47, (byte) 0xff, (byte) 0x5c, (byte) 0xf0, (byte) 0xb8, (byte) 0x04, + (byte) 0x2c, (byte) 0xfd, (byte) 0xe2, (byte) 0xb1, (byte) 0x4a, (byte) 0x0a, + (byte) 0x69, (byte) 0x1c, (byte) 0x80, (byte) 0x2b, (byte) 0xb4, (byte) 0x50, + (byte) 0x65, (byte) 0x5c, (byte) 0x76, (byte) 0x78, (byte) 0x9a, (byte) 0x0c, + (byte) 0x05, (byte) 0x62, (byte) 0xf0, (byte) 0xc4, (byte) 0x1c, (byte) 0x38, + (byte) 0x15, (byte) 0xd0, (byte) 0xe2, (byte) 0x5a, (byte) 0x3d, (byte) 0xb6, + (byte) 0xe0, (byte) 0x88, (byte) 0x85, (byte) 0xd1, (byte) 0x4f, (byte) 0x7e, + (byte) 0xfc, (byte) 0x77, (byte) 0x0d, (byte) 0x2a, (byte) 0x45, (byte) 0xd5, + (byte) 0xf8, (byte) 0x3c, (byte) 0x7b, (byte) 0x2d, (byte) 0x1b, (byte) 0x82, + (byte) 0xfe, (byte) 0x58, (byte) 0x22, (byte) 0x47, (byte) 0x06, (byte) 0x58, + (byte) 0x8b, (byte) 0x4f, (byte) 0xfb, (byte) 0x9b, (byte) 0x1c, (byte) 0x70, + (byte) 0x36, (byte) 0x12, (byte) 0x04, (byte) 0x17, (byte) 0x47, (byte) 0x8a, + (byte) 0x0a, (byte) 0xec, (byte) 0x12, (byte) 0x3b, (byte) 0xf8, (byte) 0xd2, + (byte) 0xdc, (byte) 0x3c, (byte) 0xc8, (byte) 0x46, (byte) 0xc6, (byte) 0x51, + (byte) 0x06, (byte) 0x06, (byte) 0xcb, (byte) 0x84, (byte) 0x67, (byte) 0xb5, + (byte) 0x68, (byte) 0xd9, (byte) 0x9c, (byte) 0xd4, (byte) 0x16, (byte) 0x5c, + (byte) 0xb4, (byte) 0xe2, (byte) 0x55, (byte) 0xe6, (byte) 0x3a, (byte) 0x73, + (byte) 0x01, (byte) 0x1d, (byte) 0x6f, (byte) 0x30, (byte) 0x31, (byte) 0x59, + (byte) 0x8b, (byte) 0x2f, (byte) 0x4c, (byte) 0xe7, (byte) 0x86, (byte) 0x4c, + (byte) 0x39, (byte) 0x4e, (byte) 0x67, (byte) 0x3b, (byte) 0x22, (byte) 0x9b, + (byte) 0x85, (byte) 0x5a, (byte) 0xc3, (byte) 0x29, (byte) 0xaf, (byte) 0x8c, + (byte) 0x7c, (byte) 0x59, (byte) 0x4a, (byte) 0x24, (byte) 0xfa, (byte) 0xba, + (byte) 0x55, (byte) 0x40, (byte) 0x13, (byte) 0x64, (byte) 0xd8, (byte) 0xcb, + (byte) 0x4b, (byte) 0x98, (byte) 0x3f, (byte) 0xae, (byte) 0x20, (byte) 0xfd, + (byte) 0x8a, (byte) 0x50, (byte) 0x73, (byte) 0xe4, + }; + + public void testRSA_ECB_NoPadding_Private_OnlyDoFinal_Success() throws Exception { + for (String provider : RSA_PROVIDERS) { + testRSA_ECB_NoPadding_Private_OnlyDoFinal_Success(provider); + } + } + + private void testRSA_ECB_NoPadding_Private_OnlyDoFinal_Success(String provider) throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus, + RSA_2048_privateExponent); + + final PrivateKey privKey = kf.generatePrivate(keySpec); + + Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider); + + /* + * You're actually decrypting with private keys, but there is no + * distinction made here. It's all keyed off of what kind of key you're + * using. ENCRYPT_MODE and DECRYPT_MODE are the same. + */ + c.init(Cipher.ENCRYPT_MODE, privKey); + byte[] encrypted = c.doFinal(RSA_2048_Vector1); + assertTrue("Encrypted should match expected", + Arrays.equals(RSA_Vector1_Encrypt_Private, encrypted)); + + c.init(Cipher.DECRYPT_MODE, privKey); + encrypted = c.doFinal(RSA_2048_Vector1); + assertTrue("Encrypted should match expected", + Arrays.equals(RSA_Vector1_Encrypt_Private, encrypted)); + } + + public void testRSA_ECB_NoPadding_Private_UpdateThenEmptyDoFinal_Success() throws Exception { + for (String provider : RSA_PROVIDERS) { + testRSA_ECB_NoPadding_Private_UpdateThenEmptyDoFinal_Success(provider); + } + } + + private void testRSA_ECB_NoPadding_Private_UpdateThenEmptyDoFinal_Success(String provider) throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus, + RSA_2048_privateExponent); + + final PrivateKey privKey = kf.generatePrivate(keySpec); + + Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider); + + /* + * You're actually decrypting with private keys, but there is no + * distinction made here. It's all keyed off of what kind of key you're + * using. ENCRYPT_MODE and DECRYPT_MODE are the same. + */ + c.init(Cipher.ENCRYPT_MODE, privKey); + c.update(RSA_2048_Vector1); + byte[] encrypted = c.doFinal(); + assertTrue("Encrypted should match expected", + Arrays.equals(RSA_Vector1_Encrypt_Private, encrypted)); + + c.init(Cipher.DECRYPT_MODE, privKey); + c.update(RSA_2048_Vector1); + encrypted = c.doFinal(); + assertTrue("Encrypted should match expected", + Arrays.equals(RSA_Vector1_Encrypt_Private, encrypted)); + } + + public void testRSA_ECB_NoPadding_Private_SingleByteUpdateThenEmptyDoFinal_Success() + throws Exception { + for (String provider : RSA_PROVIDERS) { + testRSA_ECB_NoPadding_Private_SingleByteUpdateThenEmptyDoFinal_Success(provider); + } + } + + private void testRSA_ECB_NoPadding_Private_SingleByteUpdateThenEmptyDoFinal_Success(String provider) + throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus, + RSA_2048_privateExponent); + + final PrivateKey privKey = kf.generatePrivate(keySpec); + + Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider); + + /* + * You're actually decrypting with private keys, but there is no + * distinction made here. It's all keyed off of what kind of key you're + * using. ENCRYPT_MODE and DECRYPT_MODE are the same. + */ + c.init(Cipher.ENCRYPT_MODE, privKey); + int i; + for (i = 0; i < RSA_2048_Vector1.length / 2; i++) { + c.update(RSA_2048_Vector1, i, 1); + } + byte[] encrypted = c.doFinal(RSA_2048_Vector1, i, RSA_2048_Vector1.length - i); + assertTrue("Encrypted should match expected", + Arrays.equals(RSA_Vector1_Encrypt_Private, encrypted)); + + c.init(Cipher.DECRYPT_MODE, privKey); + for (i = 0; i < RSA_2048_Vector1.length / 2; i++) { + c.update(RSA_2048_Vector1, i, 1); + } + encrypted = c.doFinal(RSA_2048_Vector1, i, RSA_2048_Vector1.length - i); + assertTrue("Encrypted should match expected", + Arrays.equals(RSA_Vector1_Encrypt_Private, encrypted)); + } + + public void testRSA_ECB_NoPadding_Private_OnlyDoFinalWithOffset_Success() throws Exception { + for (String provider : RSA_PROVIDERS) { + testRSA_ECB_NoPadding_Private_OnlyDoFinalWithOffset_Success(provider); + } + } + + private void testRSA_ECB_NoPadding_Private_OnlyDoFinalWithOffset_Success(String provider) throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus, + RSA_2048_privateExponent); + final PrivateKey privKey = kf.generatePrivate(keySpec); + + Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider); + + /* + * You're actually decrypting with private keys, but there is no + * distinction made here. It's all keyed off of what kind of key you're + * using. ENCRYPT_MODE and DECRYPT_MODE are the same. + */ + c.init(Cipher.ENCRYPT_MODE, privKey); + byte[] encrypted = new byte[RSA_Vector1_Encrypt_Private.length]; + final int encryptLen = c + .doFinal(RSA_2048_Vector1, 0, RSA_2048_Vector1.length, encrypted, 0); + assertEquals("Encrypted size should match expected", RSA_Vector1_Encrypt_Private.length, + encryptLen); + assertTrue("Encrypted should match expected", + Arrays.equals(RSA_Vector1_Encrypt_Private, encrypted)); + + c.init(Cipher.DECRYPT_MODE, privKey); + final int decryptLen = c + .doFinal(RSA_2048_Vector1, 0, RSA_2048_Vector1.length, encrypted, 0); + assertEquals("Encrypted size should match expected", RSA_Vector1_Encrypt_Private.length, + decryptLen); + assertTrue("Encrypted should match expected", + Arrays.equals(RSA_Vector1_Encrypt_Private, encrypted)); + } + + public void testRSA_ECB_NoPadding_Public_OnlyDoFinal_Success() throws Exception { + for (String provider : RSA_PROVIDERS) { + testRSA_ECB_NoPadding_Public_OnlyDoFinal_Success(provider); + } + } + + private void testRSA_ECB_NoPadding_Public_OnlyDoFinal_Success(String provider) throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPublicKeySpec keySpec = new RSAPublicKeySpec(RSA_2048_modulus, RSA_2048_publicExponent); + + final PublicKey privKey = kf.generatePublic(keySpec); + + Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider); + + /* + * You're actually encrypting with public keys, but there is no + * distinction made here. It's all keyed off of what kind of key you're + * using. ENCRYPT_MODE and DECRYPT_MODE are the same. + */ + c.init(Cipher.ENCRYPT_MODE, privKey); + byte[] encrypted = c.doFinal(RSA_Vector1_Encrypt_Private); + assertEncryptedEqualsNoPadding(provider, Cipher.ENCRYPT_MODE, RSA_2048_Vector1, encrypted); + + c.init(Cipher.DECRYPT_MODE, privKey); + encrypted = c.doFinal(RSA_Vector1_Encrypt_Private); + assertEncryptedEqualsNoPadding(provider, Cipher.DECRYPT_MODE, RSA_2048_Vector1, encrypted); + } + + public void testRSA_ECB_NoPadding_Public_OnlyDoFinalWithOffset_Success() throws Exception { + for (String provider : RSA_PROVIDERS) { + testRSA_ECB_NoPadding_Public_OnlyDoFinalWithOffset_Success(provider); + } + } + + private void testRSA_ECB_NoPadding_Public_OnlyDoFinalWithOffset_Success(String provider) throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPublicKeySpec keySpec = new RSAPublicKeySpec(RSA_2048_modulus, RSA_2048_publicExponent); + + final PublicKey pubKey = kf.generatePublic(keySpec); + + Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider); + + /* + * You're actually encrypting with public keys, but there is no + * distinction made here. It's all keyed off of what kind of key you're + * using. ENCRYPT_MODE and DECRYPT_MODE are the same. + */ + c.init(Cipher.ENCRYPT_MODE, pubKey); + byte[] encrypted = new byte[RSA_2048_Vector1.length]; + final int encryptLen = c.doFinal(RSA_Vector1_Encrypt_Private, 0, + RSA_Vector1_Encrypt_Private.length, encrypted, 0); + assertEquals("Encrypted size should match expected", RSA_2048_Vector1.length, encryptLen); + assertEncryptedEqualsNoPadding(provider, Cipher.ENCRYPT_MODE, RSA_2048_Vector1, encrypted); + + c.init(Cipher.DECRYPT_MODE, pubKey); + int decryptLen = c.doFinal(RSA_Vector1_Encrypt_Private, 0, + RSA_Vector1_Encrypt_Private.length, encrypted, 0); + if (provider.equals("BC")) { + // BC strips the leading 0 for us on decrypt even when NoPadding is specified... + decryptLen++; + encrypted = Arrays.copyOf(encrypted, encrypted.length - 1); + } + assertEquals("Encrypted size should match expected", RSA_2048_Vector1.length, decryptLen); + assertEncryptedEqualsNoPadding(provider, Cipher.DECRYPT_MODE, RSA_2048_Vector1, encrypted); + } + + public void testRSA_ECB_NoPadding_Public_UpdateThenEmptyDoFinal_Success() throws Exception { + for (String provider : RSA_PROVIDERS) { + testRSA_ECB_NoPadding_Public_UpdateThenEmptyDoFinal_Success(provider); + } + } + + private void testRSA_ECB_NoPadding_Public_UpdateThenEmptyDoFinal_Success(String provider) throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPublicKeySpec keySpec = new RSAPublicKeySpec(RSA_2048_modulus, RSA_2048_publicExponent); + + final PublicKey privKey = kf.generatePublic(keySpec); + + Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider); + + /* + * You're actually encrypting with public keys, but there is no + * distinction made here. It's all keyed off of what kind of key you're + * using. ENCRYPT_MODE and DECRYPT_MODE are the same. + */ + c.init(Cipher.ENCRYPT_MODE, privKey); + c.update(RSA_Vector1_Encrypt_Private); + byte[] encrypted = c.doFinal(); + assertEncryptedEqualsNoPadding(provider, Cipher.ENCRYPT_MODE, RSA_2048_Vector1, encrypted); + + c.init(Cipher.DECRYPT_MODE, privKey); + c.update(RSA_Vector1_Encrypt_Private); + encrypted = c.doFinal(); + assertEncryptedEqualsNoPadding(provider, Cipher.DECRYPT_MODE, RSA_2048_Vector1, encrypted); + } + + public void testRSA_ECB_NoPadding_Public_SingleByteUpdateThenEmptyDoFinal_Success() + throws Exception { + for (String provider : RSA_PROVIDERS) { + testRSA_ECB_NoPadding_Public_SingleByteUpdateThenEmptyDoFinal_Success(provider); + } + } + + private void testRSA_ECB_NoPadding_Public_SingleByteUpdateThenEmptyDoFinal_Success(String provider) + throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPublicKeySpec keySpec = new RSAPublicKeySpec(RSA_2048_modulus, RSA_2048_publicExponent); + + final PublicKey privKey = kf.generatePublic(keySpec); + + Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider); + + /* + * You're actually encrypting with public keys, but there is no + * distinction made here. It's all keyed off of what kind of key you're + * using. ENCRYPT_MODE and DECRYPT_MODE are the same. + */ + c.init(Cipher.ENCRYPT_MODE, privKey); + int i; + for (i = 0; i < RSA_Vector1_Encrypt_Private.length / 2; i++) { + c.update(RSA_Vector1_Encrypt_Private, i, 1); + } + byte[] encrypted = c.doFinal(RSA_Vector1_Encrypt_Private, i, RSA_2048_Vector1.length - i); + assertEncryptedEqualsNoPadding(provider, Cipher.ENCRYPT_MODE, RSA_2048_Vector1, encrypted); + + c.init(Cipher.DECRYPT_MODE, privKey); + for (i = 0; i < RSA_Vector1_Encrypt_Private.length / 2; i++) { + c.update(RSA_Vector1_Encrypt_Private, i, 1); + } + encrypted = c.doFinal(RSA_Vector1_Encrypt_Private, i, RSA_2048_Vector1.length - i); + assertEncryptedEqualsNoPadding(provider, Cipher.DECRYPT_MODE, RSA_2048_Vector1, encrypted); + } + + public void testRSA_ECB_NoPadding_Public_TooSmall_Success() throws Exception { + for (String provider : RSA_PROVIDERS) { + testRSA_ECB_NoPadding_Public_TooSmall_Success(provider); + } + } + + private void testRSA_ECB_NoPadding_Public_TooSmall_Success(String provider) throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPublicKeySpec keySpec = new RSAPublicKeySpec(RSA_2048_modulus, RSA_2048_publicExponent); + + final PublicKey privKey = kf.generatePublic(keySpec); + + Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider); + + /* + * You're actually encrypting with public keys, but there is no + * distinction made here. It's all keyed off of what kind of key you're + * using. ENCRYPT_MODE and DECRYPT_MODE are the same. + */ + c.init(Cipher.ENCRYPT_MODE, privKey); + byte[] encrypted = c.doFinal(TooShort_Vector); + assertTrue("Encrypted should match expected", + Arrays.equals(RSA_Vector1_ZeroPadded_Encrypted, encrypted)); + + c.init(Cipher.DECRYPT_MODE, privKey); + encrypted = c.doFinal(TooShort_Vector); + assertTrue("Encrypted should match expected", + Arrays.equals(RSA_Vector1_ZeroPadded_Encrypted, encrypted)); + } + + public void testRSA_ECB_NoPadding_Private_TooSmall_Success() throws Exception { + for (String provider : RSA_PROVIDERS) { + testRSA_ECB_NoPadding_Private_TooSmall_Success(provider); + } + } + + private void testRSA_ECB_NoPadding_Private_TooSmall_Success(String provider) throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus, + RSA_2048_privateExponent); + + final PrivateKey privKey = kf.generatePrivate(keySpec); + + Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider); + + /* + * You're actually encrypting with public keys, but there is no + * distinction made here. It's all keyed off of what kind of key you're + * using. ENCRYPT_MODE and DECRYPT_MODE are the same. + */ + c.init(Cipher.ENCRYPT_MODE, privKey); + byte[] encrypted = c.doFinal(RSA_Vector1_ZeroPadded_Encrypted); + assertEncryptedEqualsNoPadding(provider, Cipher.ENCRYPT_MODE, + TooShort_Vector_Zero_Padded, encrypted); + + c.init(Cipher.DECRYPT_MODE, privKey); + encrypted = c.doFinal(RSA_Vector1_ZeroPadded_Encrypted); + assertEncryptedEqualsNoPadding(provider, Cipher.DECRYPT_MODE, + TooShort_Vector_Zero_Padded, encrypted); + } + + private static void assertEncryptedEqualsNoPadding(String provider, int mode, + byte[] expected, byte[] actual) { + if (provider.equals("BC") && mode == Cipher.DECRYPT_MODE) { + // BouncyCastle does us the favor of stripping leading zeroes in DECRYPT_MODE + int nonZeroOffset = 0; + for (byte b : expected) { + if (b != 0) { + break; + } + nonZeroOffset++; + } + expected = Arrays.copyOfRange(expected, nonZeroOffset, expected.length); + } + assertEquals("Encrypted should match expected", + Arrays.toString(expected), Arrays.toString(actual)); + } + + public void testRSA_ECB_NoPadding_Private_CombinedUpdateAndDoFinal_TooBig_Failure() + throws Exception { + for (String provider : RSA_PROVIDERS) { + testRSA_ECB_NoPadding_Private_CombinedUpdateAndDoFinal_TooBig_Failure(provider); + } + } + + private void testRSA_ECB_NoPadding_Private_CombinedUpdateAndDoFinal_TooBig_Failure(String provider) + throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus, + RSA_2048_privateExponent); + + final PrivateKey privKey = kf.generatePrivate(keySpec); + + Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider); + + /* + * You're actually encrypting with public keys, but there is no + * distinction made here. It's all keyed off of what kind of key you're + * using. ENCRYPT_MODE and DECRYPT_MODE are the same. + */ + c.init(Cipher.ENCRYPT_MODE, privKey); + c.update(RSA_Vector1_ZeroPadded_Encrypted); + + try { + c.doFinal(RSA_Vector1_ZeroPadded_Encrypted); + fail("Should have error when block size is too big."); + } catch (IllegalBlockSizeException success) { + assertFalse(provider, "BC".equals(provider)); + } catch (ArrayIndexOutOfBoundsException success) { + assertEquals("BC", provider); + } + } + + public void testRSA_ECB_NoPadding_Private_UpdateInAndOutPlusDoFinal_TooBig_Failure() + throws Exception { + for (String provider : RSA_PROVIDERS) { + testRSA_ECB_NoPadding_Private_UpdateInAndOutPlusDoFinal_TooBig_Failure(provider); + } + } + + private void testRSA_ECB_NoPadding_Private_UpdateInAndOutPlusDoFinal_TooBig_Failure(String provider) + throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus, + RSA_2048_privateExponent); + + final PrivateKey privKey = kf.generatePrivate(keySpec); + + Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider); + + /* + * You're actually encrypting with public keys, but there is no + * distinction made here. It's all keyed off of what kind of key you're + * using. ENCRYPT_MODE and DECRYPT_MODE are the same. + */ + c.init(Cipher.ENCRYPT_MODE, privKey); + + byte[] output = new byte[RSA_2048_Vector1.length]; + c.update(RSA_Vector1_ZeroPadded_Encrypted, 0, RSA_Vector1_ZeroPadded_Encrypted.length, + output); + + try { + c.doFinal(RSA_Vector1_ZeroPadded_Encrypted); + fail("Should have error when block size is too big."); + } catch (IllegalBlockSizeException success) { + assertFalse(provider, "BC".equals(provider)); + } catch (ArrayIndexOutOfBoundsException success) { + assertEquals("BC", provider); + } + } + + public void testRSA_ECB_NoPadding_Private_OnlyDoFinal_TooBig_Failure() throws Exception { + for (String provider : RSA_PROVIDERS) { + testRSA_ECB_NoPadding_Private_OnlyDoFinal_TooBig_Failure(provider); + } + } + + private void testRSA_ECB_NoPadding_Private_OnlyDoFinal_TooBig_Failure(String provider) throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus, + RSA_2048_privateExponent); + + final PrivateKey privKey = kf.generatePrivate(keySpec); + + Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider); + + /* + * You're actually encrypting with public keys, but there is no + * distinction made here. It's all keyed off of what kind of key you're + * using. ENCRYPT_MODE and DECRYPT_MODE are the same. + */ + c.init(Cipher.ENCRYPT_MODE, privKey); + + byte[] tooBig_Vector = new byte[RSA_Vector1_ZeroPadded_Encrypted.length * 2]; + System.arraycopy(RSA_Vector1_ZeroPadded_Encrypted, 0, tooBig_Vector, 0, + RSA_Vector1_ZeroPadded_Encrypted.length); + System.arraycopy(RSA_Vector1_ZeroPadded_Encrypted, 0, tooBig_Vector, + RSA_Vector1_ZeroPadded_Encrypted.length, RSA_Vector1_ZeroPadded_Encrypted.length); + + try { + c.doFinal(tooBig_Vector); + fail("Should have error when block size is too big."); + } catch (IllegalBlockSizeException success) { + assertFalse(provider, "BC".equals(provider)); + } catch (ArrayIndexOutOfBoundsException success) { + assertEquals("BC", provider); + } + } + + public void testRSA_ECB_NoPadding_GetBlockSize_Success() throws Exception { + for (String provider : RSA_PROVIDERS) { + testRSA_ECB_NoPadding_GetBlockSize_Success(provider); + } + } + + private void testRSA_ECB_NoPadding_GetBlockSize_Success(String provider) throws Exception { + Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider); + if (StandardNames.IS_RI) { + assertEquals(0, c.getBlockSize()); + } else { + try { + c.getBlockSize(); + fail(); + } catch (IllegalStateException expected) { + } + } + + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(RSA_2048_modulus, + RSA_2048_publicExponent); + final PublicKey pubKey = kf.generatePublic(pubKeySpec); + c.init(Cipher.ENCRYPT_MODE, pubKey); + assertEquals(getExpectedBlockSize("RSA", Cipher.ENCRYPT_MODE, provider), c.getBlockSize()); + } + + public void testRSA_ECB_NoPadding_GetOutputSize_NoInit_Failure() throws Exception { + for (String provider : RSA_PROVIDERS) { + testRSA_ECB_NoPadding_GetOutputSize_NoInit_Failure(provider); + } + } + + private void testRSA_ECB_NoPadding_GetOutputSize_NoInit_Failure(String provider) throws Exception { + Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider); + try { + c.getOutputSize(RSA_2048_Vector1.length); + fail("Should throw IllegalStateException if getOutputSize is called before init"); + } catch (IllegalStateException success) { + } + } + + public void testRSA_ECB_NoPadding_GetOutputSize_Success() throws Exception { + for (String provider : RSA_PROVIDERS) { + testRSA_ECB_NoPadding_GetOutputSize_Success(provider); + } + } + + private void testRSA_ECB_NoPadding_GetOutputSize_Success(String provider) throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(RSA_2048_modulus, + RSA_2048_publicExponent); + final PublicKey pubKey = kf.generatePublic(pubKeySpec); + + Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider); + c.init(Cipher.ENCRYPT_MODE, pubKey); + + final int modulusInBytes = RSA_2048_modulus.bitLength() / 8; + assertEquals(modulusInBytes, c.getOutputSize(RSA_2048_Vector1.length)); + assertEquals(modulusInBytes, c.getOutputSize(RSA_2048_Vector1.length * 2)); + assertEquals(modulusInBytes, c.getOutputSize(0)); + } + + public void testRSA_ECB_NoPadding_GetIV_Success() throws Exception { + for (String provider : RSA_PROVIDERS) { + testRSA_ECB_NoPadding_GetIV_Success(provider); + } + } + + private void testRSA_ECB_NoPadding_GetIV_Success(String provider) throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(RSA_2048_modulus, + RSA_2048_publicExponent); + final PublicKey pubKey = kf.generatePublic(pubKeySpec); + + Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider); + assertNull("ECB mode has no IV and should be null", c.getIV()); + + c.init(Cipher.ENCRYPT_MODE, pubKey); + + assertNull("ECB mode has no IV and should be null", c.getIV()); + } + + public void testRSA_ECB_NoPadding_GetParameters_NoneProvided_Success() throws Exception { + for (String provider : RSA_PROVIDERS) { + testRSA_ECB_NoPadding_GetParameters_NoneProvided_Success(provider); + } + } + + private void testRSA_ECB_NoPadding_GetParameters_NoneProvided_Success(String provider) throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(RSA_2048_modulus, + RSA_2048_publicExponent); + final PublicKey pubKey = kf.generatePublic(pubKeySpec); + + Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider); + assertNull("Parameters should be null", c.getParameters()); + } + + /* + * Test vector generation: + * openssl rand -hex 16 + * echo '3d4f8970b1f27537f40a39298a41555f' | sed 's/\(..\)/(byte) 0x\1, /g' + */ + private static final byte[] AES_128_KEY = new byte[] { + (byte) 0x3d, (byte) 0x4f, (byte) 0x89, (byte) 0x70, (byte) 0xb1, (byte) 0xf2, + (byte) 0x75, (byte) 0x37, (byte) 0xf4, (byte) 0x0a, (byte) 0x39, (byte) 0x29, + (byte) 0x8a, (byte) 0x41, (byte) 0x55, (byte) 0x5f, + }; + + /* + * Test key generation: + * openssl rand -hex 24 + * echo '5a7a3d7e40b64ed996f7afa15f97fd595e27db6af428e342' | sed 's/\(..\)/(byte) 0x\1, /g' + */ + private static final byte[] AES_192_KEY = new byte[] { + (byte) 0x5a, (byte) 0x7a, (byte) 0x3d, (byte) 0x7e, (byte) 0x40, (byte) 0xb6, + (byte) 0x4e, (byte) 0xd9, (byte) 0x96, (byte) 0xf7, (byte) 0xaf, (byte) 0xa1, + (byte) 0x5f, (byte) 0x97, (byte) 0xfd, (byte) 0x59, (byte) 0x5e, (byte) 0x27, + (byte) 0xdb, (byte) 0x6a, (byte) 0xf4, (byte) 0x28, (byte) 0xe3, (byte) 0x42, + }; + + /* + * Test key generation: + * openssl rand -hex 32 + * echo 'ec53c6d51d2c4973585fb0b8e51cd2e39915ff07a1837872715d6121bf861935' | sed 's/\(..\)/(byte) 0x\1, /g' + */ + private static final byte[] AES_256_KEY = new byte[] { + (byte) 0xec, (byte) 0x53, (byte) 0xc6, (byte) 0xd5, (byte) 0x1d, (byte) 0x2c, + (byte) 0x49, (byte) 0x73, (byte) 0x58, (byte) 0x5f, (byte) 0xb0, (byte) 0xb8, + (byte) 0xe5, (byte) 0x1c, (byte) 0xd2, (byte) 0xe3, (byte) 0x99, (byte) 0x15, + (byte) 0xff, (byte) 0x07, (byte) 0xa1, (byte) 0x83, (byte) 0x78, (byte) 0x72, + (byte) 0x71, (byte) 0x5d, (byte) 0x61, (byte) 0x21, (byte) 0xbf, (byte) 0x86, + (byte) 0x19, (byte) 0x35, + }; + + private static final byte[][] AES_KEYS = new byte[][] { + AES_128_KEY, AES_192_KEY, AES_256_KEY, + }; + + private static final String[] AES_MODES = new String[] { + "AES/ECB", + "AES/CBC", + "AES/CFB", + "AES/CTR", + "AES/OFB", + }; + + /* + * Test vector creation: + * echo -n 'Hello, world!' | recode ../x1 | sed 's/0x/(byte) 0x/g' + */ + private static final byte[] AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext = new byte[] { + (byte) 0x48, (byte) 0x65, (byte) 0x6C, (byte) 0x6C, (byte) 0x6F, (byte) 0x2C, + (byte) 0x20, (byte) 0x77, (byte) 0x6F, (byte) 0x72, (byte) 0x6C, (byte) 0x64, + (byte) 0x21, + }; + + /* + * Test vector creation: + * openssl enc -aes-128-ecb -K 3d4f8970b1f27537f40a39298a41555f -in blah|openssl enc -aes-128-ecb -K 3d4f8970b1f27537f40a39298a41555f -nopad -d|recode ../x1 | sed 's/0x/(byte) 0x/g' + */ + private static final byte[] AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext_Padded = new byte[] { + (byte) 0x48, (byte) 0x65, (byte) 0x6C, (byte) 0x6C, (byte) 0x6F, (byte) 0x2C, + (byte) 0x20, (byte) 0x77, (byte) 0x6F, (byte) 0x72, (byte) 0x6C, (byte) 0x64, + (byte) 0x21, (byte) 0x03, (byte) 0x03, (byte) 0x03 + }; + + /* + * Test vector generation: + * openssl enc -aes-128-ecb -K 3d4f8970b1f27537f40a39298a41555f -in blah|recode ../x1 | sed 's/0x/(byte) 0x/g' + */ + private static final byte[] AES_128_ECB_PKCS5Padding_TestVector_1_Encrypted = new byte[] { + (byte) 0x65, (byte) 0x3E, (byte) 0x86, (byte) 0xFB, (byte) 0x05, (byte) 0x5A, + (byte) 0x52, (byte) 0xEA, (byte) 0xDD, (byte) 0x08, (byte) 0xE7, (byte) 0x48, + (byte) 0x33, (byte) 0x01, (byte) 0xFC, (byte) 0x5A, + }; + + /* + * Test key generation: + * openssl rand -hex 16 + * echo 'ceaa31952dfd3d0f5af4b2042ba06094' | sed 's/\(..\)/(byte) 0x\1, /g' + */ + private static final byte[] AES_256_CBC_PKCS5Padding_TestVector_1_IV = new byte[] { + (byte) 0xce, (byte) 0xaa, (byte) 0x31, (byte) 0x95, (byte) 0x2d, (byte) 0xfd, + (byte) 0x3d, (byte) 0x0f, (byte) 0x5a, (byte) 0xf4, (byte) 0xb2, (byte) 0x04, + (byte) 0x2b, (byte) 0xa0, (byte) 0x60, (byte) 0x94, + }; + + /* + * Test vector generation: + * echo -n 'I only regret that I have but one test to write.' | recode ../x1 | sed 's/0x/(byte) 0x/g' + */ + private static final byte[] AES_256_CBC_PKCS5Padding_TestVector_1_Plaintext = new byte[] { + (byte) 0x49, (byte) 0x20, (byte) 0x6F, (byte) 0x6E, (byte) 0x6C, (byte) 0x79, + (byte) 0x20, (byte) 0x72, (byte) 0x65, (byte) 0x67, (byte) 0x72, (byte) 0x65, + (byte) 0x74, (byte) 0x20, (byte) 0x74, (byte) 0x68, (byte) 0x61, (byte) 0x74, + (byte) 0x20, (byte) 0x49, (byte) 0x20, (byte) 0x68, (byte) 0x61, (byte) 0x76, + (byte) 0x65, (byte) 0x20, (byte) 0x62, (byte) 0x75, (byte) 0x74, (byte) 0x20, + (byte) 0x6F, (byte) 0x6E, (byte) 0x65, (byte) 0x20, (byte) 0x74, (byte) 0x65, + (byte) 0x73, (byte) 0x74, (byte) 0x20, (byte) 0x74, (byte) 0x6F, (byte) 0x20, + (byte) 0x77, (byte) 0x72, (byte) 0x69, (byte) 0x74, (byte) 0x65, (byte) 0x2E + }; + + /* + * Test vector generation: + * echo -n 'I only regret that I have but one test to write.' | openssl enc -aes-256-cbc -K ec53c6d51d2c4973585fb0b8e51cd2e39915ff07a1837872715d6121bf861935 -iv ceaa31952dfd3d0f5af4b2042ba06094 | openssl enc -aes-256-cbc -K ec53c6d51d2c4973585fb0b8e51cd2e39915ff07a1837872715d6121bf861935 -iv ceaa31952dfd3d0f5af4b2042ba06094 -d -nopad | recode ../x1 | sed 's/0x/(byte) 0x/g' + */ + private static final byte[] AES_256_CBC_PKCS5Padding_TestVector_1_Plaintext_Padded = new byte[] { + (byte) 0x49, (byte) 0x20, (byte) 0x6F, (byte) 0x6E, (byte) 0x6C, (byte) 0x79, + (byte) 0x20, (byte) 0x72, (byte) 0x65, (byte) 0x67, (byte) 0x72, (byte) 0x65, + (byte) 0x74, (byte) 0x20, (byte) 0x74, (byte) 0x68, (byte) 0x61, (byte) 0x74, + (byte) 0x20, (byte) 0x49, (byte) 0x20, (byte) 0x68, (byte) 0x61, (byte) 0x76, + (byte) 0x65, (byte) 0x20, (byte) 0x62, (byte) 0x75, (byte) 0x74, (byte) 0x20, + (byte) 0x6F, (byte) 0x6E, (byte) 0x65, (byte) 0x20, (byte) 0x74, (byte) 0x65, + (byte) 0x73, (byte) 0x74, (byte) 0x20, (byte) 0x74, (byte) 0x6F, (byte) 0x20, + (byte) 0x77, (byte) 0x72, (byte) 0x69, (byte) 0x74, (byte) 0x65, (byte) 0x2E, + (byte) 0x10, (byte) 0x10, (byte) 0x10, (byte) 0x10, (byte) 0x10, (byte) 0x10, + (byte) 0x10, (byte) 0x10, (byte) 0x10, (byte) 0x10, (byte) 0x10, (byte) 0x10, + (byte) 0x10, (byte) 0x10, (byte) 0x10, (byte) 0x10 + }; + + /* + * Test vector generation: + * echo -n 'I only regret that I have but one test to write.' | openssl enc -aes-256-cbc -K ec53c6d51d2c4973585fb0b8e51cd2e39915ff07a1837872715d6121bf861935 -iv ceaa31952dfd3d0f5af4b2042ba06094 | recode ../x1 | sed 's/0x/(byte) 0x/g' + */ + private static final byte[] AES_256_CBC_PKCS5Padding_TestVector_1_Ciphertext = new byte[] { + (byte) 0x90, (byte) 0x65, (byte) 0xDD, (byte) 0xAF, (byte) 0x7A, (byte) 0xCE, + (byte) 0xAE, (byte) 0xBF, (byte) 0xE8, (byte) 0xF6, (byte) 0x9E, (byte) 0xDB, + (byte) 0xEA, (byte) 0x65, (byte) 0x28, (byte) 0xC4, (byte) 0x9A, (byte) 0x28, + (byte) 0xEA, (byte) 0xA3, (byte) 0x95, (byte) 0x2E, (byte) 0xFF, (byte) 0xF1, + (byte) 0xA0, (byte) 0xCA, (byte) 0xC2, (byte) 0xA4, (byte) 0x65, (byte) 0xCD, + (byte) 0xBF, (byte) 0xCE, (byte) 0x9E, (byte) 0xF1, (byte) 0x57, (byte) 0xF6, + (byte) 0x32, (byte) 0x2E, (byte) 0x8F, (byte) 0x93, (byte) 0x2E, (byte) 0xAE, + (byte) 0x41, (byte) 0x33, (byte) 0x54, (byte) 0xD0, (byte) 0xEF, (byte) 0x8C, + (byte) 0x52, (byte) 0x14, (byte) 0xAC, (byte) 0x2D, (byte) 0xD5, (byte) 0xA4, + (byte) 0xF9, (byte) 0x20, (byte) 0x77, (byte) 0x25, (byte) 0x91, (byte) 0x3F, + (byte) 0xD1, (byte) 0xB9, (byte) 0x00, (byte) 0x3E + }; + + private static class CipherTestParam { + public final String mode; + + public final byte[] key; + + public final byte[] iv; + + public final byte[] plaintext; + + public final byte[] ciphertext; + + public final byte[] plaintextPadded; + + public CipherTestParam(String mode, byte[] key, byte[] iv, byte[] plaintext, + byte[] plaintextPadded, byte[] ciphertext) { + this.mode = mode; + this.key = key; + this.iv = iv; + this.plaintext = plaintext; + this.plaintextPadded = plaintextPadded; + this.ciphertext = ciphertext; + } + } + + private static List<CipherTestParam> CIPHER_TEST_PARAMS = new ArrayList<CipherTestParam>(); + static { + CIPHER_TEST_PARAMS.add(new CipherTestParam("AES/ECB", AES_128_KEY, + null, + AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext, + AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext_Padded, + AES_128_ECB_PKCS5Padding_TestVector_1_Encrypted)); + if (IS_UNLIMITED) { + CIPHER_TEST_PARAMS.add(new CipherTestParam("AES/CBC", AES_256_KEY, + AES_256_CBC_PKCS5Padding_TestVector_1_IV, + AES_256_CBC_PKCS5Padding_TestVector_1_Plaintext, + AES_256_CBC_PKCS5Padding_TestVector_1_Plaintext_Padded, + AES_256_CBC_PKCS5Padding_TestVector_1_Ciphertext)); + } + } + + public void testCipher_Success() throws Exception { + for (String provider : AES_PROVIDERS) { + testCipher_Success(provider); + } + } + + private void testCipher_Success(String provider) throws Exception { + final ByteArrayOutputStream errBuffer = new ByteArrayOutputStream(); + PrintStream out = new PrintStream(errBuffer); + for (CipherTestParam p : CIPHER_TEST_PARAMS) { + try { + checkCipher(p, provider); + } catch (Exception e) { + out.append("Error encountered checking " + p.mode + ", keySize=" + + (p.key.length * 8) + "\n"); + e.printStackTrace(out); + } + } + out.flush(); + if (errBuffer.size() > 0) { + throw new Exception("Errors encountered:\n\n" + errBuffer.toString() + "\n\n"); + } + } + + private void checkCipher(CipherTestParam p, String provider) throws Exception { + SecretKey key = new SecretKeySpec(p.key, "AES"); + Cipher c = Cipher.getInstance(p.mode + "/PKCS5Padding", provider); + AlgorithmParameterSpec spec = null; + if (p.iv != null) { + spec = new IvParameterSpec(p.iv); + } + c.init(Cipher.ENCRYPT_MODE, key, spec); + + final byte[] actualCiphertext = c.doFinal(p.plaintext); + assertTrue(Arrays.equals(p.ciphertext, actualCiphertext)); + + c.init(Cipher.DECRYPT_MODE, key, spec); + + final byte[] actualPlaintext = c.doFinal(p.ciphertext); + assertTrue(Arrays.equals(p.plaintext, actualPlaintext)); + + Cipher cNoPad = Cipher.getInstance(p.mode + "/NoPadding", provider); + cNoPad.init(Cipher.DECRYPT_MODE, key, spec); + + final byte[] actualPlaintextPadded = cNoPad.doFinal(p.ciphertext); + assertTrue(Arrays.equals(p.plaintextPadded, actualPlaintextPadded)); + } + + public void testCipher_ShortBlock_Failure() throws Exception { + for (String provider : AES_PROVIDERS) { + testCipher_ShortBlock_Failure(provider); + } + } + + private void testCipher_ShortBlock_Failure(String provider) throws Exception { + final ByteArrayOutputStream errBuffer = new ByteArrayOutputStream(); + PrintStream out = new PrintStream(errBuffer); + for (CipherTestParam p : CIPHER_TEST_PARAMS) { + try { + checkCipher_ShortBlock_Failure(p, provider); + } catch (Exception e) { + out.append("Error encountered checking " + p.mode + ", keySize=" + + (p.key.length * 8) + "\n"); + e.printStackTrace(out); + } + } + out.flush(); + if (errBuffer.size() > 0) { + throw new Exception("Errors encountered:\n\n" + errBuffer.toString() + "\n\n"); + } + } + + private void checkCipher_ShortBlock_Failure(CipherTestParam p, String provider) throws Exception { + SecretKey key = new SecretKeySpec(p.key, "AES"); + Cipher c = Cipher.getInstance(p.mode + "/NoPadding", provider); + if (c.getBlockSize() == 0) { + return; + } + + c.init(Cipher.ENCRYPT_MODE, key); + try { + c.doFinal(new byte[] { 0x01, 0x02, 0x03 }); + fail("Should throw IllegalBlockSizeException on wrong-sized block"); + } catch (IllegalBlockSizeException expected) { + } + } + + public void testAES_ECB_PKCS5Padding_ShortBuffer_Failure() throws Exception { + for (String provider : AES_PROVIDERS) { + testAES_ECB_PKCS5Padding_ShortBuffer_Failure(provider); + } + } + + private void testAES_ECB_PKCS5Padding_ShortBuffer_Failure(String provider) throws Exception { + SecretKey key = new SecretKeySpec(AES_128_KEY, "AES"); + Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding", provider); + c.init(Cipher.ENCRYPT_MODE, key); + + final byte[] fragmentOutput = c.update(AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext); + if (fragmentOutput != null) { + assertEquals(0, fragmentOutput.length); + } + + // Provide null buffer. + { + try { + c.doFinal(null, 0); + fail("Should throw NullPointerException on null output buffer"); + } catch (NullPointerException expected) { + } catch (IllegalArgumentException expected) { + } + } + + // Provide short buffer. + { + final byte[] output = new byte[c.getBlockSize() - 1]; + try { + c.doFinal(output, 0); + fail("Should throw ShortBufferException on short output buffer"); + } catch (ShortBufferException expected) { + } + } + + // Start 1 byte into output buffer. + { + final byte[] output = new byte[c.getBlockSize()]; + try { + c.doFinal(output, 1); + fail("Should throw ShortBufferException on short output buffer"); + } catch (ShortBufferException expected) { + } + } + + // Should keep data for real output buffer + { + final byte[] output = new byte[c.getBlockSize()]; + assertEquals(AES_128_ECB_PKCS5Padding_TestVector_1_Encrypted.length, c.doFinal(output, 0)); + assertTrue(Arrays.equals(AES_128_ECB_PKCS5Padding_TestVector_1_Encrypted, output)); + } + } + + public void testAES_ECB_NoPadding_IncrementalUpdate_Success() throws Exception { + for (String provider : AES_PROVIDERS) { + testAES_ECB_NoPadding_IncrementalUpdate_Success(provider); + } + } + + private void testAES_ECB_NoPadding_IncrementalUpdate_Success(String provider) throws Exception { + SecretKey key = new SecretKeySpec(AES_128_KEY, "AES"); + Cipher c = Cipher.getInstance("AES/ECB/NoPadding", provider); + c.init(Cipher.ENCRYPT_MODE, key); + + for (int i = 0; i < AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext_Padded.length - 1; i++) { + final byte[] outputFragment = c.update(AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext_Padded, i, 1); + if (outputFragment != null) { + assertEquals(0, outputFragment.length); + } + } + + final byte[] output = c.doFinal(AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext_Padded, + AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext_Padded.length - 1, 1); + assertNotNull(output); + assertEquals(AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext_Padded.length, output.length); + + assertTrue(Arrays.equals(AES_128_ECB_PKCS5Padding_TestVector_1_Encrypted, output)); + } + + private static final byte[] AES_IV_ZEROES = new byte[] { + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + }; + + public void testAES_ECB_NoPadding_IvParameters_Failure() throws Exception { + for (String provider : AES_PROVIDERS) { + testAES_ECB_NoPadding_IvParameters_Failure(provider); + } + } + + private void testAES_ECB_NoPadding_IvParameters_Failure(String provider) throws Exception { + SecretKey key = new SecretKeySpec(AES_128_KEY, "AES"); + Cipher c = Cipher.getInstance("AES/ECB/NoPadding", provider); + + AlgorithmParameterSpec spec = new IvParameterSpec(AES_IV_ZEROES); + try { + c.init(Cipher.ENCRYPT_MODE, key, spec); + fail("Should not accept an IV in ECB mode"); + } catch (InvalidAlgorithmParameterException expected) { + } + } } diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java index e3ae16f..65d8690 100644 --- a/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java +++ b/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java @@ -347,6 +347,51 @@ public class SSLEngineTest extends TestCase { c.close(); } + /** + * http://code.google.com/p/android/issues/detail?id=31903 + * This test case directly tests the fix for the issue. + */ + public void test_SSLEngine_clientAuthWantedNoClientCert() throws Exception { + TestSSLContext clientAuthContext + = TestSSLContext.create(TestKeyStore.getClient(), + TestKeyStore.getServer()); + TestSSLEnginePair p = TestSSLEnginePair.create(clientAuthContext, + new TestSSLEnginePair.Hooks() { + @Override + void beforeBeginHandshake(SSLEngine client, SSLEngine server) { + server.setWantClientAuth(true); + } + }); + assertConnected(p); + clientAuthContext.close(); + } + + /** + * http://code.google.com/p/android/issues/detail?id=31903 + * This test case verifies that if the server requires a client cert + * (setNeedClientAuth) but the client does not provide one SSL connection + * establishment will fail + */ + public void test_SSLEngine_clientAuthNeededNoClientCert() throws Exception { + boolean handshakeExceptionCaught = false; + TestSSLContext clientAuthContext + = TestSSLContext.create(TestKeyStore.getClient(), + TestKeyStore.getServer()); + try { + TestSSLEnginePair.create(clientAuthContext, + new TestSSLEnginePair.Hooks() { + @Override + void beforeBeginHandshake(SSLEngine client, SSLEngine server) { + server.setNeedClientAuth(true); + } + }); + fail(); + } catch (SSLHandshakeException expected) { + } finally { + clientAuthContext.close(); + } + } + public void test_SSLEngine_getEnableSessionCreation() throws Exception { TestSSLContext c = TestSSLContext.create(); SSLEngine e = c.clientContext.createSSLEngine(); diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLSessionTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLSessionTest.java index 217dfe9..67c83bf 100644 --- a/luni/src/test/java/libcore/javax/net/ssl/SSLSessionTest.java +++ b/luni/src/test/java/libcore/javax/net/ssl/SSLSessionTest.java @@ -54,11 +54,24 @@ public class SSLSessionTest extends TestCase { } public void test_SSLSession_getCreationTime() { + // We use OpenSSL, which only returns times accurate to the nearest second. + // NativeCrypto just multiplies by 1000, which looks like truncation, which + // would make it appear as if the OpenSSL side of things was created before + // we called it. + long t0 = System.currentTimeMillis() / 1000; TestSSLSessions s = TestSSLSessions.create(); + long t1 = System.currentTimeMillis() / 1000; + assertTrue(s.invalid.getCreationTime() > 0); - assertTrue(s.server.getCreationTime() > 0); - assertTrue(s.client.getCreationTime() > 0); - assertTrue(Math.abs(s.server.getCreationTime() - s.client.getCreationTime()) < 1 * 1000); + + long sTime = s.server.getCreationTime() / 1000; + assertTrue(sTime + " >= " + t0, sTime >= t0); + assertTrue(sTime + " <= " + t1, sTime <= t1); + + long cTime = s.client.getCreationTime() / 1000; + assertTrue(cTime + " >= " + t0, cTime >= t0); + assertTrue(cTime + " <= " + t1, cTime <= t1); + s.close(); } diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java index 90cdeb9..4095081 100644 --- a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java +++ b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java @@ -16,8 +16,10 @@ package libcore.javax.net.ssl; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.lang.reflect.Method; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; @@ -30,6 +32,10 @@ import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.HashSet; import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; import javax.net.ssl.HandshakeCompletedEvent; import javax.net.ssl.HandshakeCompletedListener; import javax.net.ssl.KeyManager; @@ -38,7 +44,6 @@ import javax.net.ssl.SSLException; import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLPeerUnverifiedException; -import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLProtocolException; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocket; @@ -271,32 +276,28 @@ public class SSLSocketTest extends TestCase { SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host, c.port); final SSLSocket server = (SSLSocket) c.serverSocket.accept(); - Thread thread = new Thread(new Runnable () { - public void run() { + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future<Void> future = executor.submit(new Callable<Void>() { + @Override public Void call() throws Exception { + server.startHandshake(); + assertNotNull(server.getSession()); try { - server.startHandshake(); - assertNotNull(server.getSession()); - try { - server.getSession().getPeerCertificates(); - fail(); - } catch (SSLPeerUnverifiedException expected) { - } - Certificate[] localCertificates = server.getSession().getLocalCertificates(); - assertNotNull(localCertificates); - TestKeyStore.assertChainLength(localCertificates); - assertNotNull(localCertificates[0]); - TestSSLContext.assertServerCertificateChain(c.serverTrustManager, - localCertificates); - TestSSLContext.assertCertificateInKeyStore(localCertificates[0], - c.serverKeyStore); - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new RuntimeException(e); + server.getSession().getPeerCertificates(); + fail(); + } catch (SSLPeerUnverifiedException expected) { } + Certificate[] localCertificates = server.getSession().getLocalCertificates(); + assertNotNull(localCertificates); + TestKeyStore.assertChainLength(localCertificates); + assertNotNull(localCertificates[0]); + TestSSLContext.assertServerCertificateChain(c.serverTrustManager, + localCertificates); + TestSSLContext.assertCertificateInKeyStore(localCertificates[0], + c.serverKeyStore); + return null; } }); - thread.start(); + executor.shutdown(); client.startHandshake(); assertNotNull(client.getSession()); assertNull(client.getSession().getLocalCertificates()); @@ -307,7 +308,7 @@ public class SSLSocketTest extends TestCase { TestSSLContext.assertServerCertificateChain(c.clientTrustManager, peerCertificates); TestSSLContext.assertCertificateInKeyStore(peerCertificates[0], c.serverKeyStore); - thread.join(); + future.get(); client.close(); server.close(); c.close(); @@ -321,25 +322,24 @@ public class SSLSocketTest extends TestCase { // RI used to throw SSLException on accept, now throws on startHandshake if (StandardNames.IS_RI) { final SSLSocket server = (SSLSocket) c.serverSocket.accept(); - Thread thread = new Thread(new Runnable () { - public void run() { + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future<Void> future = executor.submit(new Callable<Void>() { + @Override public Void call() throws Exception { try { server.startHandshake(); + fail(); } catch (SSLHandshakeException expected) { - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new RuntimeException(e); } + return null; } }); - thread.start(); + executor.shutdown(); try { client.startHandshake(); fail(); } catch (SSLHandshakeException expected) { } - thread.join(); + future.get(); server.close(); } else { try { @@ -359,20 +359,16 @@ public class SSLSocketTest extends TestCase { SSLSocket client = (SSLSocket) clientContext.getSocketFactory().createSocket(c.host, c.port); final SSLSocket server = (SSLSocket) c.serverSocket.accept(); - Thread thread = new Thread(new Runnable () { - public void run() { - try { - server.startHandshake(); - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new RuntimeException(e); - } + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future<Void> future = executor.submit(new Callable<Void>() { + @Override public Void call() throws Exception { + server.startHandshake(); + return null; } }); - thread.start(); + executor.shutdown(); client.startHandshake(); - thread.join(); + future.get(); client.close(); server.close(); c.close(); @@ -383,18 +379,14 @@ public class SSLSocketTest extends TestCase { final SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host, c.port); final SSLSocket server = (SSLSocket) c.serverSocket.accept(); - Thread thread = new Thread(new Runnable () { - public void run() { - try { - server.startHandshake(); - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new RuntimeException(e); - } + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future<Void> future = executor.submit(new Callable<Void>() { + @Override public Void call() throws Exception { + server.startHandshake(); + return null; } }); - thread.start(); + executor.shutdown(); final boolean[] handshakeCompletedListenerCalled = new boolean[1]; client.addHandshakeCompletedListener(new HandshakeCompletedListener() { public void handshakeCompleted(HandshakeCompletedEvent event) { @@ -472,7 +464,7 @@ public class SSLSocketTest extends TestCase { } }); client.startHandshake(); - thread.join(); + future.get(); if (!TestSSLContext.sslServerSocketSupportsSessionTickets()) { assertNotNull(c.serverContext.getServerSessionContext().getSession( client.getSession().getId())); @@ -492,25 +484,21 @@ public class SSLSocketTest extends TestCase { final SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host, c.port); final SSLSocket server = (SSLSocket) c.serverSocket.accept(); - Thread thread = new Thread(new Runnable () { - public void run() { - try { - server.startHandshake(); - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new RuntimeException(e); - } + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future<Void> future = executor.submit(new Callable<Void>() { + @Override public Void call() throws Exception { + server.startHandshake(); + return null; } }); - thread.start(); + executor.shutdown(); client.addHandshakeCompletedListener(new HandshakeCompletedListener() { public void handshakeCompleted(HandshakeCompletedEvent event) { throw new RuntimeException("RuntimeException from handshakeCompleted"); } }); client.startHandshake(); - thread.join(); + future.get(); client.close(); server.close(); c.close(); @@ -551,22 +539,6 @@ public class SSLSocketTest extends TestCase { } } - public void test_SSLSocket_setUseClientMode_afterHandshake() throws Exception { - - // can't set after handshake - TestSSLEnginePair pair = TestSSLEnginePair.create(null); - try { - pair.server.setUseClientMode(false); - fail(); - } catch (IllegalArgumentException expected) { - } - try { - pair.client.setUseClientMode(false); - fail(); - } catch (IllegalArgumentException expected) { - } - } - private void test_SSLSocket_setUseClientMode(final boolean clientClientMode, final boolean serverClientMode) throws Exception { @@ -575,64 +547,73 @@ public class SSLSocketTest extends TestCase { c.port); final SSLSocket server = (SSLSocket) c.serverSocket.accept(); - final SSLHandshakeException[] sslHandshakeException = new SSLHandshakeException[1]; - final SocketTimeoutException[] socketTimeoutException = new SocketTimeoutException[1]; - Thread thread = new Thread(new Runnable () { - public void run() { + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future<IOException> future = executor.submit(new Callable<IOException>() { + @Override public IOException call() throws Exception { try { if (!serverClientMode) { server.setSoTimeout(1 * 1000); } server.setUseClientMode(serverClientMode); server.startHandshake(); + return null; } catch (SSLHandshakeException e) { - sslHandshakeException[0] = e; + return e; } catch (SocketTimeoutException e) { - socketTimeoutException[0] = e; - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new RuntimeException(e); + return e; } } }); - thread.start(); + executor.shutdown(); if (!clientClientMode) { client.setSoTimeout(1 * 1000); } client.setUseClientMode(clientClientMode); client.startHandshake(); - thread.join(); - if (sslHandshakeException[0] != null) { - throw sslHandshakeException[0]; - } - if (socketTimeoutException[0] != null) { - throw socketTimeoutException[0]; + IOException ioe = future.get(); + if (ioe != null) { + throw ioe; } client.close(); server.close(); c.close(); } + public void test_SSLSocket_setUseClientMode_afterHandshake() throws Exception { + + // can't set after handshake + TestSSLEnginePair pair = TestSSLEnginePair.create(null); + try { + pair.server.setUseClientMode(false); + fail(); + } catch (IllegalArgumentException expected) { + } + try { + pair.client.setUseClientMode(false); + fail(); + } catch (IllegalArgumentException expected) { + } + } + public void test_SSLSocket_untrustedServer() throws Exception { TestSSLContext c = TestSSLContext.create(TestKeyStore.getClientCA2(), TestKeyStore.getServer()); SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host, c.port); final SSLSocket server = (SSLSocket) c.serverSocket.accept(); - Thread thread = new Thread(new Runnable () { - public void run() { + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future<Void> future = executor.submit(new Callable<Void>() { + @Override public Void call() throws Exception { try { server.startHandshake(); + assertFalse(StandardNames.IS_RI); } catch (SSLHandshakeException expected) { - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new RuntimeException(e); + assertTrue(StandardNames.IS_RI); } + return null; } }); - thread.start(); + executor.shutdown(); try { client.startHandshake(); fail(); @@ -641,7 +622,7 @@ public class SSLSocketTest extends TestCase { } client.close(); server.close(); - thread.join(); + future.get(); } public void test_SSLSocket_clientAuth() throws Exception { @@ -650,43 +631,38 @@ public class SSLSocketTest extends TestCase { SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host, c.port); final SSLSocket server = (SSLSocket) c.serverSocket.accept(); - Thread thread = new Thread(new Runnable () { - public void run() { - try { - assertFalse(server.getWantClientAuth()); - assertFalse(server.getNeedClientAuth()); - - // confirm turning one on by itself - server.setWantClientAuth(true); - assertTrue(server.getWantClientAuth()); - assertFalse(server.getNeedClientAuth()); - - // confirm turning setting on toggles the other - server.setNeedClientAuth(true); - assertFalse(server.getWantClientAuth()); - assertTrue(server.getNeedClientAuth()); - - // confirm toggling back - server.setWantClientAuth(true); - assertTrue(server.getWantClientAuth()); - assertFalse(server.getNeedClientAuth()); - - server.startHandshake(); - - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new RuntimeException(e); - } + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future<Void> future = executor.submit(new Callable<Void>() { + @Override public Void call() throws Exception { + assertFalse(server.getWantClientAuth()); + assertFalse(server.getNeedClientAuth()); + + // confirm turning one on by itself + server.setWantClientAuth(true); + assertTrue(server.getWantClientAuth()); + assertFalse(server.getNeedClientAuth()); + + // confirm turning setting on toggles the other + server.setNeedClientAuth(true); + assertFalse(server.getWantClientAuth()); + assertTrue(server.getNeedClientAuth()); + + // confirm toggling back + server.setWantClientAuth(true); + assertTrue(server.getWantClientAuth()); + assertFalse(server.getNeedClientAuth()); + + server.startHandshake(); + return null; } }); - thread.start(); + executor.shutdown(); client.startHandshake(); assertNotNull(client.getSession().getLocalCertificates()); TestKeyStore.assertChainLength(client.getSession().getLocalCertificates()); TestSSLContext.assertClientCertificateChain(c.clientTrustManager, client.getSession().getLocalCertificates()); - thread.join(); + future.get(); client.close(); server.close(); c.close(); @@ -727,22 +703,20 @@ public class SSLSocketTest extends TestCase { SSLSocket client = (SSLSocket) clientContext.getSocketFactory().createSocket(c.host, c.port); final SSLSocket server = (SSLSocket) c.serverSocket.accept(); - Thread thread = new Thread(new Runnable () { - public void run() { + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future<Void> future = executor.submit(new Callable<Void>() { + @Override public Void call() throws Exception { try { server.setNeedClientAuth(true); server.startHandshake(); fail(); } catch (SSLHandshakeException expected) { - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new RuntimeException(e); } + return null; } }); - thread.start(); + executor.shutdown(); try { client.startHandshake(); fail(); @@ -750,7 +724,7 @@ public class SSLSocketTest extends TestCase { // before we would get a NullPointerException from passing // due to the null PrivateKey return by the X509KeyManager. } - thread.join(); + future.get(); client.close(); server.close(); c.close(); @@ -773,29 +747,25 @@ public class SSLSocketTest extends TestCase { SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host, c.port); final SSLSocket server = (SSLSocket) c.serverSocket.accept(); - Thread thread = new Thread(new Runnable () { - public void run() { + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future<Void> future = executor.submit(new Callable<Void>() { + @Override public Void call() throws Exception { + server.setEnableSessionCreation(false); try { - server.setEnableSessionCreation(false); - try { - server.startHandshake(); - fail(); - } catch (SSLException expected) { - } - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new RuntimeException(e); + server.startHandshake(); + fail(); + } catch (SSLException expected) { } + return null; } }); - thread.start(); + executor.shutdown(); try { client.startHandshake(); fail(); } catch (SSLException expected) { } - thread.join(); + future.get(); client.close(); server.close(); c.close(); @@ -806,29 +776,25 @@ public class SSLSocketTest extends TestCase { SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host, c.port); final SSLSocket server = (SSLSocket) c.serverSocket.accept(); - Thread thread = new Thread(new Runnable () { - public void run() { + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future<Void> future = executor.submit(new Callable<Void>() { + @Override public Void call() throws Exception { try { - try { - server.startHandshake(); - fail(); - } catch (SSLException expected) { - } - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new RuntimeException(e); + server.startHandshake(); + fail(); + } catch (SSLException expected) { } + return null; } }); - thread.start(); + executor.shutdown(); client.setEnableSessionCreation(false); try { client.startHandshake(); fail(); } catch (SSLException expected) { } - thread.join(); + future.get(); client.close(); server.close(); c.close(); @@ -1012,32 +978,25 @@ public class SSLSocketTest extends TestCase { c.host.getHostName(), c.port, false); - Thread clientThread = new Thread(new Runnable () { - public void run() { - try { - try { - wrapping.startHandshake(); - wrapping.getOutputStream().write(42); - // close the underlying socket, - // so that no SSL shutdown is sent - underlying.close(); - wrapping.close(); - } catch (SSLException expected) { - } - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new RuntimeException(e); - } + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future<Void> clientFuture = executor.submit(new Callable<Void>() { + @Override public Void call() throws Exception { + wrapping.startHandshake(); + wrapping.getOutputStream().write(42); + // close the underlying socket, + // so that no SSL shutdown is sent + underlying.close(); + wrapping.close(); + return null; } }); - clientThread.start(); + executor.shutdown(); SSLSocket server = (SSLSocket) c.serverSocket.accept(); server.startHandshake(); server.getInputStream().read(); // wait for thread to finish so we know client is closed. - clientThread.join(); + clientFuture.get(); // close should cause an SSL_shutdown which will fail // because the peer has closed, but it shouldn't throw. server.close(); @@ -1054,9 +1013,10 @@ public class SSLSocketTest extends TestCase { assertEquals(0, wrapping.getSoTimeout()); // setting wrapper sets underlying and ... - wrapping.setSoTimeout(10); - assertEquals(10, wrapping.getSoTimeout()); - assertEquals(10, underlying.getSoTimeout()); + int expectedTimeoutMillis = 1000; // 10 was too small because it was affected by rounding + wrapping.setSoTimeout(expectedTimeoutMillis); + assertEquals(expectedTimeoutMillis, wrapping.getSoTimeout()); + assertEquals(expectedTimeoutMillis, underlying.getSoTimeout()); // ... getting wrapper inspects underlying underlying.setSoTimeout(0); @@ -1091,6 +1051,52 @@ public class SSLSocketTest extends TestCase { listening.close(); } + public void test_SSLSocket_setSoWriteTimeout() throws Exception { + if (StandardNames.IS_RI) { + // RI does not support write timeout on sockets + return; + } + + final TestSSLContext c = TestSSLContext.create(); + SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host, + c.port); + final SSLSocket server = (SSLSocket) c.serverSocket.accept(); + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future<Void> future = executor.submit(new Callable<Void>() { + @Override public Void call() throws Exception { + server.startHandshake(); + return null; + } + }); + executor.shutdown(); + client.startHandshake(); + + // Reflection is used so this can compile on the RI + String expectedClassName = "org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl"; + Class actualClass = client.getClass(); + assertEquals(expectedClassName, actualClass.getName()); + Method setSoWriteTimeout = actualClass.getMethod("setSoWriteTimeout", + new Class[] { Integer.TYPE }); + setSoWriteTimeout.invoke(client, 1); + + // Try to make the size smaller (it can be 512k or even megabytes). + // Note that it may not respect your request, so read back the actual value. + int sendBufferSize = 1024; + client.setSendBufferSize(sendBufferSize); + sendBufferSize = client.getSendBufferSize(); + + try { + client.getOutputStream().write(new byte[sendBufferSize + 1]); + fail(); + } catch (SocketTimeoutException expected) { + } + + future.get(); + client.close(); + server.close(); + c.close(); + } + public void test_SSLSocket_interrupt() throws Exception { ServerSocket listening = new ServerSocket(0); @@ -1126,17 +1132,15 @@ public class SSLSocketTest extends TestCase { private void test_SSLSocket_interrupt_case(Socket toRead, final Socket toClose) throws Exception { - new Thread() { - @Override - public void run() { - try { - Thread.sleep(1 * 1000); - toClose.close(); - } catch (Exception e) { - throw new RuntimeException(e); - } + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future<Void> future = executor.submit(new Callable<Void>() { + @Override public Void call() throws Exception { + Thread.sleep(1 * 1000); + toClose.close(); + return null; } - }.start(); + }); + executor.shutdown(); try { toRead.setSoTimeout(5 * 1000); toRead.getInputStream().read(); @@ -1145,6 +1149,43 @@ public class SSLSocketTest extends TestCase { throw e; } catch (SocketException expected) { } + future.get(); + } + + /** + * b/7014266 Test to confirm that an SSLSocket.close() on one + * thread will interupt another thread blocked reading on the same + * socket. + */ + public void test_SSLSocket_interrupt_read() throws Exception { + TestSSLContext c = TestSSLContext.create(); + final Socket underlying = new Socket(c.host, c.port); + final SSLSocket wrapping = (SSLSocket) + c.clientContext.getSocketFactory().createSocket(underlying, + c.host.getHostName(), + c.port, + false); + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future<Void> clientFuture = executor.submit(new Callable<Void>() { + @Override public Void call() throws Exception { + try { + wrapping.startHandshake(); + assertFalse(StandardNames.IS_RI); + wrapping.setSoTimeout(5 * 1000); + assertEquals(-1, wrapping.getInputStream().read()); + } catch (Exception e) { + assertTrue(StandardNames.IS_RI); + } + return null; + } + }); + executor.shutdown(); + + SSLSocket server = (SSLSocket) c.serverSocket.accept(); + server.startHandshake(); + wrapping.close(); + clientFuture.get(); + server.close(); } public void test_TestSSLSocketPair_create() { diff --git a/luni/src/test/java/libcore/net/http/HttpResponseCacheTest.java b/luni/src/test/java/libcore/net/http/HttpResponseCacheTest.java index 360ca44..133924e 100644 --- a/luni/src/test/java/libcore/net/http/HttpResponseCacheTest.java +++ b/luni/src/test/java/libcore/net/http/HttpResponseCacheTest.java @@ -959,7 +959,7 @@ public final class HttpResponseCacheTest extends TestCase { HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); connection.addRequestProperty("Cache-Control", "only-if-cached"); - assertBadGateway(connection); + assertGatewayTimeout(connection); } public void testRequestOnlyIfCachedWithFullResponseCached() throws IOException { @@ -983,7 +983,7 @@ public final class HttpResponseCacheTest extends TestCase { assertEquals("A", readAscii(server.getUrl("/").openConnection())); HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); connection.addRequestProperty("Cache-Control", "only-if-cached"); - assertBadGateway(connection); + assertGatewayTimeout(connection); } public void testRequestOnlyIfCachedWithUnhelpfulResponseCached() throws IOException { @@ -993,7 +993,7 @@ public final class HttpResponseCacheTest extends TestCase { assertEquals("A", readAscii(server.getUrl("/").openConnection())); HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); connection.addRequestProperty("Cache-Control", "only-if-cached"); - assertBadGateway(connection); + assertGatewayTimeout(connection); } public void testRequestCacheControlNoCache() throws Exception { @@ -1804,13 +1804,13 @@ public final class HttpResponseCacheTest extends TestCase { } } - private void assertBadGateway(HttpURLConnection connection) throws IOException { + private void assertGatewayTimeout(HttpURLConnection connection) throws IOException { try { connection.getInputStream(); fail(); } catch (FileNotFoundException expected) { } - assertEquals(HttpURLConnection.HTTP_BAD_GATEWAY, connection.getResponseCode()); + assertEquals(504, connection.getResponseCode()); assertEquals(-1, connection.getErrorStream().read()); } diff --git a/luni/src/test/java/libcore/xml/DomSerializationTest.java b/luni/src/test/java/libcore/xml/DomSerializationTest.java new file mode 100644 index 0000000..9015f97 --- /dev/null +++ b/luni/src/test/java/libcore/xml/DomSerializationTest.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package libcore.xml; + +import java.io.StringWriter; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import junit.framework.TestCase; +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public final class DomSerializationTest extends TestCase { + private DocumentBuilder documentBuilder; + private Transformer transformer; + + @Override protected void setUp() throws Exception { + DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); + documentBuilder = builderFactory.newDocumentBuilder(); + transformer = TransformerFactory.newInstance().newTransformer(); + } + + public void testWriteDocument() throws Exception { + Document document = documentBuilder.newDocument(); + Element foo = document.createElement("foo"); + Attr quux = document.createAttribute("quux"); + quux.setValue("abc"); + foo.setAttributeNode(quux); + foo.appendChild(document.createElement("bar")); + foo.appendChild(document.createElement("baz")); + document.appendChild(foo); + assertXmlEquals("<foo quux=\"abc\"><bar/><baz/></foo>", document); + } + + public void testWriteSpecialCharactersInText() throws Exception { + Document document = documentBuilder.newDocument(); + Element foo = document.createElement("foo"); + foo.appendChild(document.createTextNode("5'8\", 5 < 6 & 7 > 3!")); + document.appendChild(foo); + assertXmlEquals("<foo>5'8\", 5 < 6 & 7 > 3!</foo>", document); + } + + private String toXml(Document document) throws Exception { + StringWriter stringWriter = new StringWriter(); + transformer.transform(new DOMSource(document), new StreamResult(stringWriter)); + return stringWriter.toString(); + } + + private void assertXmlEquals(String expectedXml, Document document) throws Exception { + String actual = toXml(document); + String declarationA = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; + String declarationB = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"; + assertTrue(actual, actual.equals(declarationA + expectedXml) + || actual.equals(declarationB + expectedXml)); + } +} diff --git a/luni/src/test/java/libcore/xml/KxmlSerializerTest.java b/luni/src/test/java/libcore/xml/KxmlSerializerTest.java new file mode 100644 index 0000000..6a75a9b --- /dev/null +++ b/luni/src/test/java/libcore/xml/KxmlSerializerTest.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package libcore.xml; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.StringWriter; +import junit.framework.TestCase; +import org.kxml2.io.KXmlSerializer; +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; +import org.xmlpull.v1.XmlSerializer; +import static tests.support.Support_Xml.domOf; + +public final class KxmlSerializerTest extends TestCase { + private static final String NAMESPACE = null; + + public void testWhitespaceInAttributeValue() throws Exception { + StringWriter stringWriter = new StringWriter(); + XmlSerializer serializer = new KXmlSerializer(); + serializer.setOutput(stringWriter); + serializer.startDocument("UTF-8", null); + serializer.startTag(NAMESPACE, "a"); + serializer.attribute(NAMESPACE, "cr", "\r"); + serializer.attribute(NAMESPACE, "lf", "\n"); + serializer.attribute(NAMESPACE, "tab", "\t"); + serializer.attribute(NAMESPACE, "space", " "); + serializer.endTag(NAMESPACE, "a"); + serializer.endDocument(); + assertXmlEquals("<a cr=\" \" lf=\" \" tab=\"	\" space=\" \" />", + stringWriter.toString()); + } + + public void testWriteDocument() throws Exception { + StringWriter stringWriter = new StringWriter(); + XmlSerializer serializer = new KXmlSerializer(); + serializer.setOutput(stringWriter); + serializer.startDocument("UTF-8", null); + serializer.startTag(NAMESPACE, "foo"); + serializer.attribute(NAMESPACE, "quux", "abc"); + serializer.startTag(NAMESPACE, "bar"); + serializer.endTag(NAMESPACE, "bar"); + serializer.startTag(NAMESPACE, "baz"); + serializer.endTag(NAMESPACE, "baz"); + serializer.endTag(NAMESPACE, "foo"); + serializer.endDocument(); + assertXmlEquals("<foo quux=\"abc\"><bar /><baz /></foo>", stringWriter.toString()); + } + + // http://code.google.com/p/android/issues/detail?id=21250 + public void testWriteSpecialCharactersInText() throws Exception { + StringWriter stringWriter = new StringWriter(); + XmlSerializer serializer = new KXmlSerializer(); + serializer.setOutput(stringWriter); + serializer.startDocument("UTF-8", null); + serializer.startTag(NAMESPACE, "foo"); + serializer.text("5'8\", 5 < 6 & 7 > 3!"); + serializer.endTag(NAMESPACE, "foo"); + serializer.endDocument(); + assertXmlEquals("<foo>5'8\", 5 < 6 & 7 > 3!</foo>", stringWriter.toString()); + } + + private void assertXmlEquals(String expectedXml, String actualXml) throws Exception { + String declaration = "<?xml version='1.0' encoding='UTF-8' ?>"; + assertEquals(declaration + expectedXml, actualXml); + } + + private static XmlSerializer newSerializer() throws IOException { + ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); + XmlSerializer serializer = new KXmlSerializer(); + serializer.setOutput(bytesOut, "UTF-8"); + serializer.startDocument("UTF-8", null); + return serializer; + } + + public void testInvalidCharactersInText() throws IOException { + XmlSerializer serializer = newSerializer(); + serializer.startTag(NAMESPACE, "root"); + for (int ch = 0; ch <= 0xffff; ++ch) { + final String s = Character.toString((char) ch); + if (isValidXmlCodePoint(ch)) { + serializer.text("a" + s + "b"); + } else { + try { + serializer.text("a" + s + "b"); + fail(s); + } catch (IllegalArgumentException expected) { + } + } + } + serializer.endTag(NAMESPACE, "root"); + } + + public void testInvalidCharactersInAttributeValues() throws IOException { + XmlSerializer serializer = newSerializer(); + serializer.startTag(NAMESPACE, "root"); + for (int ch = 0; ch <= 0xffff; ++ch) { + final String s = Character.toString((char) ch); + if (isValidXmlCodePoint(ch)) { + serializer.attribute(NAMESPACE, "a", "a" + s + "b"); + } else { + try { + serializer.attribute(NAMESPACE, "a", "a" + s + "b"); + fail(s); + } catch (IllegalArgumentException expected) { + } + } + } + serializer.endTag(NAMESPACE, "root"); + } + + public void testInvalidCharactersInCdataSections() throws IOException { + XmlSerializer serializer = newSerializer(); + serializer.startTag(NAMESPACE, "root"); + for (int ch = 0; ch <= 0xffff; ++ch) { + final String s = Character.toString((char) ch); + if (isValidXmlCodePoint(ch)) { + serializer.cdsect("a" + s + "b"); + } else { + try { + serializer.cdsect("a" + s + "b"); + fail(s); + } catch (IllegalArgumentException expected) { + } + } + } + serializer.endTag(NAMESPACE, "root"); + } + + public void testCdataWithTerminatorInside() throws Exception { + StringWriter writer = new StringWriter(); + XmlSerializer serializer = new KXmlSerializer(); + serializer.setOutput(writer); + serializer.startDocument("UTF-8", null); + serializer.startTag(NAMESPACE, "p"); + serializer.cdsect("a]]>b"); + serializer.endTag(NAMESPACE, "p"); + serializer.endDocument(); + // Adjacent CDATA sections aren't merged, so let's stick them together ourselves... + Document doc = domOf(writer.toString()); + NodeList children = doc.getFirstChild().getChildNodes(); + String text = ""; + for (int i = 0; i < children.getLength(); ++i) { + text += children.item(i).getNodeValue(); + } + assertEquals("a]]>b", text); + } + + private static boolean isValidXmlCodePoint(int c) { + // http://www.w3.org/TR/REC-xml/#charsets + return (c >= 0x20 && c <= 0xd7ff) || (c == 0x9) || (c == 0xa) || (c == 0xd) || + (c >= 0xe000 && c <= 0xfffd) || (c >= 0x10000 && c <= 0x10ffff); + } +} diff --git a/luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationTest.java b/luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationTest.java index 33ce8fb..8395c00 100644 --- a/luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationTest.java +++ b/luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationTest.java @@ -126,6 +126,17 @@ public class AnnotationTest extends TestCase { m2.getDeclaredAnnotations()[0].hashCode()); } + + public static void test35304() throws Exception { + Class c = AnnotationTest.class; + Class[] parameterTypes = new Class[] { String.class, String.class }; + Annotation[][] annotations = c.getDeclaredMethod("test35304_method", parameterTypes).getParameterAnnotations(); + assertEquals(2, annotations.length); // Two parameters. + assertEquals(0, annotations[0].length); // No annotations on the first. + assertEquals(1, annotations[1].length); // One annotation on the second. + } + + private static String test35304_method(String s1, @Deprecated String s2) { return null; } } class AnnotatedClass2 { diff --git a/luni/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipFileTest.java b/luni/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipFileTest.java index 17d251b..a423f22 100644 --- a/luni/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipFileTest.java +++ b/luni/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipFileTest.java @@ -32,6 +32,7 @@ import java.util.Enumeration; import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipFile; +import libcore.java.lang.ref.FinalizationTester; public class ZipFileTest extends junit.framework.TestCase { @@ -150,11 +151,8 @@ public class ZipFileTest extends junit.framework.TestCase { * entry1); entry1 = null; zip = null; */ - assertNotNull("Did not find entry", - test_finalize1(test_finalize2(file))); - System.gc(); - System.gc(); - System.runFinalization(); + assertNotNull("Did not find entry", test_finalize1(test_finalize2(file))); + FinalizationTester.induceFinalization(); file.delete(); assertTrue("Zip should not exist", !file.exists()); } diff --git a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/CipherTest.java b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/CipherTest.java index 7442210..c07b180 100644 --- a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/CipherTest.java +++ b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/CipherTest.java @@ -47,6 +47,7 @@ import javax.crypto.ShortBufferException; import javax.crypto.spec.DESedeKeySpec; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; +import libcore.java.security.StandardNames; import org.apache.harmony.crypto.tests.support.MyCipher; import tests.support.resource.Support_Resources; @@ -545,7 +546,10 @@ public class CipherTest extends junit.framework.TestCase { try { c.doFinal(b, 3, 6, b1, 5); fail(); - } catch (ShortBufferException expected) { + } catch (IllegalBlockSizeException maybeExpected) { + assertTrue(StandardNames.IS_RI); + } catch (ShortBufferException maybeExpected) { + assertFalse(StandardNames.IS_RI); } } diff --git a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/SealedObjectTest.java b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/SealedObjectTest.java index b3b2931..3ea57bf 100644 --- a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/SealedObjectTest.java +++ b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/SealedObjectTest.java @@ -33,6 +33,7 @@ import java.io.Serializable; import java.security.InvalidKeyException; import java.security.Key; import java.security.NoSuchProviderException; +import java.util.ArrayList; import java.util.Arrays; import javax.crypto.Cipher; @@ -43,6 +44,8 @@ import javax.crypto.SealedObject; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; +import libcore.util.SerializationTester; + /** */ public class SealedObjectTest extends TestCase { @@ -291,4 +294,23 @@ public class SealedObjectTest extends TestCase { } } + // http://code.google.com/p/android/issues/detail?id=4834 + public void testDeserialization() throws Exception { + // (Boilerplate so we can create SealedObject instances.) + KeyGenerator kg = KeyGenerator.getInstance("DES"); + Key key = kg.generateKey(); + Cipher cipher = Cipher.getInstance("DES"); + cipher.init(Cipher.ENCRYPT_MODE, key); + + // Incorrect use of readUnshared meant you couldn't have two SealedObjects + // with the same algorithm or parameters algorithm... + ArrayList<SealedObject> sealedObjects = new ArrayList<SealedObject>(); + for (int i = 0; i < 10; ++i) { + sealedObjects.add(new SealedObject("hello", cipher)); + } + String serializedForm = SerializationTester.serializeHex(sealedObjects); + + // ...so this would throw "java.io.InvalidObjectException: Unshared read of back reference". + SerializationTester.deserializeHex(serializedForm); + } } diff --git a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/CipherRSATest.java b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/CipherRSATest.java index d25d958..0e070f6 100644 --- a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/CipherRSATest.java +++ b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/CipherRSATest.java @@ -15,8 +15,6 @@ */ package org.apache.harmony.crypto.tests.javax.crypto.func; -import dalvik.annotation.AndroidOnly; - import junit.framework.TestCase; public class CipherRSATest extends TestCase { @@ -55,7 +53,6 @@ public class CipherRSATest extends TestCase { assertEquals(rsa.getFailureMessages(), 0, rsa.getTotalFailuresNumber()); } - @AndroidOnly("Fails on RI but succeeds on Android.") public void test_RSANoPadding() { CipherRSAThread rsa = new CipherRSAThread("RSA", new int[] {1024}, new String[] {"ECB"}, new String[] {"NOPADDING"}); diff --git a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/CipherRSAThread.java b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/CipherRSAThread.java index f7445b1..31e1075 100644 --- a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/CipherRSAThread.java +++ b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/CipherRSAThread.java @@ -45,6 +45,10 @@ public class CipherRSAThread extends CipherThread { cip.init(Cipher.DECRYPT_MODE, kp.getPrivate()); cip.doFinal(output, 0, outputSize, decrypted); - checkEncodedData(input, decrypted); + if ("NOPADDING".equals(getPadding())) { + checkPaddedEncodedData(input, decrypted, outputSize - input.length); + } else { + checkEncodedData(input, decrypted); + } } } diff --git a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/CipherThread.java b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/CipherThread.java index 4dac176..2fd388b 100644 --- a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/CipherThread.java +++ b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/func/CipherThread.java @@ -57,6 +57,20 @@ public abstract class CipherThread implements Runnable { } } + public void checkPaddedEncodedData(byte[] original, byte[] encoded, int offset) + throws Exception { + for (int i = 0; i < offset; i++) { + if (encoded[i] != 0) { + throw new Exception("Encoded data is not properly padded at offset " + i); + } + } + for (int i = 0; i < original.length; i++) { + if (original[i] != encoded[i + offset]) { + throw new Exception("Source and encoded data not match " + getCipherParameters()); + } + } + } + public void launcher() { Thread thread = null; diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java index 3ca11f7..07e3de5 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java @@ -19,7 +19,6 @@ package org.apache.harmony.luni.tests.java.net; import dalvik.annotation.BrokenTest; import junit.framework.TestCase; import tests.support.Support_Configuration; -import tests.support.Support_PortManager; import tests.support.Support_TestWebData; import tests.support.Support_TestWebServer; import tests.support.resource.Support_Resources; @@ -220,9 +219,8 @@ public class URLConnectionTest extends TestCase { public void setUp() throws Exception { super.setUp(); - port = Support_PortManager.getNextPort(); server = new Support_TestWebServer(); - server.initServer(port, false); + port = server.initServer(); url = new URL("http://localhost:" + port + "/test1"); uc = url.openConnection(); url2 = new URL("http://localhost:" + port + "/test2"); diff --git a/luni/src/test/java/org/apache/harmony/security/tests/java/security/KeyRepTest.java b/luni/src/test/java/org/apache/harmony/security/tests/java/security/KeyRepTest.java index 0dad827..a6529e8 100644 --- a/luni/src/test/java/org/apache/harmony/security/tests/java/security/KeyRepTest.java +++ b/luni/src/test/java/org/apache/harmony/security/tests/java/security/KeyRepTest.java @@ -26,199 +26,146 @@ import java.io.NotSerializableException; import java.io.ObjectStreamException; import java.security.KeyRep; import java.security.Security; -import java.util.Iterator; import java.util.Set; - import junit.framework.TestCase; -/** - * - * - */ public class KeyRepTest extends TestCase { - private static final Set<String> keyFactoryAlgorithm; + private static final Set<String> keyFactoryAlgorithms = Security.getAlgorithms("KeyFactory"); static { - keyFactoryAlgorithm = Security.getAlgorithms("KeyFactory"); + assertFalse(keyFactoryAlgorithms.isEmpty()); } public final void testKeyRep01() { - try { - assertNotNull(new KeyRep(KeyRep.Type.SECRET, "", "", new byte[] {})); - } catch (Exception e) { - fail("Unexpected exception " + e.getMessage()); - } - - try { - assertNotNull(new KeyRep(KeyRep.Type.PUBLIC, "", "", new byte[] {})); - } catch (Exception e) { - fail("Unexpected exception " + e.getMessage()); - } - - try { - assertNotNull(new KeyRep(KeyRep.Type.PRIVATE, "", "", new byte[] {})); - } catch (Exception e) { - fail("Unexpected exception " + e.getMessage()); - } + assertNotNull(new KeyRep(KeyRep.Type.SECRET, "", "", new byte[] {})); + assertNotNull(new KeyRep(KeyRep.Type.PUBLIC, "", "", new byte[] {})); + assertNotNull(new KeyRep(KeyRep.Type.PRIVATE, "", "", new byte[] {})); } public final void testKeyRep02() { try { new KeyRep(null, "", "", new byte[] {}); fail("NullPointerException has not been thrown (type)"); - } catch (NullPointerException ok) { - + } catch (NullPointerException expected) { } try { new KeyRep(KeyRep.Type.SECRET, null, "", new byte[] {}); fail("NullPointerException has not been thrown (alg)"); - } catch (NullPointerException ok) { - + } catch (NullPointerException expected) { } try { new KeyRep(KeyRep.Type.PRIVATE, "", null, new byte[] {}); fail("NullPointerException has not been thrown (format)"); - } catch (NullPointerException ok) { - + } catch (NullPointerException expected) { } try { new KeyRep(KeyRep.Type.PUBLIC, "", "", null); fail("NullPointerException has not been thrown (encoding)"); - } catch (NullPointerException ok) { - + } catch (NullPointerException expected) { } } - public final void testReadResolve01() throws ObjectStreamException { - KeyRepChild kr = new KeyRepChild(KeyRep.Type.SECRET, "", "", - new byte[] {}); + public final void testReadResolve01() throws Exception { + KeyRepChild kr = new KeyRepChild(KeyRep.Type.SECRET, "", "", new byte[] {}); try { kr.readResolve(); fail("NotSerializableException has not been thrown (no format)"); - } catch (NotSerializableException ok) { - + } catch (NotSerializableException expected) { } kr = new KeyRepChild(KeyRep.Type.SECRET, "", "X.509", new byte[] {}); try { kr.readResolve(); fail("NotSerializableException has not been thrown (unacceptable format)"); - } catch (NotSerializableException ok) { - + } catch (NotSerializableException expected) { } kr = new KeyRepChild(KeyRep.Type.SECRET, "", "RAW", new byte[] {}); try { kr.readResolve(); fail("NotSerializableException has not been thrown (empty key)"); - } catch (NotSerializableException ok) { - + } catch (NotSerializableException expected) { } } - public final void testReadResolve02() throws ObjectStreamException { - KeyRepChild kr = new KeyRepChild(KeyRep.Type.PUBLIC, "", "", - new byte[] {}); + public final void testReadResolve02() throws Exception { + KeyRepChild kr = new KeyRepChild(KeyRep.Type.PUBLIC, "", "", new byte[] {}); try { kr.readResolve(); fail("NotSerializableException has not been thrown (no format)"); - } catch (NotSerializableException ok) { - + } catch (NotSerializableException expected) { } kr = new KeyRepChild(KeyRep.Type.PUBLIC, "", "RAW", new byte[] {}); try { kr.readResolve(); fail("NotSerializableException has not been thrown (unacceptable format)"); - } catch (NotSerializableException ok) { - + } catch (NotSerializableException expected) { } - kr = new KeyRepChild(KeyRep.Type.PUBLIC, "bla-bla", "X.509", - new byte[] {}); + kr = new KeyRepChild(KeyRep.Type.PUBLIC, "bla-bla", "X.509", new byte[] {}); try { kr.readResolve(); fail("NotSerializableException has not been thrown (unknown KeyFactory algorithm)"); - } catch (NotSerializableException ok) { - + } catch (NotSerializableException expected) { } } - public final void testReadResolve03() throws ObjectStreamException { - KeyRepChild kr = new KeyRepChild(KeyRep.Type.PRIVATE, "", "", - new byte[] {}); + public final void testReadResolve03() throws Exception { + KeyRepChild kr = new KeyRepChild(KeyRep.Type.PRIVATE, "", "", new byte[] {}); try { kr.readResolve(); fail("NotSerializableException has not been thrown (no format)"); - } catch (NotSerializableException ok) { - + } catch (NotSerializableException expected) { } kr = new KeyRepChild(KeyRep.Type.PRIVATE, "", "RAW", new byte[] {}); try { kr.readResolve(); fail("NotSerializableException has not been thrown (unacceptable format)"); - } catch (NotSerializableException ok) { - + } catch (NotSerializableException expected) { } - kr = new KeyRepChild(KeyRep.Type.PRIVATE, "bla-bla", "PKCS#8", - new byte[] {}); + kr = new KeyRepChild(KeyRep.Type.PRIVATE, "bla-bla", "PKCS#8", new byte[] {}); try { kr.readResolve(); fail("NotSerializableException has not been thrown (unknown KeyFactory algorithm)"); - } catch (NotSerializableException ok) { - + } catch (NotSerializableException expected) { } } - public final void testReadResolve04() throws ObjectStreamException { - if (keyFactoryAlgorithm.isEmpty()) { - System.err.println(getName() - + ": skipped - no KeyFactory algorithms available"); - return; - } else { - } - for (Iterator<String> i = keyFactoryAlgorithm.iterator(); i.hasNext();) { - KeyRepChild kr = new KeyRepChild(KeyRep.Type.PUBLIC, i.next(), - "X.509", new byte[] { 1, 2, 3 }); + public final void testReadResolve04() throws Exception { + for (String algorithm : keyFactoryAlgorithms) { + KeyRepChild kr = new KeyRepChild(KeyRep.Type.PUBLIC, algorithm, "X.509", + new byte[] { 1, 2, 3 }); try { kr.readResolve(); - fail("NotSerializableException has not been thrown (no format)"); - } catch (NotSerializableException ok) { - + fail("NotSerializableException has not been thrown (no format) " + algorithm); + } catch (NotSerializableException expected) { } } } - public final void testReadResolve05() throws ObjectStreamException { - if (keyFactoryAlgorithm.isEmpty()) { - System.err.println(getName() - + ": skipped - no KeyFactory algorithms available"); - return; - } else { - } - for (Iterator<String> i = keyFactoryAlgorithm.iterator(); i.hasNext();) { - KeyRepChild kr = new KeyRepChild(KeyRep.Type.PRIVATE, i.next(), - "PKCS#8", new byte[] { 1, 2, 3 }); + public final void testReadResolve05() throws Exception { + for (String algorithm : keyFactoryAlgorithms) { + KeyRepChild kr = new KeyRepChild(KeyRep.Type.PRIVATE, algorithm, "PKCS#8", + new byte[] { 1, 2, 3 }); try { kr.readResolve(); - fail("NotSerializableException has not been thrown (no format)"); - } catch (NotSerializableException ok) { - + fail("NotSerializableException has not been thrown (no format) " + algorithm); + } catch (NotSerializableException expected) { } } } class KeyRepChild extends KeyRep { - public KeyRepChild(KeyRep.Type type, String algorithm, String format, - byte[] encoded) { + public KeyRepChild(KeyRep.Type type, String algorithm, String format, byte[] encoded) { super(type, algorithm, format, encoded); } - public Object readResolve() throws ObjectStreamException { + // Overriden to make public for testing + @Override public Object readResolve() throws ObjectStreamException { return super.readResolve(); } - } } diff --git a/luni/src/test/java/org/apache/harmony/security/tests/java/security/KeyStore2Test.java b/luni/src/test/java/org/apache/harmony/security/tests/java/security/KeyStore2Test.java index fd27edc..d303903 100644 --- a/luni/src/test/java/org/apache/harmony/security/tests/java/security/KeyStore2Test.java +++ b/luni/src/test/java/org/apache/harmony/security/tests/java/security/KeyStore2Test.java @@ -49,6 +49,7 @@ import java.util.Calendar; import java.util.Enumeration; import java.util.HashSet; import java.util.Set; +import libcore.java.security.StandardNames; import tests.support.Support_TestProvider; public class KeyStore2Test extends junit.framework.TestCase { @@ -817,8 +818,9 @@ public class KeyStore2Test extends junit.framework.TestCase { try { keyTest.setEntry("alias", pke, null); - fail(); - } catch (Exception expected) { + assertFalse(StandardNames.IS_RI); // BKS KeyStore does not require a password + } catch (KeyStoreException e) { + assertTrue(StandardNames.IS_RI); // JKS KeyStore requires a password } keyTest.setEntry("alias", pke, pp); diff --git a/luni/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreLoadStoreParameterTest.java b/luni/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreLoadStoreParameterTest.java deleted file mode 100644 index 81ec30d..0000000 --- a/luni/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreLoadStoreParameterTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.apache.harmony.security.tests.java.security; - -import java.security.KeyStore; - -public class KeyStoreLoadStoreParameterTest { - - class MyLoadStoreParameter implements KeyStore.LoadStoreParameter { - public KeyStore.ProtectionParameter getProtectionParameter() { - return null; - } - } - - - -} diff --git a/luni/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreSpiTest.java b/luni/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreSpiTest.java index 4fdddbb..a85459b 100644 --- a/luni/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreSpiTest.java +++ b/luni/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreSpiTest.java @@ -15,21 +15,15 @@ * limitations under the License. */ -/** - * @author Vera Y. Petrashkova - * @version $Revision$ - */ - package org.apache.harmony.security.tests.java.security; -import junit.framework.TestCase; - -import org.apache.harmony.security.tests.support.MyKeyStoreSpi; -import org.apache.harmony.security.tests.support.MyLoadStoreParams; - import java.io.IOException; import java.io.InputStream; import java.security.InvalidKeyException; +import java.security.Key; +import java.security.KeyStore.LoadStoreParameter; +import java.security.KeyStore.Entry; +import java.security.KeyStore.ProtectionParameter; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.KeyStoreSpi; @@ -39,16 +33,15 @@ import java.security.PublicKey; import java.security.SignatureException; import java.security.UnrecoverableEntryException; import java.security.UnrecoverableKeyException; -import java.security.KeyStore.LoadStoreParameter; import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.util.Date; +import javax.crypto.SecretKey; +import junit.framework.TestCase; +import org.apache.harmony.security.tests.support.MyKeyStoreSpi; +import org.apache.harmony.security.tests.support.MyLoadStoreParams; -/** - * Tests for <code>KeyStoreSpi</code> constructor and methods - * - */ public class KeyStoreSpiTest extends TestCase { @SuppressWarnings("cast") @@ -86,62 +79,73 @@ public class KeyStoreSpiTest extends TestCase { try { assertFalse(ksSpi.engineEntryInstanceOf(null, KeyStore.TrustedCertificateEntry.class)); - } catch (NullPointerException e) { - // ok + } catch (NullPointerException expected) { } try { assertFalse(ksSpi.engineEntryInstanceOf( "test_engineEntryInstanceOf_Alias1", null)); - } catch (NullPointerException e) { - // ok + } catch (NullPointerException expected) { } } - public void testKeyStoteSpi01() throws IOException, + public void testKeyStoreSpi01() throws IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableEntryException, KeyStoreException { - KeyStoreSpi ksSpi = new MyKeyStoreSpi(); + final boolean[] keyEntryWasSet = new boolean[1]; + KeyStoreSpi ksSpi = new MyKeyStoreSpi() { + @Override public void engineSetKeyEntry(String alias, Key key, char[] password, + Certificate[] chain) throws KeyStoreException { keyEntryWasSet[0] = true; } + }; + + BadKeyStoreEntry badEntry = new BadKeyStoreEntry(); + BadKeyStoreProtectionParameter badParameter = new BadKeyStoreProtectionParameter(); - tmpEntry entry = new tmpEntry(); - tmpProtection pPar = new tmpProtection(); + KeyStore.SecretKeyEntry dummyEntry = new KeyStore.SecretKeyEntry(new SecretKey() { + @Override public String getAlgorithm() { return null; } + @Override public String getFormat() { return null; } + @Override public byte[] getEncoded() { return null; } + }); try { ksSpi.engineStore(null); - } catch (UnsupportedOperationException e) { + } catch (UnsupportedOperationException expected) { } assertNull("Not null entry", ksSpi.engineGetEntry("aaa", null)); - assertNull("Not null entry", ksSpi.engineGetEntry(null, pPar)); - assertNull("Not null entry", ksSpi.engineGetEntry("aaa", pPar)); + assertNull("Not null entry", ksSpi.engineGetEntry(null, badParameter)); + assertNull("Not null entry", ksSpi.engineGetEntry("aaa", badParameter)); try { ksSpi.engineSetEntry("", null, null); fail("KeyStoreException or NullPointerException must be thrown"); - } catch (KeyStoreException e) { - } catch (NullPointerException e) { + } catch (KeyStoreException expected) { + } catch (NullPointerException expected) { } try { ksSpi.engineSetEntry("", new KeyStore.TrustedCertificateEntry( new MyCertificate("type", new byte[0])), null); fail("KeyStoreException must be thrown"); - } catch (KeyStoreException e) { + } catch (KeyStoreException expected) { } try { - ksSpi.engineSetEntry("aaa", entry, null); + ksSpi.engineSetEntry("aaa", badEntry, null); fail("KeyStoreException must be thrown"); - } catch (KeyStoreException e) { + } catch (KeyStoreException expected) { } + + ksSpi.engineSetEntry("aaa", dummyEntry, null); + assertTrue(keyEntryWasSet[0]); } /** * Test for <code>KeyStoreSpi()</code> constructor and abstract engine * methods. Assertion: creates new KeyStoreSpi object. */ - public void testKeyStoteSpi02() throws NoSuchAlgorithmException, + public void testKeyStoreSpi02() throws NoSuchAlgorithmException, UnrecoverableKeyException, CertificateException { KeyStoreSpi ksSpi = new MyKeyStoreSpi(); assertNull("engineGetKey(..) must return null", ksSpi.engineGetKey("", @@ -155,23 +159,23 @@ public class KeyStoreSpiTest extends TestCase { try { ksSpi.engineSetKeyEntry("", null, new char[0], new Certificate[0]); fail("KeyStoreException must be thrown from engineSetKeyEntry(..)"); - } catch (KeyStoreException e) { + } catch (KeyStoreException expected) { } try { ksSpi.engineSetKeyEntry("", new byte[0], new Certificate[0]); fail("KeyStoreException must be thrown from engineSetKeyEntry(..)"); - } catch (KeyStoreException e) { + } catch (KeyStoreException expected) { } try { ksSpi.engineSetCertificateEntry("", null); fail("KeyStoreException must be thrown " + "from engineSetCertificateEntry(..)"); - } catch (KeyStoreException e) { + } catch (KeyStoreException expected) { } try { ksSpi.engineDeleteEntry(""); fail("KeyStoreException must be thrown from engineDeleteEntry(..)"); - } catch (KeyStoreException e) { + } catch (KeyStoreException expected) { } assertNull("engineAliases() must return null", ksSpi.engineAliases()); assertFalse("engineContainsAlias(..) must return false", ksSpi @@ -180,7 +184,7 @@ public class KeyStoreSpiTest extends TestCase { try { ksSpi.engineStore(null, null); fail("IOException must be thrown"); - } catch (IOException e) { + } catch (IOException expected) { } } @@ -202,35 +206,30 @@ public class KeyStoreSpiTest extends TestCase { try { ksSpi.engineLoad(null); fail("Should throw exception"); - } catch (RuntimeException e) { - assertSame(msg, e.getMessage()); + } catch (RuntimeException expected) { + assertSame(msg, expected.getMessage()); } // test: protection parameter is null try { ksSpi.engineLoad(new MyLoadStoreParams(null)); fail("No expected UnsupportedOperationException"); - } catch (UnsupportedOperationException e) { + } catch (UnsupportedOperationException expected) { } // test: protection parameter is not instanceof // PasswordProtection or CallbackHandlerProtection try { - ksSpi.engineLoad(new MyLoadStoreParams(new tmpProtection())); + ksSpi.engineLoad(new MyLoadStoreParams(new BadKeyStoreProtectionParameter())); fail("No expected UnsupportedOperationException"); - } catch (UnsupportedOperationException e) { + } catch (UnsupportedOperationException expected) { } } } -/** - * Additional class implements KeyStore.Entry interface - */ -class tmpEntry implements KeyStore.Entry { -} - -class tmpProtection implements KeyStore.ProtectionParameter { -} +// These are "Bad" because they are not expected inner subclasses of the KeyStore class. +class BadKeyStoreEntry implements Entry {} +class BadKeyStoreProtectionParameter implements ProtectionParameter {} @SuppressWarnings("unused") class MyCertificate extends Certificate { diff --git a/luni/src/test/java/org/apache/harmony/security/tests/java/security/SecureRandom2Test.java b/luni/src/test/java/org/apache/harmony/security/tests/java/security/SecureRandom2Test.java index cf030c7..aa0ec67 100644 --- a/luni/src/test/java/org/apache/harmony/security/tests/java/security/SecureRandom2Test.java +++ b/luni/src/test/java/org/apache/harmony/security/tests/java/security/SecureRandom2Test.java @@ -301,40 +301,15 @@ public class SecureRandom2Test extends TestCase { * as it tends to be error prone and open up security holes. * See {@link SecureRandom} for more details about insecure seeding. * - * @see #testSameSeedGeneratesSameResultsWhenConstructorIsUsed() + * Note that this only works with the Harmony "Crypto" provider. */ public void testSameSeedGeneratesSameResults() throws Exception { byte[] seed1 = { 'a', 'b', 'c' }; - SecureRandom sr1 = SecureRandom.getInstance("SHA1PRNG"); + SecureRandom sr1 = SecureRandom.getInstance("SHA1PRNG", "Crypto"); sr1.setSeed(seed1); byte[] seed2 = { 'a', 'b', 'c' }; - SecureRandom sr2 = SecureRandom.getInstance("SHA1PRNG"); - sr2.setSeed(seed2); - - assertTrue(sr1.nextLong() == sr2.nextLong()); - } - - /** - * Same tests as {@link #testSameSeedGeneratesSameResults()}, except - * here we use the constructor, not {@link SecureRandom#getInstance(String)}. - * - * Note that Android behaves differently than the reference implementation. - * This test fails on the reference implementation. - * - * In the future, it may make sense to change our implementation to - * match the reference implementation. It may also make sense to - * disallow seeding {@code SecureRandom} completely, as it tends to - * be error prone and open up security holes. See {@link SecureRandom} - * for more details about insecure seeding. - */ - public void testSameSeedGeneratesSameResultsWhenConstructorIsUsed() { - byte[] seed1 = { 'a', 'b', 'c' }; - SecureRandom sr1 = new SecureRandom(); - sr1.setSeed(seed1); - - byte[] seed2 = { 'a', 'b', 'c' }; - SecureRandom sr2 = new SecureRandom(); + SecureRandom sr2 = SecureRandom.getInstance("SHA1PRNG", "Crypto"); sr2.setSeed(seed2); assertTrue(sr1.nextLong() == sr2.nextLong()); @@ -348,10 +323,12 @@ public class SecureRandom2Test extends TestCase { * SHA1PRNG, so users of {@code SecureRandom} should not assume * the same seed will always produce the same value. This test * is not a guarantee of future compatibility. + * + * In fact, this test only works with the Harmony "Crypto" provider. */ public void testAlwaysSameValueWithSameSeed() throws Exception { byte[] seed1 = { 'a', 'b', 'c' }; - SecureRandom sr1 = SecureRandom.getInstance("SHA1PRNG"); + SecureRandom sr1 = SecureRandom.getInstance("SHA1PRNG", "Crypto"); sr1.setSeed(seed1); // This long value has no special meaning and may change in the future. diff --git a/luni/src/test/java/org/apache/harmony/security/tests/java/security/Security2Test.java b/luni/src/test/java/org/apache/harmony/security/tests/java/security/Security2Test.java index d9f4dd7..68e7cbc 100644 --- a/luni/src/test/java/org/apache/harmony/security/tests/java/security/Security2Test.java +++ b/luni/src/test/java/org/apache/harmony/security/tests/java/security/Security2Test.java @@ -20,14 +20,14 @@ package org.apache.harmony.security.tests.java.security; import java.security.InvalidParameterException; import java.security.Provider; import java.security.Security; -import java.util.Hashtable; -import java.util.Iterator; +import java.util.HashMap; import java.util.Map; import java.util.Set; +import junit.framework.TestCase; import tests.support.Support_ProviderTrust; import tests.support.Support_TestProvider; -public class Security2Test extends junit.framework.TestCase { +public class Security2Test extends TestCase { /** * java.security.Security#getProviders(java.lang.String) @@ -36,16 +36,13 @@ public class Security2Test extends junit.framework.TestCase { // Test for method void // java.security.Security.getProviders(java.lang.String) - Hashtable<String, Integer> allSupported = new Hashtable<String, Integer>(); + Map<String, Integer> allSupported = new HashMap<String, Integer>(); Provider[] allProviders = Security.getProviders(); // Add all non-alias entries to allSupported - for (int i = 0; i < allProviders.length; i++) { - Provider provider = allProviders[i]; - Iterator it = provider.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = (Map.Entry) it.next(); - String key = (String) entry.getKey(); + for (Provider provider : allProviders) { + for (Object k : provider.keySet()) { + String key = (String) k; // No aliases and no provider data if (!isAlias(key) && !isProviderData(key)) { addOrIncrementTable(allSupported, key); @@ -56,22 +53,18 @@ public class Security2Test extends junit.framework.TestCase { // Now walk through aliases. If an alias has actually been added // to the allSupported table then increment the count of the // entry that is being aliased. - for (int i = 0; i < allProviders.length; i++) { - Provider provider = allProviders[i]; - Iterator it = provider.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = (Map.Entry) it.next(); + for (Provider provider : allProviders) { + for (Map.Entry entry : provider.entrySet()) { String key = (String) entry.getKey(); if (isAlias(key)) { String aliasVal = key.substring("ALG.ALIAS.".length()); - String aliasKey = aliasVal.substring(0, aliasVal - .indexOf(".") + 1) + String aliasKey = aliasVal.substring(0, aliasVal.indexOf(".") + 1) + entry.getValue(); // Skip over nonsense alias declarations where alias and // aliased are identical. Such entries can occur. - if (!aliasVal.equals(aliasKey)) { + if (!aliasVal.equalsIgnoreCase(aliasKey)) { // Has a real entry been added for aliasValue ? - if (allSupported.containsKey(aliasVal)) { + if (allSupported.containsKey(aliasVal.toUpperCase())) { // Add 1 to the provider count of the thing being // aliased addOrIncrementTable(allSupported, aliasKey); @@ -81,17 +74,13 @@ public class Security2Test extends junit.framework.TestCase { }// end while more entries }// end for all providers - Provider provTest[] = null; - Iterator it = allSupported.keySet().iterator(); - while (it.hasNext()) { - String filterString = (String) it.next(); + for (String filterString : allSupported.keySet()) { try { - provTest = Security.getProviders(filterString); - int expected = ((Integer) allSupported.get(filterString)) - .intValue(); - assertEquals( - "Unexpected number of providers returned for filter " - + filterString, expected, provTest.length); + Provider[] provTest = Security.getProviders(filterString); + int expected = allSupported.get(filterString); + assertEquals("Unexpected number of providers returned for filter " + filterString + + ":\n" + allSupported, + expected, provTest.length); } catch (InvalidParameterException e) { // NO OP } @@ -99,62 +88,43 @@ public class Security2Test extends junit.framework.TestCase { // exception try { - provTest = Security.getProviders("Signature.SHA1withDSA :512"); + Security.getProviders("Signature.SHA1withDSA :512"); fail("InvalidParameterException should be thrown <Signature.SHA1withDSA :512>"); } catch (InvalidParameterException e) { // Expected } } - /** - * @param key - * @return - */ private boolean isProviderData(String key) { return key.toUpperCase().startsWith("PROVIDER."); } - /** - * @param key - * @return - */ private boolean isAlias(String key) { return key.toUpperCase().startsWith("ALG.ALIAS."); } - /** - * @param table - * @param key - */ - private void addOrIncrementTable(Hashtable<String, Integer> table, String key) { + private void addOrIncrementTable(Map<String, Integer> table, String k) { + String key = k.toUpperCase(); if (table.containsKey(key)) { - Integer before = (Integer) table.get(key); - table.put(key, new Integer(before.intValue() + 1)); + int before = table.get(key); + table.put(key, before + 1); } else { - table.put(key, new Integer(1)); + table.put(key, 1); } } - /** - * @param filterMap - * @return - */ private int getProvidersCount(Map filterMap) { int result = 0; Provider[] allProviders = Security.getProviders(); // for each provider - for (int i = 0; i < allProviders.length; i++) { - Provider provider = allProviders[i]; + for (Provider provider : allProviders) { Set allProviderKeys = provider.keySet(); boolean noMatchFoundForFilterEntry = false; // for each filter item - Set allFilterKeys = filterMap.keySet(); - Iterator fkIter = allFilterKeys.iterator(); - while (fkIter.hasNext()) { - String filterString = ((String) fkIter.next()).trim(); - + for (Object filter : filterMap.keySet()) { + String filterString = (String) filter; // Remove any "=" characters that may be on the end of the // map keys (no, I don't know why they might be there either // but I have seen them) @@ -211,10 +181,10 @@ public class Security2Test extends junit.framework.TestCase { // Test for method void // java.security.Security.getProviders(java.util.Map) - Map<String, String> filter = new Hashtable<String, String>(); + Map<String, String> filter = new HashMap<String, String>(); filter.put("KeyStore.BKS", ""); filter.put("Signature.SHA1withDSA", ""); - Provider provTest[] = Security.getProviders(filter); + Provider[] provTest = Security.getProviders(filter); if (provTest == null) { assertEquals("Filter : <KeyStore.BKS>,<Signature.SHA1withDSA>", 0, getProvidersCount(filter)); @@ -223,7 +193,7 @@ public class Security2Test extends junit.framework.TestCase { getProvidersCount(filter), provTest.length); } - filter = new Hashtable<String, String>(); + filter = new HashMap<String, String>(); filter.put("MessageDigest.SHA-384", ""); filter.put("CertificateFactory.X.509", ""); filter.put("KeyFactory.RSA", ""); @@ -237,7 +207,7 @@ public class Security2Test extends junit.framework.TestCase { getProvidersCount(filter), provTest.length); } - filter = new Hashtable<String, String>(); + filter = new HashMap<String, String>(); filter.put("MessageDigest.SHA1", ""); filter.put("TrustManagerFactory.X509", ""); provTest = Security.getProviders(filter); @@ -250,7 +220,7 @@ public class Security2Test extends junit.framework.TestCase { getProvidersCount(filter), provTest.length); } - filter = new Hashtable<String, String>(); + filter = new HashMap<String, String>(); filter.put("CertificateFactory.X509", ""); provTest = Security.getProviders(filter); if (provTest == null) { @@ -261,7 +231,7 @@ public class Security2Test extends junit.framework.TestCase { getProvidersCount(filter), provTest.length); } - filter = new Hashtable<String, String>(); + filter = new HashMap<String, String>(); filter.put("Provider.id name", "DRLCertFactory"); provTest = Security.getProviders(filter); assertNull("Filter : <Provider.id name, DRLCertFactory >", @@ -270,7 +240,7 @@ public class Security2Test extends junit.framework.TestCase { // exception - no attribute name after the service.algorithm yet we // still supply an expected value. This is not valid. try { - filter = new Hashtable<String, String>(); + filter = new HashMap<String, String>(); filter.put("Signature.SHA1withDSA", "512"); provTest = Security.getProviders(filter); fail("InvalidParameterException should be thrown <Signature.SHA1withDSA><512>"); @@ -280,7 +250,7 @@ public class Security2Test extends junit.framework.TestCase { // exception - space character in the service.algorithm pair. Not valid. try { - filter = new Hashtable<String, String>(); + filter = new HashMap<String, String>(); filter.put("Signature. KeySize", "512"); provTest = Security.getProviders(filter); fail("InvalidParameterException should be thrown <Signature. KeySize><512>"); @@ -320,11 +290,9 @@ public class Security2Test extends junit.framework.TestCase { assertTrue("Failed to add provider", addResult != -1); Security.removeProvider(entrust.getName()); - Provider provTest[] = Security.getProviders(); - for (int i = 0; i < provTest.length; i++) { - assertTrue( - "the provider entrust is found after it was removed", - provTest[i].getName() != entrust.getName()); + for (Provider provider : Security.getProviders()) { + assertTrue("the provider entrust is found after it was removed", + provider.getName() != entrust.getName()); } } finally { // Tidy up - the following calls do nothing if the providers were diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/CertPinManagerTest.java b/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/CertPinManagerTest.java new file mode 100644 index 0000000..8359c99 --- /dev/null +++ b/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/CertPinManagerTest.java @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xnet.provider.jsse; + +import java.io.File; +import java.io.FileWriter; +import java.security.cert.X509Certificate; +import java.security.KeyStore; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.List; +import junit.framework.TestCase; +import libcore.java.security.TestKeyStore; + +public class CertPinManagerTest extends TestCase { + + private X509Certificate[] chain; + private List<X509Certificate> shortChain; + private List<X509Certificate> longChain; + private String shortPin; + private String longPin; + private List<File> tmpFiles = new ArrayList<File>(); + + private String writeTmpPinFile(String text) throws Exception { + File tmp = File.createTempFile("pins", null); + FileWriter fstream = new FileWriter(tmp); + fstream.write(text); + fstream.close(); + tmpFiles.add(tmp); + return tmp.getPath(); + } + + private static String getFingerprint(X509Certificate cert) throws NoSuchAlgorithmException { + MessageDigest dgst = MessageDigest.getInstance("SHA512"); + byte[] encoded = cert.getPublicKey().getEncoded(); + byte[] fingerprint = dgst.digest(encoded); + return IntegralToString.bytesToHexString(fingerprint, false); + } + + @Override + public void setUp() throws Exception { + super.setUp(); + // build some valid chains + KeyStore.PrivateKeyEntry pke = TestKeyStore.getServer().getPrivateKey("RSA", "RSA"); + chain = (X509Certificate[]) pke.getCertificateChain(); + X509Certificate root = chain[2]; + X509Certificate server = chain[0]; + + // build the short and long chains + shortChain = new ArrayList<X509Certificate>(); + shortChain.add(root); + longChain = new ArrayList<X509Certificate>(); + longChain.add(server); + + // we'll use the root as the pin for the short entry and the server as the pin for the long + shortPin = getFingerprint(root); + longPin = getFingerprint(server); + } + + @Override + public void tearDown() throws Exception { + try { + for (File f : tmpFiles) { + f.delete(); + } + tmpFiles.clear(); + } finally { + super.tearDown(); + } + } + + public void testPinFileMaximumLookup() throws Exception { + + // write a pinfile with two entries, one longer than the other + String shortEntry = "*.google.com=true|" + shortPin; + String longEntry = "*.clients.google.com=true|" + longPin; + + // create the pinFile + String path = writeTmpPinFile(shortEntry + "\n" + longEntry); + CertPinManager pf = new CertPinManager(path, new TrustedCertificateStore()); + + // verify that the shorter chain doesn't work for a name matching the longer + assertTrue("short chain long uri failed", + pf.chainIsNotPinned("android.clients.google.com", shortChain)); + // verify that the longer chain doesn't work for a name matching the shorter + assertTrue("long chain short uri failed", + pf.chainIsNotPinned("android.google.com", longChain)); + // verify that the shorter chain works for the shorter domain + assertTrue("short chain short uri failed", + !pf.chainIsNotPinned("android.google.com", shortChain)); + // and the same for the longer + assertTrue("long chain long uri failed", + !pf.chainIsNotPinned("android.clients.google.com", longChain)); + } + + public void testPinEntryMalformedEntry() throws Exception { + // set up the pinEntry with a bogus entry + String entry = "*.google.com="; + try { + new PinListEntry(entry, new TrustedCertificateStore()); + fail("Accepted an empty pin list entry."); + } catch (PinEntryException expected) { + } + } + + public void testPinEntryNull() throws Exception { + // set up the pinEntry with a bogus entry + String entry = null; + try { + new PinListEntry(entry, new TrustedCertificateStore()); + fail("Accepted a basically wholly bogus entry."); + } catch (NullPointerException expected) { + } + } + + public void testPinEntryEmpty() throws Exception { + // set up the pinEntry with a bogus entry + try { + new PinListEntry("", new TrustedCertificateStore()); + fail("Accepted an empty entry."); + } catch (PinEntryException expected) { + } + } + + public void testPinEntryPinFailure() throws Exception { + // write a pinfile with two entries, one longer than the other + String shortEntry = "*.google.com=true|" + shortPin; + + // set up the pinEntry with a pinlist that doesn't match what we'll give it + PinListEntry e = new PinListEntry(shortEntry, new TrustedCertificateStore()); + assertTrue("Not enforcing!", e.getEnforcing()); + // verify that it doesn't accept + boolean retval = e.chainIsNotPinned(longChain); + assertTrue("Accepted an incorrect pinning, this is very bad", retval); + } + + public void testPinEntryPinSuccess() throws Exception { + // write a pinfile with two entries, one longer than the other + String shortEntry = "*.google.com=true|" + shortPin; + + // set up the pinEntry with a pinlist that matches what we'll give it + PinListEntry e = new PinListEntry(shortEntry, new TrustedCertificateStore()); + assertTrue("Not enforcing!", e.getEnforcing()); + // verify that it accepts + boolean retval = e.chainIsNotPinned(shortChain); + assertTrue("Failed on a correct pinning, this is very bad", !retval); + } + + public void testPinEntryNonEnforcing() throws Exception { + // write a pinfile with two entries, one longer than the other + String shortEntry = "*.google.com=false|" + shortPin; + + // set up the pinEntry with a pinlist that matches what we'll give it + PinListEntry e = new PinListEntry(shortEntry, new TrustedCertificateStore()); + assertFalse("Enforcing!", e.getEnforcing()); + // verify that it accepts + boolean retval = e.chainIsNotPinned(shortChain); + assertTrue("Failed on an unenforced pinning, this is bad-ish", !retval); + } +} diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java b/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java index c8df4ab..303c234 100644 --- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java +++ b/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java @@ -21,10 +21,14 @@ import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketTimeoutException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; import java.security.KeyStore; import java.security.KeyStore.PrivateKeyEntry; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPrivateCrtKey; +import java.security.interfaces.RSAPrivateKey; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -38,6 +42,7 @@ import javax.net.ssl.SSLException; import javax.net.ssl.SSLProtocolException; import javax.security.auth.x500.X500Principal; import junit.framework.TestCase; +import libcore.io.IoUtils; import libcore.java.security.StandardNames; import libcore.java.security.TestKeyStore; import org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSLHandshakeCallbacks; @@ -47,7 +52,8 @@ public class NativeCryptoTest extends TestCase { private static final int NULL = 0; private static final FileDescriptor INVALID_FD = new FileDescriptor(); - private static final SSLHandshakeCallbacks DUMMY_CB = new TestSSLHandshakeCallbacks(-1, null); + private static final SSLHandshakeCallbacks DUMMY_CB + = new TestSSLHandshakeCallbacks(null, 0, null); private static final long TIMEOUT_SECONDS = 5; @@ -131,6 +137,87 @@ public class NativeCryptoTest extends TestCase { assertEquals(Arrays.deepToString(expected), Arrays.deepToString(actual)); } + public void test_EVP_PKEY_cmp() throws Exception { + try { + NativeCrypto.EVP_PKEY_cmp(NULL, NULL); + fail("Should throw NullPointerException when arguments are NULL"); + } catch (NullPointerException expected) { + } + + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); + kpg.initialize(512); + + KeyPair kp1 = kpg.generateKeyPair(); + RSAPrivateCrtKey privKey1 = (RSAPrivateCrtKey) kp1.getPrivate(); + + KeyPair kp2 = kpg.generateKeyPair(); + RSAPrivateCrtKey privKey2 = (RSAPrivateCrtKey) kp2.getPrivate(); + + int pkey1 = 0, pkey1_copy = 0, pkey2 = 0; + try { + pkey1 = NativeCrypto.EVP_PKEY_new_RSA(privKey1.getModulus().toByteArray(), + privKey1.getPublicExponent().toByteArray(), + privKey1.getPrivateExponent().toByteArray(), + privKey1.getPrimeP().toByteArray(), + privKey1.getPrimeQ().toByteArray(), + privKey1.getPrimeExponentP().toByteArray(), + privKey1.getPrimeExponentQ().toByteArray(), + privKey1.getCrtCoefficient().toByteArray()); + assertNotSame(NULL, pkey1); + + pkey1_copy = NativeCrypto.EVP_PKEY_new_RSA(privKey1.getModulus().toByteArray(), + privKey1.getPublicExponent().toByteArray(), + privKey1.getPrivateExponent().toByteArray(), + privKey1.getPrimeP().toByteArray(), + privKey1.getPrimeQ().toByteArray(), + privKey1.getPrimeExponentP().toByteArray(), + privKey1.getPrimeExponentQ().toByteArray(), + privKey1.getCrtCoefficient().toByteArray()); + assertNotSame(NULL, pkey1_copy); + + pkey2 = NativeCrypto.EVP_PKEY_new_RSA(privKey2.getModulus().toByteArray(), + privKey2.getPublicExponent().toByteArray(), + privKey2.getPrivateExponent().toByteArray(), + privKey2.getPrimeP().toByteArray(), + privKey2.getPrimeQ().toByteArray(), + privKey2.getPrimeExponentP().toByteArray(), + privKey2.getPrimeExponentQ().toByteArray(), + privKey2.getCrtCoefficient().toByteArray()); + assertNotSame(NULL, pkey2); + + try { + NativeCrypto.EVP_PKEY_cmp(pkey1, NULL); + fail("Should throw NullPointerException when arguments are NULL"); + } catch (NullPointerException expected) { + } + + try { + NativeCrypto.EVP_PKEY_cmp(NULL, pkey1); + fail("Should throw NullPointerException when arguments are NULL"); + } catch (NullPointerException expected) { + } + + assertEquals("Same keys should be the equal", 1, + NativeCrypto.EVP_PKEY_cmp(pkey1, pkey1)); + + assertEquals("Same keys should be the equal", 1, + NativeCrypto.EVP_PKEY_cmp(pkey1, pkey1_copy)); + + assertEquals("Different keys should not be equal", 0, + NativeCrypto.EVP_PKEY_cmp(pkey1, pkey2)); + } finally { + if (pkey1 != 0) { + NativeCrypto.EVP_PKEY_free(pkey1); + } + if (pkey1_copy != 0) { + NativeCrypto.EVP_PKEY_free(pkey1_copy); + } + if (pkey2 != 0) { + NativeCrypto.EVP_PKEY_free(pkey2); + } + } + } + public void test_SSL_CTX_new() throws Exception { int c = NativeCrypto.SSL_CTX_new(); assertTrue(c != NULL); @@ -490,11 +577,14 @@ public class NativeCryptoTest extends TestCase { } public static class TestSSLHandshakeCallbacks implements SSLHandshakeCallbacks { + private final Socket socket; private final int sslNativePointer; private final Hooks hooks; - public TestSSLHandshakeCallbacks(int sslNativePointer, + public TestSSLHandshakeCallbacks(Socket socket, + int sslNativePointer, Hooks hooks) { + this.socket = socket; this.sslNativePointer = sslNativePointer; this.hooks = hooks; } @@ -546,6 +636,10 @@ public class NativeCryptoTest extends TestCase { } this.handshakeCompletedCalled = true; } + + public Socket getSocket() { + return socket; + } } public static class ServerHooks extends Hooks { @@ -577,18 +671,19 @@ public class NativeCryptoTest extends TestCase { ExecutorService executor = Executors.newSingleThreadExecutor(); Future<TestSSLHandshakeCallbacks> future = executor.submit( new Callable<TestSSLHandshakeCallbacks>() { - public TestSSLHandshakeCallbacks call() throws Exception { + @Override public TestSSLHandshakeCallbacks call() throws Exception { Socket socket = (client ? new Socket(listener.getInetAddress(), listener.getLocalPort()) : listener.accept()); if (timeout == -1) { - return null; + return new TestSSLHandshakeCallbacks(socket, 0, null); } FileDescriptor fd = socket.getFileDescriptor$(); int c = hooks.getContext(); int s = hooks.beforeHandshake(c); - TestSSLHandshakeCallbacks callback = new TestSSLHandshakeCallbacks(s, hooks); + TestSSLHandshakeCallbacks callback + = new TestSSLHandshakeCallbacks(socket, s, hooks); if (DEBUG) { System.out.println("ssl=0x" + Integer.toString(s, 16) + " handshake" @@ -598,14 +693,19 @@ public class NativeCryptoTest extends TestCase { + " timeout=" + timeout + " client=" + client); } - int session = NativeCrypto.SSL_do_handshake(s, fd, callback, timeout, client, - npnProtocols); - if (DEBUG) { - System.out.println("ssl=0x" + Integer.toString(s, 16) - + " handshake" - + " session=0x" + Integer.toString(session, 16)); + int session = NULL; + try { + session = NativeCrypto.SSL_do_handshake(s, fd, callback, timeout, client, + npnProtocols); + if (DEBUG) { + System.out.println("ssl=0x" + Integer.toString(s, 16) + + " handshake" + + " session=0x" + Integer.toString(session, 16)); + } + } finally { + // Ensure afterHandshake is called to free resources + hooks.afterHandshake(session, s, c, socket, fd, callback); } - hooks.afterHandshake(session, s, c, socket, fd, callback); return callback; } }); @@ -777,17 +877,21 @@ public class NativeCryptoTest extends TestCase { Socket sock, FileDescriptor fd, SSLHandshakeCallbacks callback) throws Exception { - NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_PEER); - NativeCrypto.SSL_set_options( - s, NativeCrypto.SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); - NativeCrypto.SSL_renegotiate(s); - NativeCrypto.SSL_write(s, fd, callback, new byte[] { 42 }, 0, 1); - super.afterHandshake(session, s, c, sock, fd, callback); + try { + NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_PEER); + NativeCrypto.SSL_set_options( + s, NativeCrypto.SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); + NativeCrypto.SSL_renegotiate(s); + NativeCrypto.SSL_write(s, fd, callback, new byte[] { 42 }, 0, 1, + (int) ((TIMEOUT_SECONDS * 1000) / 2)); + } catch (IOException expected) { + } finally { + super.afterHandshake(session, s, c, sock, fd, callback); + } } }; Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null); Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null); - server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); try { client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); } catch (ExecutionException e) { @@ -795,35 +899,49 @@ public class NativeCryptoTest extends TestCase { throw e; } } + server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); } public void test_SSL_do_handshake_client_timeout() throws Exception { // client timeout final ServerSocket listener = new ServerSocket(0); + Socket serverSocket = null; try { Hooks cHooks = new Hooks(); Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()); Future<TestSSLHandshakeCallbacks> client = handshake(listener, 1, true, cHooks, null); Future<TestSSLHandshakeCallbacks> server = handshake(listener, -1, false, sHooks, null); + serverSocket = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS).getSocket(); client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); fail(); } catch (ExecutionException expected) { + if (SocketTimeoutException.class != expected.getCause().getClass()) { + expected.printStackTrace(); + } assertEquals(SocketTimeoutException.class, expected.getCause().getClass()); + } finally { + // Manually close peer socket when testing timeout + IoUtils.closeQuietly(serverSocket); } } public void test_SSL_do_handshake_server_timeout() throws Exception { // server timeout final ServerSocket listener = new ServerSocket(0); + Socket clientSocket = null; try { Hooks cHooks = new Hooks(); Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()); Future<TestSSLHandshakeCallbacks> client = handshake(listener, -1, true, cHooks, null); Future<TestSSLHandshakeCallbacks> server = handshake(listener, 1, false, sHooks, null); + clientSocket = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS).getSocket(); server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); fail(); } catch (ExecutionException expected) { assertEquals(SocketTimeoutException.class, expected.getCause().getClass()); + } finally { + // Manually close peer socket when testing timeout + IoUtils.closeQuietly(clientSocket); } } @@ -1150,7 +1268,7 @@ public class NativeCryptoTest extends TestCase { SSLHandshakeCallbacks callback) throws Exception { NativeCrypto.SSL_renegotiate(s); - NativeCrypto.SSL_write(s, fd, callback, new byte[] { 42 }, 0, 1); + NativeCrypto.SSL_write(s, fd, callback, new byte[] { 42 }, 0, 1, 0); super.afterHandshake(session, s, c, sock, fd, callback); } }; @@ -1317,7 +1435,7 @@ public class NativeCryptoTest extends TestCase { Socket sock, FileDescriptor fd, SSLHandshakeCallbacks callback) throws Exception { - NativeCrypto.SSL_write(s, fd, callback, BYTES, 0, BYTES.length); + NativeCrypto.SSL_write(s, fd, callback, BYTES, 0, BYTES.length, 0); super.afterHandshake(session, s, c, sock, fd, callback); } }; @@ -1360,7 +1478,7 @@ public class NativeCryptoTest extends TestCase { public void test_SSL_write() throws Exception { try { - NativeCrypto.SSL_write(NULL, null, null, null, 0, 0); + NativeCrypto.SSL_write(NULL, null, null, null, 0, 0, 0); fail(); } catch (NullPointerException expected) { } @@ -1370,7 +1488,7 @@ public class NativeCryptoTest extends TestCase { int c = NativeCrypto.SSL_CTX_new(); int s = NativeCrypto.SSL_new(c); try { - NativeCrypto.SSL_write(s, null, DUMMY_CB, null, 0, 1); + NativeCrypto.SSL_write(s, null, DUMMY_CB, null, 0, 1, 0); fail(); } catch (NullPointerException expected) { } @@ -1383,7 +1501,7 @@ public class NativeCryptoTest extends TestCase { int c = NativeCrypto.SSL_CTX_new(); int s = NativeCrypto.SSL_new(c); try { - NativeCrypto.SSL_write(s, INVALID_FD, null, null, 0, 1); + NativeCrypto.SSL_write(s, INVALID_FD, null, null, 0, 1, 0); fail(); } catch (NullPointerException expected) { } @@ -1396,7 +1514,7 @@ public class NativeCryptoTest extends TestCase { int c = NativeCrypto.SSL_CTX_new(); int s = NativeCrypto.SSL_new(c); try { - NativeCrypto.SSL_write(s, INVALID_FD, DUMMY_CB, null, 0, 1); + NativeCrypto.SSL_write(s, INVALID_FD, DUMMY_CB, null, 0, 1, 0); fail(); } catch (NullPointerException expected) { } @@ -1409,7 +1527,7 @@ public class NativeCryptoTest extends TestCase { int c = NativeCrypto.SSL_CTX_new(); int s = NativeCrypto.SSL_new(c); try { - NativeCrypto.SSL_write(s, INVALID_FD, DUMMY_CB, new byte[1], 0, 1); + NativeCrypto.SSL_write(s, INVALID_FD, DUMMY_CB, new byte[1], 0, 1, 0); fail(); } catch (SSLException expected) { } @@ -1628,76 +1746,6 @@ public class NativeCryptoTest extends TestCase { server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); } - public void test_SSL_SESSION_compress_meth_null() throws Exception { - try { - NativeCrypto.SSL_SESSION_compress_meth(NULL, NULL); - fail(); - } catch (NullPointerException expected) { - } - - { - int c = NativeCrypto.SSL_CTX_new(); - try { - NativeCrypto.SSL_SESSION_compress_meth(c, NULL); - } catch (NullPointerException expected) { - } - NativeCrypto.SSL_CTX_free(c); - } - } - - public void test_SSL_SESSION_compress_meth_NULL() throws Exception { - final ServerSocket listener = new ServerSocket(0); - - Hooks cHooks = new Hooks() { - @Override - public void afterHandshake(int session, int s, int c, - Socket sock, FileDescriptor fd, - SSLHandshakeCallbacks callback) - throws Exception { - assertEquals("NULL", NativeCrypto.SSL_SESSION_compress_meth(c, session)); - super.afterHandshake(session, s, c, sock, fd, callback); - } - }; - Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()); - Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null); - Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null); - client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); - server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); - } - - public void test_SSL_SESSION_compress_meth_ZLIB() throws Exception { - final ServerSocket listener = new ServerSocket(0); - - Hooks cHooks = new Hooks() { - @Override - public int beforeHandshake(int c) throws SSLException { - int s = super.beforeHandshake(c); - NativeCrypto.SSL_clear_options(s, NativeCrypto.SSL_OP_NO_COMPRESSION); - return s; - } - @Override - public void afterHandshake(int session, int s, int c, - Socket sock, FileDescriptor fd, - SSLHandshakeCallbacks callback) - throws Exception { - assertEquals("ZLIB", NativeCrypto.SSL_SESSION_compress_meth(c, session)); - super.afterHandshake(session, s, c, sock, fd, callback); - } - }; - Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) { - @Override - public int beforeHandshake(int c) throws SSLException { - int s = super.beforeHandshake(c); - NativeCrypto.SSL_clear_options(s, NativeCrypto.SSL_OP_NO_COMPRESSION); - return s; - } - }; - Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null); - Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null); - client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); - server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); - } - public void test_SSL_SESSION_free() throws Exception { try { NativeCrypto.SSL_SESSION_free(NULL); @@ -1728,6 +1776,12 @@ public class NativeCryptoTest extends TestCase { assertNotNull(b); int session2 = NativeCrypto.d2i_SSL_SESSION(b); assertTrue(session2 != NULL); + + // Make sure d2i_SSL_SESSION retores SSL_SESSION_cipher value http://b/7091840 + assertTrue(NativeCrypto.SSL_SESSION_cipher(session2) != null); + assertEquals(NativeCrypto.SSL_SESSION_cipher(session), + NativeCrypto.SSL_SESSION_cipher(session2)); + NativeCrypto.SSL_SESSION_free(session2); super.afterHandshake(session, s, c, sock, fd, callback); } @@ -1749,7 +1803,7 @@ public class NativeCryptoTest extends TestCase { assertEquals(NULL, NativeCrypto.d2i_SSL_SESSION(new byte[0])); assertEquals(NULL, NativeCrypto.d2i_SSL_SESSION(new byte[1])); - // positively testing by test_i2d_SSL_SESSION + // positive testing by test_i2d_SSL_SESSION } public void test_X509_NAME_hashes() { @@ -1771,4 +1825,25 @@ public class NativeCryptoTest extends TestCase { // Success } } + + public void test_RAND_bytes_Success() throws Exception { + byte[] output = new byte[32]; + NativeCrypto.RAND_bytes(output); + + boolean isZero = true; + for (int i = 0; i < output.length; i++) { + isZero &= (output[i] == 0); + } + + assertFalse("Random output was zero. This is a very low probability event " + + "and probably indicates an error.", isZero); + } + + public void test_RAND_bytes_Null_Failure() throws Exception { + byte[] output = null; + try { + NativeCrypto.RAND_bytes(output); + fail("Should be an error on null buffer input"); + } catch (RuntimeException success) { } + } } diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImplTest.java b/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImplTest.java index 26ebc85..fe5f4f0 100644 --- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImplTest.java +++ b/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImplTest.java @@ -16,9 +16,15 @@ package org.apache.harmony.xnet.provider.jsse; -import java.security.KeyStore; +import java.io.File; +import java.io.FileWriter; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; +import java.security.KeyStore; +import java.security.MessageDigest; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; @@ -27,12 +33,41 @@ import libcore.java.security.TestKeyStore; public class TrustManagerImplTest extends TestCase { + private List<File> tmpFiles = new ArrayList<File>(); + + private String getFingerprint(X509Certificate cert) throws Exception { + MessageDigest dgst = MessageDigest.getInstance("SHA512"); + byte[] encoded = cert.getPublicKey().getEncoded(); + byte[] fingerprint = dgst.digest(encoded); + return IntegralToString.bytesToHexString(fingerprint, false); + } + + private String writeTmpPinFile(String text) throws Exception { + File tmp = File.createTempFile("pins", null); + FileWriter fstream = new FileWriter(tmp); + fstream.write(text); + fstream.close(); + tmpFiles.add(tmp); + return tmp.getPath(); + } + + @Override + public void tearDown() throws Exception { + try { + for (File f : tmpFiles) { + f.delete(); + } + tmpFiles.clear(); + } finally { + super.tearDown(); + } + } + /** * Ensure that our non-standard behavior of learning to trust new * intermediate CAs does not regress. http://b/3404902 */ public void testLearnIntermediate() throws Exception { - // chain3 should be server/intermediate/root KeyStore.PrivateKeyEntry pke = TestKeyStore.getServer().getPrivateKey("RSA", "RSA"); X509Certificate[] chain3 = (X509Certificate[])pke.getCertificateChain(); @@ -63,6 +98,52 @@ public class TrustManagerImplTest extends TestCase { assertValid(chain1, tm); } + public void testGetFullChain() throws Exception { + // build the trust manager + KeyStore.PrivateKeyEntry pke = TestKeyStore.getServer().getPrivateKey("RSA", "RSA"); + X509Certificate[] chain3 = (X509Certificate[])pke.getCertificateChain(); + X509Certificate root = chain3[2]; + X509TrustManager tm = trustManager(root); + + // build the chains we'll use for testing + X509Certificate intermediate = chain3[1]; + X509Certificate server = chain3[0]; + X509Certificate[] chain2 = new X509Certificate[] { server, intermediate }; + X509Certificate[] chain1 = new X509Certificate[] { server }; + + assertTrue(tm instanceof TrustManagerImpl); + TrustManagerImpl tmi = (TrustManagerImpl) tm; + List<X509Certificate> certs = tmi.checkServerTrusted(chain2, "RSA", "purple.com"); + assertEquals(Arrays.asList(chain3), certs); + certs = tmi.checkServerTrusted(chain1, "RSA", "purple.com"); + assertEquals(Arrays.asList(chain3), certs); + } + + public void testCertPinning() throws Exception { + // chain3 should be server/intermediate/root + KeyStore.PrivateKeyEntry pke = TestKeyStore.getServer().getPrivateKey("RSA", "RSA"); + X509Certificate[] chain3 = (X509Certificate[]) pke.getCertificateChain(); + X509Certificate root = chain3[2]; + X509Certificate intermediate = chain3[1]; + X509Certificate server = chain3[0]; + X509Certificate[] chain2 = new X509Certificate[] { server, intermediate }; + X509Certificate[] chain1 = new X509Certificate[] { server }; + + // test without a hostname, expecting failure + assertInvalidPinned(chain1, trustManager(root, "gugle.com", root), null); + // test without a hostname, expecting success + assertValidPinned(chain3, trustManager(root, "gugle.com", root), null, chain3); + // test an unpinned hostname that should fail + assertInvalidPinned(chain1, trustManager(root, "gugle.com", root), "purple.com"); + // test an unpinned hostname that should succeed + assertValidPinned(chain3, trustManager(root, "gugle.com", root), "purple.com", chain3); + // test a pinned hostname that should fail + assertInvalidPinned(chain1, trustManager(intermediate, "gugle.com", root), "gugle.com"); + // test a pinned hostname that should succeed + assertValidPinned(chain2, trustManager(intermediate, "gugle.com", server), "gugle.com", + chain2); + } + private X509TrustManager trustManager(X509Certificate ca) throws Exception { KeyStore keyStore = TestKeyStore.createKeyStore(); keyStore.setCertificateEntry("alias", ca); @@ -73,10 +154,45 @@ public class TrustManagerImplTest extends TestCase { return (X509TrustManager) tmf.getTrustManagers()[0]; } + private TrustManagerImpl trustManager(X509Certificate ca, String hostname, X509Certificate pin) + throws Exception { + // build the cert pin manager + CertPinManager cm = certManager(hostname, pin); + // insert it into the trust manager + KeyStore keyStore = TestKeyStore.createKeyStore(); + keyStore.setCertificateEntry("alias", ca); + return new TrustManagerImpl(keyStore, cm); + } + + private CertPinManager certManager(String hostname, X509Certificate pin) throws Exception { + String pinString = ""; + if (pin != null) { + pinString = hostname + "=true|" + getFingerprint(pin); + } + // write it to a pinfile + String path = writeTmpPinFile(pinString); + // build the certpinmanager + return new CertPinManager(path, new TrustedCertificateStore()); + } + private void assertValid(X509Certificate[] chain, X509TrustManager tm) throws Exception { - tm.checkClientTrusted(chain, "RSA"); + if (tm instanceof TrustManagerImpl) { + TrustManagerImpl tmi = (TrustManagerImpl) tm; + tmi.checkServerTrusted(chain, "RSA"); + } tm.checkServerTrusted(chain, "RSA"); } + + private void assertValidPinned(X509Certificate[] chain, X509TrustManager tm, String hostname, + X509Certificate[] fullChain) throws Exception { + if (tm instanceof TrustManagerImpl) { + TrustManagerImpl tmi = (TrustManagerImpl) tm; + List<X509Certificate> checkedChain = tmi.checkServerTrusted(chain, "RSA", hostname); + assertEquals(checkedChain, Arrays.asList(fullChain)); + } + tm.checkServerTrusted(chain, "RSA"); + } + private void assertInvalid(X509Certificate[] chain, X509TrustManager tm) { try { tm.checkClientTrusted(chain, "RSA"); @@ -89,4 +205,15 @@ public class TrustManagerImplTest extends TestCase { } catch (CertificateException expected) { } } + + private void assertInvalidPinned(X509Certificate[] chain, X509TrustManager tm, String hostname) + throws Exception { + assertTrue(tm.getClass().getName(), tm instanceof TrustManagerImpl); + try { + TrustManagerImpl tmi = (TrustManagerImpl) tm; + tmi.checkServerTrusted(chain, "RSA", hostname); + fail(); + } catch (CertificateException expected) { + } + } } diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateStoreTest.java b/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateStoreTest.java index 6d0f50c..8f9b7fa 100644 --- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateStoreTest.java +++ b/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateStoreTest.java @@ -22,11 +22,13 @@ import java.io.OutputStream; import java.security.KeyStore; import java.security.PrivateKey; import java.security.PublicKey; +import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; import java.util.HashSet; +import java.util.List; import java.util.NoSuchElementException; import java.util.Set; import javax.security.auth.x500.X500Principal; @@ -411,6 +413,15 @@ public class TrustedCertificateStoreTest extends TestCase { assertAliases(alias1, alias2); assertEquals(getChain()[2], store.findIssuer(getChain()[1])); assertEquals(getChain()[1], store.findIssuer(getChain()[0])); + + X509Certificate[] expected = getChain(); + List<X509Certificate> actualList = store.getCertificateChain(expected[0]); + + assertEquals("Generated CA list should be same length", expected.length, actualList.size()); + for (int i = 0; i < expected.length; i++) { + assertEquals("Chain value should be the same for position " + i, expected[i], + actualList.get(i)); + } resetStore(); } @@ -519,6 +530,26 @@ public class TrustedCertificateStoreTest extends TestCase { assertDeleted(getCa1(), getAliasSystemCa1()); } + public void testIsUserAddedCertificate() throws Exception { + assertFalse(store.isUserAddedCertificate(getCa1())); + assertFalse(store.isUserAddedCertificate(getCa2())); + install(getCa1(), getAliasSystemCa1()); + assertFalse(store.isUserAddedCertificate(getCa1())); + assertFalse(store.isUserAddedCertificate(getCa2())); + install(getCa1(), getAliasUserCa1()); + assertTrue(store.isUserAddedCertificate(getCa1())); + assertFalse(store.isUserAddedCertificate(getCa2())); + install(getCa2(), getAliasUserCa2()); + assertTrue(store.isUserAddedCertificate(getCa1())); + assertTrue(store.isUserAddedCertificate(getCa2())); + store.deleteCertificateEntry(getAliasUserCa1()); + assertFalse(store.isUserAddedCertificate(getCa1())); + assertTrue(store.isUserAddedCertificate(getCa2())); + store.deleteCertificateEntry(getAliasUserCa2()); + assertFalse(store.isUserAddedCertificate(getCa1())); + assertFalse(store.isUserAddedCertificate(getCa2())); + } + private void assertRootCa(X509Certificate x, String alias) { assertIntermediateCa(x, alias); assertEquals(x, store.findIssuer(x)); diff --git a/luni/src/test/java/tests/api/java/lang/ref/PhantomReferenceTest.java b/luni/src/test/java/tests/api/java/lang/ref/PhantomReferenceTest.java index 06221c9..6470579 100644 --- a/luni/src/test/java/tests/api/java/lang/ref/PhantomReferenceTest.java +++ b/luni/src/test/java/tests/api/java/lang/ref/PhantomReferenceTest.java @@ -20,6 +20,7 @@ package tests.api.java.lang.ref; import java.lang.ref.PhantomReference; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; +import libcore.java.lang.ref.FinalizationTester; //TODO: write a test to verify that the referent's finalize() happens // before the PhantomReference is enqueued. @@ -81,8 +82,8 @@ public class PhantomReferenceTest extends junit.framework.TestCase { Thread t = new TestThread(); t.start(); t.join(); - System.gc(); - System.runFinalization(); + + FinalizationTester.induceFinalization(); assertNull("get() should return null.", tprs[0].get()); assertNull("get() should return null.", tprs[1].get()); diff --git a/luni/src/test/java/tests/api/java/lang/ref/ReferenceQueueTest.java b/luni/src/test/java/tests/api/java/lang/ref/ReferenceQueueTest.java index dc7e738..cad61b3 100644 --- a/luni/src/test/java/tests/api/java/lang/ref/ReferenceQueueTest.java +++ b/luni/src/test/java/tests/api/java/lang/ref/ReferenceQueueTest.java @@ -22,6 +22,7 @@ import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; +import libcore.java.lang.ref.FinalizationTester; public class ReferenceQueueTest extends junit.framework.TestCase { static Boolean b; @@ -97,8 +98,7 @@ public class ReferenceQueueTest extends junit.framework.TestCase { sr.enqueue(); wr.enqueue(); - System.gc(); - System.runFinalization(); + FinalizationTester.induceFinalization(); assertNull(rq.poll()); } diff --git a/luni/src/test/java/tests/api/java/lang/ref/ReferenceTest.java b/luni/src/test/java/tests/api/java/lang/ref/ReferenceTest.java index a1a7a8c..7461b47 100644 --- a/luni/src/test/java/tests/api/java/lang/ref/ReferenceTest.java +++ b/luni/src/test/java/tests/api/java/lang/ref/ReferenceTest.java @@ -22,6 +22,7 @@ import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; import junit.framework.AssertionFailedError; +import libcore.java.lang.ref.FinalizationTester; public class ReferenceTest extends junit.framework.TestCase { Object tmpA, tmpB, tmpC, obj; @@ -146,16 +147,14 @@ public class ReferenceTest extends junit.framework.TestCase { ReferenceQueue<Object> queue = new ReferenceQueue<Object>(); r = newWeakReference(queue); - System.gc(); - System.runFinalization(); + FinalizationTester.induceFinalization(); Reference ref = queue.remove(); assertNotNull("Object not enqueued.", ref); assertSame("Unexpected ref1", ref, r); assertNull("Object could not be reclaimed1.", r.get()); r = newWeakReference(queue); - System.gc(); - System.runFinalization(); + FinalizationTester.induceFinalization(); // wait for the reference queue thread to enqueue the newly-finalized object Thread.yield(); @@ -213,8 +212,7 @@ public class ReferenceTest extends junit.framework.TestCase { Thread t = new TestThread(); t.start(); t.join(); - System.gc(); - System.runFinalization(); + FinalizationTester.induceFinalization(); ref = rq.remove(5000L); // Give up after five seconds. assertNotNull("Object not garbage collected.", ref); @@ -238,8 +236,7 @@ public class ReferenceTest extends junit.framework.TestCase { public void test_get() { WeakReference ref = newWeakReference(null); - System.gc(); - System.runFinalization(); + FinalizationTester.induceFinalization(); assertNull("get() doesn't return null after gc for WeakReference", ref.get()); obj = new Object(); @@ -322,8 +319,7 @@ public class ReferenceTest extends junit.framework.TestCase { Thread t = new TestThread(); t.start(); t.join(); - System.gc(); - System.runFinalization(); + FinalizationTester.induceFinalization(); Thread.sleep(1000); if (error != null) { throw error; diff --git a/luni/src/test/java/tests/api/java/lang/ref/SoftReferenceTest.java b/luni/src/test/java/tests/api/java/lang/ref/SoftReferenceTest.java index 77c6536..197d829 100644 --- a/luni/src/test/java/tests/api/java/lang/ref/SoftReferenceTest.java +++ b/luni/src/test/java/tests/api/java/lang/ref/SoftReferenceTest.java @@ -22,6 +22,7 @@ import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.util.Vector; +import libcore.java.lang.ref.FinalizationTester; public class SoftReferenceTest extends junit.framework.TestCase { static Boolean bool; @@ -124,8 +125,7 @@ public class SoftReferenceTest extends junit.framework.TestCase { TestThread t = new TestThread(); t.start(); t.join(); - System.gc(); - System.runFinalization(); + FinalizationTester.induceFinalization(); ref = rq.poll(); assertNotNull("Object not garbage collected.", ref); assertNull("Object is not null.", ref.get()); diff --git a/luni/src/test/java/tests/api/java/util/SimpleTimeZoneTest.java b/luni/src/test/java/tests/api/java/util/SimpleTimeZoneTest.java index e27ec0d..618cbe4 100644 --- a/luni/src/test/java/tests/api/java/util/SimpleTimeZoneTest.java +++ b/luni/src/test/java/tests/api/java/util/SimpleTimeZoneTest.java @@ -691,6 +691,7 @@ public class SimpleTimeZoneTest extends junit.framework.TestCase { * java.util.SimpleTimeZone#setStartRule(int, int, int, int, boolean) */ public void test_setStartRuleIIIIZ() { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); // Test for method void java.util.SimpleTimeZone.setStartRule(int, int, // int, int, boolean) SimpleTimeZone st = new SimpleTimeZone(TimeZone.getTimeZone("EST").getRawOffset(), "EST"); diff --git a/luni/src/test/java/tests/api/java/util/WeakHashMapTest.java b/luni/src/test/java/tests/api/java/util/WeakHashMapTest.java index 0e43bf6..d1a43e5 100644 --- a/luni/src/test/java/tests/api/java/util/WeakHashMapTest.java +++ b/luni/src/test/java/tests/api/java/util/WeakHashMapTest.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.WeakHashMap; +import libcore.java.lang.ref.FinalizationTester; import tests.support.Support_MapTest2; @@ -208,7 +209,7 @@ public class WeakHashMapTest extends junit.framework.TestCase { do { System.gc(); System.gc(); - Runtime.getRuntime().runFinalization(); + FinalizationTester.induceFinalization(); count++; } while (count <= 5 && entrySet.size() == 100); @@ -240,7 +241,8 @@ public class WeakHashMapTest extends junit.framework.TestCase { WeakHashMap map = new WeakHashMap(); map.put(null, "value"); // add null key System.gc(); - System.runFinalization(); + System.gc(); + FinalizationTester.induceFinalization(); map.remove("nothing"); // Cause objects in queue to be removed assertEquals("null key was removed", 1, map.size()); } @@ -315,7 +317,7 @@ public class WeakHashMapTest extends junit.framework.TestCase { do { System.gc(); System.gc(); - Runtime.getRuntime().runFinalization(); + FinalizationTester.induceFinalization(); count++; } while (count <= 5 && keySet.size() == 100); @@ -352,7 +354,7 @@ public class WeakHashMapTest extends junit.framework.TestCase { do { System.gc(); System.gc(); - Runtime.getRuntime().runFinalization(); + FinalizationTester.induceFinalization(); count++; } while (count <= 5 && valuesCollection.size() == 100); diff --git a/luni/src/test/java/tests/api/javax/net/ServerSocketFactoryTest.java b/luni/src/test/java/tests/api/javax/net/ServerSocketFactoryTest.java index 053200f..34d7aed 100644 --- a/luni/src/test/java/tests/api/javax/net/ServerSocketFactoryTest.java +++ b/luni/src/test/java/tests/api/javax/net/ServerSocketFactoryTest.java @@ -30,158 +30,77 @@ import javax.net.ServerSocketFactory; import junit.framework.TestCase; -import tests.support.Support_PortManager; - - -/** - * Tests for <code>ServerSocketFactory</code> class constructors and methods. - */ public class ServerSocketFactoryTest extends TestCase { - /** - * javax.net.SocketFactory#SocketFactory() - */ public void test_Constructor() { - try { - ServerSocketFactory sf = new MyServerSocketFactory(); - } catch (Exception e) { - fail("Unexpected exception " + e.toString()); - } + ServerSocketFactory sf = new MyServerSocketFactory(); } - /** - * javax.net.ServerSocketFactory#createServerSocket() - */ - public final void test_createServerSocket_01() { + public final void test_createServerSocket() throws Exception { ServerSocketFactory sf = ServerSocketFactory.getDefault(); - try { - ServerSocket ss = sf.createServerSocket(); - assertNotNull(ss); - } catch (SocketException e) { - } catch (Exception e) { - fail(e.toString()); - } + ServerSocket ss = sf.createServerSocket(); + assertNotNull(ss); + ss.close(); } - /** - * javax.net.ServerSocketFactory#createServerSocket(int port) - */ - public final void test_createServerSocket_02() { + public final void test_createServerSocket_I() throws Exception { ServerSocketFactory sf = ServerSocketFactory.getDefault(); - int portNumber = Support_PortManager.getNextPort(); - - try { - ServerSocket ss = sf.createServerSocket(portNumber); - assertNotNull(ss); - } catch (Exception ex) { - fail("Unexpected exception: " + ex); - } + ServerSocket ss = sf.createServerSocket(0); + assertNotNull(ss); try { - sf.createServerSocket(portNumber); + sf.createServerSocket(ss.getLocalPort()); fail("IOException wasn't thrown"); - } catch (IOException ioe) { - //expected - } catch (Exception ex) { - fail(ex + " was thrown instead of IOException"); + } catch (IOException expected) { } + ss.close(); + try { sf.createServerSocket(-1); fail("IllegalArgumentException wasn't thrown"); - } catch (IllegalArgumentException ioe) { - //expected - } catch (Exception ex) { - fail(ex + " was thrown instead of IllegalArgumentException"); + } catch (IllegalArgumentException expected) { } } - /** - * javax.net.ServerSocketFactory#createServerSocket(int port, int backlog) - */ - public final void test_createServerSocket_03() { + public final void test_createServerSocket_II() throws Exception { ServerSocketFactory sf = ServerSocketFactory.getDefault(); - int portNumber = Support_PortManager.getNextPort(); - - try { - ServerSocket ss = sf.createServerSocket(portNumber, 0); - assertNotNull(ss); - } catch (Exception ex) { - fail("Unexpected exception: " + ex); - } + ServerSocket ss = sf.createServerSocket(0, 0); + assertNotNull(ss); try { - sf.createServerSocket(portNumber, 0); + sf.createServerSocket(ss.getLocalPort(), 0); fail("IOException wasn't thrown"); - } catch (IOException ioe) { - //expected - } catch (Exception ex) { - fail(ex + " was thrown instead of IOException"); + } catch (IOException expected) { } + ss.close(); + try { sf.createServerSocket(65536, 0); fail("IllegalArgumentException wasn't thrown"); - } catch (IllegalArgumentException ioe) { - //expected - } catch (Exception ex) { - fail(ex + " was thrown instead of IllegalArgumentException"); + } catch (IllegalArgumentException expected) { } } - /** - * javax.net.ServerSocketFactory#createServerSocket(int port, int backlog, InetAddress ifAddress) - */ - public final void test_createServerSocket_04() { + public final void test_createServerSocket_IIInetAddress() throws Exception { ServerSocketFactory sf = ServerSocketFactory.getDefault(); - int portNumber = Support_PortManager.getNextPort(); - try { - ServerSocket ss = sf.createServerSocket(portNumber, 0, InetAddress.getLocalHost()); - assertNotNull(ss); - } catch (Exception ex) { - fail("Unexpected exception: " + ex); - } + ServerSocket ss = sf.createServerSocket(0, 0, InetAddress.getLocalHost()); + assertNotNull(ss); try { - sf.createServerSocket(portNumber, 0, InetAddress.getLocalHost()); + sf.createServerSocket(ss.getLocalPort(), 0, InetAddress.getLocalHost()); fail("IOException wasn't thrown"); - } catch (IOException ioe) { - //expected - } catch (Exception ex) { - fail(ex + " was thrown instead of IOException"); + } catch (IOException expected) { } + ss.close(); + try { sf.createServerSocket(Integer.MAX_VALUE, 0, InetAddress.getLocalHost()); fail("IllegalArgumentException wasn't thrown"); - } catch (IllegalArgumentException ioe) { - //expected - } catch (Exception ex) { - fail(ex + " was thrown instead of IllegalArgumentException"); - } - } - - /** - * javax.net.ServerSocketFactory#getDefault() - */ - public final void test_getDefault() { - ServerSocketFactory sf = ServerSocketFactory.getDefault(); - ServerSocket s; - try { - s = sf.createServerSocket(0); - s.close(); - } catch (IOException e) { - } - try { - s = sf.createServerSocket(0, 50); - s.close(); - } catch (IOException e) { - } - try { - s = sf.createServerSocket(0, 50, InetAddress.getLocalHost()); - s.close(); - } catch (IOException e) { + } catch (IllegalArgumentException expected) { } } } diff --git a/luni/src/test/java/tests/api/javax/net/SocketFactoryTest.java b/luni/src/test/java/tests/api/javax/net/SocketFactoryTest.java index 2250602..e939a9b 100644 --- a/luni/src/test/java/tests/api/javax/net/SocketFactoryTest.java +++ b/luni/src/test/java/tests/api/javax/net/SocketFactoryTest.java @@ -33,200 +33,135 @@ import javax.net.SocketFactory; import junit.framework.TestCase; -import tests.support.Support_PortManager; - - -/** - * Tests for <code>SocketFactory</code> class methods. - */ public class SocketFactoryTest extends TestCase { - /** - * javax.net.SocketFactory#SocketFactory() - */ - public void test_Constructor() { - try { - MySocketFactory sf = new MySocketFactory(); - } catch (Exception e) { - fail("Unexpected exception " + e.toString()); - } + public void test_Constructor() throws Exception { + new MySocketFactory(); } - /** - * javax.net.SocketFactory#createSocket() - */ - public final void test_createSocket_01() { + public final void test_createSocket() throws Exception { SocketFactory sf = SocketFactory.getDefault(); - try { - Socket s = sf.createSocket(); - assertNotNull(s); - assertEquals(-1, s.getLocalPort()); - assertEquals(0, s.getPort()); - } catch (Exception e) { - fail("Unexpected exception: " + e); - } + Socket s = sf.createSocket(); + assertNotNull(s); + assertEquals(-1, s.getLocalPort()); + assertEquals(0, s.getPort()); MySocketFactory msf = new MySocketFactory(); try { msf.createSocket(); fail("No expected SocketException"); - } catch (SocketException e) { - } catch (IOException e) { - fail(e.toString()); + } catch (SocketException expected) { } } - /** - * javax.net.SocketFactory#createSocket(String host, int port) - */ - public final void test_createSocket_02() { + public final void test_createSocket_StringI() throws Exception { SocketFactory sf = SocketFactory.getDefault(); - int portNumber = Support_PortManager.getNextPort(); - int sport = startServer("Cons String,I"); + int sport = new ServerSocket(0).getLocalPort(); int[] invalidPorts = {Integer.MIN_VALUE, -1, 65536, Integer.MAX_VALUE}; - try { - Socket s = sf.createSocket(InetAddress.getLocalHost().getHostName(), sport); - assertNotNull(s); - assertTrue("Failed to create socket", s.getPort() == sport); - } catch (Exception e) { - fail("Unexpected exception: " + e); - } + Socket s = sf.createSocket(InetAddress.getLocalHost().getHostName(), sport); + assertNotNull(s); + assertTrue("Failed to create socket", s.getPort() == sport); try { - Socket s = sf.createSocket("bla-bla", sport); + sf.createSocket("bla-bla", sport); fail("UnknownHostException wasn't thrown"); - } catch (UnknownHostException uhe) { - //expected - } catch (Exception e) { - fail(e + " was thrown instead of UnknownHostException"); + } catch (UnknownHostException expected) { } for (int i = 0; i < invalidPorts.length; i++) { try { - Socket s = sf.createSocket(InetAddress.getLocalHost().getHostName(), invalidPorts[i]); + sf.createSocket(InetAddress.getLocalHost().getHostName(), invalidPorts[i]); fail("IllegalArgumentException wasn't thrown for " + invalidPorts[i]); - } catch (IllegalArgumentException iae) { - //expected - } catch (Exception e) { - fail(e + " was thrown instead of IllegalArgumentException for " + invalidPorts[i]); + } catch (IllegalArgumentException expected) { } } try { - Socket s = sf.createSocket(InetAddress.getLocalHost().getHostName(), portNumber); + sf.createSocket(InetAddress.getLocalHost().getHostName(), s.getLocalPort()); fail("IOException wasn't thrown"); - } catch (IOException ioe) { - //expected + } catch (IOException expected) { } SocketFactory f = SocketFactory.getDefault(); try { - Socket s = f.createSocket("localhost", 8082); + f.createSocket(InetAddress.getLocalHost().getHostName(), 8082); fail("IOException wasn't thrown ..."); - } catch (IOException e) { + } catch (IOException expected) { } } - /** - * javax.net.SocketFactory#createSocket(InetAddress host, int port) - */ - public final void test_createSocket_03() { + public final void test_createSocket_InetAddressI() throws Exception { SocketFactory sf = SocketFactory.getDefault(); - int portNumber = Support_PortManager.getNextPort(); - int sport = startServer("Cons InetAddress,I"); + int sport = new ServerSocket(0).getLocalPort(); int[] invalidPorts = {Integer.MIN_VALUE, -1, 65536, Integer.MAX_VALUE}; - try { - Socket s = sf.createSocket(InetAddress.getLocalHost(), sport); - assertNotNull(s); - assertTrue("Failed to create socket", s.getPort() == sport); - } catch (Exception e) { - fail("Unexpected exception: " + e); - } + Socket s = sf.createSocket(InetAddress.getLocalHost(), sport); + assertNotNull(s); + assertTrue("Failed to create socket", s.getPort() == sport); for (int i = 0; i < invalidPorts.length; i++) { try { - Socket s = sf.createSocket(InetAddress.getLocalHost(), invalidPorts[i]); + sf.createSocket(InetAddress.getLocalHost(), invalidPorts[i]); fail("IllegalArgumentException wasn't thrown for " + invalidPorts[i]); - } catch (IllegalArgumentException iae) { - //expected - } catch (Exception e) { - fail(e + " was thrown instead of IllegalArgumentException for " + invalidPorts[i]); + } catch (IllegalArgumentException expected) { } } try { - Socket s = sf.createSocket(InetAddress.getLocalHost(), portNumber); + sf.createSocket(InetAddress.getLocalHost(), s.getLocalPort()); fail("IOException wasn't thrown"); - } catch (IOException ioe) { - //expected + } catch (IOException expected) { } SocketFactory f = SocketFactory.getDefault(); try { - Socket s = f.createSocket(InetAddress.getLocalHost(), 8081); + f.createSocket(InetAddress.getLocalHost(), 8081); fail("IOException wasn't thrown ..."); - } catch (IOException e) { + } catch (IOException expected) { } } - /** - * javax.net.SocketFactory#createSocket(InetAddress address, int port, - * InetAddress localAddress, int localPort) - */ - public final void test_createSocket_04() { + public final void test_createSocket_InetAddressIInetAddressI() throws Exception { SocketFactory sf = SocketFactory.getDefault(); - int portNumber = Support_PortManager.getNextPort(); - int sport = startServer("Cons InetAddress,I,InetAddress,I"); + int sport = new ServerSocket(0).getLocalPort(); int[] invalidPorts = {Integer.MIN_VALUE, -1, 65536, Integer.MAX_VALUE}; - try { - Socket s = sf.createSocket(InetAddress.getLocalHost(), sport, - InetAddress.getLocalHost(), portNumber); - assertNotNull(s); - assertTrue("1: Failed to create socket", s.getPort() == sport); - assertTrue("2: Failed to create socket", s.getLocalPort() == portNumber); - } catch (Exception e) { - fail("Unexpected exception: " + e); - } + Socket s = sf.createSocket(InetAddress.getLocalHost(), sport, + InetAddress.getLocalHost(), 0); + assertNotNull(s); + assertTrue("1: Failed to create socket", s.getPort() == sport); + int portNumber = s.getLocalPort(); for (int i = 0; i < invalidPorts.length; i++) { try { - Socket s = sf.createSocket(InetAddress.getLocalHost(), invalidPorts[i], - InetAddress.getLocalHost(), portNumber); + sf.createSocket(InetAddress.getLocalHost(), invalidPorts[i], + InetAddress.getLocalHost(), portNumber); fail("IllegalArgumentException wasn't thrown for " + invalidPorts[i]); - } catch (IllegalArgumentException iae) { - //expected - } catch (Exception e) { - fail(e + " was thrown instead of IllegalArgumentException for " + invalidPorts[i]); + } catch (IllegalArgumentException expected) { } try { - Socket s = sf.createSocket(InetAddress.getLocalHost(), sport, - InetAddress.getLocalHost(), invalidPorts[i]); + sf.createSocket(InetAddress.getLocalHost(), sport, + InetAddress.getLocalHost(), invalidPorts[i]); fail("IllegalArgumentException wasn't thrown for " + invalidPorts[i]); - } catch (IllegalArgumentException iae) { - //expected - } catch (Exception e) { - fail(e + " was thrown instead of IllegalArgumentException for " + invalidPorts[i]); + } catch (IllegalArgumentException expected) { } } try { - Socket s = sf.createSocket(InetAddress.getLocalHost(), sport, - InetAddress.getLocalHost(), portNumber); + sf.createSocket(InetAddress.getLocalHost(), sport, + InetAddress.getLocalHost(), portNumber); fail("IOException wasn't thrown"); - } catch (IOException ioe) { - //expected + } catch (IOException expected) { } SocketFactory f = SocketFactory.getDefault(); try { - Socket s = f.createSocket(InetAddress.getLocalHost(), 8081, InetAddress.getLocalHost(), 8082); + f.createSocket(InetAddress.getLocalHost(), 8081, InetAddress.getLocalHost(), 8082); fail("IOException wasn't thrown ..."); - } catch (IOException e) { + } catch (IOException expected) { } } @@ -234,59 +169,41 @@ public class SocketFactoryTest extends TestCase { * javax.net.SocketFactory#createSocket(String host, int port, * InetAddress localHost, int localPort) */ - public final void test_createSocket_05() { + public final void test_createSocket_05() throws Exception { SocketFactory sf = SocketFactory.getDefault(); - int portNumber = Support_PortManager.getNextPort(); - int sport = startServer("Cons String,I,InetAddress,I"); + int sport = new ServerSocket(0).getLocalPort(); int[] invalidPorts = {Integer.MIN_VALUE, -1, 65536, Integer.MAX_VALUE}; - try { - Socket s = sf.createSocket(InetAddress.getLocalHost().getHostName(), sport, - InetAddress.getLocalHost(), portNumber); - assertNotNull(s); - assertTrue("1: Failed to create socket", s.getPort() == sport); - assertTrue("2: Failed to create socket", s.getLocalPort() == portNumber); - } catch (Exception e) { - fail("Unexpected exception: " + e); - } + Socket s = sf.createSocket(InetAddress.getLocalHost().getHostName(), sport, + InetAddress.getLocalHost(), 0); + assertNotNull(s); + assertTrue("1: Failed to create socket", s.getPort() == sport); - portNumber = Support_PortManager.getNextPort(); try { - Socket s = sf.createSocket("bla-bla", sport, InetAddress.getLocalHost(), portNumber); + sf.createSocket("bla-bla", sport, InetAddress.getLocalHost(), 0); fail("UnknownHostException wasn't thrown"); - } catch (UnknownHostException uhe) { - //expected - } catch (Exception e) { - fail(e + " was thrown instead of UnknownHostException"); + } catch (UnknownHostException expected) { } for (int i = 0; i < invalidPorts.length; i++) { - portNumber = Support_PortManager.getNextPort(); try { - Socket s = sf.createSocket(InetAddress.getLocalHost().getHostName(), invalidPorts[i], - InetAddress.getLocalHost(), portNumber); + sf.createSocket(InetAddress.getLocalHost().getHostName(), invalidPorts[i], + InetAddress.getLocalHost(), 0); fail("IllegalArgumentException wasn't thrown for " + invalidPorts[i]); - } catch (IllegalArgumentException iae) { - //expected - } catch (Exception e) { - fail(e + " was thrown instead of IllegalArgumentException for " + invalidPorts[i]); + } catch (IllegalArgumentException expected) { } try { - Socket s = sf.createSocket(InetAddress.getLocalHost().getHostName(), sport, - InetAddress.getLocalHost(), invalidPorts[i]); + sf.createSocket(InetAddress.getLocalHost().getHostName(), sport, + InetAddress.getLocalHost(), invalidPorts[i]); fail("IllegalArgumentException wasn't thrown for " + invalidPorts[i]); - } catch (IllegalArgumentException iae) { - //expected - } catch (Exception e) { - fail(e + " was thrown instead of IllegalArgumentException for " + invalidPorts[i]); + } catch (IllegalArgumentException expected) { } } - SocketFactory f = SocketFactory.getDefault(); try { - Socket s = f.createSocket("localhost", 8081, InetAddress.getLocalHost(), 8082); + sf.createSocket(InetAddress.getLocalHost().getHostName(), 8081, InetAddress.getLocalHost(), 8082); fail("IOException wasn't thrown ..."); - } catch (IOException e) { + } catch (IOException expected) { } } @@ -297,12 +214,12 @@ public class SocketFactoryTest extends TestCase { SocketFactory sf = SocketFactory.getDefault(); Socket s; try { - s = sf.createSocket("localhost", 8082); + s = sf.createSocket(InetAddress.getLocalHost().getHostName(), 8082); s.close(); } catch (IOException e) { } try { - s = sf.createSocket("localhost", 8081, InetAddress.getLocalHost(), 8082); + s = sf.createSocket(InetAddress.getLocalHost().getHostName(), 8081, InetAddress.getLocalHost(), 8082); s.close(); } catch (IOException e) { } @@ -317,17 +234,6 @@ public class SocketFactoryTest extends TestCase { } catch (IOException e) { } } - - protected int startServer(String name) { - int portNumber = Support_PortManager.getNextPort(); - ServerSocket ss = null; - try { - ss = new ServerSocket(portNumber); - } catch (IOException e) { - fail(name + ": " + e); - } - return ss.getLocalPort(); - } } class MySocketFactory extends SocketFactory { diff --git a/luni/src/test/java/tests/api/javax/net/ssl/HandshakeCompletedEventTest.java b/luni/src/test/java/tests/api/javax/net/ssl/HandshakeCompletedEventTest.java index 8a02f9c..c075cea 100644 --- a/luni/src/test/java/tests/api/javax/net/ssl/HandshakeCompletedEventTest.java +++ b/luni/src/test/java/tests/api/javax/net/ssl/HandshakeCompletedEventTest.java @@ -42,7 +42,6 @@ import javax.security.cert.X509Certificate; import junit.framework.TestCase; import libcore.io.Base64; import org.apache.harmony.xnet.tests.support.mySSLSession; -import tests.support.Support_PortManager; /** * Tests for <code>HandshakeCompletedEvent</code> class constructors and methods. @@ -50,7 +49,7 @@ import tests.support.Support_PortManager; */ public class HandshakeCompletedEventTest extends TestCase { - String certificate = "-----BEGIN CERTIFICATE-----\n" + private String certificate = "-----BEGIN CERTIFICATE-----\n" + "MIICZTCCAdICBQL3AAC2MA0GCSqGSIb3DQEBAgUAMF8xCzAJBgNVBAYTAlVTMSAw\n" + "HgYDVQQKExdSU0EgRGF0YSBTZWN1cml0eSwgSW5jLjEuMCwGA1UECxMlU2VjdXJl\n" + "IFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05NzAyMjAwMDAwMDBa\n" @@ -200,11 +199,10 @@ public class HandshakeCompletedEventTest extends TestCase { // TrustManager - SSLSocket socket; - SSLSocket serverSocket; - MyHandshakeListener listener; - int port = Support_PortManager.getNextPort(); - String host = "localhost"; + private SSLSocket socket; + private SSLServerSocket serverSocket; + private MyHandshakeListener listener; + private String host = "localhost"; private String PASSWORD = "android"; @@ -398,35 +396,34 @@ public class HandshakeCompletedEventTest extends TestCase { private boolean provideKeys; - public TestServer(boolean provideKeys, int clientAuth, String keys) { + public TestServer(boolean provideKeys, int clientAuth, String keys) throws Exception { this.keys = keys; this.clientAuth = clientAuth; this.provideKeys = provideKeys; trustManager = new TestTrustManager(); - } - public void run() { - try { - KeyManager[] keyManagers = provideKeys ? getKeyManagers(keys) : null; - TrustManager[] trustManagers = new TrustManager[] { trustManager }; + KeyManager[] keyManagers = provideKeys ? getKeyManagers(keys) : null; + TrustManager[] trustManagers = new TrustManager[] { trustManager }; - SSLContext sslContext = SSLContext.getInstance("TLS"); - sslContext.init(keyManagers, trustManagers, null); + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(keyManagers, trustManagers, null); - SSLServerSocket serverSocket = (SSLServerSocket) - sslContext.getServerSocketFactory().createServerSocket(); + serverSocket = (SSLServerSocket) sslContext.getServerSocketFactory().createServerSocket(); - if (clientAuth == CLIENT_AUTH_WANTED) { - serverSocket.setWantClientAuth(true); - } else if (clientAuth == CLIENT_AUTH_NEEDED) { - serverSocket.setNeedClientAuth(true); - } else { - serverSocket.setWantClientAuth(false); - } + if (clientAuth == CLIENT_AUTH_WANTED) { + serverSocket.setWantClientAuth(true); + } else if (clientAuth == CLIENT_AUTH_NEEDED) { + serverSocket.setNeedClientAuth(true); + } else { + serverSocket.setWantClientAuth(false); + } - serverSocket.bind(new InetSocketAddress(port)); + serverSocket.bind(new InetSocketAddress(0)); + } + public void run() { + try { SSLSocket clientSocket = (SSLSocket)serverSocket.accept(); InputStream istream = clientSocket.getInputStream(); @@ -497,7 +494,7 @@ public class HandshakeCompletedEventTest extends TestCase { SSLSocket socket = (SSLSocket)sslContext.getSocketFactory().createSocket(); - socket.connect(new InetSocketAddress(port)); + socket.connect(serverSocket.getLocalSocketAddress()); socket.addHandshakeCompletedListener(listener); socket.startHandshake(); diff --git a/luni/src/test/java/tests/api/javax/net/ssl/SSLServerSocketTest.java b/luni/src/test/java/tests/api/javax/net/ssl/SSLServerSocketTest.java index cc96782..5086f65 100644 --- a/luni/src/test/java/tests/api/javax/net/ssl/SSLServerSocketTest.java +++ b/luni/src/test/java/tests/api/javax/net/ssl/SSLServerSocketTest.java @@ -20,8 +20,6 @@ import junit.framework.TestCase; import libcore.io.Base64; -import tests.support.Support_PortManager; - import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -120,127 +118,78 @@ public class SSLServerSocketTest extends TestCase { /** * javax.net.ssl.SSLServerSocket#SSLServerSocket() */ - public void testConstructor_01() { - try { - SSLServerSocket ssl = new mySSLServerSocket(); - } catch (Exception ex) { - fail("Unexpected exception was thrown " + ex); - } + public void testConstructor() throws Exception { + SSLServerSocket ssl = new mySSLServerSocket(); } /** * javax.net.ssl.SSLServerSocket#SSLServerSocket(int port) */ - public void testConstructor_02() { - SSLServerSocket ssl; - int portNumber = Support_PortManager.getNextPort(); + public void testConstructor_I() throws Exception { int[] port_invalid = {-1, 65536, Integer.MIN_VALUE, Integer.MAX_VALUE}; - try { - ssl = new mySSLServerSocket(portNumber); - assertEquals(portNumber, ssl.getLocalPort()); - } catch (Exception ex) { - fail("Unexpected exception was thrown " + ex); - } + SSLServerSocket ssl = new mySSLServerSocket(0); for (int i = 0; i < port_invalid.length; i++) { try { - ssl = new mySSLServerSocket(port_invalid[i]); + new mySSLServerSocket(port_invalid[i]); fail("IllegalArgumentException should be thrown"); - } catch (IllegalArgumentException iae) { - //expected - } catch (Exception e) { - fail(e + " was thrown instead of IllegalArgumentException"); + } catch (IllegalArgumentException expected) { } } try { - ssl = new mySSLServerSocket(portNumber); - new mySSLServerSocket(portNumber); + new mySSLServerSocket(ssl.getLocalPort()); fail("IOException Expected when opening an already opened port"); - } catch (IOException ioe) { - // expected - } catch (Exception ex) { - fail("Unexpected exception was thrown " + ex); + } catch (IOException expected) { } } /** * javax.net.ssl.SSLServerSocket#SSLServerSocket(int port, int backlog) */ - public void testConstructor_03() { - mySSLServerSocket ssl; - int portNumber = Support_PortManager.getNextPort(); + public void testConstructor_II() throws Exception { + mySSLServerSocket ssl = new mySSLServerSocket(0, 1); int[] port_invalid = {-1, Integer.MIN_VALUE, Integer.MAX_VALUE}; - try { - ssl = new mySSLServerSocket(portNumber, 1); - assertEquals(portNumber, ssl.getLocalPort()); - } catch (Exception ex) { - fail("Unexpected exception was thrown"); - } - for (int i = 0; i < port_invalid.length; i++) { try { - ssl = new mySSLServerSocket(port_invalid[i], 1); + new mySSLServerSocket(port_invalid[i], 1); fail("IllegalArgumentException should be thrown"); - } catch (IllegalArgumentException iae) { - // expected - } catch (Exception e) { - fail(e + " was thrown instead of IllegalArgumentException"); + } catch (IllegalArgumentException expected) { } } - portNumber = Support_PortManager.getNextPort(); try { - ssl = new mySSLServerSocket(portNumber, 1); - new mySSLServerSocket(portNumber, 1); + new mySSLServerSocket(ssl.getLocalPort(), 1); fail("IOException should be thrown"); - } catch (IOException ioe) { + } catch (IOException expected) { } } /** * javax.net.ssl.SSLServerSocket#SSLServerSocket(int port, int backlog, InetAddress address) */ - public void testConstructor_04() { - mySSLServerSocket ssl; - InetAddress ia = null; - int portNumber = Support_PortManager.getNextPort(); - int[] port_invalid = {-1, 65536, Integer.MIN_VALUE, Integer.MAX_VALUE}; + public void testConstructor_IIInetAddress() throws Exception { + // A null InetAddress is okay. + new mySSLServerSocket(0, 0, null); - try { - ssl = new mySSLServerSocket(portNumber, 0, ia); - assertEquals(portNumber, ssl.getLocalPort()); - } catch (Exception ex) { - fail("Unexpected exception was thrown"); - } + int[] port_invalid = {-1, 65536, Integer.MIN_VALUE, Integer.MAX_VALUE}; - portNumber = Support_PortManager.getNextPort(); - try { - ssl = new mySSLServerSocket(portNumber, 0, InetAddress.getLocalHost()); - assertEquals(portNumber, ssl.getLocalPort()); - } catch (Exception ex) { - fail("Unexpected exception was thrown"); - } + mySSLServerSocket ssl = new mySSLServerSocket(0, 0, InetAddress.getLocalHost()); for (int i = 0; i < port_invalid.length; i++) { try { - ssl = new mySSLServerSocket(port_invalid[i], 1, InetAddress.getLocalHost()); + new mySSLServerSocket(port_invalid[i], 1, InetAddress.getLocalHost()); fail("IllegalArgumentException should be thrown"); - } catch (IllegalArgumentException iae) { - // expected - } catch (Exception e) { - fail(e + " was thrown instead of IllegalArgumentException"); + } catch (IllegalArgumentException expected) { } } - portNumber = Support_PortManager.getNextPort(); try { - ssl = new mySSLServerSocket(portNumber, 0, InetAddress.getLocalHost()); - new mySSLServerSocket(portNumber, 0, InetAddress.getLocalHost()); - fail("IOException should be thrown for"); - } catch (IOException ioe) { + new mySSLServerSocket(ssl.getLocalPort(), 0, InetAddress.getLocalHost()); + fail("IOException should be thrown for"); + } catch (IOException expected) { } } diff --git a/luni/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java b/luni/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java index ec23cae..5084422 100644 --- a/luni/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java +++ b/luni/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java @@ -39,12 +39,7 @@ import junit.framework.TestCase; import libcore.io.Base64; import tests.api.javax.net.ssl.HandshakeCompletedEventTest.MyHandshakeListener; import tests.api.javax.net.ssl.HandshakeCompletedEventTest.TestTrustManager; -import tests.support.Support_PortManager; -/** - * Tests for SSLSession class - * - */ public class SSLSessionTest extends TestCase { // set to true if on Android, false if on RI @@ -57,7 +52,7 @@ public class SSLSessionTest extends TestCase { public void test_getPeerHost() throws Exception { SSLSession s = clientSession; assertEquals(InetAddress.getLocalHost().getHostName(), s.getPeerHost()); - assertEquals(port, s.getPeerPort()); + assertEquals(serverSocket.getLocalPort(), s.getPeerPort()); } /** @@ -258,12 +253,10 @@ public class SSLSessionTest extends TestCase { TestClient client; @Override - protected void setUp() { - port = Support_PortManager.getNextPort(); + protected void setUp() throws Exception { String serverKeys = (useBKS ? SERVER_KEYS_BKS : SERVER_KEYS_JKS); String clientKeys = (useBKS ? CLIENT_KEYS_BKS : CLIENT_KEYS_JKS); - server = new TestServer(true, - TestServer.CLIENT_AUTH_WANTED, serverKeys); + server = new TestServer(true, TestServer.CLIENT_AUTH_WANTED, serverKeys); client = new TestClient(true, clientKeys); serverThread = new Thread(server); @@ -453,8 +446,7 @@ public class SSLSessionTest extends TestCase { + "NMGpCX6qmjbkJQLVK/Yfo1ePaUexPSOX0G9m8+DoV3iyNw6at01NRw=="; - int port; - SSLSocket serverSocket; + SSLServerSocket serverSocket; MyHandshakeListener listener; String host = "localhost"; boolean notFinished = true; @@ -489,36 +481,35 @@ public class SSLSessionTest extends TestCase { private KeyStore store; - public TestServer(boolean provideKeys, int clientAuth, String keys) { + public TestServer(boolean provideKeys, int clientAuth, String keys) throws Exception { this.keys = keys; this.clientAuth = clientAuth; this.provideKeys = provideKeys; trustManager = new TestTrustManager(); - } - public void run() { - try { - store = provideKeys ? getKeyStore(keys) : null; - KeyManager[] keyManagers = store != null ? getKeyManagers(store) : null; - TrustManager[] trustManagers = new TrustManager[] { trustManager }; + store = provideKeys ? getKeyStore(keys) : null; + KeyManager[] keyManagers = store != null ? getKeyManagers(store) : null; + TrustManager[] trustManagers = new TrustManager[] { trustManager }; - SSLContext sslContext = SSLContext.getInstance("TLS"); - sslContext.init(keyManagers, trustManagers, null); + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(keyManagers, trustManagers, null); - SSLServerSocket serverSocket = (SSLServerSocket)sslContext - .getServerSocketFactory().createServerSocket(); + serverSocket = (SSLServerSocket)sslContext.getServerSocketFactory().createServerSocket(); - if (clientAuth == CLIENT_AUTH_WANTED) { - serverSocket.setWantClientAuth(true); - } else if (clientAuth == CLIENT_AUTH_NEEDED) { - serverSocket.setNeedClientAuth(true); - } else { - serverSocket.setWantClientAuth(false); - } + if (clientAuth == CLIENT_AUTH_WANTED) { + serverSocket.setWantClientAuth(true); + } else if (clientAuth == CLIENT_AUTH_NEEDED) { + serverSocket.setNeedClientAuth(true); + } else { + serverSocket.setWantClientAuth(false); + } - serverSocket.bind(new InetSocketAddress(port)); + serverSocket.bind(null); + } + public void run() { + try { SSLSocket clientSocket = (SSLSocket)serverSocket.accept(); InputStream istream = clientSocket.getInputStream(); @@ -589,7 +580,7 @@ public class SSLSessionTest extends TestCase { SSLSocket socket = (SSLSocket)clientSslContext.getSocketFactory().createSocket(); - socket.connect(new InetSocketAddress(port)); + socket.connect(serverSocket.getLocalSocketAddress()); OutputStream ostream = socket.getOutputStream(); ostream.write(testData.getBytes()); ostream.flush(); diff --git a/luni/src/test/java/tests/api/javax/net/ssl/SSLSocketFactoryTest.java b/luni/src/test/java/tests/api/javax/net/ssl/SSLSocketFactoryTest.java index 02abcc2..0d91116 100644 --- a/luni/src/test/java/tests/api/javax/net/ssl/SSLSocketFactoryTest.java +++ b/luni/src/test/java/tests/api/javax/net/ssl/SSLSocketFactoryTest.java @@ -25,16 +25,13 @@ import javax.net.ssl.SSLSocketFactory; import junit.framework.TestCase; -import tests.support.Support_PortManager; - public class SSLSocketFactoryTest extends TestCase { private ServerSocket ss; protected int startServer(String name) { - int portNumber = Support_PortManager.getNextPort(); try { - ss = new ServerSocket(portNumber); + ss = new ServerSocket(0); } catch (IOException e) { fail(name + ": " + e); } diff --git a/luni/src/test/java/tests/api/javax/net/ssl/SSLSocketTest.java b/luni/src/test/java/tests/api/javax/net/ssl/SSLSocketTest.java index ab60f72..b4cbde2 100644 --- a/luni/src/test/java/tests/api/javax/net/ssl/SSLSocketTest.java +++ b/luni/src/test/java/tests/api/javax/net/ssl/SSLSocketTest.java @@ -38,7 +38,6 @@ import javax.security.cert.X509Certificate; import junit.framework.TestCase; import libcore.io.Base64; import tests.api.javax.net.ssl.HandshakeCompletedEventTest.TestTrustManager; -import tests.support.Support_PortManager; import libcore.java.security.StandardNames; public class SSLSocketTest extends TestCase { @@ -51,7 +50,7 @@ public class SSLSocketTest extends TestCase { /** * javax.net.ssl.SSLSocket#SSLSocket() */ - public void testConstructor_01() throws Exception { + public void testConstructor() throws Exception { SSLSocket ssl = getSSLSocket(); assertNotNull(ssl); ssl.close(); @@ -60,7 +59,7 @@ public class SSLSocketTest extends TestCase { /** * javax.net.ssl.SSLSocket#SSLSocket(InetAddress address, int port) */ - public void testConstructor_02() throws UnknownHostException, IOException { + public void testConstructor_InetAddressI() throws Exception { int sport = startServer("Cons InetAddress,I"); int[] invalidPort = {-1, Integer.MIN_VALUE, 65536, Integer.MAX_VALUE}; @@ -88,15 +87,13 @@ public class SSLSocketTest extends TestCase { * javax.net.ssl.SSLSocket#SSLSocket(InetAddress address, int port, * InetAddress clientAddress, int clientPort) */ - public void testConstructor_03() throws UnknownHostException, IOException { + public void testConstructor_InetAddressIInetAddressI() throws Exception { int sport = startServer("Cons InetAddress,I,InetAddress,I"); - int portNumber = Support_PortManager.getNextPort(); SSLSocket ssl = getSSLSocket(InetAddress.getLocalHost(), sport, - InetAddress.getLocalHost(), portNumber); + InetAddress.getLocalHost(), 0); assertNotNull(ssl); assertEquals(sport, ssl.getPort()); - assertEquals(portNumber, ssl.getLocalPort()); ssl.close(); try { @@ -137,7 +134,7 @@ public class SSLSocketTest extends TestCase { /** * javax.net.ssl.SSLSocket#SSLSocket(String host, int port) */ - public void testConstructor_04() throws UnknownHostException, IOException { + public void testConstructor_StringI() throws Exception { int sport = startServer("Cons String,I"); int[] invalidPort = {-1, Integer.MIN_VALUE, 65536, Integer.MAX_VALUE}; @@ -171,28 +168,25 @@ public class SSLSocketTest extends TestCase { * javax.net.ssl.SSLSocket#SSLSocket(String host, int port, InetAddress clientAddress, * int clientPort) */ - public void testConstructor_05() throws UnknownHostException, IOException { + public void testConstructor_StringIInetAddressI() throws Exception { int sport = startServer("Cons String,I,InetAddress,I"); - int portNumber = Support_PortManager.getNextPort(); int[] invalidPort = {-1, Integer.MIN_VALUE, 65536, Integer.MAX_VALUE}; SSLSocket ssl = getSSLSocket(InetAddress.getLocalHost().getHostName(), sport, - InetAddress.getLocalHost(), portNumber); + InetAddress.getLocalHost(), 0); assertNotNull(ssl); assertEquals(sport, ssl.getPort()); - assertEquals(portNumber, ssl.getLocalPort()); try { - getSSLSocket("localhost", 8081, InetAddress.getLocalHost(), 8082); + getSSLSocket(InetAddress.getLocalHost().getHostName(), 8081, InetAddress.getLocalHost(), 8082); fail(); } catch (IOException expected) { } for (int i = 0; i < invalidPort.length; i++) { - portNumber = Support_PortManager.getNextPort(); try { getSSLSocket(InetAddress.getLocalHost().getHostName(), invalidPort[i], - InetAddress.getLocalHost(), portNumber); + InetAddress.getLocalHost(), 0); fail(); } catch (IllegalArgumentException expected) { } @@ -204,9 +198,8 @@ public class SSLSocketTest extends TestCase { } } - portNumber = Support_PortManager.getNextPort(); try { - getSSLSocket("bla-bla", sport, InetAddress.getLocalHost(), portNumber); + getSSLSocket("bla-bla", sport, InetAddress.getLocalHost(), 0); fail(); } catch (UnknownHostException expected) { } @@ -422,12 +415,10 @@ public class SSLSocketTest extends TestCase { ssl.close(); } - boolean useBKS = !StandardNames.IS_RI; + private boolean useBKS = !StandardNames.IS_RI; private String PASSWORD = "android"; - private int port = Support_PortManager.getNextPort(); - private boolean serverReady = false; /** @@ -551,7 +542,7 @@ public class SSLSocketTest extends TestCase { SSLServerSocket serverSocket = (SSLServerSocket) sslContext.getServerSocketFactory().createServerSocket(); try { - serverSocket.bind(new InetSocketAddress(port)); + serverSocket.bind(new InetSocketAddress(0)); sport = serverSocket.getLocalPort(); serverReady = true; diff --git a/luni/src/test/java/tests/api/org/apache/harmony/kernel/dalvik/ThreadsTest.java b/luni/src/test/java/tests/api/org/apache/harmony/kernel/dalvik/ThreadsTest.java index 286d4ab..19c6229 100644 --- a/luni/src/test/java/tests/api/org/apache/harmony/kernel/dalvik/ThreadsTest.java +++ b/luni/src/test/java/tests/api/org/apache/harmony/kernel/dalvik/ThreadsTest.java @@ -17,7 +17,8 @@ package tests.api.org.apache.harmony.kernel.dalvik; import java.lang.reflect.Field; - +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.TimeUnit; import junit.framework.Assert; import junit.framework.TestCase; import sun.misc.Unsafe; @@ -27,8 +28,6 @@ import sun.misc.Unsafe; */ public class ThreadsTest extends TestCase { private static Unsafe UNSAFE = null; - private static RuntimeException INITIALIZEFAILED = null; - static { /* * Set up {@link #UNSAFE}. This subverts the access check to @@ -42,78 +41,94 @@ public class ThreadsTest extends TestCase { UNSAFE = (Unsafe) field.get(null); } catch (NoSuchFieldException ex) { - INITIALIZEFAILED = new RuntimeException(ex); + throw new RuntimeException(ex); } catch (IllegalAccessException ex) { - INITIALIZEFAILED = new RuntimeException(ex); + throw new RuntimeException(ex); } } /** Test the case where the park times out. */ - public void test_parkFor_1() { - Parker parker = new Parker(false, 500); + public void test_parkFor_1() throws Exception { + CyclicBarrier barrier = new CyclicBarrier(2); + Parker parker = new Parker(barrier, false, 500); Thread parkerThread = new Thread(parker); Thread waiterThread = - new Thread(new WaitAndUnpark(1000, parkerThread)); + new Thread(new WaitAndUnpark(barrier, 1000, parkerThread)); parkerThread.start(); waiterThread.start(); parker.assertDurationIsInRange(500); + waiterThread.join(); + parkerThread.join(); } /** Test the case where the unpark happens before the timeout. */ - public void test_parkFor_2() { - Parker parker = new Parker(false, 1000); + public void test_parkFor_2() throws Exception { + CyclicBarrier barrier = new CyclicBarrier(2); + Parker parker = new Parker(barrier, false, 1000); Thread parkerThread = new Thread(parker); Thread waiterThread = - new Thread(new WaitAndUnpark(300, parkerThread)); + new Thread(new WaitAndUnpark(barrier, 300, parkerThread)); parkerThread.start(); waiterThread.start(); parker.assertDurationIsInRange(300); + waiterThread.join(); + parkerThread.join(); } /** Test the case where the thread is preemptively unparked. */ - public void test_parkFor_3() { - Parker parker = new Parker(false, 1000); + public void test_parkFor_3() throws Exception { + CyclicBarrier barrier = new CyclicBarrier(1); + Parker parker = new Parker(barrier, false, 1000); Thread parkerThread = new Thread(parker); UNSAFE.unpark(parkerThread); parkerThread.start(); parker.assertDurationIsInRange(0); + parkerThread.join(); } /** Test the case where the park times out. */ - public void test_parkUntil_1() { - Parker parker = new Parker(true, 500); + public void test_parkUntil_1() throws Exception { + CyclicBarrier barrier = new CyclicBarrier(2); + Parker parker = new Parker(barrier, true, 500); Thread parkerThread = new Thread(parker); Thread waiterThread = - new Thread(new WaitAndUnpark(1000, parkerThread)); + new Thread(new WaitAndUnpark(barrier, 1000, parkerThread)); parkerThread.start(); waiterThread.start(); parker.assertDurationIsInRange(500); + waiterThread.join(); + parkerThread.join(); } /** Test the case where the unpark happens before the timeout. */ - public void test_parkUntil_2() { - Parker parker = new Parker(true, 1000); + public void test_parkUntil_2() throws Exception { + CyclicBarrier barrier = new CyclicBarrier(2); + Parker parker = new Parker(barrier, true, 1000); Thread parkerThread = new Thread(parker); Thread waiterThread = - new Thread(new WaitAndUnpark(300, parkerThread)); + new Thread(new WaitAndUnpark(barrier, 300, parkerThread)); parkerThread.start(); waiterThread.start(); parker.assertDurationIsInRange(300); + waiterThread.join(); + parkerThread.join(); } /** Test the case where the thread is preemptively unparked. */ - public void test_parkUntil_3() { - Parker parker = new Parker(true, 1000); + public void test_parkUntil_3() throws Exception { + CyclicBarrier barrier = new CyclicBarrier(1); + Parker parker = new Parker(barrier, true, 1000); Thread parkerThread = new Thread(parker); UNSAFE.unpark(parkerThread); parkerThread.start(); parker.assertDurationIsInRange(0); + parkerThread.join(); } // TODO: Add more tests. @@ -123,6 +138,9 @@ public class ThreadsTest extends TestCase { * the indicated value, noting the duration of time actually parked. */ private static class Parker implements Runnable { + + private final CyclicBarrier barrier; + /** whether {@link #amount} is milliseconds to wait in an * absolute fashion (<code>true</code>) or nanoseconds to wait * in a relative fashion (<code>false</code>) */ @@ -147,7 +165,8 @@ public class ThreadsTest extends TestCase { * either case, this constructor takes a duration to park for * @param parkMillis the number of milliseconds to be parked */ - public Parker(boolean absolute, long parkMillis) { + public Parker(CyclicBarrier barrier, boolean absolute, long parkMillis) { + this.barrier = barrier; this.absolute = absolute; // Multiply by 1000000 because parkFor() takes nanoseconds. @@ -155,8 +174,14 @@ public class ThreadsTest extends TestCase { } public void run() { + try { + barrier.await(60, TimeUnit.SECONDS); + } catch (Exception e) { + throw new AssertionError(e); + } boolean absolute = this.absolute; long amount = this.amount; + long startNanos = System.nanoTime(); long start = System.currentTimeMillis(); if (absolute) { @@ -165,11 +190,11 @@ public class ThreadsTest extends TestCase { UNSAFE.park(false, amount); } - long end = System.currentTimeMillis(); + long endNanos = System.nanoTime(); synchronized (this) { - startMillis = start; - endMillis = end; + startMillis = startNanos / 1000000; + endMillis = endNanos / 1000000; completed = true; notifyAll(); } @@ -187,11 +212,10 @@ public class ThreadsTest extends TestCase { if (! completed) { try { wait(maxWaitMillis); - } catch (InterruptedException ex) { - // Ignore it. + } catch (InterruptedException ignored) { } if (! completed) { - Assert.fail("parker hanging"); + Assert.fail("parker hung for more than " + maxWaitMillis + " ms"); } } @@ -200,7 +224,7 @@ public class ThreadsTest extends TestCase { } /** - * Asserts that the actual duration is within 5% of the + * Asserts that the actual duration is within 10% of the * given expected time. * * @param expectedMillis the expected duration, in milliseconds @@ -210,18 +234,20 @@ public class ThreadsTest extends TestCase { * Allow a bit more slop for the maximum on "expected * instantaneous" results. */ - long minimum = (long) ((double) expectedMillis * 0.95); + long minimum = (long) ((double) expectedMillis * 0.90); long maximum = - Math.max((long) ((double) expectedMillis * 1.05), 10); + Math.max((long) ((double) expectedMillis * 1.10), 10); long waitMillis = Math.max(expectedMillis * 10, 10); long duration = getDurationMillis(waitMillis); if (duration < minimum) { Assert.fail("expected duration: " + expectedMillis + - "; actual too short: " + duration); + " minimum duration: " + minimum + + " actual duration too short: " + duration); } else if (duration > maximum) { Assert.fail("expected duration: " + expectedMillis + - "; actual too long: " + duration); + " maximum duration: " + maximum + + " actual duration too long: " + duration); } } } @@ -231,16 +257,23 @@ public class ThreadsTest extends TestCase { * specified amount of time and then unparks an indicated thread. */ private static class WaitAndUnpark implements Runnable { + private final CyclicBarrier barrier; private final long waitMillis; private final Thread thread; - public WaitAndUnpark(long waitMillis, Thread thread) { + public WaitAndUnpark(CyclicBarrier barrier, long waitMillis, Thread thread) { + this.barrier = barrier; this.waitMillis = waitMillis; this.thread = thread; } public void run() { try { + barrier.await(60, TimeUnit.SECONDS); + } catch (Exception e) { + throw new AssertionError(e); + } + try { Thread.sleep(waitMillis); } catch (InterruptedException ex) { throw new RuntimeException("shouldn't happen", ex); @@ -249,11 +282,4 @@ public class ThreadsTest extends TestCase { UNSAFE.unpark(thread); } } - - @Override - protected void setUp() throws Exception { - if (INITIALIZEFAILED != null) { - throw INITIALIZEFAILED; - } - } } |