PipedInputStreamTest.java revision e09ba12220c2cbbe9d91514da4d0f8fd8543b239
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 23import dalvik.annotation.TestLevel; 24import dalvik.annotation.TestTargetClass; 25import dalvik.annotation.TestTargetNew; 26 27@TestTargetClass(PipedInputStream.class) 28public class PipedInputStreamTest extends junit.framework.TestCase { 29 30 private final int BUFFER_SIZE = 1024; 31 32 static class PWriter implements Runnable { 33 PipedOutputStream pos; 34 35 public byte bytes[]; 36 37 public void run() { 38 try { 39 pos.write(bytes); 40 synchronized (this) { 41 notify(); 42 } 43 } catch (Exception e) { 44 e.printStackTrace(System.out); 45 System.out.println("Error while running the writer thread."); 46 } 47 } 48 49 public PWriter(PipedOutputStream pout, int nbytes) { 50 pos = pout; 51 bytes = new byte[nbytes]; 52 for (int i = 0; i < bytes.length; i++) 53 bytes[i] = (byte) (System.currentTimeMillis() % 9); 54 } 55 } 56 57 static class PWriter2 implements Runnable { 58 PipedOutputStream pos; 59 60 public boolean keepRunning = true; 61 62 public void run() { 63 try { 64 pos.write(42); 65 pos.close(); 66 while (keepRunning) { 67 Thread.sleep(1000); 68 } 69 } catch (Exception e) { 70 e.printStackTrace(System.out); 71 System.out.println("Error while running the writer thread."); 72 } 73 } 74 75 public PWriter2(PipedOutputStream pout) { 76 pos = pout; 77 } 78 } 79 80 Thread t; 81 82 PWriter pw; 83 84 PipedInputStream pis; 85 86 PipedOutputStream pos; 87 88 /** 89 * @tests java.io.PipedInputStream#PipedInputStream() 90 */ 91 @TestTargetNew( 92 level = TestLevel.COMPLETE, 93 notes = "", 94 method = "PipedInputStream", 95 args = {} 96 ) 97 public void test_Constructor() throws IOException { 98 pis = new PipedInputStream(); 99 assertEquals("There should not be any bytes available. ", 0, pis.available()); 100 pis.close(); 101 } 102 103 /** 104 * @tests java.io.PipedInputStream#PipedInputStream(java.io.PipedOutputStream) 105 */ 106 @TestTargetNew( 107 level = TestLevel.COMPLETE, 108 notes = "", 109 method = "PipedInputStream", 110 args = {java.io.PipedOutputStream.class} 111 ) 112 public void test_ConstructorLjava_io_PipedOutputStream() throws IOException { 113 pos = new PipedOutputStream(new PipedInputStream()); 114 115 try { 116 pis = new PipedInputStream(pos); 117 fail("IOException expected since the output stream is already connected."); 118 } catch (IOException e) { 119 // Expected. 120 } 121 122 pis = new PipedInputStream(new PipedOutputStream()); 123 assertEquals("There should not be any bytes available. ", 0, pis.available()); 124 125 pis.close(); 126 pos.close(); 127 } 128 129 /** 130 * @tests java.io.PipedInputStream#available() 131 */ 132 @TestTargetNew( 133 level = TestLevel.COMPLETE, 134 notes = "No IOException checking because it is never thrown in the source code.", 135 method = "available", 136 args = {} 137 ) 138 public void test_available() throws Exception { 139 // Test for method int java.io.PipedInputStream.available() 140 pis = new PipedInputStream(); 141 pos = new PipedOutputStream(); 142 143 pis.connect(pos); 144 t = new Thread(pw = new PWriter(pos, 1000)); 145 t.start(); 146 147 synchronized (pw) { 148 pw.wait(10000); 149 } 150 assertEquals("Test 1: Incorrect number of bytes available. ", 151 1000, pis.available()); 152 153 PipedInputStream pin = new PipedInputStream(); 154 PipedOutputStream pout = new PipedOutputStream(pin); 155 // Writing another byte would cause the write to wait 156 // for a read before returning 157 for (int i = 0; i < BUFFER_SIZE; i++) 158 pout.write(i); 159 assertEquals("Test 2: Incorrect number of bytes available. ", 160 BUFFER_SIZE, pin.available()); 161 } 162 163 /** 164 * @tests java.io.PipedInputStream#close() 165 */ 166 @TestTargetNew( 167 level = TestLevel.COMPLETE, 168 notes = "No IOException checking because it is never thrown in the source code.", 169 method = "close", 170 args = {} 171 ) 172 public void test_close() throws IOException { 173 // Test for method void java.io.PipedInputStream.close() 174 pis = new PipedInputStream(); 175 pos = new PipedOutputStream(); 176 pis.connect(pos); 177 pis.close(); 178 try { 179 pos.write((byte) 127); 180 fail("IOException expected."); 181 } catch (IOException e) { 182 // The spec for PipedInput says an exception should be thrown if 183 // a write is attempted to a closed input. The PipedOuput spec 184 // indicates that an exception should be thrown only when the 185 // piped input thread is terminated without closing 186 return; 187 } 188 } 189 190 /** 191 * @tests java.io.PipedInputStream#connect(java.io.PipedOutputStream) 192 */ 193 @TestTargetNew( 194 level = TestLevel.COMPLETE, 195 notes = "", 196 method = "connect", 197 args = {java.io.PipedOutputStream.class} 198 ) 199 public void test_connectLjava_io_PipedOutputStream() throws Exception { 200 // Test for method void 201 // java.io.PipedInputStream.connect(java.io.PipedOutputStream) 202 pis = new PipedInputStream(); 203 pos = new PipedOutputStream(); 204 assertEquals("Test 1: Not-connected pipe returned more than zero available bytes. ", 205 0, pis.available()); 206 207 pis.connect(pos); 208 t = new Thread(pw = new PWriter(pos, 1000)); 209 t.start(); 210 211 synchronized (pw) { 212 pw.wait(10000); 213 } 214 assertEquals("Test 2: Unexpected number of bytes available. ", 215 1000, pis.available()); 216 217 try { 218 pis.connect(pos); 219 fail("Test 3: IOException expected when reconnecting the pipe."); 220 } catch (IOException e) { 221 // Expected. 222 } 223 224 pis.close(); 225 pos.close(); 226 } 227 228 /** 229 * @tests java.io.PipedInputStream#read() 230 */ 231 @TestTargetNew( 232 level = TestLevel.PARTIAL_COMPLETE, 233 notes = "", 234 method = "read", 235 args = {} 236 ) 237 public void test_read() throws Exception { 238 pis = new PipedInputStream(); 239 pos = new PipedOutputStream(); 240 241 try { 242 pis.read(); 243 fail("Test 1: IOException expected since the stream is not connected."); 244 } catch (IOException e) { 245 // Expected. 246 } 247 248 pis.connect(pos); 249 t = new Thread(pw = new PWriter(pos, 100)); 250 t.start(); 251 252 synchronized (pw) { 253 pw.wait(5000); 254 } 255 assertEquals("Test 2: Unexpected number of bytes available. ", 256 100, pis.available()); 257 258 for (int i = 0; i < 100; i++) { 259 assertEquals("Test 3: read() returned incorrect byte. ", 260 pw.bytes[i], (byte) pis.read()); 261 } 262 263 try { 264 pis.read(); 265 fail("Test 4: IOException expected since the thread that has " + 266 "written to the pipe is no longer alive."); 267 } catch (IOException e) { 268 // Expected. 269 } 270 271 pis.close(); 272 try { 273 pis.read(); 274 fail("Test 5: IOException expected since the stream is closed."); 275 } catch (IOException e) { 276 // Expected. 277 } 278 } 279 280 /** 281 * @tests java.io.PipedInputStream#read() 282 */ 283 @TestTargetNew( 284 level = TestLevel.PARTIAL_COMPLETE, 285 notes = "Checks that read returns -1 if the PipedOutputStream connected to this PipedInputStream is closed.", 286 method = "read", 287 args = {} 288 ) 289 public void test_read_2() throws Exception { 290 Thread writerThread; 291 PWriter2 pwriter; 292 293 pos = new PipedOutputStream(); 294 pis = new PipedInputStream(pos); 295 writerThread = new Thread(pwriter = new PWriter2(pos)); 296 writerThread.start(); 297 298 synchronized (pwriter) { 299 pwriter.wait(5000); 300 } 301 pis.read(); 302 assertEquals("Test 1: No more data indication expected. ", -1, pis.read()); 303 pwriter.keepRunning = false; 304 305 pis.close(); 306 } 307 308 /** 309 * @tests java.io.PipedInputStream#read(byte[], int, int) 310 */ 311 @TestTargetNew( 312 level = TestLevel.PARTIAL_COMPLETE, 313 notes = "Tests read from unconnected, connected and closed pipe.", 314 method = "read", 315 args = {byte[].class, int.class, int.class} 316 ) 317 public void test_read$BII() throws Exception { 318 byte[] buf = new byte[400]; 319 pis = new PipedInputStream(); 320 pos = new PipedOutputStream(); 321 322 try { 323 pis.read(buf, 0, 10); 324 fail("Test 1: IOException expected since the stream is not connected."); 325 } catch (IOException e) { 326 // Expected. 327 } 328 329 pis.connect(pos); 330 t = new Thread(pw = new PWriter(pos, 1000)); 331 t.start(); 332 333 synchronized (pw) { 334 pw.wait(10000); 335 } 336 assertEquals("Test 2: Unexpected number of bytes available. ", 337 1000, pis.available()); 338 pis.read(buf, 0, 400); 339 for (int i = 0; i < 400; i++) { 340 assertEquals("Test 3: read() returned incorrect byte. ", 341 pw.bytes[i], buf[i]); 342 } 343 344 pis.close(); 345 try { 346 pis.read(buf, 0, 10); 347 fail("Test 4: IOException expected since the stream is closed."); 348 } catch (IOException e) { 349 // Expected. 350 } 351 } 352 353 /** 354 * @tests java.io.PipedInputStream#read(byte[], int, int) 355 * Regression for HARMONY-387 356 */ 357 @TestTargetNew( 358 level = TestLevel.PARTIAL_COMPLETE, 359 notes = "Tests illegal length argument.", 360 method = "read", 361 args = {byte[].class, int.class, int.class} 362 ) 363 public void test_read$BII_2() throws IOException { 364 PipedInputStream obj = new PipedInputStream(); 365 try { 366 obj.read(new byte[0], 0, -1); 367 fail("IndexOutOfBoundsException expected."); 368 } catch (IndexOutOfBoundsException t) { 369 assertEquals( 370 "IndexOutOfBoundsException rather than a subclass expected.", 371 IndexOutOfBoundsException.class, t.getClass()); 372 } 373 } 374 375 /** 376 * @tests java.io.PipedInputStream#read(byte[], int, int) 377 */ 378 @TestTargetNew( 379 level = TestLevel.PARTIAL_COMPLETE, 380 notes = "Tests illegal offset argument.", 381 method = "read", 382 args = {byte[].class, int.class, int.class} 383 ) 384 public void test_read$BII_3() throws IOException { 385 PipedInputStream obj = new PipedInputStream(); 386 try { 387 obj.read(new byte[10], -1, 1); 388 fail("IndexOutOfBoundsException expected."); 389 } catch (IndexOutOfBoundsException e) { 390 // Expected 391 assertTrue(e.getClass().equals(IndexOutOfBoundsException.class)); 392 } 393 try { 394 obj.read(new byte[10], 0, -1); 395 fail("IndexOutOfBoundsException expected."); 396 } catch (IndexOutOfBoundsException e) { 397 // Expected 398 assertTrue(e.getClass().equals(IndexOutOfBoundsException.class)); 399 } 400 try { 401 obj.read(new byte[10], 9, 2); 402 fail("IndexOutOfBoundsException expected."); 403 } catch (IndexOutOfBoundsException e) { 404 // Expected 405 assertTrue(e.getClass().equals(IndexOutOfBoundsException.class)); 406 } 407 } 408 409 /** 410 * @tests java.io.PipedInputStream#receive(int) 411 */ 412 @TestTargetNew( 413 level = TestLevel.COMPLETE, 414 notes = "", 415 method = "receive", 416 args = {int.class} 417 ) 418 public void test_receive() throws IOException { 419 pis = new PipedInputStream(); 420 pos = new PipedOutputStream(); 421 422 // test if writer recognizes dead reader 423 pis.connect(pos); 424 class WriteRunnable implements Runnable { 425 426 boolean pass = false; 427 428 boolean readerAlive = true; 429 430 public void run() { 431 try { 432 pos.write(1); 433 while (readerAlive) { 434 Thread.sleep(100); 435 } 436 try { 437 pos.write(new byte[BUFFER_SIZE]); 438 // should throw exception since buffer is full and 439 // reader thread is now dead 440 pos.write(1); 441 } catch (IOException e) { 442 pass = true; 443 } 444 } catch (IOException e) { 445 // ignore 446 } catch (InterruptedException e) { 447 // ignore 448 } 449 } 450 } 451 WriteRunnable writeRunnable = new WriteRunnable(); 452 Thread writeThread = new Thread(writeRunnable); 453 class ReadRunnable implements Runnable { 454 455 boolean pass; 456 457 public void run() { 458 try { 459 pis.read(); 460 pass = true; 461 } catch (IOException e) {} 462 } 463 } 464 ; 465 ReadRunnable readRunnable = new ReadRunnable(); 466 Thread readThread = new Thread(readRunnable); 467 writeThread.start(); 468 readThread.start(); 469 while (readThread.isAlive()) 470 ; 471 writeRunnable.readerAlive = false; 472 assertTrue("reader thread failed to read", readRunnable.pass); 473 while (writeThread.isAlive()) 474 ; 475 assertTrue("writer thread failed to recognize dead reader", 476 writeRunnable.pass); 477 478 // attempt to write to stream after writer closed 479 pis = new PipedInputStream(); 480 pos = new PipedOutputStream(); 481 482 pis.connect(pos); 483 class MyRunnable implements Runnable { 484 485 boolean pass; 486 487 public void run() { 488 try { 489 pos.write(1); 490 } catch (IOException e) { 491 pass = true; 492 } 493 } 494 } 495 MyRunnable myRun = new MyRunnable(); 496 synchronized (pis) { 497 t = new Thread(myRun); 498 // thread t will be blocked inside pos.write(1) 499 // when it tries to call the synchronized method pis.receive 500 // because we hold the monitor for object pis 501 t.start(); 502 try { 503 // wait for thread t to get to the call to pis.receive 504 Thread.sleep(100); 505 } catch (InterruptedException e) {} 506 // now we close 507 pos.close(); 508 } 509 // we have exited the synchronized block, so now thread t will make 510 // a call to pis.receive AFTER the output stream was closed, 511 // in which case an IOException should be thrown 512 while (t.isAlive()) { 513 ; 514 } 515 assertTrue( 516 "write failed to throw IOException on closed PipedOutputStream", 517 myRun.pass); 518 } 519 520 /** 521 * Tears down the fixture, for example, close a network connection. This 522 * method is called after a test is executed. 523 */ 524 protected void tearDown() throws Exception { 525 try { 526 if (t != null) { 527 t.interrupt(); 528 } 529 } catch (Exception ignore) { 530 } 531 super.tearDown(); 532 } 533} 534