harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jessewil...@apache.org
Subject svn commit: r834317 - in /harmony/enhanced/classlib/trunk: modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/ support/src/test/java/org/apache/harmony/testframework/
Date Tue, 10 Nov 2009 03:12:06 GMT
Author: jessewilson
Date: Tue Nov 10 03:12:06 2009
New Revision: 834317

URL: http://svn.apache.org/viewvc?rev=834317&view=rev
Log:
A bunch of new tests for OutputStreams.

This uses composition to create many tests (86 tests in this case) with few lines of code.
This is most useful for things like OutputStream and Collection where there are multiple implementations
that satisfy the same core behaviour. I intend to eventually create a similar set of testers
for InputStreams, Readers and Writers. The main advantage of this style of test is that it
becomes easy to check that all implementations conform to a specified behaviour.

The motivation for this specific set is a bug in FilteredStream.flush(), where we are ignoring
an exception thrown by an underlying stream. These tests fail! There should be 7 new failures.
I intend to commit a change that has the fix tomorrow.

Added:
    harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/OutputStreamTesterTest.java
    harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/SinkTester.java
    harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/WrapperTester.java

Added: harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/OutputStreamTesterTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/OutputStreamTesterTest.java?rev=834317&view=auto
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/OutputStreamTesterTest.java
(added)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/OutputStreamTesterTest.java
Tue Nov 10 03:12:06 2009
@@ -0,0 +1,203 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.luni.tests.java.io;
+
+import junit.framework.TestSuite;
+import org.apache.harmony.testframework.SinkTester;
+import org.apache.harmony.testframework.WrapperTester;
+import tests.support.Streams;
+
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.io.PrintStream;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+/**
+ * Tests basic {@link OutputStream} behaviors for the luni implementations of
+ * the type.
+ */
+public class OutputStreamTesterTest {
+
+    public static junit.framework.Test suite() {
+        TestSuite suite = new TestSuite();
+
+        // sink tests
+        suite.addTest(new FileOutputStreamSinkTester(true).createTests());
+        suite.addTest(new FileOutputStreamSinkTester(false).createTests());
+        suite.addTest(new ByteArrayOutputStreamSinkTester(0).createTests());
+        suite.addTest(new ByteArrayOutputStreamSinkTester(4).createTests());
+        suite.addTest(new PipedOutputStreamSinkTester().createTests());
+
+        // wrapper tests
+        suite.addTest(new BufferedOutputStreamTester(1).createTests());
+        suite.addTest(new BufferedOutputStreamTester(5).createTests());
+        suite.addTest(new BufferedOutputStreamTester(1024).createTests());
+        suite.addTest(new FilterOutputStreamTester().createTests());
+        suite.addTest(new DataOutputStreamTester().createTests());
+        suite.addTest(new ObjectOutputStreamTester().createTests());
+        suite.addTest(new PrintStreamTester().createTests());
+
+        return suite;
+    }
+
+    public static class FileOutputStreamSinkTester extends SinkTester {
+
+        private final boolean append;
+        private File file;
+
+        private FileOutputStreamSinkTester(boolean append) {
+            this.append = append;
+        }
+
+        public OutputStream create() throws IOException {
+            file = File.createTempFile("FileOutputStreamSinkTester", "tmp");
+            file.deleteOnExit();
+            return new FileOutputStream(file, append);
+        }
+
+        public byte[] getBytes() throws IOException {
+            return Streams.bytesFromStream(new FileInputStream(file));
+        }
+    }
+
+    private static class ByteArrayOutputStreamSinkTester extends SinkTester {
+
+        private final int size;
+        private ByteArrayOutputStream stream;
+
+        private ByteArrayOutputStreamSinkTester(int size) {
+            this.size = size;
+        }
+
+        public OutputStream create() throws IOException {
+            stream = new ByteArrayOutputStream(size);
+            return stream;
+        }
+
+        public byte[] getBytes() throws IOException {
+            return stream.toByteArray();
+        }
+    }
+
+    private static class PipedOutputStreamSinkTester extends SinkTester {
+
+        private ExecutorService executor;
+        private Future<byte[]> future;
+
+        public OutputStream create() throws IOException {
+            final PipedInputStream in = new PipedInputStream();
+            PipedOutputStream out = new PipedOutputStream(in);
+
+            executor = Executors.newSingleThreadExecutor();
+            future = executor.submit(new Callable<byte[]>() {
+                final ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+                public byte[] call() throws Exception {
+                    byte[] buffer = new byte[256];
+                    int count;
+                    while ((count = in.read(buffer)) != -1) {
+                        bytes.write(buffer, 0, count);
+                    }
+                    return bytes.toByteArray();
+                }
+            });
+
+            return out;
+        }
+
+        public byte[] getBytes() throws Exception {
+            executor.shutdown();
+            return future.get();
+        }
+    }
+
+    private static class FilterOutputStreamTester extends WrapperTester {
+
+        public OutputStream create(OutputStream delegate) throws Exception {
+            return new FilterOutputStream(delegate);
+        }
+
+        public byte[] decode(byte[] delegateBytes) throws Exception {
+            return delegateBytes;
+        }
+    }
+
+    private static class BufferedOutputStreamTester extends WrapperTester {
+        private final int bufferSize;
+
+        private BufferedOutputStreamTester(int bufferSize) {
+            this.bufferSize = bufferSize;
+        }
+
+        public OutputStream create(OutputStream delegate) throws Exception {
+            return new BufferedOutputStream(delegate, bufferSize);
+        }
+
+        public byte[] decode(byte[] delegateBytes) throws Exception {
+            return delegateBytes;
+        }
+    }
+
+    private static class DataOutputStreamTester extends WrapperTester {
+
+        public OutputStream create(OutputStream delegate) throws Exception {
+            return new DataOutputStream(delegate);
+        }
+
+        public byte[] decode(byte[] delegateBytes) throws Exception {
+            return delegateBytes;
+        }
+    }
+
+    private static class ObjectOutputStreamTester extends WrapperTester {
+
+        public OutputStream create(OutputStream delegate) throws Exception {
+            return new ObjectOutputStream(delegate);
+        }
+
+        public byte[] decode(byte[] delegateBytes) throws Exception {
+            return Streams.bytesFromStream(new ObjectInputStream(
+                    new ByteArrayInputStream(delegateBytes)));
+        }
+    }
+
+    private static class PrintStreamTester extends WrapperTester {
+
+        public OutputStream create(OutputStream delegate) throws Exception {
+            return new PrintStream(delegate);
+        }
+
+        public byte[] decode(byte[] delegateBytes) throws Exception {
+            return delegateBytes;
+        }
+    }
+}

