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 libcore.java.io;
19
20import java.io.ByteArrayInputStream;
21import java.io.ByteArrayOutputStream;
22import java.io.IOException;
23import java.io.InputStreamReader;
24import java.io.OutputStreamWriter;
25import java.io.UnsupportedEncodingException;
26import java.nio.charset.Charset;
27import java.nio.charset.CharsetEncoder;
28import junit.framework.TestCase;
29import tests.support.Support_OutputStream;
30
31public class OldOutputStreamWriterTest extends TestCase {
32
33    OutputStreamWriter osw;
34    InputStreamReader isr;
35
36    private Support_OutputStream fos;
37
38    public String testString = "This is a test message with Unicode characters. \u4e2d\u56fd is China's name in Chinese";
39
40    protected void setUp() throws Exception {
41        super.setUp();
42        fos = new Support_OutputStream(500);
43        osw = new OutputStreamWriter(fos, "UTF-8");
44    }
45
46    protected void tearDown() throws Exception {
47        try {
48            if (isr != null) isr.close();
49            osw.close();
50        } catch (Exception e) {
51        }
52
53        super.tearDown();
54    }
55
56    public void test_ConstructorLjava_io_OutputStream() throws IOException {
57        OutputStreamWriter writer = null;
58
59        try {
60            writer = new OutputStreamWriter(null);
61            fail("Test 1: NullPointerException expected.");
62        } catch (NullPointerException e) {
63            // Expected
64        }
65
66        try {
67            writer = new OutputStreamWriter(new Support_OutputStream());
68        } catch (Exception e) {
69            fail("Test 2: Unexpected exception: " + e.getMessage());
70        }
71
72        // Test that the default encoding has been used.
73        assertEquals("Test 3: Incorrect default encoding used.",
74                     Charset.defaultCharset(),
75                     Charset.forName(writer.getEncoding()));
76
77        if (writer != null) writer.close();
78    }
79
80    public void test_ConstructorLjava_io_OutputStreamLjava_lang_String()
81            throws UnsupportedEncodingException {
82
83        try {
84            osw = new OutputStreamWriter(null, "utf-8");
85            fail("Test 1: NullPointerException expected.");
86        } catch (NullPointerException e) {
87            // Expected
88        }
89
90        try {
91            osw = new OutputStreamWriter(fos, (String) null);
92            fail("Test 2: NullPointerException expected.");
93        } catch (NullPointerException e) {
94            // Expected
95        }
96
97        try {
98            osw = new OutputStreamWriter(fos, "");
99            fail("Test 3: UnsupportedEncodingException expected.");
100        } catch (UnsupportedEncodingException e) {
101            // Expected
102        }
103
104        try {
105            osw = new OutputStreamWriter(fos, "Bogus");
106            fail("Test 4: UnsupportedEncodingException expected.");
107        } catch (UnsupportedEncodingException e) {
108            // Expected
109        }
110
111        try {
112            osw = new OutputStreamWriter(fos, "8859_1");
113        } catch (UnsupportedEncodingException e) {
114            fail("Test 5: Unexpected UnsupportedEncodingException.");
115        }
116
117        assertEquals("Test 6: Encoding not set correctly. ",
118                Charset.forName("8859_1"),
119                Charset.forName(osw.getEncoding()));
120    }
121
122    public void test_ConstructorLjava_io_OutputStreamLjava_nio_charset_Charset()
123            throws IOException {
124        OutputStreamWriter writer;
125        Support_OutputStream out = new Support_OutputStream();
126        Charset cs = Charset.forName("ascii");
127
128        try {
129            writer = new OutputStreamWriter(null, cs);
130            fail("Test 1: NullPointerException expected.");
131        } catch (NullPointerException e) {
132            // Expected
133        }
134
135        try {
136            writer = new OutputStreamWriter(out, (Charset) null);
137            fail("Test 2: NullPointerException expected.");
138        } catch (NullPointerException e) {
139            // Expected
140        }
141
142        writer = new OutputStreamWriter(out, cs);
143        assertEquals("Test 3: Encoding not set correctly. ",
144                     cs, Charset.forName(writer.getEncoding()));
145        writer.close();
146    }
147
148    public void test_ConstructorLjava_io_OutputStreamLjava_nio_charset_CharsetEncoder()
149            throws IOException {
150        OutputStreamWriter writer;
151        Support_OutputStream out = new Support_OutputStream();
152        Charset cs = Charset.forName("ascii");
153        CharsetEncoder enc = cs.newEncoder();
154
155        try {
156            writer = new OutputStreamWriter(null, enc);
157            fail("Test 1: NullPointerException expected.");
158        } catch (NullPointerException e) {
159            // Expected
160        }
161
162        try {
163            writer = new OutputStreamWriter(out, (CharsetEncoder) null);
164            fail("Test 2: NullPointerException expected.");
165        } catch (NullPointerException e) {
166            // Expected
167        }
168
169        writer = new OutputStreamWriter(out, cs);
170        assertEquals("Test 3: CharacterEncoder not set correctly. ",
171                     cs, Charset.forName(writer.getEncoding()));
172        writer.close();
173    }
174
175    public void test_close() {
176
177        fos.setThrowsException(true);
178        try {
179            osw.close();
180            fail("Test 1: IOException expected.");
181        } catch (IOException e) {
182            // Expected.
183        }
184
185/* Test 2 does not work and has therefore been disabled (see Ticket #87).
186        // Test 2: Write should not fail since the closing
187        // in test 1 has not been successful.
188        try {
189            osw.write("Lorem ipsum...");
190        } catch (IOException e) {
191            fail("Test 2: Unexpected IOException.");
192        }
193
194        // Test 3: Close should succeed.
195        fos.setThrowsException(false);
196        try {
197            osw.close();
198        } catch (IOException e) {
199            fail("Test 3: Unexpected IOException.");
200        }
201*/
202
203        ByteArrayOutputStream bout = new ByteArrayOutputStream();
204        try {
205            OutputStreamWriter writer = new OutputStreamWriter(bout,
206                    "ISO2022JP");
207            writer.write(new char[] { 'a' });
208            writer.close();
209            // The default is ASCII, there should not be any mode changes.
210            String converted = new String(bout.toByteArray(), "ISO8859_1");
211            assertTrue("Test 4: Invalid conversion: " + converted,
212                       converted.equals("a"));
213
214            bout.reset();
215            writer = new OutputStreamWriter(bout, "ISO2022JP");
216            writer.write(new char[] { '\u3048' });
217            writer.flush();
218            // The byte sequence should not switch to ASCII mode until the
219            // stream is closed.
220            converted = new String(bout.toByteArray(), "ISO8859_1");
221            assertTrue("Test 5: Invalid conversion: " + converted,
222                       converted.equals("\u001b$B$("));
223            writer.close();
224            converted = new String(bout.toByteArray(), "ISO8859_1");
225            assertTrue("Test 6: Invalid conversion: " + converted,
226                       converted.equals("\u001b$B$(\u001b(B"));
227
228            bout.reset();
229            writer = new OutputStreamWriter(bout, "ISO2022JP");
230            writer.write(new char[] { '\u3048' });
231            writer.write(new char[] { '\u3048' });
232            writer.close();
233            // There should not be a mode switch between writes.
234            assertEquals("Test 7: Invalid conversion. ",
235                         "\u001b$B$($(\u001b(B",
236                         new String(bout.toByteArray(), "ISO8859_1"));
237        } catch (UnsupportedEncodingException e) {
238            // Can't test missing converter.
239            System.out.println(e);
240        } catch (IOException e) {
241            fail("Unexpected: " + e);
242        }
243    }
244
245    public void test_flush() {
246        // Test for method void java.io.OutputStreamWriter.flush()
247        try {
248            char[] buf = new char[testString.length()];
249            osw.write(testString, 0, testString.length());
250            osw.flush();
251            openInputStream();
252            isr.read(buf, 0, buf.length);
253            assertTrue("Test 1: Characters have not been flushed.",
254                       new String(buf, 0, buf.length).equals(testString));
255        } catch (Exception e) {
256            fail("Test 1: Unexpected exception: " + e.getMessage());
257        }
258
259        fos.setThrowsException(true);
260        try {
261            osw.flush();
262            fail("Test 2: IOException expected.");
263        } catch (IOException e) {
264            // Expected
265        }
266        fos.setThrowsException(false);
267    }
268
269    public void test_write_US_ASCII() throws Exception {
270        testEncodeCharset("US-ASCII", 128);
271    }
272
273    public void test_write_ISO_8859_1() throws Exception {
274        testEncodeCharset("ISO-8859-1", 256);
275    }
276
277    public void test_write_UTF_16BE() throws Exception {
278        testEncodeCharset("UTF-16BE", 0xd800);
279    }
280
281    public void test_write_UTF_16LE() throws Exception {
282        testEncodeCharset("UTF-16LE", 0xd800);
283    }
284
285    public void test_write_UTF_16() throws Exception {
286        testEncodeCharset("UTF-16", 0xd800);
287    }
288
289    public void test_write_UTF_8() throws Exception {
290        testEncodeCharset("UTF-8", 0xd800);
291    }
292
293    private void testEncodeCharset(String charset, int maxChar) throws Exception {
294        char[] chars = new char[maxChar];
295        for (int i = 0; i < maxChar; i++) {
296            chars[i] = (char) i;
297        }
298
299        // to byte array
300        ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
301        OutputStreamWriter charsOut = new OutputStreamWriter(bytesOut, charset);
302        charsOut.write(chars);
303        charsOut.flush();
304
305        // decode from byte array, one character at a time
306        ByteArrayInputStream bytesIn = new ByteArrayInputStream(bytesOut.toByteArray());
307        InputStreamReader charsIn = new InputStreamReader(bytesIn, charset);
308        for (int i = 0; i < maxChar; i++) {
309            assertEquals(i, charsIn.read());
310        }
311        assertEquals(-1, charsIn.read());
312
313        // decode from byte array, using byte buffers
314        bytesIn = new ByteArrayInputStream(bytesOut.toByteArray());
315        charsIn = new InputStreamReader(bytesIn, charset);
316        char[] decoded = new char[maxChar];
317        for (int r = 0; r < maxChar; ) {
318            r += charsIn.read(decoded, r, maxChar - r);
319        }
320        assertEquals(-1, charsIn.read());
321        for (int i = 0; i < maxChar; i++) {
322            assertEquals(i, decoded[i]);
323        }
324    }
325
326    public void test_getEncoding() throws IOException {
327        OutputStreamWriter writer;
328        writer = new OutputStreamWriter(new Support_OutputStream(), "utf-8");
329        assertEquals("Test 1: Incorrect encoding returned.",
330                     Charset.forName("utf-8"),
331                     Charset.forName(writer.getEncoding()));
332
333        writer.close();
334        assertNull("Test 2: getEncoding() did not return null for a closed writer.",
335                   writer.getEncoding());
336    }
337
338    public void test_write$CII() throws IOException {
339        char[] chars = testString.toCharArray();
340        ByteArrayOutputStream baos = new ByteArrayOutputStream();
341        Support_OutputStream out = new Support_OutputStream(500);
342        OutputStreamWriter writer;
343
344        writer = new OutputStreamWriter(out, "utf-8");
345
346        try {
347            writer.write(chars, -1, 1);
348            fail("Test 1: IndexOutOfBoundsException expected.");
349        } catch (IndexOutOfBoundsException e) {
350            // Expected
351        }
352
353        try {
354            writer.write(chars, 0, -1);
355            fail("Test 2: IndexOutOfBoundsException expected.");
356        } catch (IndexOutOfBoundsException e) {
357            // Expected
358        }
359
360        try {
361            writer.write(new char[0], 0, 1);
362            fail("Test 3: IndexOutOfBoundsException expected.");
363        } catch (IndexOutOfBoundsException e) {
364            // Expected
365        }
366
367        try {
368            writer.write((char[]) null, 0, 1);
369            fail("Test 4: NullPointerException expected.");
370        } catch (NullPointerException e) {
371            // Expected
372        }
373
374        try {
375            writer.write(chars, 1, chars.length);
376            fail("Test 5a: IndexOutOfBoundsException expected.");
377        } catch (IndexOutOfBoundsException e) {
378            // Expected
379        }
380        try {
381            writer.write(chars, 0, chars.length + 1);
382            fail("Test 5b: IndexOutOfBoundsException expected.");
383        } catch (IndexOutOfBoundsException e) {
384            // Expected
385        }
386        try {
387            writer.write(chars, chars.length, 1);
388            fail("Test 5c: IndexOutOfBoundsException expected.");
389        } catch (IndexOutOfBoundsException e) {
390            // Expected
391        }
392        try {
393            writer.write(chars, chars.length + 1, 0);
394            fail("Test 5d: IndexOutOfBoundsException expected.");
395        } catch (IndexOutOfBoundsException e) {
396            // Expected
397        }
398
399        out.setThrowsException(true);
400        try {
401            for (int i = 0; i < 200; i++) {
402                writer.write(chars, 0, chars.length);
403            }
404            fail("Test 6: IOException expected.");
405        } catch (IOException e) {
406            // Expected
407        }
408        out.setThrowsException(false);
409
410        writer.close();
411        writer = new OutputStreamWriter(baos, "utf-8");
412        writer.write(chars, 1, 2);
413        writer.flush();
414        assertEquals("Test 7: write(char[], int, int) has not produced the " +
415                     "expected content in the output stream.",
416                     "hi", baos.toString("utf-8"));
417
418        writer.write(chars, 0, chars.length);
419        writer.flush();
420        assertEquals("Test 8: write(char[], int, int) has not produced the " +
421                "expected content in the output stream.",
422                "hi" + testString, baos.toString("utf-8"));
423
424        writer.close();
425        try {
426            writer.write((char[]) null, -1, -1);
427            fail("Test 9: IOException expected.");
428        } catch (IOException e) {
429            // Expected
430        }
431    }
432
433    public void test_writeI() throws IOException {
434        Support_OutputStream out = new Support_OutputStream(500);
435        OutputStreamWriter writer;
436
437        out.setThrowsException(true);
438        writer = new OutputStreamWriter(out, "utf-8");
439        try {
440            // Since there is an internal buffer in the encoder, more than
441            // one character needs to be written.
442            for (int i = 0; i < 200; i++) {
443                for (int j = 0; j < testString.length(); j++) {
444                    writer.write(testString.charAt(j));
445                }
446            }
447            fail("Test 1: IOException expected.");
448        } catch (IOException e) {
449            // Expected
450        }
451        out.setThrowsException(false);
452        writer.close();
453
454        writer = new OutputStreamWriter(out, "utf-8");
455        writer.write(1);
456        writer.flush();
457        String str = new String(out.toByteArray(), "utf-8");
458        assertEquals("Test 2: ", "\u0001", str);
459
460        writer.write(2);
461        writer.flush();
462        str = new String(out.toByteArray(), "utf-8");
463        assertEquals("Test 3: ", "\u0001\u0002", str);
464
465        writer.write(-1);
466        writer.flush();
467        str = new String(out.toByteArray(), "utf-8");
468        assertEquals("Test 4: ", "\u0001\u0002\uffff", str);
469
470        writer.write(0xfedcb);
471        writer.flush();
472        str = new String(out.toByteArray(), "utf-8");
473        assertEquals("Test 5: ", "\u0001\u0002\uffff\uedcb", str);
474
475        writer.close();
476        try {
477            writer.write(1);
478            fail("Test 6: IOException expected.");
479        } catch (IOException e) {
480            // Expected
481        }
482    }
483
484    public void test_writeLjava_lang_StringII() throws IOException {
485        ByteArrayOutputStream baos = new ByteArrayOutputStream();
486        Support_OutputStream out = new Support_OutputStream(500);
487        OutputStreamWriter writer;
488
489        writer = new OutputStreamWriter(out, "utf-8");
490
491        try {
492            writer.write("Lorem", -1, 0);
493            fail("Test 1: IndexOutOfBoundsException expected.");
494        } catch (IndexOutOfBoundsException e) {
495            // Expected
496        }
497
498        try {
499            writer.write("Lorem", 0, -1);
500            fail("Test 2: IndexOutOfBoundsException expected.");
501        } catch (IndexOutOfBoundsException e) {
502            // Expected
503        }
504
505        try {
506            writer.write("", 0, 1);
507            fail("Test 3: IndexOutOfBoundsException expected.");
508        } catch (IndexOutOfBoundsException e) {
509            // Expected
510        }
511
512        try {
513            writer.write(testString, 1, testString.length());
514            fail("Test 4a: IndexOutOfBoundsException expected.");
515        } catch (IndexOutOfBoundsException e) {
516            // Expected
517        }
518
519        try {
520            writer.write(testString, 0, testString.length() + 1);
521            fail("Test 4b: IndexOutOfBoundsException expected.");
522        } catch (IndexOutOfBoundsException e) {
523            // Expected
524        }
525
526        try {
527            writer.write(testString, testString.length(), 1);
528            fail("Test 4c: IndexOutOfBoundsException expected.");
529        } catch (IndexOutOfBoundsException e) {
530            // Expected
531        }
532
533        try {
534            writer.write(testString, testString.length() + 1, 0);
535            fail("Test 4d: IndexOutOfBoundsException expected.");
536        } catch (IndexOutOfBoundsException e) {
537            // Expected
538        }
539
540        try {
541            writer.write((String) null, 0, 1);
542            fail("Test 5: NullPointerException expected.");
543        } catch (NullPointerException e) {
544            // Expected
545        }
546
547        out.setThrowsException(true);
548        try {
549            for (int i = 0; i < 200; i++) {
550                writer.write(testString, 0, testString.length());
551            }
552            fail("Test 6: IOException expected.");
553        } catch (IOException e) {
554            // Expected
555        }
556        out.setThrowsException(false);
557
558        writer.close();
559        writer = new OutputStreamWriter(baos, "utf-8");
560
561        writer.write("abc", 1, 2);
562        writer.flush();
563        assertEquals("Test 7: write(String, int, int) has not produced the " +
564                     "expected content in the output stream.",
565                     "bc", baos.toString("utf-8"));
566
567        writer.write(testString, 0, testString.length());
568        writer.flush();
569        assertEquals("Test 7: write(String, int, int) has not produced the " +
570                     "expected content in the output stream.",
571                     "bc" + testString, baos.toString("utf-8"));
572
573        writer.close();
574        try {
575            writer.write("abc", 0, 1);
576            fail("Test 8: IOException expected.");
577        } catch (IOException e) {
578            // Expected
579        }
580    }
581
582    private void openInputStream() {
583        try {
584            isr = new InputStreamReader(new ByteArrayInputStream(fos.toByteArray()), "UTF-8");
585        } catch (UnsupportedEncodingException e) {
586            fail("UTF-8 not supported");
587        }
588    }
589}
590