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
18package org.apache.harmony.luni.tests.java.io;
19
20import java.io.IOException;
21import java.io.PipedReader;
22import java.io.PipedWriter;
23
24public class PipedWriterTest extends junit.framework.TestCase {
25
26	static class PReader implements Runnable {
27		public PipedReader pr;
28
29		public char[] buf = new char[10];
30
31		public PReader(PipedWriter pw) {
32			try {
33				pr = new PipedReader(pw);
34			} catch (IOException e) {
35				System.out.println("Exception setting up reader: "
36						+ e.toString());
37			}
38		}
39
40		public PReader(PipedReader pr) {
41			this.pr = pr;
42		}
43
44		public void run() {
45			try {
46				int r = 0;
47				for (int i = 0; i < buf.length; i++) {
48					r = pr.read();
49					if (r == -1)
50						break;
51					buf[i] = (char) r;
52				}
53			} catch (Exception e) {
54				System.out.println("Exception reading ("
55						+ Thread.currentThread().getName() + "): "
56						+ e.toString());
57			}
58		}
59	}
60
61	Thread rdrThread;
62
63	PReader reader;
64
65	PipedWriter pw;
66
67	/**
68	 * @tests java.io.PipedWriter#PipedWriter()
69	 */
70	public void test_Constructor() {
71		// Test for method java.io.PipedWriter()
72		// Used in tests
73	}
74
75	/**
76     * @tests java.io.PipedWriter#PipedWriter(java.io.PipedReader)
77     */
78    public void test_ConstructorLjava_io_PipedReader() throws Exception {
79        // Test for method java.io.PipedWriter(java.io.PipedReader)
80        char[] buf = new char[10];
81        "HelloWorld".getChars(0, 10, buf, 0);
82        PipedReader rd = new PipedReader();
83        pw = new PipedWriter(rd);
84        rdrThread = new Thread(reader = new PReader(rd), "Constructor(Reader)");
85        rdrThread.start();
86        pw.write(buf);
87        pw.close();
88        rdrThread.join(500);
89        assertEquals("Failed to construct writer", "HelloWorld", new String(
90                reader.buf));
91    }
92
93    /**
94     * @tests java.io.PipedWriter#close()
95     */
96    public void test_close() throws Exception {
97        // Test for method void java.io.PipedWriter.close()
98        char[] buf = new char[10];
99        "HelloWorld".getChars(0, 10, buf, 0);
100        PipedReader rd = new PipedReader();
101        pw = new PipedWriter(rd);
102        reader = new PReader(rd);
103        pw.close();
104        try {
105            pw.write(buf);
106            fail("Should have thrown exception when attempting to write to closed writer.");
107        } catch (Exception e) {
108            // correct
109        }
110    }
111
112    /**
113     * @tests java.io.PipedWriter#connect(java.io.PipedReader)
114     */
115    public void test_connectLjava_io_PipedReader() throws Exception {
116        // Test for method void java.io.PipedWriter.connect(java.io.PipedReader)
117        char[] buf = new char[10];
118        "HelloWorld".getChars(0, 10, buf, 0);
119        PipedReader rd = new PipedReader();
120        pw = new PipedWriter();
121        pw.connect(rd);
122        rdrThread = new Thread(reader = new PReader(rd), "connect");
123        rdrThread.start();
124        pw.write(buf);
125        pw.close();
126        rdrThread.join(500);
127        assertEquals("Failed to write correct chars", "HelloWorld", new String(
128                reader.buf));
129    }
130
131    /**
132     * @tests java.io.PipedWriter#flush()
133     */
134    public void test_flush() throws Exception {
135        // Test for method void java.io.PipedWriter.flush()
136        char[] buf = new char[10];
137        "HelloWorld".getChars(0, 10, buf, 0);
138        pw = new PipedWriter();
139        rdrThread = new Thread(reader = new PReader(pw), "flush");
140        rdrThread.start();
141        pw.write(buf);
142        pw.flush();
143        rdrThread.join(700);
144        assertEquals("Failed to flush chars", "HelloWorld", new String(
145                reader.buf));
146    }
147
148    /**
149     * @tests java.io.PipedWriter#flush()
150     * Regression HARMONY-6293
151     */
152    public void test_flushAfterClose() throws Exception {
153
154        PipedReader pr = new PipedReader();
155        pw = new PipedWriter(pr);
156    	pw.close();
157    	try {
158            pw.flush();
159            fail("should throw IOException");
160        } catch (IOException e) {
161            // expected
162        }
163
164        pr = new PipedReader();
165        pw = new PipedWriter(pr);
166        pr.close();
167
168        try {
169            pw.flush();
170            fail("should throw IOException");
171        } catch (IOException e) {
172            // expected
173        }
174    }
175
176    /**
177     * @tests java.io.PipedWriter#write(char[], int, int)
178     */
179    public void test_write$CII() throws Exception {
180        // Test for method void java.io.PipedWriter.write(char [], int, int)
181        char[] buf = new char[10];
182        "HelloWorld".getChars(0, 10, buf, 0);
183        pw = new PipedWriter();
184        rdrThread = new Thread(reader = new PReader(pw), "writeCII");
185        rdrThread.start();
186        pw.write(buf, 0, 10);
187        pw.close();
188        rdrThread.join(1000);
189        assertEquals("Failed to write correct chars", "HelloWorld", new String(
190                reader.buf));
191    }
192
193    /**
194     * @tests java.io.PipedWriter#write(char[], int, int) Regression for
195     *        HARMONY-387
196     */
197    public void test_write$CII_2() throws IOException {
198        PipedReader pr = new PipedReader();
199        PipedWriter obj = null;
200        try {
201            obj = new java.io.PipedWriter(pr);
202            obj.write(new char[0], (int) 0, (int) -1);
203            fail("IndexOutOfBoundsException expected");
204        } catch (IndexOutOfBoundsException expected) {
205        }
206    }
207
208    /**
209     * @tests java.io.PipedWriter#write(char[], int, int)
210     */
211    public void test_write$CII_3() throws IOException {
212        PipedReader pr = new PipedReader();
213        PipedWriter obj = null;
214        try {
215            obj = new java.io.PipedWriter(pr);
216            obj.write(new char[0], (int) -1, (int) 0);
217            fail();
218        } catch (IndexOutOfBoundsException expected) {}
219    }
220
221    /**
222     * @tests java.io.PipedWriter#write(char[], int, int)
223     */
224    public void test_write$CII_4() throws IOException {
225        PipedReader pr = new PipedReader();
226        PipedWriter obj = null;
227        try {
228            obj = new java.io.PipedWriter(pr);
229            obj.write(new char[0], (int) -1, (int) -1);
230            fail();
231        } catch (IndexOutOfBoundsException expected) {}
232    }
233
234    /**
235     * @tests java.io.PipedWriter#write(char[], int, int)
236     */
237    public void test_write$CII_5() throws IOException {
238        PipedReader pr = new PipedReader();
239        PipedWriter obj = null;
240        try {
241            obj = new PipedWriter(pr);
242            obj.write((char[]) null, (int) -1, (int) 0);
243            fail("NullPointerException expected");
244        } catch (IndexOutOfBoundsException t) {
245            fail("NullPointerException expected");
246        } catch (NullPointerException t) {}
247    }
248
249    /**
250     * @tests java.io.PipedWriter#write(char[], int, int)
251     */
252    public void test_write$CII_6() throws IOException {
253        PipedReader pr = new PipedReader();
254        PipedWriter obj = null;
255        try {
256            obj = new PipedWriter(pr);
257            obj.write((char[]) null, (int) -1, (int) -1);
258            fail("NullPointerException expected");
259        } catch (IndexOutOfBoundsException t) {
260            fail("NullPointerException expected");
261        } catch (NullPointerException t) {}
262    }
263
264    /**
265     * @tests java.io.PipedWriter#write(char[], int, int)
266     */
267    public void test_write$CII_notConnected() throws IOException {
268        // Regression test for Harmony-2404
269        // create not connected pipe
270        PipedWriter obj = new PipedWriter();
271
272        // char array is null
273        try {
274            obj.write((char[]) null, 0, 1);
275            fail("IOException expected");
276        } catch (IOException ioe) {
277            // expected
278        }
279
280        // negative offset
281        try {
282            obj.write( new char[] { 1 }, -10, 1);
283            fail("IOException expected");
284        } catch (IOException ioe) {
285            // expected
286        }
287
288        // wrong offset
289        try {
290            obj.write( new char[] { 1 }, 10, 1);
291            fail("IOException expected");
292        } catch (IOException ioe) {
293            // expected
294        }
295
296        // negative length
297        try {
298            obj.write( new char[] { 1 }, 0, -10);
299            fail("IOException expected");
300        } catch (IOException ioe) {
301            // expected
302        }
303
304        // all valid params
305        try {
306            obj.write( new char[] { 1, 1 }, 0, 1);
307            fail("IOException expected");
308        } catch (IOException ioe) {
309            // expected
310        }
311    }
312
313    /**
314     * @tests java.io.PipedWriter#write(int)
315     */
316    public void test_write_I_MultiThread() throws IOException {
317        final PipedReader pr = new PipedReader();
318        final PipedWriter pw = new PipedWriter();
319        // test if writer recognizes dead reader
320        pr.connect(pw);
321
322        class WriteRunnable implements Runnable {
323            boolean pass = false;
324            volatile boolean readerAlive = true;
325            public void run() {
326                try {
327                    pw.write(1);
328                    while (readerAlive) {
329                    // wait the reader thread dead
330                    }
331                    try {
332                        // should throw exception since reader thread
333                        // is now dead
334                        pw.write(1);
335                    } catch (IOException e) {
336                        pass = true;
337                    }
338                } catch (IOException e) {
339                  //ignore
340                }
341            }
342        }
343        WriteRunnable writeRunnable = new WriteRunnable();
344        Thread writeThread = new Thread(writeRunnable);
345        class ReadRunnable implements Runnable {
346            boolean pass;
347            public void run() {
348                try {
349                    pr.read();
350                    pass = true;
351                } catch (IOException e) {
352                  //ignore
353                }
354            }
355        }
356        ReadRunnable readRunnable = new ReadRunnable();
357        Thread readThread = new Thread(readRunnable);
358        writeThread.start();
359        readThread.start();
360        while (readThread.isAlive()) {
361           //wait the reader thread dead
362        }
363        writeRunnable.readerAlive = false;
364        assertTrue("reader thread failed to read", readRunnable.pass);
365        while (writeThread.isAlive()) {
366           //wait the writer thread dead
367        }
368        assertTrue("writer thread failed to recognize dead reader",
369                writeRunnable.pass);
370    }
371
372    /**
373     * @tests java.io.PipedWriter#write(char[],int,int)
374     */
375    public void test_write_$CII_MultiThread() throws Exception {
376        final PipedReader pr = new PipedReader();
377        final PipedWriter pw = new PipedWriter();
378
379        // test if writer recognizes dead reader
380        pr.connect(pw);
381
382        class WriteRunnable implements Runnable {
383            boolean pass = false;
384
385            volatile boolean readerAlive = true;
386
387            public void run() {
388                try {
389                    pw.write(1);
390                    while (readerAlive) {
391                    // wait the reader thread dead
392                    }
393                    try {
394                        // should throw exception since reader thread
395                        // is now dead
396                        char[] buf = new char[10];
397                        pw.write(buf, 0, 10);
398                    } catch (IOException e) {
399                        pass = true;
400                    }
401                } catch (IOException e) {
402                  //ignore
403                }
404            }
405        }
406        WriteRunnable writeRunnable = new WriteRunnable();
407        Thread writeThread = new Thread(writeRunnable);
408        class ReadRunnable implements Runnable {
409            boolean pass;
410
411            public void run() {
412                try {
413                    pr.read();
414                    pass = true;
415                } catch (IOException e) {
416                  //ignore
417                }
418            }
419        }
420        ReadRunnable readRunnable = new ReadRunnable();
421        Thread readThread = new Thread(readRunnable);
422        writeThread.start();
423        readThread.start();
424        while (readThread.isAlive()) {
425            //wait the reader thread dead
426        }
427        writeRunnable.readerAlive = false;
428        assertTrue("reader thread failed to read", readRunnable.pass);
429        while (writeThread.isAlive()) {
430            //wait the writer thread dead
431        }
432        assertTrue("writer thread failed to recognize dead reader",
433                writeRunnable.pass);
434    }
435
436    /**
437     * @tests java.io.PipedWriter#write(int)
438     */
439    public void test_writeI() throws Exception {
440        // Test for method void java.io.PipedWriter.write(int)
441
442        pw = new PipedWriter();
443        rdrThread = new Thread(reader = new PReader(pw), "writeI");
444        rdrThread.start();
445        pw.write(1);
446        pw.write(2);
447        pw.write(3);
448        pw.close();
449        rdrThread.join(1000);
450        assertTrue("Failed to write correct chars: " + (int) reader.buf[0]
451                + " " + (int) reader.buf[1] + " " + (int) reader.buf[2],
452                reader.buf[0] == 1 && reader.buf[1] == 2 && reader.buf[2] == 3);
453    }
454
455    /**
456     * Tears down the fixture, for example, close a network connection. This
457     * method is called after a test is executed.
458     */
459    protected void tearDown() throws Exception {
460        try {
461            if (rdrThread != null) {
462                rdrThread.interrupt();
463            }
464        } catch (Exception ignore) {}
465        try {
466            if (pw != null) {
467                pw.close();
468            }
469        } catch (Exception ignore) {}
470        super.tearDown();
471    }
472}
473