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 package org.apache.harmony.luni.tests.java.io; 18 19 import java.io.IOException; 20 import java.io.PipedInputStream; 21 import java.io.PipedOutputStream; 22 23 public class PipedInputStreamTest extends junit.framework.TestCase { 24 25 static class PWriter implements Runnable { 26 PipedOutputStream pos; 27 28 public byte bytes[]; 29 run()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 PWriter(PipedOutputStream pout, int nbytes)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 51 Thread t; 52 53 PWriter pw; 54 55 PipedInputStream pis; 56 57 PipedOutputStream pos; 58 59 /** 60 * @tests java.io.PipedInputStream#PipedInputStream() 61 */ test_Constructor()62 public void test_Constructor() { 63 // Test for method java.io.PipedInputStream() 64 // Used in tests 65 } 66 67 /** 68 * @tests java.io.PipedInputStream#PipedInputStream(java.io.PipedOutputStream) 69 */ test_ConstructorLjava_io_PipedOutputStream()70 public void test_ConstructorLjava_io_PipedOutputStream() throws Exception { 71 // Test for method java.io.PipedInputStream(java.io.PipedOutputStream) 72 pis = new PipedInputStream(new PipedOutputStream()); 73 pis.available(); 74 } 75 76 77 /** 78 * @test java.io.PipedInputStream#read() 79 */ test_readException()80 public void test_readException() throws IOException { 81 pis = new PipedInputStream(); 82 pos = new PipedOutputStream(); 83 84 try { 85 pis.connect(pos); 86 t = new Thread(pw = new PWriter(pos, 1000)); 87 t.start(); 88 while (true) { 89 pis.read(); 90 t.interrupt(); 91 } 92 } catch (IOException expected) { 93 } finally { 94 try { 95 pis.close(); 96 pos.close(); 97 } catch (IOException ee) {} 98 } 99 } 100 101 /** 102 * @tests java.io.PipedInputStream#available() 103 */ test_available()104 public void test_available() throws Exception { 105 pis = new PipedInputStream(); 106 pos = new PipedOutputStream(); 107 108 pis.connect(pos); 109 t = new Thread(pw = new PWriter(pos, 1000)); 110 t.start(); 111 112 synchronized (pw) { 113 pw.wait(10000); 114 } 115 assertTrue("Available returned incorrect number of bytes: " 116 + pis.available(), pis.available() == 1000); 117 118 PipedInputStream pin = new PipedInputStream(); 119 PipedOutputStream pout = new PipedOutputStream(pin); 120 // We know the PipedInputStream buffer size is 1024. 121 // Writing another byte would cause the write to wait 122 // for a read before returning 123 for (int i = 0; i < 1024; i++) { 124 pout.write(i); 125 } 126 assertEquals("Incorrect available count", 1024 , pin.available()); 127 } 128 129 /** 130 * @tests java.io.PipedInputStream#close() 131 */ test_close()132 public void test_close() throws IOException { 133 // Test for method void java.io.PipedInputStream.close() 134 pis = new PipedInputStream(); 135 pos = new PipedOutputStream(); 136 pis.connect(pos); 137 pis.close(); 138 try { 139 pos.write((byte) 127); 140 fail("Failed to throw expected exception"); 141 } catch (IOException e) { 142 // The spec for PipedInput saya an exception should be thrown if 143 // a write is attempted to a closed input. The PipedOuput spec 144 // indicates that an exception should be thrown only when the 145 // piped input thread is terminated without closing 146 return; 147 } 148 } 149 150 /** 151 * @tests java.io.PipedInputStream#connect(java.io.PipedOutputStream) 152 */ test_connectLjava_io_PipedOutputStream()153 public void test_connectLjava_io_PipedOutputStream() throws Exception { 154 pis = new PipedInputStream(); 155 pos = new PipedOutputStream(); 156 assertEquals("Non-conected pipe returned non-zero available bytes", 0, 157 pis.available()); 158 159 pis.connect(pos); 160 t = new Thread(pw = new PWriter(pos, 1000)); 161 t.start(); 162 163 synchronized (pw) { 164 pw.wait(10000); 165 } 166 assertEquals("Available returned incorrect number of bytes", 1000, pis 167 .available()); 168 } 169 170 /** 171 * @tests java.io.PipedInputStream#read() 172 */ test_read()173 public void test_read() throws Exception { 174 pis = new PipedInputStream(); 175 pos = new PipedOutputStream(); 176 177 pis.connect(pos); 178 t = new Thread(pw = new PWriter(pos, 1000)); 179 t.start(); 180 181 synchronized (pw) { 182 pw.wait(10000); 183 } 184 assertEquals("Available returned incorrect number of bytes", 1000, pis 185 .available()); 186 assertEquals("read returned incorrect byte", pw.bytes[0], (byte) pis 187 .read()); 188 } 189 190 /** 191 * @tests java.io.PipedInputStream#read(byte[], int, int) 192 */ test_read$BII()193 public void test_read$BII() throws Exception { 194 pis = new PipedInputStream(); 195 pos = new PipedOutputStream(); 196 197 pis.connect(pos); 198 t = new Thread(pw = new PWriter(pos, 1000)); 199 t.start(); 200 201 byte[] buf = new byte[400]; 202 synchronized (pw) { 203 pw.wait(10000); 204 } 205 assertTrue("Available returned incorrect number of bytes: " 206 + pis.available(), pis.available() == 1000); 207 pis.read(buf, 0, 400); 208 for (int i = 0; i < 400; i++) { 209 assertEquals("read returned incorrect byte[]", pw.bytes[i], buf[i]); 210 } 211 } 212 213 /** 214 * @tests java.io.PipedInputStream#read(byte[], int, int) 215 * Regression for HARMONY-387 216 */ test_read$BII_2()217 public void test_read$BII_2() throws IOException { 218 PipedInputStream obj = new PipedInputStream(); 219 try { 220 obj.read(new byte[0], 0, -1); 221 fail(); 222 } catch (IndexOutOfBoundsException expected) { 223 } 224 } 225 226 /** 227 * @tests java.io.PipedInputStream#read(byte[], int, int) 228 */ test_read$BII_3()229 public void test_read$BII_3() throws IOException { 230 PipedInputStream obj = new PipedInputStream(); 231 try { 232 obj.read(new byte[0], -1, 0); 233 fail(); 234 } catch (IndexOutOfBoundsException expected) { 235 } 236 } 237 238 /** 239 * @tests java.io.PipedInputStream#read(byte[], int, int) 240 */ test_read$BII_4()241 public void test_read$BII_4() throws IOException { 242 PipedInputStream obj = new PipedInputStream(); 243 try { 244 obj.read(new byte[0], -1, -1); 245 fail(); 246 } catch (IndexOutOfBoundsException expected) { 247 } 248 } 249 250 /** 251 * @tests java.io.PipedInputStream#receive(int) 252 */ test_receive()253 public void test_receive() throws IOException { 254 pis = new PipedInputStream(); 255 pos = new PipedOutputStream(); 256 257 // test if writer recognizes dead reader 258 pis.connect(pos); 259 class WriteRunnable implements Runnable { 260 261 boolean pass = false; 262 263 volatile boolean readerAlive = true; 264 265 public void run() { 266 try { 267 pos.write(1); 268 while (readerAlive) { 269 ; 270 } 271 try { 272 // should throw exception since reader thread 273 // is now dead 274 pos.write(1); 275 } catch (IOException e) { 276 pass = true; 277 } 278 } catch (IOException e) { 279 } 280 } 281 } 282 WriteRunnable writeRunnable = new WriteRunnable(); 283 Thread writeThread = new Thread(writeRunnable); 284 class ReadRunnable implements Runnable { 285 286 boolean pass; 287 288 public void run() { 289 try { 290 pis.read(); 291 pass = true; 292 } catch (IOException e) { 293 } 294 } 295 } 296 ; 297 ReadRunnable readRunnable = new ReadRunnable(); 298 Thread readThread = new Thread(readRunnable); 299 writeThread.start(); 300 readThread.start(); 301 while (readThread.isAlive()) { 302 ; 303 } 304 writeRunnable.readerAlive = false; 305 assertTrue("reader thread failed to read", readRunnable.pass); 306 while (writeThread.isAlive()) { 307 ; 308 } 309 assertTrue("writer thread failed to recognize dead reader", 310 writeRunnable.pass); 311 312 // attempt to write to stream after writer closed 313 pis = new PipedInputStream(); 314 pos = new PipedOutputStream(); 315 316 pis.connect(pos); 317 class MyRunnable implements Runnable { 318 319 boolean pass; 320 321 public void run() { 322 try { 323 pos.write(1); 324 } catch (IOException e) { 325 pass = true; 326 } 327 } 328 } 329 MyRunnable myRun = new MyRunnable(); 330 synchronized (pis) { 331 t = new Thread(myRun); 332 // thread t will be blocked inside pos.write(1) 333 // when it tries to call the synchronized method pis.receive 334 // because we hold the monitor for object pis 335 t.start(); 336 try { 337 // wait for thread t to get to the call to pis.receive 338 Thread.sleep(100); 339 } catch (InterruptedException e) { 340 } 341 // now we close 342 pos.close(); 343 } 344 // we have exited the synchronized block, so now thread t will make 345 // a call to pis.receive AFTER the output stream was closed, 346 // in which case an IOException should be thrown 347 while (t.isAlive()) { 348 ; 349 } 350 assertTrue( 351 "write failed to throw IOException on closed PipedOutputStream", 352 myRun.pass); 353 } 354 355 static class Worker extends Thread { 356 PipedOutputStream out; 357 Worker(PipedOutputStream pos)358 Worker(PipedOutputStream pos) { 359 this.out = pos; 360 } 361 run()362 public void run() { 363 try { 364 out.write(20); 365 out.close(); 366 Thread.sleep(5000); 367 } catch (Exception e) { 368 } 369 } 370 } 371 test_read_after_write_close()372 public void test_read_after_write_close() throws Exception{ 373 PipedInputStream in = new PipedInputStream(); 374 PipedOutputStream out = new PipedOutputStream(); 375 in.connect(out); 376 Thread worker = new Worker(out); 377 worker.start(); 378 Thread.sleep(2000); 379 assertEquals("Should read 20.", 20, in.read()); 380 worker.join(); 381 assertEquals("Write end is closed, should return -1", -1, in.read()); 382 byte[] buf = new byte[1]; 383 assertEquals("Write end is closed, should return -1", -1, in.read(buf, 0, 1)); 384 assertEquals("Buf len 0 should return first", 0, in.read(buf, 0, 0)); 385 in.close(); 386 out.close(); 387 } 388 389 /** 390 * Tears down the fixture, for example, close a network connection. This 391 * method is called after a test is executed. 392 */ tearDown()393 protected void tearDown() throws Exception { 394 try { 395 if (t != null) { 396 t.interrupt(); 397 } 398 } catch (Exception ignore) { 399 } 400 super.tearDown(); 401 } 402 403 404 /** 405 * @tests java.io.PipedInputStream#PipedInputStream(java.io.PipedOutputStream, 406 * int) 407 * @since 1.6 408 */ test_Constructor_LPipedOutputStream_I()409 public void test_Constructor_LPipedOutputStream_I() throws Exception { 410 // Test for method java.io.PipedInputStream(java.io.PipedOutputStream, 411 // int) 412 MockPipedInputStream mpis = new MockPipedInputStream( 413 new PipedOutputStream(), 100); 414 int bufferLength = mpis.bufferLength(); 415 assertEquals(100, bufferLength); 416 417 try { 418 pis = new PipedInputStream(null, -1); 419 fail("Should throw IllegalArgumentException"); //$NON-NLS-1$ 420 } catch (IllegalArgumentException e) { 421 // expected 422 } 423 424 try { 425 pis = new PipedInputStream(null, 0); 426 fail("Should throw IllegalArgumentException"); //$NON-NLS-1$ 427 } catch (IllegalArgumentException e) { 428 // expected 429 } 430 } 431 432 /** 433 * @tests java.io.PipedInputStream#PipedInputStream(int) 434 * @since 1.6 435 */ test_Constructor_I()436 public void test_Constructor_I() throws Exception { 437 // Test for method java.io.PipedInputStream(int) 438 MockPipedInputStream mpis = new MockPipedInputStream(100); 439 int bufferLength = mpis.bufferLength(); 440 assertEquals(100, bufferLength); 441 442 try { 443 pis = new PipedInputStream(-1); 444 fail("Should throw IllegalArgumentException"); //$NON-NLS-1$ 445 } catch (IllegalArgumentException e) { 446 // expected 447 } 448 449 try { 450 pis = new PipedInputStream(0); 451 fail("Should throw IllegalArgumentException"); //$NON-NLS-1$ 452 } catch (IllegalArgumentException e) { 453 // expected 454 } 455 } 456 457 static class MockPipedInputStream extends PipedInputStream { 458 MockPipedInputStream(java.io.PipedOutputStream src, int bufferSize)459 public MockPipedInputStream(java.io.PipedOutputStream src, 460 int bufferSize) throws IOException { 461 super(src, bufferSize); 462 } 463 MockPipedInputStream(int bufferSize)464 public MockPipedInputStream(int bufferSize) { 465 super(bufferSize); 466 } 467 bufferLength()468 public int bufferLength() { 469 return super.buffer.length; 470 } 471 } 472 } 473