InputStreamReaderTest.java revision 561ee011997c6c2f1befbfaa9d5f0a99771c1d63
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.BufferedInputStream;
21import java.io.ByteArrayInputStream;
22import java.io.ByteArrayOutputStream;
23import java.io.IOException;
24import java.io.InputStream;
25import java.io.InputStreamReader;
26import java.io.OutputStreamWriter;
27import java.io.PrintStream;
28import java.io.UnsupportedEncodingException;
29import java.nio.charset.Charset;
30import java.nio.charset.CharsetDecoder;
31import java.nio.charset.CodingErrorAction;
32import java.nio.charset.MalformedInputException;
33import java.util.Arrays;
34
35import junit.framework.TestCase;
36
37public class InputStreamReaderTest extends TestCase {
38
39    static class LimitedByteArrayInputStream extends ByteArrayInputStream {
40
41        // A ByteArrayInputStream that only returns a single byte per read
42        byte[] bytes;
43
44        int count;
45
46        public LimitedByteArrayInputStream(int type) {
47            super(new byte[0]);
48            switch (type) {
49            case 0:
50                bytes = new byte[] { 0x61, 0x72 };
51                break;
52            case 1:
53                bytes = new byte[] { (byte) 0xff, (byte) 0xfe, 0x61, 0x72 };
54                break;
55            case 2:
56                bytes = new byte[] { '\u001b', '$', 'B', '6', 'e', 'B', 'h',
57                        '\u001b', '(', 'B' };
58                break;
59            }
60            count = bytes.length;
61        }
62
63        @Override
64        public int available() {
65            return count;
66        }
67
68        @Override
69        public int read() {
70            if (count == 0) {
71                return -1;
72            }
73            count--;
74            return bytes[bytes.length - count];
75        }
76
77        @Override
78        public int read(byte[] buffer, int offset, int length) {
79            if (count == 0) {
80                return -1;
81            }
82            if (length == 0) {
83                return 0;
84            }
85            buffer[offset] = bytes[bytes.length - count];
86            count--;
87            return 1;
88        }
89    }
90
91    public String fileString = "Test_All_Tests\nTest_java_io_BufferedInputStream\nTest_java_io_BufferedOutputStream\nTest_java_io_ByteArrayInputStream\nTest_java_io_ByteArrayOutputStream\nTest_java_io_DataInputStream\n";
92
93    private InputStream fis;
94
95    private InputStream in;
96
97    private InputStreamReader is;
98
99    private InputStreamReader reader;
100
101    private final String source = "This is a test message with Unicode character. \u4e2d\u56fd is China's name in Chinese";
102
103    /*
104     * @see TestCase#setUp()
105     */
106    @Override
107    protected void setUp() throws Exception {
108        super.setUp();
109
110        in = new ByteArrayInputStream(source.getBytes("UTF-8"));
111        reader = new InputStreamReader(in, "UTF-8");
112
113        ByteArrayOutputStream bos = new ByteArrayOutputStream();
114        OutputStreamWriter osw = new OutputStreamWriter(bos);
115        char[] buf = new char[fileString.length()];
116        fileString.getChars(0, fileString.length(), buf, 0);
117        osw.write(buf);
118        osw.close();
119        fis = new ByteArrayInputStream(bos.toByteArray());
120        is = new InputStreamReader(fis);
121    }
122
123    /*
124     * @see TestCase#tearDown()
125     */
126    @Override
127    protected void tearDown() throws Exception {
128        try {
129            in.close();
130            is.close();
131            fis.close();
132        } catch (IOException e) {
133            // Ignored
134        }
135
136        super.tearDown();
137    }
138
139    /**
140     * @tests java.io.InputStreamReader#close()
141     */
142    public void test_close() throws IOException {
143        is.close();
144        try {
145            is.read();
146            fail("Should throw IOException");
147        } catch (IOException e) {
148            // Expected
149        }
150
151        reader.close();
152        try {
153            reader.ready();
154            fail("Should throw IOException");
155        } catch (IOException e) {
156            // Expected
157        }
158
159        // Should be a no-op
160        reader.close();
161
162        // Tests after reader closed
163        in = new BufferedInputStream(
164                this
165                        .getClass()
166                        .getClassLoader()
167                        .getResourceAsStream(
168                                "org/apache/harmony/luni/tests/java/io/testfile-utf8.txt"));
169        reader = new InputStreamReader(in, "utf-8");
170        in.close();
171        try {
172            int count = reader.read(new char[1]);
173            fail("count:" + count);
174        } catch (IOException e) {
175            // Expected
176        }
177        try {
178            reader.read();
179            fail();
180        } catch (IOException e) {
181            // Expected
182        }
183
184        assertFalse(reader.ready());
185        Charset cs = Charset.forName("utf-8");
186        assertEquals(cs, Charset.forName(reader.getEncoding()));
187    }
188
189    /**
190     * @tests java.io.InputStreamReader#InputStreamReader(java.io.InputStream)
191     */
192    public void test_ConstructorLjava_io_InputStream() throws IOException {
193        try {
194            reader = new InputStreamReader(null);
195            fail();
196        } catch (NullPointerException e) {
197            // Expected
198        }
199        InputStreamReader reader2 = new InputStreamReader(in);
200        reader2.close();
201    }
202
203    /**
204     * @tests java.io.InputStreamReader#InputStreamReader(java.io.InputStream,
205     *        java.lang.String)
206     */
207    public void test_ConstructorLjava_io_InputStreamLjava_lang_String()
208            throws IOException {
209        is = new InputStreamReader(fis, "8859_1");
210
211        try {
212            is = new InputStreamReader(fis, "Bogus");
213            fail("Failed to throw Unsupported Encoding exception");
214        } catch (UnsupportedEncodingException e) {
215            assertNotNull(e.getMessage());
216        }
217
218        try {
219            reader = new InputStreamReader(null, "utf-8");
220            fail();
221        } catch (NullPointerException e) {
222            // Expected
223        }
224        try {
225            reader = new InputStreamReader(in, (String) null);
226            fail();
227        } catch (NullPointerException e) {
228            // Expected
229        }
230        try {
231            reader = new InputStreamReader(in, "");
232            fail();
233        } catch (UnsupportedEncodingException e) {
234            // Expected
235        }
236        try {
237            reader = new InputStreamReader(in, "badname");
238            fail();
239        } catch (UnsupportedEncodingException e) {
240            // Expected
241        }
242        InputStreamReader reader2 = new InputStreamReader(in, "utf-8");
243        assertEquals(Charset.forName(reader2.getEncoding()), Charset
244                .forName("utf-8"));
245        reader2.close();
246        reader2 = new InputStreamReader(in, "utf8");
247        assertEquals(Charset.forName(reader2.getEncoding()), Charset
248                .forName("utf-8"));
249        reader2.close();
250    }
251
252    /**
253     * @tests java.io.InputStreamReader(java.io.InputStream,
254     *        java.nio.charset.Charset)
255     */
256    public void test_ConstructorLjava_io_InputStreamLjava_nio_charset_Charset()
257            throws IOException {
258        Charset cs = Charset.forName("utf-8");
259        try {
260            reader = new InputStreamReader(null, cs);
261            fail();
262        } catch (NullPointerException e) {
263            // Expected
264        }
265        try {
266            reader = new InputStreamReader(in, (Charset) null);
267            fail();
268        } catch (NullPointerException e) {
269            // Expected
270        }
271        InputStreamReader reader2 = new InputStreamReader(in, cs);
272        assertEquals(Charset.forName(reader2.getEncoding()), cs);
273        reader2.close();
274    }
275
276    /**
277     * @tests java.io.InputStreamReader(java.io.InputStream,
278     *        java.nio.charset.CharsetDecoder)
279     */
280    public void test_ConstructorLjava_io_InputStreamLjava_nio_charset_CharsetDecoder()
281            throws IOException {
282        CharsetDecoder decoder = Charset.forName("utf-8").newDecoder();
283        try {
284            reader = new InputStreamReader(null, decoder);
285            fail();
286        } catch (NullPointerException e) {
287            // Expected
288        }
289        try {
290            reader = new InputStreamReader(in, (CharsetDecoder) null);
291            fail();
292        } catch (NullPointerException e) {
293            // Expected
294        }
295        InputStreamReader reader2 = new InputStreamReader(in, decoder);
296        assertEquals(Charset.forName(reader2.getEncoding()), decoder.charset());
297        reader2.close();
298    }
299
300    /**
301     * @tests java.io.InputStreamReader#getEncoding()
302     */
303    public void test_getEncoding() throws IOException {
304        InputStreamReader isr = new InputStreamReader(fis, "8859_1");
305        assertEquals("Returned incorrect encoding when setting 8859_1",
306                "ISO8859_1", isr.getEncoding());
307
308        isr = new InputStreamReader(fis, "ISO-8859-1");
309        assertEquals("Returned incorrect encoding when setting ISO-8859-1",
310                "ISO8859_1", isr.getEncoding());
311
312        byte b[] = new byte[5];
313        isr = new InputStreamReader(new ByteArrayInputStream(b), "UTF-16BE");
314        isr.close();
315        assertNull(isr.getEncoding());
316
317        try {
318            isr = new InputStreamReader(System.in, "UTF-16BE");
319        } catch (UnsupportedEncodingException e) {
320            // Ignored
321        }
322        assertEquals("UnicodeBigUnmarked", isr.getEncoding());
323    }
324
325    /**
326     * @tests java.io.InputStreamReader#read()
327     */
328    public void test_read() throws IOException {
329        assertEquals('T', (char) reader.read());
330        assertEquals('h', (char) reader.read());
331        assertEquals('i', (char) reader.read());
332        assertEquals('s', (char) reader.read());
333        assertEquals(' ', (char) reader.read());
334        reader.read(new char[source.length() - 5], 0, source.length() - 5);
335        assertEquals(-1, reader.read());
336
337        int c = is.read();
338        assertTrue("returned incorrect char", (char) c == fileString.charAt(0));
339        InputStreamReader reader = new InputStreamReader(
340                new ByteArrayInputStream(new byte[] { (byte) 0xe8, (byte) 0x9d,
341                        (byte) 0xa5 }), "UTF8");
342        assertTrue("wrong double byte char", reader.read() == '\u8765');
343
344        // Regression for HARMONY-166
345        InputStream in;
346
347        in = new LimitedByteArrayInputStream(0);
348        reader = new InputStreamReader(in, "UTF-16BE");
349        assertEquals("Incorrect byte UTF-16BE", '\u6172', reader.read());
350
351        in = new LimitedByteArrayInputStream(0);
352        reader = new InputStreamReader(in, "UTF-16LE");
353        assertEquals("Incorrect byte UTF-16BE", '\u7261', reader.read());
354
355        in = new LimitedByteArrayInputStream(1);
356        reader = new InputStreamReader(in, "UTF-16");
357        assertEquals("Incorrect byte UTF-16BE", '\u7261', reader.read());
358
359        /*
360         * Temporarily commented out due to lack of ISO2022 support in ICU4J 3.8
361         * in = new LimitedByteArrayInputStream(2); reader = new
362         * InputStreamReader(in, "ISO2022JP"); assertEquals("Incorrect byte
363         * ISO2022JP 1", '\u4e5d', reader.read()); assertEquals("Incorrect byte
364         * ISO2022JP 2", '\u7b2c', reader.read());
365         */
366    }
367
368    /*
369     * Class under test for int read() Regression for Harmony-411
370     */
371    public void test_read_1() throws IOException {
372        // if the decoder is constructed by InputStreamReader itself, the
373        // decoder's default error action is REPLACE
374        InputStreamReader isr = new InputStreamReader(new ByteArrayInputStream(
375                new byte[] { -32, -96 }), "UTF-8");
376        assertEquals("read() return incorrect value", 65533, isr.read());
377
378        InputStreamReader isr2 = new InputStreamReader(
379                new ByteArrayInputStream(new byte[] { -32, -96 }), Charset
380                        .forName("UTF-8"));
381        assertEquals("read() return incorrect value", 65533, isr2.read());
382
383        // if the decoder is passed in, keep its status intact
384        CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
385        decoder.onMalformedInput(CodingErrorAction.REPORT);
386        InputStreamReader isr3 = new InputStreamReader(
387                new ByteArrayInputStream(new byte[] { -32, -96 }), decoder);
388        try {
389            isr3.read();
390            fail("Should throw MalformedInputException");
391        } catch (MalformedInputException e) {
392            // expected
393        }
394
395        CharsetDecoder decoder2 = Charset.forName("UTF-8").newDecoder();
396        decoder2.onMalformedInput(CodingErrorAction.IGNORE);
397        InputStreamReader isr4 = new InputStreamReader(
398                new ByteArrayInputStream(new byte[] { -32, -96 }), decoder2);
399        assertEquals("read() return incorrect value", -1, isr4.read());
400
401        CharsetDecoder decoder3 = Charset.forName("UTF-8").newDecoder();
402        decoder3.onMalformedInput(CodingErrorAction.REPLACE);
403        InputStreamReader isr5 = new InputStreamReader(
404                new ByteArrayInputStream(new byte[] { -32, -96 }), decoder3);
405        assertEquals("read() return incorrect value", 65533, isr5.read());
406    }
407
408    public void test_read_specialCharset() throws IOException {
409        reader.close();
410        in = this.getClass().getClassLoader().getResourceAsStream(
411                "org/apache/harmony/luni/tests/java/io/testfile-utf8.txt");
412        reader = new InputStreamReader(in, "utf-8");
413        int c;
414        StringBuffer sb = new StringBuffer();
415        while ((c = reader.read()) != -1) {
416            sb.append((char) c);
417        }
418        // delete BOM
419        assertEquals(source, sb.deleteCharAt(0).toString());
420
421        sb.setLength(0);
422        reader.close();
423        in = this.getClass().getClassLoader().getResourceAsStream(
424                "org/apache/harmony/luni/tests/java/io/testfile.txt");
425        try {
426            reader = new InputStreamReader(in, "gb18030");
427        } catch (UnsupportedEncodingException e) {
428            System.out
429                    .println("GB18030 is not supported, abort test InputStreamReaderTest.testSpecialCharsetReading().");
430        }
431        while ((c = reader.read()) != -1) {
432            sb.append((char) c);
433        }
434        assertEquals(source, sb.toString());
435    }
436
437    /**
438     * @tests java.io.InputStreamReader#read(char[], int, int)
439     */
440    public void test_read$CII() throws IOException {
441        char[] rbuf = new char[100];
442        char[] sbuf = new char[100];
443        fileString.getChars(0, 100, sbuf, 0);
444        is.read(rbuf, 0, 100);
445        for (int i = 0; i < rbuf.length; i++) {
446            assertTrue("returned incorrect chars", rbuf[i] == sbuf[i]);
447        }
448
449        // Test successive reads
450        byte[] data = new byte[8192 * 2];
451        Arrays.fill(data, (byte) 116); // 116 = ISO-8859-1 value for 't'
452        ByteArrayInputStream bis = new ByteArrayInputStream(data);
453        InputStreamReader isr = new InputStreamReader(bis, "ISO-8859-1");
454
455        // One less than the InputStreamReader.BUFFER_SIZE
456        char[] buf = new char[8191];
457        int bytesRead = isr.read(buf, 0, buf.length);
458        assertFalse(-1 == bytesRead);
459        bytesRead = isr.read(buf, 0, buf.length);
460        assertFalse(-1 == bytesRead);
461
462        bis = new ByteArrayInputStream(source.getBytes("UTF-8"));
463        isr = new InputStreamReader(in, "UTF-8");
464        char[] chars = new char[source.length()];
465        assertEquals(source.length() - 3, isr.read(chars, 0, chars.length - 3));
466        assertEquals(3, isr.read(chars, 0, 10));
467    }
468
469    /*
470     * Class under test for int read(char[], int, int)
471     */
472    public void test_read$CII_1() throws IOException {
473        try {
474            // Throws IndexOutOfBoundsException before NullPointerException
475            reader.read(null, -1, 1);
476            fail("Should throw IndexOutOfBoundsException");
477        } catch (IndexOutOfBoundsException e) {
478            // expected
479        }
480
481        try {
482            // Throws NullPointerException before IndexOutOfBoundsException
483            reader.read(null, 0, -1);
484            fail("Should throw NullPointerException");
485        } catch (NullPointerException e) {
486            // expected
487        }
488
489        try {
490            reader.read(null, 0, 1);
491            fail();
492        } catch (NullPointerException e) {
493            // Expected
494        }
495        try {
496            reader.read(new char[3], -1, 1);
497            fail();
498        } catch (IndexOutOfBoundsException e) {
499            // Expected
500        }
501        try {
502            reader.read(new char[3], 0, -1);
503            fail();
504        } catch (IndexOutOfBoundsException e) {
505            // Expected
506        }
507        try {
508            reader.read(new char[3], 1, 3);
509            fail();
510        } catch (IndexOutOfBoundsException e) {
511            // Expected
512        }
513        assertEquals(0, reader.read(new char[3], 3, 0));
514        char[] chars = new char[source.length()];
515        assertEquals(0, reader.read(chars, 0, 0));
516        assertEquals(0, chars[0]);
517        assertEquals(3, reader.read(chars, 0, 3));
518        assertEquals(5, reader.read(chars, 3, 5));
519        assertEquals(source.length() - 8, reader.read(chars, 8,
520                chars.length - 8));
521        assertTrue(Arrays.equals(chars, source.toCharArray()));
522        assertEquals(-1, reader.read(chars, 0, chars.length));
523        assertTrue(Arrays.equals(chars, source.toCharArray()));
524    }
525
526    /**
527     * @tests java.io.InputStreamReader#ready()
528     */
529    public void test_ready() throws IOException {
530        assertTrue("Ready test failed", is.ready());
531        is.read();
532        assertTrue("More chars, but not ready", is.ready());
533
534        assertTrue(reader.ready());
535        reader.read(new char[source.length()]);
536        assertFalse(reader.ready());
537    }
538}
539