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