001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.harmony.luni.tests.java.io;
018:
019: import java.io.IOException;
020: import java.io.PipedInputStream;
021: import java.io.PipedOutputStream;
022:
023: import junit.framework.TestCase;
024:
025: public class PipedInputStreamTest extends TestCase {
026:
027: static class PWriter implements Runnable {
028: PipedOutputStream pos;
029:
030: public byte bytes[];
031:
032: public void run() {
033: try {
034: pos.write(bytes);
035: synchronized (this ) {
036: notify();
037: }
038: } catch (IOException e) {
039: e.printStackTrace(System.out);
040: System.out.println("Could not write bytes");
041: }
042: }
043:
044: public PWriter(PipedOutputStream pout, int nbytes) {
045: pos = pout;
046: bytes = new byte[nbytes];
047: for (int i = 0; i < bytes.length; i++) {
048: bytes[i] = (byte) (System.currentTimeMillis() % 9);
049: }
050: }
051: }
052:
053: Thread t;
054:
055: PWriter pw;
056:
057: PipedInputStream pis;
058:
059: PipedOutputStream pos;
060:
061: /**
062: * @tests java.io.PipedInputStream#PipedInputStream()
063: */
064: public void test_Constructor() {
065: // Used in tests
066: }
067:
068: /**
069: * @tests java.io.PipedInputStream#PipedInputStream(java.io.PipedOutputStream)
070: */
071: public void test_ConstructorLjava_io_PipedOutputStream()
072: throws IOException {
073: pis = new PipedInputStream(new PipedOutputStream());
074: pis.available();
075: }
076:
077: /**
078: * @tests java.io.PipedInputStream#available()
079: */
080: public void test_available() throws Exception {
081: pis = new PipedInputStream();
082: pos = new PipedOutputStream();
083:
084: pis.connect(pos);
085: t = new Thread(pw = new PWriter(pos, 1000));
086: t.start();
087:
088: synchronized (pw) {
089: pw.wait(10000);
090: }
091: assertTrue("Available returned incorrect number of bytes: "
092: + pis.available(), pis.available() == 1000);
093:
094: PipedInputStream pin = new PipedInputStream();
095: PipedOutputStream pout = new PipedOutputStream(pin);
096: // We know the PipedInputStream buffer size is 1024.
097: // Writing another byte would cause the write to wait
098: // for a read before returning
099: for (int i = 0; i < 1024; i++) {
100: pout.write(i);
101: }
102: assertEquals("Incorrect available count", 1024, pin.available());
103: }
104:
105: /**
106: * @tests java.io.PipedInputStream#close()
107: */
108: public void test_close() throws IOException {
109: pis = new PipedInputStream();
110: pos = new PipedOutputStream();
111: pis.connect(pos);
112: pis.close();
113: try {
114: pos.write((byte) 127);
115: fail("Failed to throw expected exception");
116: } catch (IOException e) {
117: // The spec for PipedInput saya an exception should be thrown if
118: // a write is attempted to a closed input. The PipedOuput spec
119: // indicates that an exception should be thrown only when the
120: // piped input thread is terminated without closing
121: }
122: }
123:
124: /**
125: * @tests java.io.PipedInputStream#connect(java.io.PipedOutputStream)
126: */
127: public void test_connectLjava_io_PipedOutputStream()
128: throws Exception {
129: pis = new PipedInputStream();
130: pos = new PipedOutputStream();
131: assertEquals(
132: "Non-conected pipe returned non-zero available bytes",
133: 0, 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",
143: 1000, pis.available());
144: }
145:
146: /**
147: * @tests java.io.PipedInputStream#read()
148: */
149: public void test_read() throws Exception {
150: pis = new PipedInputStream();
151: pos = new PipedOutputStream();
152:
153: pis.connect(pos);
154: t = new Thread(pw = new PWriter(pos, 1000));
155: t.start();
156:
157: synchronized (pw) {
158: pw.wait(10000);
159: }
160: assertEquals("Available returned incorrect number of bytes",
161: 1000, pis.available());
162: assertEquals("read returned incorrect byte", pw.bytes[0],
163: (byte) pis.read());
164: }
165:
166: /**
167: * @tests java.io.PipedInputStream#read(byte[], int, int)
168: */
169: public void test_read$BII() throws Exception {
170: pis = new PipedInputStream();
171: pos = new PipedOutputStream();
172:
173: pis.connect(pos);
174: t = new Thread(pw = new PWriter(pos, 1000));
175: t.start();
176:
177: byte[] buf = new byte[400];
178: synchronized (pw) {
179: pw.wait(10000);
180: }
181: assertTrue("Available returned incorrect number of bytes: "
182: + pis.available(), pis.available() == 1000);
183: pis.read(buf, 0, 400);
184: for (int i = 0; i < 400; i++) {
185: assertEquals("read returned incorrect byte[]", pw.bytes[i],
186: buf[i]);
187: }
188: }
189:
190: /**
191: * @tests java.io.PipedInputStream#read(byte[], int, int) Regression for
192: * HARMONY-387
193: */
194: public void test_read$BII_2() throws IOException {
195: PipedInputStream obj = new PipedInputStream();
196: try {
197: obj.read(new byte[0], 0, -1);
198: fail("IndexOutOfBoundsException expected");
199: } catch (IndexOutOfBoundsException t) {
200: assertEquals(
201: "IndexOutOfBoundsException rather than a subclass expected",
202: IndexOutOfBoundsException.class, t.getClass());
203: }
204: }
205:
206: /**
207: * @tests java.io.PipedInputStream#read(byte[], int, int)
208: */
209: public void test_read$BII_3() throws IOException {
210: PipedInputStream obj = new PipedInputStream();
211: try {
212: obj.read(new byte[0], -1, 0);
213: fail("IndexOutOfBoundsException expected");
214: } catch (ArrayIndexOutOfBoundsException t) {
215: fail("IndexOutOfBoundsException expected");
216: } catch (IndexOutOfBoundsException t) {
217: }
218: }
219:
220: /**
221: * @tests java.io.PipedInputStream#read(byte[], int, int)
222: */
223: public void test_read$BII_4() throws IOException {
224: PipedInputStream obj = new PipedInputStream();
225: try {
226: obj.read(new byte[0], -1, -1);
227: fail("IndexOutOfBoundsException expected");
228: } catch (ArrayIndexOutOfBoundsException t) {
229: fail("IndexOutOfBoundsException expected");
230: } catch (IndexOutOfBoundsException t) {
231: }
232: }
233:
234: /**
235: * @tests java.io.PipedInputStream#receive(int)
236: */
237: public void test_receive() throws IOException {
238: pis = new PipedInputStream();
239: pos = new PipedOutputStream();
240:
241: // test if writer recognizes dead reader
242: pis.connect(pos);
243: class WriteRunnable implements Runnable {
244:
245: boolean pass = false;
246:
247: boolean readerAlive = true;
248:
249: public void run() {
250: try {
251: pos.write(1);
252: while (readerAlive) {
253: ;
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: }
266: WriteRunnable writeRunnable = new WriteRunnable();
267: Thread writeThread = new Thread(writeRunnable);
268: class ReadRunnable implements Runnable {
269:
270: boolean pass;
271:
272: public void run() {
273: try {
274: pis.read();
275: pass = true;
276: } catch (IOException e) {
277: }
278: }
279: }
280: ;
281: ReadRunnable readRunnable = new ReadRunnable();
282: Thread readThread = new Thread(readRunnable);
283: writeThread.start();
284: readThread.start();
285: while (readThread.isAlive()) {
286: ;
287: }
288: writeRunnable.readerAlive = false;
289: assertTrue("reader thread failed to read", readRunnable.pass);
290: while (writeThread.isAlive()) {
291: ;
292: }
293: assertTrue("writer thread failed to recognize dead reader",
294: writeRunnable.pass);
295:
296: // attempt to write to stream after writer closed
297: pis = new PipedInputStream();
298: pos = new PipedOutputStream();
299:
300: pis.connect(pos);
301: class MyRunnable implements Runnable {
302:
303: boolean pass;
304:
305: public void run() {
306: try {
307: pos.write(1);
308: } catch (IOException e) {
309: pass = true;
310: }
311: }
312: }
313: MyRunnable myRun = new MyRunnable();
314: synchronized (pis) {
315: t = new Thread(myRun);
316: // thread t will be blocked inside pos.write(1)
317: // when it tries to call the synchronized method pis.receive
318: // because we hold the monitor for object pis
319: t.start();
320: try {
321: // wait for thread t to get to the call to pis.receive
322: Thread.sleep(100);
323: } catch (InterruptedException e) {
324: }
325: // now we close
326: pos.close();
327: }
328: // we have exited the synchronized block, so now thread t will make
329: // a call to pis.receive AFTER the output stream was closed,
330: // in which case an IOException should be thrown
331: while (t.isAlive()) {
332: ;
333: }
334: assertTrue(
335: "write failed to throw IOException on closed PipedOutputStream",
336: myRun.pass);
337: }
338:
339: /**
340: * Tears down the fixture, for example, close a network connection. This
341: * method is called after a test is executed.
342: */
343: @Override
344: protected void tearDown() throws Exception {
345: try {
346: if (t != null) {
347: t.interrupt();
348: }
349: } catch (Exception ignore) {
350: }
351: super.tearDown();
352: }
353: }
|