/*
* 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.tomcat.util.buf;
import java.nio.charset.Charset;
import java.nio.charset.MalformedInputException;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
import org.junit.
Assert;
import org.junit.Test;
public class TestB2CConverter {
private static final byte[] UTF16_MESSAGE =
new byte[] {-2, -1, 0, 65, 0, 66, 0, 67};
private static final byte[] UTF8_INVALID =
new byte[] {-8, -69, -73, -77};
private static final byte[] UTF8_PARTIAL =
new byte[] {-50};
@Test
public void testSingleMessage()
throws Exception {
testMessages(1);
}
@Test
public void testTwoMessage()
throws Exception {
testMessages(2);
}
@Test
public void testManyMessage()
throws Exception {
testMessages(10);
}
private void testMessages(
int msgCount)
throws Exception {
B2CConverter conv =
new B2CConverter(StandardCharsets.UTF_16);
ByteChunk bc =
new ByteChunk();
CharChunk cc =
new CharChunk(32);
for (
int i = 0; i < msgCount; i++) {
bc.append(UTF16_MESSAGE, 0, UTF16_MESSAGE.length);
conv.convert(bc, cc,
true);
Assert.assertEquals(
"ABC", cc.toString());
bc.recycle();
cc.recycle();
conv.recycle();
}
System.out.println(cc);
}
@Test
public void testLeftoverSize() {
float maxLeftover = 0;
String charsetName =
"UNSET";
for (Charset charset : Charset.availableCharsets().values()) {
float leftover;
if (charset.name().toLowerCase(Locale.ENGLISH).startsWith(
"x-")) {
// Non-standard charset that browsers won't be using
// Likely something used internally by the JRE
continue;
}
try {
leftover = charset.newEncoder().maxBytesPerChar();
}
catch (UnsupportedOperationException uoe) {
// Skip it
continue;
}
if (leftover > maxLeftover) {
maxLeftover = leftover;
charsetName = charset.name();
}
}
Assert.assertTrue(
"Limit needs to be at least " + maxLeftover +
" (used in charset '" + charsetName +
"')",
maxLeftover <= B2CConverter.LEFTOVER_SIZE);
}
@Test(expected=MalformedInputException.
class)
public void testBug54602a()
throws Exception {
// Check invalid input is rejected straight away
B2CConverter conv =
new B2CConverter(StandardCharsets.UTF_8);
ByteChunk bc =
new ByteChunk();
CharChunk cc =
new CharChunk();
bc.append(UTF8_INVALID, 0, UTF8_INVALID.length);
cc.allocate(bc.getLength(), -1);
conv.convert(bc, cc,
false);
}
@Test(expected=MalformedInputException.
class)
public void testBug54602b()
throws Exception {
// Check partial input is rejected
B2CConverter conv =
new B2CConverter(StandardCharsets.UTF_8);
ByteChunk bc =
new ByteChunk();
CharChunk cc =
new CharChunk();
bc.append(UTF8_PARTIAL, 0, UTF8_PARTIAL.length);
cc.allocate(bc.getLength(), -1);
conv.convert(bc, cc,
true);
}
@Test
public void testBug54602c()
throws Exception {
// Check partial input is rejected once it is known to be all available
B2CConverter conv =
new B2CConverter(StandardCharsets.UTF_8);
ByteChunk bc =
new ByteChunk();
CharChunk cc =
new CharChunk();
bc.append(UTF8_PARTIAL, 0, UTF8_PARTIAL.length);
cc.allocate(bc.getLength(), -1);
conv.convert(bc, cc,
false);
Exception e =
null;
try {
conv.convert(bc, cc,
true);
}
catch (MalformedInputException mie) {
e = mie;
}
Assert.assertNotNull(e);
}
}