13bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes/*
23bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes * Copyright (C) 2010 The Android Open Source Project
33bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes *
43bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
53bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes * you may not use this file except in compliance with the License.
63bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes * You may obtain a copy of the License at
73bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes *
83bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
93bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes *
103bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes * Unless required by applicable law or agreed to in writing, software
113bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
123bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes * See the License for the specific language governing permissions and
143bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes * limitations under the License.
153bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes */
163bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes
173bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughespackage libcore.java.io;
183bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes
193bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughesimport java.io.*;
203bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughesimport java.util.Arrays;
213bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughesimport junit.framework.TestCase;
223bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes
233bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughespublic class OutputStreamWriterTest extends TestCase {
243bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes    private class FlushCountingOutputStream extends OutputStream {
253bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        int flushCount;
263bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        public void write(int b) {
273bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        }
283bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        @Override public void flush() throws IOException {
293bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes            ++flushCount;
303bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        }
313bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes    }
323bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes
333bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes    public void testFlushCount() throws Exception {
343bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        FlushCountingOutputStream os = new FlushCountingOutputStream();
353bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        OutputStreamWriter writer = new OutputStreamWriter(os, "UTF-8");
363bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        char[] chars = new char[16*1024];
373bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        Arrays.fill(chars, 'x');
383bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        for (int i = 0; i < 10; ++i) {
393bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes            writer.write(chars);
403bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        }
413bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        assertEquals(0, os.flushCount);
423bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        writer.flush();
433bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        assertEquals(1, os.flushCount);
443bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        writer.close();
453bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        assertEquals(1, os.flushCount);
463bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes    }
473bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes
483bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes    private void testFlush(boolean includeSecondHalf) throws Exception {
493bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        // OutputStreamWriter has an internal 8KiB buffer.
503bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        // We write enough characters to fill that, but leave data in the encoder.
513bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        // (Specifically, half a surrogate pair.)
523bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        // On flush/close, the writer needs to admit defeat and write the replacement character.
533bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        ByteArrayOutputStream baos = new ByteArrayOutputStream();
543bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        OutputStreamWriter writer = new OutputStreamWriter(baos, "UTF-32BE");
553bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        char[] cs = new char[8192/4 + 1];
563bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        Arrays.fill(cs, 'x');
573bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        cs[cs.length - 1] = '\ud842'; // One half of a surrogate pair (the other being U+df9f).
583bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        writer.write(cs, 0, cs.length);
593bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        writer.flush();
60555453327f26f4c9c610caa2851c87c3794c7764Elliott Hughes        assertEquals(8192, baos.size()); // Just the 'x's so far.
613bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        if (includeSecondHalf) {
623bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes            writer.write(0xdf9f);
633bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        }
643bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        writer.close();
653bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        // We should have 8192 32-bit big-endian 'x's...
663bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        byte[] bytes = baos.toByteArray();
673bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        assertEquals(8196, bytes.length);
683bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        int i = 0;
693bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        while (i < 8192) {
703bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes            assertEquals((byte) 0, bytes[i++]);
713bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes            assertEquals((byte) 0, bytes[i++]);
723bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes            assertEquals((byte) 0, bytes[i++]);
733bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes            assertEquals((byte) 'x', bytes[i++]);
743bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        }
753bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        if (includeSecondHalf) {
763bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes            // ...followed by a 32-bit big-endian U+20b9f.
773bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes            assertEquals((byte) 0x00, bytes[i++]);
783bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes            assertEquals((byte) 0x02, bytes[i++]);
793bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes            assertEquals((byte) 0x0b, bytes[i++]);
803bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes            assertEquals((byte) 0x9f, bytes[i++]);
813bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        } else {
823bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes            // ...followed by a 32-bit big-endian replacement character (U+fffd).
833bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes            assertEquals((byte) 0, bytes[i++]);
843bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes            assertEquals((byte) 0, bytes[i++]);
853bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes            assertEquals((byte) 0xff, bytes[i++]);
863bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes            assertEquals((byte) 0xfd, bytes[i++]);
873bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        }
883bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes    }
893bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes
903bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes    public void testFlush_halfSurrogate() throws Exception {
913bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        testFlush(false);
923bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes    }
933bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes
943bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes    public void testFlush_wholeSurrogate() throws Exception {
953bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes        testFlush(true);
963bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes    }
973bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes}
98