1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package org.apache.harmony.testframework; 19 20import junit.framework.Assert; 21import junit.framework.TestCase; 22import junit.framework.TestSuite; 23 24import java.io.IOException; 25import java.io.OutputStream; 26import java.util.Arrays; 27import java.util.Random; 28 29/** 30 * Tests behaviour common to all implementations of {@link OutputStream}. This 31 * adapts streams that collects untransformed bytes so that they may be tested. 32 */ 33public abstract class SinkTester { 34 35 private boolean throwsExceptions = true; 36 37 /** 38 * Creates a new output stream ready to receive an arbitrary number of 39 * bytes. Each time this method is invoked, any previously returned output 40 * streams may be discarded. 41 */ 42 public abstract OutputStream create() throws Exception; 43 44 /** 45 * Returns the current set of bytes written to the output stream last 46 * returned by {@link #create}, and releases any resources held by that 47 * stream. 48 */ 49 public abstract byte[] getBytes() throws Exception; 50 51 /** 52 * Configures whether the stream is expected to throw exceptions when an 53 * error is encountered. Classes like {@code PrintStream} report errors via 54 * an API method instead. 55 */ 56 public SinkTester setThrowsExceptions(boolean throwsExceptions) { 57 this.throwsExceptions = throwsExceptions; 58 return this; 59 } 60 61 public final TestSuite createTests() { 62 TestSuite result = new TestSuite(); 63 result.addTest(new SinkTestCase("sinkTestNoWriting")); 64 result.addTest(new SinkTestCase("sinkTestWriteZeroBytes")); 65 result.addTest(new SinkTestCase("sinkTestWriteByteByByte")); 66 result.addTest(new SinkTestCase("sinkTestWriteArray")); 67 result.addTest(new SinkTestCase("sinkTestWriteOffset")); 68 result.addTest(new SinkTestCase("sinkTestWriteLargeArray")); 69 70 if (throwsExceptions) { 71 result.addTest(new SinkTestCase("sinkTestWriteAfterClose")); 72 } else { 73 result.addTest(new SinkTestCase("sinkTestWriteAfterCloseSuppressed")); 74 } 75 76 return result; 77 } 78 79 @Override public String toString() { 80 return getClass().getName(); 81 } 82 83 private static void assertArrayEquals(byte[] expected, byte[] actual) { 84 Assert.assertEquals(Arrays.toString(expected), Arrays.toString(actual)); 85 } 86 87 public class SinkTestCase extends TestCase { 88 89 private SinkTestCase(String name) { 90 super(name); 91 } 92 93 public void sinkTestNoWriting() throws Exception { 94 byte[] expected = new byte[] {}; 95 96 OutputStream out = create(); 97 out.close(); 98 assertArrayEquals(expected, getBytes()); 99 } 100 101 public void sinkTestWriteZeroBytes() throws Exception { 102 byte[] expected = new byte[] {}; 103 104 OutputStream out = create(); 105 byte[] a = new byte[1024]; 106 out.write(a, 1000, 0); 107 out.write(a, 0, 0); 108 out.write(new byte[] {}); 109 110 out.close(); 111 assertArrayEquals(expected, getBytes()); 112 } 113 114 public void sinkTestWriteByteByByte() throws Exception { 115 byte[] expected = new byte[] { 5, 6, 7, 3, 4, 5, 3, 2, 1 }; 116 117 OutputStream out = create(); 118 for (byte b : expected) { 119 out.write(b); 120 } 121 122 out.close(); 123 assertArrayEquals(expected, getBytes()); 124 } 125 126 public void sinkTestWriteArray() throws Exception { 127 byte[] expected = new byte[] { 128 5, 6, 129 7, 3, 4, 5, 130 3, 2, 1 131 }; 132 133 OutputStream out = create(); 134 135 byte[] a = new byte[] { 5, 6 }; 136 out.write(a); 137 138 byte[] b = new byte[] { 7, 3, 4, 5 }; 139 out.write(b); 140 141 byte[] c = new byte[] { 3, 2, 1 }; 142 out.write(c); 143 144 out.close(); 145 assertArrayEquals(expected, getBytes()); 146 } 147 148 public void sinkTestWriteOffset() throws Exception { 149 byte[] expected = new byte[] { 150 5, 6, 151 7, 3, 4, 5, 152 3, 2, 1 153 }; 154 155 OutputStream out = create(); 156 157 byte[] a = new byte[1024]; 158 a[1000] = 5; 159 a[1001] = 6; 160 out.write(a, 1000, 2); 161 162 byte[] b = new byte[1024]; 163 b[1020] = 7; 164 b[1021] = 3; 165 b[1022] = 4; 166 b[1023] = 5; 167 out.write(b, 1020, 4); 168 169 byte[] c = new byte[1024]; 170 c[0] = 3; 171 c[1] = 2; 172 c[2] = 1; 173 out.write(c, 0, 3); 174 175 out.close(); 176 assertArrayEquals(expected, getBytes()); 177 } 178 179 public void sinkTestWriteLargeArray() throws Exception { 180 byte[] expected = new byte[(1024 * 1024) + 1]; // 1 MB + 1 byte 181 new Random().nextBytes(expected); 182 183 OutputStream out = create(); 184 out.write(expected); 185 out.close(); 186 187 assertArrayEquals(expected, getBytes()); 188 } 189 190 public void sinkTestWriteAfterClose() throws Exception { 191 byte[] expectedBytes = { 5, 6 }; 192 OutputStream out = create(); 193 194 out.write(expectedBytes); 195 out.close(); 196 197 try { 198 out.write(new byte[] { 7, 3, 4, 5 }); 199 fail("expected already closed exception"); 200 } catch (IOException expected) { 201 } 202 203 assertArrayEquals(expectedBytes, getBytes()); 204 } 205 206 public void sinkTestWriteAfterCloseSuppressed() throws Exception { 207 OutputStream out = create(); 208 out.write(new byte[] { 5, 6 }); 209 out.close(); 210 out.write(new byte[] { 7, 3, 4, 5 }); // no exception expected! 211 } 212 213 // adding a new test? Don't forget to update createTests(). 214 215 @Override public String getName() { 216 return SinkTester.this.toString() + ":" + super.getName(); 217 } 218 } 219} 220