PipedInputStreamTest.java revision 2ad60cfc28e14ee8f0bb038720836a4696c478ad
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 */ 17package tests.api.java.io; 18 19import java.io.IOException; 20import java.io.PipedInputStream; 21import java.io.PipedOutputStream; 22 23public class PipedInputStreamTest extends junit.framework.TestCase { 24 25 static class PWriter implements Runnable { 26 PipedOutputStream pos; 27 28 public byte bytes[]; 29 30 public void run() { 31 try { 32 pos.write(bytes); 33 synchronized (this) { 34 notify(); 35 } 36 } catch (IOException e) { 37 e.printStackTrace(System.out); 38 System.out.println("Could not write bytes"); 39 } 40 } 41 42 public PWriter(PipedOutputStream pout, int nbytes) { 43 pos = pout; 44 bytes = new byte[nbytes]; 45 for (int i = 0; i < bytes.length; i++) 46 bytes[i] = (byte) (System.currentTimeMillis() % 9); 47 } 48 } 49 50 Thread t; 51 52 PWriter pw; 53 54 PipedInputStream pis; 55 56 PipedOutputStream pos; 57 58 /** 59 * @tests java.io.PipedInputStream#PipedInputStream() 60 */ 61 public void test_Constructor() { 62 // Test for method java.io.PipedInputStream() 63 // Used in tests 64 } 65 66 /** 67 * @tests java.io.PipedInputStream#PipedInputStream(java.io.PipedOutputStream) 68 */ 69 public void test_ConstructorLjava_io_PipedOutputStream() throws Exception { 70 // Test for method java.io.PipedInputStream(java.io.PipedOutputStream) 71 pis = new PipedInputStream(new PipedOutputStream()); 72 pis.available(); 73 } 74 75 /** 76 * @tests java.io.PipedInputStream#available() 77 */ 78 public void test_available() throws Exception { 79 // Test for method int java.io.PipedInputStream.available() 80 pis = new PipedInputStream(); 81 pos = new PipedOutputStream(); 82 83 pis.connect(pos); 84 t = new Thread(pw = new PWriter(pos, 1000)); 85 t.start(); 86 87 synchronized (pw) { 88 pw.wait(10000); 89 } 90 assertTrue("Available returned incorrect number of bytes: " 91 + pis.available(), pis.available() == 1000); 92 93 PipedInputStream pin = new PipedInputStream(); 94 PipedOutputStream pout = new PipedOutputStream(pin); 95 // We know the PipedInputStream buffer size is 1024. 96 // Writing another byte would cause the write to wait 97 // for a read before returning 98 for (int i = 0; i < 1024; i++) 99 pout.write(i); 100 assertEquals("Incorrect available count", 1024 , pin.available()); 101 } 102 103 /** 104 * @tests java.io.PipedInputStream#close() 105 */ 106 public void test_close() throws IOException { 107 // Test for method void java.io.PipedInputStream.close() 108 pis = new PipedInputStream(); 109 pos = new PipedOutputStream(); 110 pis.connect(pos); 111 pis.close(); 112 try { 113 pos.write((byte) 127); 114 fail("Failed to throw expected exception"); 115 } catch (IOException e) { 116 // The spec for PipedInput saya an exception should be thrown if 117 // a write is attempted to a closed input. The PipedOuput spec 118 // indicates that an exception should be thrown only when the 119 // piped input thread is terminated without closing 120 return; 121 } 122 } 123 124 /** 125 * @tests java.io.PipedInputStream#connect(java.io.PipedOutputStream) 126 */ 127 public void test_connectLjava_io_PipedOutputStream() throws Exception { 128 // Test for method void 129 // java.io.PipedInputStream.connect(java.io.PipedOutputStream) 130 pis = new PipedInputStream(); 131 pos = new PipedOutputStream(); 132 assertEquals("Non-conected pipe returned non-zero available bytes", 0, 133 pis.available()); 134 135 pis.connect(pos); 136 t = new Thread(pw = new PWriter(pos, 1000)); 137 t.start(); 138 139 synchronized (pw) { 140 pw.wait(10000); 141 } 142 assertEquals("Available returned incorrect number of bytes", 1000, pis 143 .available()); 144 } 145 146 /** 147 * @tests java.io.PipedInputStream#read() 148 */ 149 public void test_read() throws Exception { 150 // Test for method int java.io.PipedInputStream.read() 151 pis = new PipedInputStream(); 152 pos = new PipedOutputStream(); 153 154 pis.connect(pos); 155 t = new Thread(pw = new PWriter(pos, 1000)); 156 t.start(); 157 158 synchronized (pw) { 159 pw.wait(10000); 160 } 161 assertEquals("Available returned incorrect number of bytes", 1000, pis 162 .available()); 163 assertEquals("read returned incorrect byte", pw.bytes[0], (byte) pis 164 .read()); 165 } 166 167 /** 168 * @tests java.io.PipedInputStream#read(byte[], int, int) 169 */ 170 public void test_read$BII() throws Exception { 171 // Test for method int java.io.PipedInputStream.read(byte [], int, int) 172 pis = new PipedInputStream(); 173 pos = new PipedOutputStream(); 174 175 pis.connect(pos); 176 t = new Thread(pw = new PWriter(pos, 1000)); 177 t.start(); 178 179 byte[] buf = new byte[400]; 180 synchronized (pw) { 181 pw.wait(10000); 182 } 183 assertTrue("Available returned incorrect number of bytes: " 184 + pis.available(), pis.available() == 1000); 185 pis.read(buf, 0, 400); 186 for (int i = 0; i < 400; i++) { 187 assertEquals("read returned incorrect byte[]", pw.bytes[i], buf[i]); 188 } 189 } 190 191 /** 192 * @tests java.io.PipedInputStream#read(byte[], int, int) 193 * Regression for HARMONY-387 194 */ 195 public void test_read$BII_2() throws IOException { 196 PipedInputStream obj = new PipedInputStream(); 197 try { 198 obj.read(new byte[0], 0, -1); 199 fail("IndexOutOfBoundsException expected"); 200 } catch (IndexOutOfBoundsException t) { 201 assertEquals( 202 "IndexOutOfBoundsException rather than a subclass expected", 203 IndexOutOfBoundsException.class, t.getClass()); 204 } 205 } 206 207 /** 208 * @tests java.io.PipedInputStream#read(byte[], int, int) 209 */ 210 public void test_read$BII_3() throws IOException { 211 PipedInputStream obj = new PipedInputStream(); 212 try { 213 obj.read(new byte[0], -1, 0); 214 fail("IndexOutOfBoundsException expected"); 215 } catch (ArrayIndexOutOfBoundsException t) { 216 fail("IndexOutOfBoundsException expected"); 217 } catch (IndexOutOfBoundsException t) { 218 } 219 } 220 221 /** 222 * @tests java.io.PipedInputStream#read(byte[], int, int) 223 */ 224 public void test_read$BII_4() throws IOException { 225 PipedInputStream obj = new PipedInputStream(); 226 try { 227 obj.read(new byte[0], -1, -1); 228 fail("IndexOutOfBoundsException expected"); 229 } catch (ArrayIndexOutOfBoundsException t) { 230 fail("IndexOutOfBoundsException expected"); 231 } catch (IndexOutOfBoundsException t) { 232 } 233 } 234 235 /** 236 * @tests java.io.PipedInputStream#receive(int) 237 */ 238 public void test_receive() throws IOException { 239 pis = new PipedInputStream(); 240 pos = new PipedOutputStream(); 241 242 // test if writer recognizes dead reader 243 pis.connect(pos); 244 class WriteRunnable implements Runnable { 245 246 boolean pass = false; 247 248 boolean readerAlive = true; 249 250 public void run() { 251 try { 252 pos.write(1); 253 while (readerAlive) 254 ; 255 try { 256 // should throw exception since reader thread 257 // is now dead 258 pos.write(1); 259 } catch (IOException e) { 260 pass = true; 261 } 262 } catch (IOException e) {} 263 } 264 } 265 WriteRunnable writeRunnable = new WriteRunnable(); 266 Thread writeThread = new Thread(writeRunnable); 267 class ReadRunnable implements Runnable { 268 269 boolean pass; 270 271 public void run() { 272 try { 273 int one = pis.read(); 274 pass = true; 275 } catch (IOException e) {} 276 } 277 } 278 ; 279 ReadRunnable readRunnable = new ReadRunnable(); 280 Thread readThread = new Thread(readRunnable); 281 writeThread.start(); 282 readThread.start(); 283 while (readThread.isAlive()) 284 ; 285 writeRunnable.readerAlive = false; 286 assertTrue("reader thread failed to read", readRunnable.pass); 287 while (writeThread.isAlive()) 288 ; 289 assertTrue("writer thread failed to recognize dead reader", 290 writeRunnable.pass); 291 292 // attempt to write to stream after writer closed 293 pis = new PipedInputStream(); 294 pos = new PipedOutputStream(); 295 296 pis.connect(pos); 297 class MyRunnable implements Runnable { 298 299 boolean pass; 300 301 public void run() { 302 try { 303 pos.write(1); 304 } catch (IOException e) { 305 pass = true; 306 } 307 } 308 } 309 MyRunnable myRun = new MyRunnable(); 310 synchronized (pis) { 311 t = new Thread(myRun); 312 // thread t will be blocked inside pos.write(1) 313 // when it tries to call the synchronized method pis.receive 314 // because we hold the monitor for object pis 315 t.start(); 316 try { 317 // wait for thread t to get to the call to pis.receive 318 Thread.sleep(100); 319 } catch (InterruptedException e) {} 320 // now we close 321 pos.close(); 322 } 323 // we have exited the synchronized block, so now thread t will make 324 // a call to pis.receive AFTER the output stream was closed, 325 // in which case an IOException should be thrown 326 while (t.isAlive()) { 327 ; 328 } 329 assertTrue( 330 "write failed to throw IOException on closed PipedOutputStream", 331 myRun.pass); 332 } 333 334 /** 335 * Tears down the fixture, for example, close a network connection. This 336 * method is called after a test is executed. 337 */ 338 protected void tearDown() throws Exception { 339 try { 340 if (t != null) { 341 t.interrupt(); 342 } 343 } catch (Exception ignore) { 344 } 345 super.tearDown(); 346 } 347} 348