Added: harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/SinkTester.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/SinkTester.java?rev=834317&view=auto
==============================================================================
--- harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/SinkTester.java
(added)
+++ harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/SinkTester.java
Tue Nov 10 03:12:06 2009
@@ -0,0 +1,171 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.testframework;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.junit.Assert;
+
+import java.io.OutputStream;
+import java.util.Random;
+
+/**
+ * Tests behaviour common to all implementations of {@link OutputStream}. This
+ * adapts streams that collects untransformed bytes so that they may be tested.
+ */
+public abstract class SinkTester {
+
+    /**
+     * Creates a new output stream ready to receive an arbitrary number of
+     * bytes. Each time this method is invoked, any previously returned output
+     * streams may be discarded.
+     */
+    public abstract OutputStream create() throws Exception;
+
+    /**
+     * Returns the current set of bytes written to the output stream last
+     * returned by {@link #create}, and releases any resources held by that
+     * stream.
+     */
+    public abstract byte[] getBytes() throws Exception;
+
+    public final TestSuite createTests() {
+        TestSuite result = new TestSuite();
+        result.addTest(new SinkTestCase("sinkTestNoWriting"));
+        result.addTest(new SinkTestCase("sinkTestWriteZeroBytes"));
+        result.addTest(new SinkTestCase("sinkTestWriteByteByByte"));
+        result.addTest(new SinkTestCase("sinkTestWriteArray"));
+        result.addTest(new SinkTestCase("sinkTestWriteOffset"));
+        result.addTest(new SinkTestCase("sinkTestWriteLargeArray"));
+        return result;
+    }
+
+    @Override public String toString() {
+        return getClass().getName();
+    }
+
+    public class SinkTestCase extends TestCase {
+
+        private SinkTestCase(String name) {
+            super(name);
+        }
+
+        public void sinkTestNoWriting() throws Exception {
+            byte[] expected = new byte[] {};
+
+            OutputStream out = create();
+            out.close();
+            Assert.assertArrayEquals(expected, getBytes());
+        }
+
+        public void sinkTestWriteZeroBytes() throws Exception {
+            byte[] expected = new byte[] {};
+
+            OutputStream out = create();
+            byte[] a = new byte[1024];
+            out.write(a, 1000, 0);
+            out.write(a, 0, 0);
+            out.write(new byte[] {});
+
+            out.close();
+            Assert.assertArrayEquals(expected, getBytes());
+        }
+
+        public void sinkTestWriteByteByByte() throws Exception {
+            byte[] expected = new byte[] { 5, 6, 7, 3, 4, 5, 3, 2, 1 };
+
+            OutputStream out = create();
+            for (byte b : expected) {
+                out.write(b);
+            }
+
+            out.close();
+            Assert.assertArrayEquals(expected, getBytes());
+        }
+
+        public void sinkTestWriteArray() throws Exception {
+            byte[] expected = new byte[] {
+                    5, 6,
+                    7, 3, 4, 5,
+                    3, 2, 1
+            };
+
+            OutputStream out = create();
+
+            byte[] a = new byte[] { 5, 6 };
+            out.write(a);
+
+            byte[] b = new byte[] { 7, 3, 4, 5 };
+            out.write(b);
+
+            byte[] c = new byte[] { 3, 2, 1 };
+            out.write(c);
+
+            out.close();
+            Assert.assertArrayEquals(expected, getBytes());
+        }
+
+        public void sinkTestWriteOffset() throws Exception {
+            byte[] expected = new byte[] {
+                    5, 6,
+                    7, 3, 4, 5,
+                    3, 2, 1
+            };
+
+            OutputStream out = create();
+
+            byte[] a = new byte[1024];
+            a[1000] = 5;
+            a[1001] = 6;
+            out.write(a, 1000, 2);
+
+            byte[] b = new byte[1024];
+            b[1020] = 7;
+            b[1021] = 3;
+            b[1022] = 4;
+            b[1023] = 5;
+            out.write(b, 1020, 4);
+
+            byte[] c = new byte[1024];
+            c[0] = 3;
+            c[1] = 2;
+            c[2] = 1;
+            out.write(c, 0, 3);
+
+            out.close();
+            Assert.assertArrayEquals(expected, getBytes());
+        }
+
+        public void sinkTestWriteLargeArray() throws Exception {
+            byte[] expected = new byte[(1024 * 1024) + 1]; // 1 MB + 1 byte
+            new Random().nextBytes(expected);
+
+            OutputStream out = create();
+            out.write(expected);
+            out.close();
+
+            Assert.assertArrayEquals(expected, getBytes());
+        }
+
+        // adding a new test? Don't forget to update createTests().
+
+        @Override public String getName() {
+            return SinkTester.this.toString() + ":" + super.getName();
+        }
+    }
+}

