blob: 5958c225b76f2c61d3e20711c7c8f5d928267a37 [file] [log] [blame]
package org.apache.logging.log4j.core.layout;/*
* 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.
*/
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Tests the {@code TextEncoderHelper} class.
*/
public class StringBuilderEncoderTest {
@Test
public void testEncodeText_TextFitCharBuff_BytesFitByteBuff() throws Exception {
final StringBuilderEncoder helper = new StringBuilderEncoder(StandardCharsets.UTF_8, 16, 8 * 1024);
final StringBuilder text = createText(15);
final SpyByteBufferDestination destination = new SpyByteBufferDestination(17, 17);
helper.encode(text, destination);
assertEquals("drained", 0, destination.drainPoints.size());
assertEquals("destination.buf.pos", text.length(), destination.buffer.position());
for (int i = 0; i < text.length(); i++) {
assertEquals("char at " + i, (byte) text.charAt(i), destination.buffer.get(i));
}
}
@Test
public void testEncodeText_TextFitCharBuff_BytesDontFitByteBuff() throws Exception {
final StringBuilderEncoder helper = new StringBuilderEncoder(StandardCharsets.UTF_8, 16, 8 * 1024);
final StringBuilder text = createText(15);
final SpyByteBufferDestination destination = new SpyByteBufferDestination(14, 15);
helper.encode(text, destination);
assertEquals("drained", 1, destination.drainPoints.size());
assertEquals("drained[0].from", 0, destination.drainPoints.get(0).position);
assertEquals("drained[0].to", destination.buffer.capacity(), destination.drainPoints.get(0).limit);
assertEquals("drained[0].length", destination.buffer.capacity(), destination.drainPoints.get(0).length());
assertEquals("destination.buf.pos", text.length() - destination.buffer.capacity(),
destination.buffer.position());
for (int i = 0; i < destination.buffer.capacity(); i++) {
assertEquals("char at " + i, (byte) text.charAt(i), destination.drained.get(i));
}
for (int i = destination.buffer.capacity(); i < text.length(); i++) {
final int bufIx = i - destination.buffer.capacity();
assertEquals("char at " + i, (byte) text.charAt(i), destination.buffer.get(bufIx));
}
}
@Test
public void testEncodeText_TextFitCharBuff_BytesDontFitByteBuff_MultiplePasses() throws Exception {
final StringBuilderEncoder helper = new StringBuilderEncoder(StandardCharsets.UTF_8, 16, 8 * 1024);
final StringBuilder text = createText(15);
final SpyByteBufferDestination destination = new SpyByteBufferDestination(4, 20);
helper.encode(text, destination);
assertEquals("drained", 3, destination.drainPoints.size());
assertEquals("drained[0].from", 0, destination.drainPoints.get(0).position);
assertEquals("drained[0].to", destination.buffer.capacity(), destination.drainPoints.get(0).limit);
assertEquals("drained[0].length", destination.buffer.capacity(), destination.drainPoints.get(0).length());
assertEquals("drained[1].from", 0, destination.drainPoints.get(1).position);
assertEquals("drained[1].to", destination.buffer.capacity(), destination.drainPoints.get(1).limit);
assertEquals("drained[1].length", destination.buffer.capacity(), destination.drainPoints.get(1).length());
assertEquals("drained[2].from", 0, destination.drainPoints.get(2).position);
assertEquals("drained[2].to", destination.buffer.capacity(), destination.drainPoints.get(2).limit);
assertEquals("drained[2].length", destination.buffer.capacity(), destination.drainPoints.get(2).length());
assertEquals("destination.buf.pos", text.length() - 3 * destination.buffer.capacity(),
destination.buffer.position());
for (int i = 0; i < 3 * destination.buffer.capacity(); i++) {
assertEquals("char at " + i, (byte) text.charAt(i), destination.drained.get(i));
}
for (int i = 3 * destination.buffer.capacity(); i < text.length(); i++) {
final int bufIx = i - 3 * destination.buffer.capacity();
assertEquals("char at " + i, (byte) text.charAt(i), destination.buffer.get(bufIx));
}
}
@Test
public void testEncodeText_TextDoesntFitCharBuff_BytesFitByteBuff() throws Exception {
final StringBuilderEncoder helper = new StringBuilderEncoder(StandardCharsets.UTF_8, 4, 8 * 1024);
final StringBuilder text = createText(15);
final SpyByteBufferDestination destination = new SpyByteBufferDestination(17, 17);
helper.encode(text, destination);
assertEquals("drained", 0, destination.drainPoints.size());
assertEquals("destination.buf.pos", text.length(), destination.buffer.position());
for (int i = 0; i < text.length(); i++) {
assertEquals("char at " + i, (byte) text.charAt(i), destination.buffer.get(i));
}
}
@Test
public void testEncodeText_JapaneseTextUtf8DoesntFitCharBuff_BytesFitByteBuff() throws Exception {
final StringBuilderEncoder helper = new StringBuilderEncoder(StandardCharsets.UTF_8, 4, 8 * 1024);
final StringBuilder text = new StringBuilder( // 日本語テスト文章
"\u65e5\u672c\u8a9e\u30c6\u30b9\u30c8\u6587\u7ae0");
final SpyByteBufferDestination destination = new SpyByteBufferDestination(50, 50);
helper.encode(text, destination);
assertEquals("drained", 0, destination.drainPoints.size());
destination.drain(destination.getByteBuffer());
final byte[] utf8 = text.toString().getBytes(StandardCharsets.UTF_8);
for (int i = 0; i < utf8.length; i++) {
assertEquals("byte at " + i, utf8[i], destination.drained.get(i));
}
}
@Test
public void testEncodeText_JapaneseTextShiftJisDoesntFitCharBuff_BytesFitByteBuff() throws Exception {
final Charset SHIFT_JIS = Charset.forName("Shift_JIS");
final StringBuilderEncoder helper = new StringBuilderEncoder(SHIFT_JIS, 4, 8 * 1024);
final StringBuilder text = new StringBuilder( // 日本語テスト文章
"\u65e5\u672c\u8a9e\u30c6\u30b9\u30c8\u6587\u7ae0");
final SpyByteBufferDestination destination = new SpyByteBufferDestination(50, 50);
helper.encode(text, destination);
assertEquals("drained", 0, destination.drainPoints.size());
destination.drain(destination.getByteBuffer());
final byte[] bytes = text.toString().getBytes(SHIFT_JIS);
for (int i = 0; i < bytes.length; i++) {
assertEquals("byte at " + i, bytes[i], destination.drained.get(i));
}
}
@Test
public void testEncodeText_TextDoesntFitCharBuff_BytesDontFitByteBuff() throws Exception {
final StringBuilderEncoder helper = new StringBuilderEncoder(StandardCharsets.UTF_8, 4, 8 * 1024);
final StringBuilder text = createText(15);
final SpyByteBufferDestination destination = new SpyByteBufferDestination(3, 17);
helper.encode(text, destination);
assertEquals("drained", 4, destination.drainPoints.size());
assertEquals("destination.buf.pos", 3, destination.buffer.position());
for (int i = 0; i < text.length() - 3; i++) {
assertEquals("char at " + i, (byte) text.charAt(i), destination.drained.get(i));
}
for (int i = 0; i < 3; i++) {
assertEquals("char at " + (12 + i), (byte) text.charAt(12 + i), destination.buffer.get(i));
}
}
@Test
public void testEncodeText_JapaneseTextUtf8DoesntFitCharBuff_BytesDontFitByteBuff() throws Exception {
final StringBuilderEncoder helper = new StringBuilderEncoder(StandardCharsets.UTF_8, 4, 8 * 1024);
final StringBuilder text = new StringBuilder( // 日本語テスト文章
"\u65e5\u672c\u8a9e\u30c6\u30b9\u30c8\u6587\u7ae0");
final SpyByteBufferDestination destination = new SpyByteBufferDestination(3, 50);
helper.encode(text, destination);
assertEquals("drained", 7, destination.drainPoints.size());
destination.drain(destination.getByteBuffer());
final byte[] utf8 = text.toString().getBytes(StandardCharsets.UTF_8);
for (int i = 0; i < utf8.length; i++) {
assertEquals("byte at " + i, utf8[i], destination.drained.get(i));
}
}
@Test
public void testEncodeText_JapaneseTextUtf8DoesntFitCharBuff_DoesntFitTempByteBuff_BytesDontFitDestinationByteBuff() throws Exception {
final StringBuilderEncoder helper = new StringBuilderEncoder(StandardCharsets.UTF_8, 4, 5);
final StringBuilder text = new StringBuilder( // 日本語テスト文章日本語テスト文章
"\u65e5\u672c\u8a9e\u30c6\u30b9\u30c8\u6587\u7ae0\u65e5\u672c\u8a9e\u30c6\u30b9\u30c8\u6587\u7ae0");
final SpyByteBufferDestination destination = new SpyByteBufferDestination(3, 50);
helper.encode(text, destination);
assertEquals("drained", 15, destination.drainPoints.size());
destination.drain(destination.getByteBuffer());
final byte[] utf8 = text.toString().getBytes(StandardCharsets.UTF_8);
for (int i = 0; i < utf8.length; i++) {
assertEquals("byte at " + i, utf8[i], destination.drained.get(i));
}
}
@Test
public void testEncodeText_JapaneseTextShiftJisDoesntFitCharBuff_BytesDontFitByteBuff() throws Exception {
final Charset SHIFT_JIS = Charset.forName("Shift_JIS");
final StringBuilderEncoder helper = new StringBuilderEncoder(SHIFT_JIS, 4, 8 * 1024);
final StringBuilder text = new StringBuilder( // 日本語テスト文章
"\u65e5\u672c\u8a9e\u30c6\u30b9\u30c8\u6587\u7ae0");
final SpyByteBufferDestination destination = new SpyByteBufferDestination(3, 50);
helper.encode(text, destination);
destination.drain(destination.getByteBuffer());
final byte[] bytes = text.toString().getBytes(SHIFT_JIS);
for (int i = 0; i < bytes.length; i++) {
assertEquals("byte at " + i, bytes[i], destination.drained.get(i));
}
}
@Test
public void testEncodeText_JapaneseTextShiftJisDoesntFitCharBuff_DoesntFitTempByteBuff_BytesDontFitDestinationByteBuff() throws Exception {
final Charset SHIFT_JIS = Charset.forName("Shift_JIS");
final StringBuilderEncoder helper = new StringBuilderEncoder(SHIFT_JIS, 4, 5);
final StringBuilder text = new StringBuilder( // 日本語テスト文章日本語テスト文章
"\u65e5\u672c\u8a9e\u30c6\u30b9\u30c8\u6587\u7ae0\u65e5\u672c\u8a9e\u30c6\u30b9\u30c8\u6587\u7ae0");
final SpyByteBufferDestination destination = new SpyByteBufferDestination(3, 50);
helper.encode(text, destination);
destination.drain(destination.getByteBuffer());
final byte[] bytes = text.toString().getBytes(SHIFT_JIS);
for (int i = 0; i < bytes.length; i++) {
assertEquals("byte at " + i, bytes[i], destination.drained.get(i));
}
}
@Test
public void testCopyCopiesAllDataIfSuffientRemainingSpace() throws Exception {
final CharBuffer buff = CharBuffer.wrap(new char[16]);
final StringBuilder text = createText(15);
final int length = TextEncoderHelper.copy(text, 0, buff);
assertEquals("everything fits", text.length(), length);
for (int i = 0; i < length; i++) {
assertEquals("char at " + i, text.charAt(i), buff.get(i));
}
assertEquals("position moved by length", text.length(), buff.position());
}
@Test
public void testCopyUpToRemainingSpace() throws Exception {
final CharBuffer buff = CharBuffer.wrap(new char[3]);
final StringBuilder text = createText(15);
final int length = TextEncoderHelper.copy(text, 0, buff);
assertEquals("partial copy", buff.capacity(), length);
for (int i = 0; i < length; i++) {
assertEquals("char at " + i, text.charAt(i), buff.get(i));
}
assertEquals("no space remaining", 0, buff.remaining());
assertEquals("position at end", buff.capacity(), buff.position());
}
@Test
public void testCopyDoesNotWriteBeyondStringText() throws Exception {
final CharBuffer buff = CharBuffer.wrap(new char[5]);
assertEquals("initial buffer position", 0, buff.position());
final StringBuilder text = createText(2);
final int length = TextEncoderHelper.copy(text, 0, buff);
assertEquals("full copy", text.length(), length);
for (int i = 0; i < length; i++) {
assertEquals("char at " + i, text.charAt(i), buff.get(i));
}
assertEquals("resulting buffer position", text.length(), buff.position());
for (int i = length; i < buff.capacity(); i++) {
assertEquals("unset char at " + i, 0, buff.get(i));
}
}
@Test
public void testCopyStartsAtBufferPosition() throws Exception {
final CharBuffer buff = CharBuffer.wrap(new char[10]);
final int START_POSITION = 5;
buff.position(START_POSITION); // set start position
final StringBuilder text = createText(15);
final int length = TextEncoderHelper.copy(text, 0, buff);
assertEquals("partial copy", buff.capacity() - START_POSITION, length);
for (int i = 0; i < length; i++) {
assertEquals("char at " + i, text.charAt(i), buff.get(START_POSITION + i));
}
assertEquals("buffer position at end", buff.capacity(), buff.position());
}
@Test
public void testEncode_ALotWithoutErrors() throws Exception {
final StringBuilderEncoder helper = new StringBuilderEncoder(Charset.defaultCharset());
final StringBuilder text = new StringBuilder("2016-04-13 21:07:47,487 DEBUG [org.apache.logging.log4j.perf.jmh.FileAppenderBenchmark.log4j2ParameterizedString-jmh-worker-1] FileAppenderBenchmark - This is a debug [2383178] message\r\n");
final int DESTINATION_SIZE = 1024 * 1024;
final SpyByteBufferDestination destination = new SpyByteBufferDestination(256 * 1024, DESTINATION_SIZE);
final int max = DESTINATION_SIZE / text.length();
for (int i = 0; i < max; i++) {
helper.encode(text, destination);
}
// no error
}
private StringBuilder createText(final int length) {
final StringBuilder result = new StringBuilder(length);
for (int i = 0; i < length; i++) {
result.append((char) (' ' + i)); // space=0x20
}
return result;
}
}