• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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