Added: harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/WrapperTester.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/WrapperTester.java?rev=834317&view=auto
==============================================================================
--- harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/WrapperTester.java
(added)
+++ harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/WrapperTester.java
Tue Nov 10 03:12:06 2009
@@ -0,0 +1,135 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.testframework;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Tests behaviour common to wrapping and filtering implementations of {@link
+ * OutputStream}.
+ */
+public abstract class WrapperTester {
+
+    /**
+     * Creates a new output stream that receives one stream of bytes, optionally
+     * transforms it, and emits another stream of bytes to {@code delegate}.
+     */
+    public abstract OutputStream create(OutputStream delegate) throws Exception;
+
+    /**
+     * Decodes the bytes received by the delegate into their original form: the
+     * bytes originally received by this wrapper.
+     */
+    public abstract byte[] decode(byte[] delegateBytes) throws Exception;
+
+    public final TestSuite createTests() {
+        TestSuite result = new TestSuite();
+        result.addTest(new WrapperSinkTester().createTests());
+        result.addTest(new WrapperTestCase("wrapperTestFlushThrowsViaFlush"));
+        result.addTest(new WrapperTestCase("wrapperTestFlushThrowsViaClose"));
+        return result;
+    }
+
+    @Override public String toString() {
+        return getClass().getName();
+    }
+
+    private class WrapperSinkTester extends SinkTester {
+        private ByteArrayOutputStream delegate;
+
+        @Override public OutputStream create() throws Exception {
+            delegate = new ByteArrayOutputStream();
+            return WrapperTester.this.create(delegate);
+        }
+
+        @Override public byte[] getBytes() throws Exception {
+            return WrapperTester.this.decode(delegate.toByteArray());
+        }
+
+        @Override public String toString() {
+            return WrapperTester.this.toString();
+        }
+    }
+
+    public class WrapperTestCase extends TestCase {
+
+        private WrapperTestCase(String name) {
+            super(name);
+        }
+
+        public void wrapperTestFlushThrowsViaFlush() throws Exception {
+            FailOnFlushOutputStream delegate = new FailOnFlushOutputStream();
+
+            OutputStream o = create(delegate);
+            try {
+                // any of these is permitted to flush
+                o.write(new byte[] { 8, 6, 7, 5 });
+                o.write(new byte[] { 3, 0, 9 });
+                o.flush();
+                assertTrue(delegate.flushed);
+                fail("flush exception ignored");
+            } catch (IOException expected) {
+                assertEquals("Flush failed" , expected.getMessage());
+            }
+        }
+
+        public void wrapperTestFlushThrowsViaClose() throws Exception {
+            FailOnFlushOutputStream delegate = new FailOnFlushOutputStream();
+
+            OutputStream o = create(delegate);
+            try {
+                // any of these is permitted to flush
+                o.write(new byte[] { 8, 6, 7, 5 });
+                o.write(new byte[] { 3, 0, 9 });
+                o.close();
+                assertTrue(delegate.flushed);
+                fail("flush exception ignored");
+            } catch (IOException expected) {
+                assertEquals("Flush failed" , expected.getMessage());
+            }
+        }
+
+        // adding a new test? Don't forget to update createTests().
+
+        @Override public String getName() {
+            return WrapperTester.this.toString() + ":" + super.getName();
+        }
+
+        private class FailOnFlushOutputStream extends ByteArrayOutputStream {
+            boolean flushed = false;
+
+            @Override public void close() throws IOException {
+                flush();
+                super.close();
+            }
+
+            @Override public void flush() throws IOException {
+                if (!flushed) {
+                    flushed = true;
+                    throw new IOException("Flush failed");
+                }
+                super.flush();
+            }
+        }
+    }
+}



Mime
View raw message