Home | History | Annotate | Download | only in io
      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 
     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 
     51 	Thread t;
     52 
     53 	PWriter pw;
     54 
     55 	PipedInputStream pis;
     56 
     57 	PipedOutputStream pos;
     58 
     59 	/**
     60 	 * @tests java.io.PipedInputStream#PipedInputStream()
     61 	 */
     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 	 */
     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      */
     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      */
    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 	 */
    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 	 */
    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 	 */
    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 	 */
    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      */
    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      */
    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      */
    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      */
    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 
    358         Worker(PipedOutputStream pos) {
    359             this.out = pos;
    360         }
    361 
    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 
    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 	 */
    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      */
    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      */
    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 
    459         public MockPipedInputStream(java.io.PipedOutputStream src,
    460                 int bufferSize) throws IOException {
    461             super(src, bufferSize);
    462         }
    463 
    464         public MockPipedInputStream(int bufferSize) {
    465             super(bufferSize);
    466         }
    467 
    468         public int bufferLength() {
    469             return super.buffer.length;
    470         }
    471     }
    472 }
    473