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