/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.portal.kernel.io; import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter; import com.liferay.portal.kernel.test.ReflectionTestUtil; import com.liferay.portal.kernel.test.rule.CodeCoverageAssertor; import com.liferay.portal.kernel.util.StringPool; import java.io.CharArrayWriter; import java.io.IOException; import java.io.Writer; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharsetDecoder; import java.nio.charset.CodingErrorAction; import java.util.concurrent.atomic.AtomicBoolean; import org.junit.Assert; import org.junit.ClassRule; import org.junit.Test; /** * @author Shuyang Zhou */ public class WriterOutputStreamTest { @ClassRule public static final CodeCoverageAssertor codeCoverageAssertor = CodeCoverageAssertor.INSTANCE; @Test public void testClose() throws IOException { final AtomicBoolean closeAtomicBoolean = new AtomicBoolean(); DummyWriter dummyWriter = new DummyWriter() { @Override public void close() { closeAtomicBoolean.set(true); } }; try (WriterOutputStream writerOutputStream = new WriterOutputStream( dummyWriter)) { Assert.assertFalse(closeAtomicBoolean.get()); } Assert.assertTrue(closeAtomicBoolean.get()); } @Test public void testConstructor() { DummyWriter dummyWriter = new DummyWriter(); WriterOutputStream writerOutputStream = new WriterOutputStream( dummyWriter); Assert.assertSame(dummyWriter, _getWriter(writerOutputStream)); Assert.assertSame( StringPool.DEFAULT_CHARSET_NAME, writerOutputStream.getEncoding()); Assert.assertEquals( _getDefaultOutputBufferSize(), _getOutputBufferSize(writerOutputStream)); Assert.assertFalse(_isAutoFlush(writerOutputStream)); writerOutputStream = new WriterOutputStream(dummyWriter, null); Assert.assertSame(dummyWriter, _getWriter(writerOutputStream)); Assert.assertSame( StringPool.DEFAULT_CHARSET_NAME, writerOutputStream.getEncoding()); Assert.assertEquals( _getDefaultOutputBufferSize(), _getOutputBufferSize(writerOutputStream)); Assert.assertFalse(_isAutoFlush(writerOutputStream)); String encoding = "US-ASCII"; writerOutputStream = new WriterOutputStream(dummyWriter, encoding); Assert.assertSame(dummyWriter, _getWriter(writerOutputStream)); Assert.assertSame(encoding, writerOutputStream.getEncoding()); Assert.assertEquals( _getDefaultOutputBufferSize(), _getOutputBufferSize(writerOutputStream)); Assert.assertFalse(_isAutoFlush(writerOutputStream)); writerOutputStream = new WriterOutputStream( dummyWriter, encoding, true); Assert.assertSame(dummyWriter, _getWriter(writerOutputStream)); Assert.assertSame(encoding, writerOutputStream.getEncoding()); Assert.assertEquals( _getDefaultOutputBufferSize(), _getOutputBufferSize(writerOutputStream)); Assert.assertTrue(_isAutoFlush(writerOutputStream)); writerOutputStream = new WriterOutputStream(dummyWriter, encoding, 32); Assert.assertSame(dummyWriter, _getWriter(writerOutputStream)); Assert.assertSame(encoding, writerOutputStream.getEncoding()); Assert.assertEquals(1, _getInputBufferSize(writerOutputStream)); Assert.assertEquals(32, _getOutputBufferSize(writerOutputStream)); Assert.assertFalse(_isAutoFlush(writerOutputStream)); writerOutputStream = new WriterOutputStream( dummyWriter, encoding, 32, true); Assert.assertSame(dummyWriter, _getWriter(writerOutputStream)); Assert.assertSame(encoding, writerOutputStream.getEncoding()); Assert.assertEquals(1, _getInputBufferSize(writerOutputStream)); Assert.assertEquals(32, _getOutputBufferSize(writerOutputStream)); Assert.assertTrue(_isAutoFlush(writerOutputStream)); writerOutputStream = new WriterOutputStream( dummyWriter, encoding, 0, true); Assert.assertSame(dummyWriter, _getWriter(writerOutputStream)); Assert.assertSame(encoding, writerOutputStream.getEncoding()); Assert.assertEquals(1, _getInputBufferSize(writerOutputStream)); Assert.assertEquals( _getDefaultOutputBufferSize(), _getOutputBufferSize(writerOutputStream)); Assert.assertTrue(_isAutoFlush(writerOutputStream)); try { new WriterOutputStream(dummyWriter, encoding, 0, false); Assert.fail(); } catch (IllegalArgumentException iae) { Assert.assertEquals( "Output buffer size 0 must be a positive number", iae.getMessage()); } } @Test public void testFlush() throws IOException { final AtomicBoolean flushed = new AtomicBoolean(); CharArrayWriter charArrayWriter = new CharArrayWriter() { @Override public void flush() { flushed.set(true); } }; WriterOutputStream writerOutputStream = new WriterOutputStream( charArrayWriter, StringPool.UTF8, 2); Assert.assertFalse(flushed.get()); writerOutputStream.write('a'); Assert.assertFalse(flushed.get()); Assert.assertEquals(0, charArrayWriter.size()); writerOutputStream.write('b'); Assert.assertFalse(flushed.get()); Assert.assertEquals(0, charArrayWriter.size()); writerOutputStream.write('c'); Assert.assertFalse(flushed.get()); Assert.assertEquals("ab", charArrayWriter.toString()); writerOutputStream.write('d'); Assert.assertFalse(flushed.get()); Assert.assertEquals("ab", charArrayWriter.toString()); writerOutputStream.flush(); Assert.assertTrue(flushed.get()); Assert.assertEquals("abcd", charArrayWriter.toString()); } @Test public void testWrite() throws IOException { CharArrayWriter charArrayWriter = new CharArrayWriter(); WriterOutputStream writerOutputStream = new WriterOutputStream( charArrayWriter, StringPool.UTF8, true); int charNumber = 0; String unalignedOutput = "非对齐测试中文输出"; byte[] unalignedInput = unalignedOutput.getBytes(StringPool.UTF8); for (byte b : unalignedInput) { writerOutputStream.write(b); int currentCharNumber = charArrayWriter.size(); if (currentCharNumber > charNumber) { charNumber = currentCharNumber; Assert.assertEquals( unalignedOutput.charAt(charNumber - 1), charArrayWriter.toCharArray()[charNumber - 1]); } } Assert.assertEquals(unalignedOutput, charArrayWriter.toString()); } @Test public void testWriteBlock() throws IOException { _testWriteBlock(false); _testWriteBlock(true); } @Test public void testWriteBlockUnaligned() throws IOException { CharArrayWriter charArrayWriter = new CharArrayWriter(); String unalignedOutput = "非对齐测试中文输出"; try (WriterOutputStream writerOutputStream = new WriterOutputStream( charArrayWriter, StringPool.UTF8, true)) { byte[] unalignedInput = unalignedOutput.getBytes(StringPool.UTF8); writerOutputStream.write(unalignedInput[0]); writerOutputStream.write( unalignedInput, 1, unalignedInput.length - 2); writerOutputStream.write(unalignedInput[unalignedInput.length - 1]); } Assert.assertEquals(unalignedOutput, charArrayWriter.toString()); } @Test public void testWriteError() { WriterOutputStream writerOutputStream = new WriterOutputStream( new DummyWriter(), "US-ASCII"); CharsetDecoder charsetDecoder = ReflectionTestUtil.getFieldValue( writerOutputStream, "_charsetDecoder"); charsetDecoder.onMalformedInput(CodingErrorAction.REPORT); try { writerOutputStream.write(new byte[] {-1, -2, -3, -4}); Assert.fail(); } catch (IOException ioe) { Assert.assertEquals( "Unexcepted coder result MALFORMED[1]", ioe.getMessage()); } } private int _getDefaultOutputBufferSize() { return ReflectionTestUtil.getFieldValue( WriterOutputStream.class, "_DEFAULT_OUTPUT_BUFFER_SIZE"); } private int _getInputBufferSize(WriterOutputStream writerOutputStream) { ByteBuffer inputByteBuffer = ReflectionTestUtil.getFieldValue( writerOutputStream, "_inputByteBuffer"); return inputByteBuffer.capacity(); } private int _getOutputBufferSize(WriterOutputStream writerOutputStream) { CharBuffer outputBuffer = ReflectionTestUtil.getFieldValue( writerOutputStream, "_outputCharBuffer"); return outputBuffer.capacity(); } private Writer _getWriter(WriterOutputStream writerOutputStream) { return ReflectionTestUtil.getFieldValue(writerOutputStream, "_writer"); } private boolean _isAutoFlush(WriterOutputStream writerOutputStream) { return ReflectionTestUtil.getFieldValue( writerOutputStream, "_autoFlush"); } private void _testWriteBlock(boolean autoFlush) throws IOException { final AtomicBoolean flushed = new AtomicBoolean(); UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter() { @Override public void flush() { flushed.set(true); } }; WriterOutputStream writerOutputStream = new WriterOutputStream( unsyncStringWriter, "US-ASCII", 2, autoFlush); writerOutputStream.write( new byte[] { (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g' }, 1, 5); Assert.assertFalse(flushed.get()); if (!autoFlush) { writerOutputStream.flush(); Assert.assertTrue(flushed.get()); flushed.set(false); } Assert.assertEquals("bcdef", unsyncStringWriter.toString()); unsyncStringWriter.reset(); writerOutputStream = new WriterOutputStream( unsyncStringWriter, "US-ASCII", 4, autoFlush); writerOutputStream.write( new byte[] { (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g' }, 1, 5); Assert.assertFalse(flushed.get()); if (!autoFlush) { writerOutputStream.flush(); Assert.assertTrue(flushed.get()); flushed.set(false); } Assert.assertEquals("bcdef", unsyncStringWriter.toString()); unsyncStringWriter.reset(); writerOutputStream = new WriterOutputStream( unsyncStringWriter, "US-ASCII", autoFlush); writerOutputStream.write(new byte[] {(byte)'a', (byte)'b', (byte)'c'}); Assert.assertFalse(flushed.get()); if (!autoFlush) { writerOutputStream.flush(); Assert.assertTrue(flushed.get()); flushed.set(false); } Assert.assertEquals("abc", unsyncStringWriter.toString()); } }