/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.harmony.tests.java.io; import junit.framework.TestCase; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; public class OutputStreamWriterTest extends TestCase { private static final int UPPER = 0xd800; private static final int BUFFER_SIZE = 10000; private ByteArrayOutputStream out; private OutputStreamWriter writer; static private final String source = "This is a test message with Unicode character. \u4e2d\u56fd is China's name in Chinese"; static private final String[] MINIMAL_CHARSETS = new String[] { "US-ASCII", "ISO-8859-1", "UTF-16BE", "UTF-16LE", "UTF-16", "UTF-8" }; OutputStreamWriter osw; InputStreamReader isr; private ByteArrayOutputStream fos; String testString = "Test_All_Tests\nTest_java_io_BufferedInputStream\nTest_java_io_BufferedOutputStream\nTest_java_io_ByteArrayInputStream\nTest_java_io_ByteArrayOutputStream\nTest_java_io_DataInputStream\n"; /* * @see TestCase#setUp() */ @Override protected void setUp() throws Exception { super.setUp(); out = new ByteArrayOutputStream(); writer = new OutputStreamWriter(out, "utf-8"); fos = new ByteArrayOutputStream(); osw = new OutputStreamWriter(fos); } /* * @see TestCase#tearDown() */ @Override protected void tearDown() throws Exception { try { writer.close(); if (isr != null) { isr.close(); } osw.close(); } catch (Exception e) { // Ignored } super.tearDown(); } public void testClose() throws Exception { writer.flush(); writer.close(); try { writer.flush(); fail(); } catch (IOException e) { // Expected } } public void testFlush() throws Exception { writer.write(source); writer.flush(); String result = out.toString("utf-8"); assertEquals(source, result); } /* * Class under test for void write(char[], int, int) */ public void testWritecharArrayintint() throws IOException { char[] chars = source.toCharArray(); // Throws IndexOutOfBoundsException if offset is negative try { writer.write((char[]) null, -1, -1); fail(); } catch (NullPointerException exception) { } catch (IndexOutOfBoundsException exception) { } // throws NullPointerException though count is negative try { writer.write((char[]) null, 1, -1); fail(); } catch (NullPointerException exception) { } catch (IndexOutOfBoundsException exception) { } try { writer.write((char[]) null, 1, 1); fail(); } catch (NullPointerException e) { // Expected } try { writer.write(new char[0], 0, 1); fail(); } catch (IndexOutOfBoundsException e) { // Expected } try { writer.write(chars, -1, 1); fail(); } catch (IndexOutOfBoundsException e) { // Expected } try { writer.write(chars, 0, -1); fail(); } catch (IndexOutOfBoundsException e) { // Expected } try { writer.write(chars, 1, chars.length); fail(); } catch (IndexOutOfBoundsException e) { // Expected } writer.write(chars, 1, 2); writer.flush(); assertEquals("hi", out.toString("utf-8")); writer.write(chars, 0, chars.length); writer.flush(); assertEquals("hi" + source, out.toString("utf-8")); writer.close(); // After the stream is closed, should throw IOException first try { writer.write((char[]) null, -1, -1); fail("should throw IOException"); } catch (IOException e) { // Expected } } /* * Class under test for void write(int) */ public void testWriteint() throws IOException { writer.write(1); writer.flush(); String str = new String(out.toByteArray(), "utf-8"); assertEquals("\u0001", str); writer.write(2); writer.flush(); str = new String(out.toByteArray(), "utf-8"); assertEquals("\u0001\u0002", str); writer.write(-1); writer.flush(); str = new String(out.toByteArray(), "utf-8"); assertEquals("\u0001\u0002\uffff", str); writer.write(0xfedcb); writer.flush(); str = new String(out.toByteArray(), "utf-8"); assertEquals("\u0001\u0002\uffff\uedcb", str); writer.close(); // After the stream is closed, should throw IOException try { writer.write(1); fail("should throw IOException"); } catch (IOException e) { // expected } } /* * Class under test for void write(String, int, int) */ public void testWriteStringintint() throws IOException { try { writer.write((String) null, 1, 1); fail(); } catch (NullPointerException e) { // Expected } try { writer.write("", 0, 1); fail(); } catch (StringIndexOutOfBoundsException e) { // Expected } try { writer.write("abc", -1, 1); fail(); } catch (StringIndexOutOfBoundsException e) { // Expected } try { writer.write("abc", 0, -1); fail(); } catch (IndexOutOfBoundsException e) { // Expected } try { writer.write("abc", 1, 3); fail(); } catch (StringIndexOutOfBoundsException e) { // Expected } try { writer.write((String) null, -1, -1); fail(); } catch (NullPointerException expected) { } catch (IndexOutOfBoundsException expected) { } // Throws NullPointerException before StringIndexOutOfBoundsException try { writer.write((String) null, -1, 0); fail(); } catch (NullPointerException expected) { } catch (IndexOutOfBoundsException expected) { } writer.write("abc", 1, 2); writer.flush(); assertEquals("bc", out.toString("utf-8")); writer.write(source, 0, source.length()); writer.flush(); assertEquals("bc" + source, out.toString("utf-8")); writer.close(); // Throws IndexOutOfBoundsException first if count is negative try { writer.write((String) null, 0, -1); fail(); } catch (NullPointerException expected) { } catch (IndexOutOfBoundsException expected) { } try { writer.write((String) null, -1, 0); fail(); } catch (NullPointerException expected) { } catch (IndexOutOfBoundsException expected) { } try { writer.write("abc", -1, 0); fail("should throw StringIndexOutOfBoundsException"); } catch (StringIndexOutOfBoundsException e) { // Expected } // Throws IOException try { writer.write("abc", 0, 1); fail("should throw IOException"); } catch (IOException e) { // expected } } /* * Class under test for void OutputStreamWriter(OutputStream) */ public void testOutputStreamWriterOutputStream() throws IOException { try { writer = new OutputStreamWriter(null); fail(); } catch (NullPointerException e) { // Expected } OutputStreamWriter writer2 = new OutputStreamWriter(out); writer2.close(); } /* * Class under test for void OutputStreamWriter(OutputStream, String) */ public void testOutputStreamWriterOutputStreamString() throws IOException { try { writer = new OutputStreamWriter(null, "utf-8"); fail(); } catch (NullPointerException e) { // Expected } try { writer = new OutputStreamWriter(out, ""); fail(); } catch (UnsupportedEncodingException e) { // Expected } try { writer = new OutputStreamWriter(out, "badname"); fail(); } catch (UnsupportedEncodingException e) { // Expected } try { writer = new OutputStreamWriter(out, (String) null); fail(); } catch (NullPointerException e) { // Expected } OutputStreamWriter writer2 = new OutputStreamWriter(out, "ascii"); assertEquals(Charset.forName("ascii"), Charset.forName(writer2 .getEncoding())); writer2.close(); } /* * Class under test for void OutputStreamWriter(OutputStream) */ public void testOutputStreamWriterOutputStreamCharset() throws IOException { Charset cs = Charset.forName("ascii"); try { writer = new OutputStreamWriter(null, cs); fail(); } catch (NullPointerException e) { // Expected } try { writer = new OutputStreamWriter(out, (Charset) null); fail(); } catch (NullPointerException e) { // Expected } OutputStreamWriter writer2 = new OutputStreamWriter(out, cs); assertEquals(cs, Charset.forName(writer2.getEncoding())); writer2.close(); } /* * Class under test for void OutputStreamWriter(OutputStream, String) */ public void testOutputStreamWriterOutputStreamCharsetEncoder() throws IOException { Charset cs = Charset.forName("ascii"); CharsetEncoder enc = cs.newEncoder(); try { writer = new OutputStreamWriter(null, enc); fail(); } catch (NullPointerException e) { // Expected } try { writer = new OutputStreamWriter(out, (CharsetEncoder) null); fail(); } catch (NullPointerException e) { // Expected } OutputStreamWriter writer2 = new OutputStreamWriter(out, enc); assertEquals(cs, Charset.forName(writer2.getEncoding())); writer2.close(); } public void testGetEncoding() { Charset cs = Charset.forName("utf-8"); assertEquals(cs, Charset.forName(writer.getEncoding())); } public void testHandleEarlyEOFChar_1() throws IOException { String str = "All work and no play makes Jack a dull boy\n"; //$NON-NLS-1$ int NUMBER = 2048; int j = 0; int len = str.length() * NUMBER; char[] strChars = new char[len]; for (int i = 0; i < NUMBER; ++i) { for (int k = 0; k < str.length(); ++k) { strChars[j++] = str.charAt(k); } } File f = File.createTempFile("one", "by_one"); f.deleteOnExit(); FileWriter fw = new FileWriter(f); fw.write(strChars); fw.close(); FileInputStream fis = new FileInputStream(f); InputStreamReader in = new InputStreamReader(fis); for (int offset = 0; offset < strChars.length; ++offset) { int b = in.read(); assertFalse("Early EOF at offset", -1 == b); } } public void testHandleEarlyEOFChar_2() throws IOException { int capacity = 65536; byte[] bytes = new byte[capacity]; byte[] bs = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' }; for (int i = 0; i < bytes.length; i++) { bytes[i] = bs[i / 8192]; } String inputStr = new String(bytes); int len = inputStr.length(); File f = File.createTempFile("FileWriterBugTest ", null); //$NON-NLS-1$ f.deleteOnExit(); FileWriter writer = new FileWriter(f); writer.write(inputStr); writer.close(); long flen = f.length(); FileReader reader = new FileReader(f); char[] outChars = new char[capacity]; int outCount = reader.read(outChars); String outStr = new String(outChars, 0, outCount); assertEquals(len, flen); assertEquals(inputStr, outStr); } public void testSingleCharIO() throws Exception { InputStreamReader isr = null; for (int i = 0; i < MINIMAL_CHARSETS.length; ++i) { try { out = new ByteArrayOutputStream(); writer = new OutputStreamWriter(out, MINIMAL_CHARSETS[i]); int upper = UPPER; switch (i) { case 0: upper = 128; break; case 1: upper = 256; break; } for (int c = 0; c < upper; ++c) { writer.write(c); } writer.flush(); byte[] result = out.toByteArray(); isr = new InputStreamReader(new ByteArrayInputStream(result), MINIMAL_CHARSETS[i]); for (int expected = 0; expected < upper; ++expected) { assertEquals("Error when reading bytes in " + MINIMAL_CHARSETS[i], expected, isr.read()); } } finally { try { isr.close(); } catch (Exception e) { } try { writer.close(); } catch (Exception e) { } } } } public void testBlockIO() throws Exception { InputStreamReader isr = null; char[] largeBuffer = new char[BUFFER_SIZE]; for (int i = 0; i < MINIMAL_CHARSETS.length; ++i) { try { out = new ByteArrayOutputStream(); writer = new OutputStreamWriter(out, MINIMAL_CHARSETS[i]); int upper = UPPER; switch (i) { case 0: upper = 128; break; case 1: upper = 256; break; } int m = 0; for (int c = 0; c < upper; ++c) { largeBuffer[m++] = (char) c; if (m == BUFFER_SIZE) { writer.write(largeBuffer); m = 0; } } writer.write(largeBuffer, 0, m); writer.flush(); byte[] result = out.toByteArray(); isr = new InputStreamReader(new ByteArrayInputStream(result), MINIMAL_CHARSETS[i]); int expected = 0, read = 0, j = 0; while (expected < upper) { if (j == read) { read = isr.read(largeBuffer); j = 0; } assertEquals("Error when reading bytes in " + MINIMAL_CHARSETS[i], expected++, largeBuffer[j++]); } } finally { try { isr.close(); } catch (Exception e) { } try { writer.close(); } catch (Exception e) { } } } } /** * java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream) */ public void test_ConstructorLjava_io_OutputStream() { assertTrue("Used in tests", true); } /** * java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream, *java.lang.String) */ public void test_ConstructorLjava_io_OutputStreamLjava_lang_String() throws UnsupportedEncodingException { osw = new OutputStreamWriter(fos, "8859_1"); try { osw = new OutputStreamWriter(fos, "Bogus"); fail("Failed to throw Unsupported Encoding exception"); } catch (UnsupportedEncodingException e) { // Expected } } /** * java.io.OutputStreamWriter#close() */ public void test_close() throws IOException { osw.close(); try { osw.write(testString, 0, testString.length()); fail("Chars written after close"); } catch (IOException e) { // Expected } ByteArrayOutputStream bout = new ByteArrayOutputStream(); try { OutputStreamWriter writer = new OutputStreamWriter(bout, "ISO2022JP"); writer.write(new char[] { 'a' }); writer.close(); // the default is ASCII, there should not be any mode changes String converted = new String(bout.toByteArray(), "ISO8859_1"); assertTrue("invalid conversion 1: " + converted, converted .equals("a")); bout.reset(); writer = new OutputStreamWriter(bout, "ISO2022JP"); writer.write(new char[] { '\u3048' }); writer.flush(); // the byte sequence should not switch to ASCII mode until the // stream is closed converted = new String(bout.toByteArray(), "ISO8859_1"); assertTrue("invalid conversion 2: " + converted, converted .equals("\u001b$B$(")); writer.close(); converted = new String(bout.toByteArray(), "ISO8859_1"); assertTrue("invalid conversion 3: " + converted, converted .equals("\u001b$B$(\u001b(B")); bout.reset(); writer = new OutputStreamWriter(bout, "ISO2022JP"); writer.write(new char[] { '\u3048' }); writer.write(new char[] { '\u3048' }); writer.close(); // there should not be a mode switch between writes assertEquals("invalid conversion 4", "\u001b$B$($(\u001b(B", new String(bout.toByteArray(), "ISO8859_1")); } catch (UnsupportedEncodingException e) { // Can't test missing converter System.out.println(e); } } /** * java.io.OutputStreamWriter#flush() */ public void test_flush() throws IOException { char[] buf = new char[testString.length()]; osw.write(testString, 0, testString.length()); osw.flush(); openInputStream(); isr.read(buf, 0, buf.length); assertTrue("Chars not flushed", new String(buf, 0, buf.length) .equals(testString)); } /** * Unlike the RI, we return the canonical encoding name and not something * java specific. */ public void test_getEncoding() throws IOException { try { osw = new OutputStreamWriter(fos, "8859_1"); } catch (UnsupportedEncodingException e) { assertEquals("Returned incorrect encoding", "8859_1", osw .getEncoding()); } OutputStreamWriter out = new OutputStreamWriter( new ByteArrayOutputStream(), "UTF-16BE"); out.close(); String result = out.getEncoding(); assertNull(result); out = null; try { out = new OutputStreamWriter(new ByteArrayOutputStream(), "UTF-16BE"); } catch (UnsupportedEncodingException e) { // ok } result = out.getEncoding(); assertEquals("UTF-16BE", result); } /** * java.io.OutputStreamWriter#write(char[], int, int) */ public void test_write$CII() throws IOException { char[] buf = new char[testString.length()]; osw.write(testString, 0, testString.length()); osw.close(); openInputStream(); isr.read(buf, 0, buf.length); assertTrue("Incorrect chars returned", new String(buf, 0, buf.length) .equals(testString)); } /** * java.io.OutputStreamWriter#write(int) */ public void test_writeI() throws IOException { osw.write('T'); osw.close(); openInputStream(); int c = isr.read(); assertEquals("Incorrect char returned", 'T', (char) c); } /** * java.io.OutputStreamWriter#write(java.lang.String, int, int) */ public void test_writeLjava_lang_StringII() throws IOException { char[] buf = new char[testString.length()]; osw.write(testString, 0, testString.length()); osw.close(); openInputStream(); isr.read(buf); assertTrue("Incorrect chars returned", new String(buf, 0, buf.length) .equals(testString)); } private void openInputStream() { isr = new InputStreamReader(new ByteArrayInputStream(fos.toByteArray())); } }