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