blob: ef219be3791fe60cbec0d86ee706afc6fcb2951a [file] [log] [blame]
/* 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 tests.api.java.nio.charset;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.MalformedInputException;
import java.nio.charset.UnmappableCharacterException;
import java.nio.charset.UnsupportedCharsetException;
import java.util.Arrays;
import junit.framework.TestCase;
/**
* API unit test for java.nio.charset.CharsetEncoder
*/
public class CharsetEncoderTest extends TestCase {
static final int MAX_BYTES = 3;
static final float AVER_BYTES = 0.5f;
// charset for mock class
private static final Charset MOCKCS = new MockCharset("CharsetEncoderTest_mock", new String[0]);
Charset cs = MOCKCS;
// default encoder
CharsetEncoder encoder;
// default for Charset abstract class
byte[] defaultReplacement = new byte[] { 63 };
// specific for Charset implementation subclass
byte[] specifiedReplacement = new byte[] { 63 };
static final String unistr = " buffer";// \u8000\u8001\u00a5\u3000\r\n";
byte[] unibytes = new byte[] { 32, 98, 117, 102, 102, 101, 114 };
byte[] unibytesWithRep = null;
byte[] surrogate = new byte[0];
protected void setUp() throws Exception {
super.setUp();
encoder = cs.newEncoder();
if (null == unibytesWithRep) {
byte[] replacement = encoder.replacement();
unibytesWithRep = new byte[replacement.length + unibytes.length];
System.arraycopy(replacement, 0, unibytesWithRep, 0,
replacement.length);
System.arraycopy(unibytes, 0, unibytesWithRep, replacement.length,
unibytes.length);
}
}
/*
* @see TestCase#tearDown()
*/
protected void tearDown() throws Exception {
super.tearDown();
}
public void testSpecificDefaultValue() {
assertTrue(encoder.averageBytesPerChar() == AVER_BYTES);
assertTrue(encoder.maxBytesPerChar() == MAX_BYTES);
}
public void testDefaultValue() {
assertEquals(CodingErrorAction.REPORT, encoder.malformedInputAction());
assertEquals(CodingErrorAction.REPORT, encoder.unmappableCharacterAction());
assertSame(encoder, encoder.onMalformedInput(CodingErrorAction.IGNORE));
assertSame(encoder, encoder.onUnmappableCharacter(CodingErrorAction.IGNORE));
if (encoder instanceof MockCharsetEncoder) {
assertTrue(Arrays.equals(encoder.replacement(), defaultReplacement));
} else {
assertTrue(Arrays.equals(encoder.replacement(), specifiedReplacement));
}
}
/*
* Class under test for constructor CharsetEncoder(Charset, float, float)
*/
public void testCharsetEncoderCharsetfloatfloat() {
// default value
encoder = new MockCharsetEncoder(cs, (float) AVER_BYTES, MAX_BYTES);
assertSame(encoder.charset(), cs);
assertTrue(encoder.averageBytesPerChar() == AVER_BYTES);
assertTrue(encoder.maxBytesPerChar() == MAX_BYTES);
assertEquals(CodingErrorAction.REPORT, encoder.malformedInputAction());
assertEquals(CodingErrorAction.REPORT, encoder
.unmappableCharacterAction());
assertEquals(new String(encoder.replacement()), new String(
defaultReplacement));
assertSame(encoder, encoder.onMalformedInput(CodingErrorAction.IGNORE));
assertSame(encoder, encoder
.onUnmappableCharacter(CodingErrorAction.IGNORE));
// normal case
CharsetEncoder ec = new MockCharsetEncoder(cs, 1, MAX_BYTES);
assertSame(ec.charset(), cs);
assertEquals(1.0, ec.averageBytesPerChar(), 0);
assertTrue(ec.maxBytesPerChar() == MAX_BYTES);
/*
* ------------------------ Exceptional cases -------------------------
*/
// NullPointerException: null charset
try {
ec = new MockCharsetEncoder(null, 1, MAX_BYTES);
fail("should throw null pointer exception");
} catch (NullPointerException e) {
}
ec = new MockCharsetEncoder(new MockCharset("mock", new String[0]), 1,
MAX_BYTES);
// Commented out since the comment is wrong since MAX_BYTES > 1
// // OK: average length less than max length
// ec = new MockCharsetEncoder(cs, MAX_BYTES, 1);
// assertTrue(ec.averageBytesPerChar() == MAX_BYTES);
// assertTrue(ec.maxBytesPerChar() == 1);
// Illegal Argument: zero length
try {
ec = new MockCharsetEncoder(cs, 0, MAX_BYTES);
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
}
try {
ec = new MockCharsetEncoder(cs, 1, 0);
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
}
// Illegal Argument: negative length
try {
ec = new MockCharsetEncoder(cs, -1, MAX_BYTES);
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
}
try {
ec = new MockCharsetEncoder(cs, 1, -1);
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
}
}
/*
* Class under test for constructor CharsetEncoder(Charset, float, float,
* byte[])
*/
public void testCharsetEncoderCharsetfloatfloatbyteArray() {
byte[] ba = getLegalByteArray();
// normal case
CharsetEncoder ec = new MockCharsetEncoder(cs, 1, MAX_BYTES, ba);
assertSame(ec.charset(), cs);
assertEquals(1.0, ec.averageBytesPerChar(), 0.0);
assertTrue(ec.maxBytesPerChar() == MAX_BYTES);
assertSame(ba, ec.replacement());
/*
* ------------------------ Exceptional cases -------------------------
*/
// NullPointerException: null charset
try {
ec = new MockCharsetEncoder(null, 1, MAX_BYTES, ba);
fail("should throw null pointer exception");
} catch (NullPointerException e) {
}
// Illegal Argument: null byte array
try {
ec = new MockCharsetEncoder(cs, 1, MAX_BYTES, null);
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
}
// Illegal Argument: empty byte array
try {
ec = new MockCharsetEncoder(cs, 1, MAX_BYTES, new byte[0]);
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
}
// Illegal Argument: byte array is longer than max length
try {
ec = new MockCharsetEncoder(cs, 1, MAX_BYTES, new byte[] { 1, 2,
MAX_BYTES, 4 });
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
}
// Commented out since the comment is wrong since MAX_BYTES > 1
// This test throws IllegalArgumentException on Harmony and RI
// // OK: average length less than max length
// ec = new MockCharsetEncoder(cs, MAX_BYTES, ba.length, ba);
// assertTrue(ec.averageBytesPerChar() == MAX_BYTES);
// assertTrue(ec.maxBytesPerChar() == ba.length);
// Illegal Argument: zero length
try {
ec = new MockCharsetEncoder(cs, 0, MAX_BYTES, ba);
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
}
try {
ec = new MockCharsetEncoder(cs, 1, 0, ba);
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
}
// Illegal Argument: negative length
try {
ec = new MockCharsetEncoder(cs, -1, MAX_BYTES, ba);
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
}
try {
ec = new MockCharsetEncoder(cs, 1, -1, ba);
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
}
}
/*
* Class under test for boolean canEncode(char)
*/
public void testCanEncodechar() throws CharacterCodingException {
// for non-mapped char
assertTrue(encoder.canEncode('\uc2c0'));
// surrogate char for unicode
// 1st byte: d800-dbff
// 2nd byte: dc00-dfff
assertTrue(encoder.canEncode('\ud800'));
// valid surrogate pair
assertTrue(encoder.canEncode('\udc00'));
}
/*-----------------------------------------
* Class under test for illegal state case
* methods which can change internal states are two encode, flush, two canEncode, reset
* -----------------------------------------
*/
// Normal case: just after reset, and it also means reset can be done
// anywhere
public void testResetIllegalState() throws CharacterCodingException {
assertSame(encoder, encoder.reset());
encoder.canEncode('\ud901');
assertSame(encoder, encoder.reset());
encoder.canEncode("\ud901\udc00");
assertSame(encoder, encoder.reset());
encoder.encode(CharBuffer.wrap("aaa"));
assertSame(encoder, encoder.reset());
encoder.encode(CharBuffer.wrap("aaa"), ByteBuffer.allocate(3), false);
assertSame(encoder, encoder.reset());
encoder.encode(CharBuffer.wrap("aaa"), ByteBuffer.allocate(3), true);
assertSame(encoder, encoder.reset());
}
public void testFlushIllegalState() throws CharacterCodingException {
CharBuffer in = CharBuffer.wrap("aaa");
ByteBuffer out = ByteBuffer.allocate(5);
// Normal case: after encode with endOfInput is true
assertSame(encoder, encoder.reset());
encoder.encode(in, out, true);
out.rewind();
CoderResult result = encoder.flush(out);
// Illegal state: flush twice
try {
encoder.flush(out);
fail("should throw IllegalStateException");
} catch (IllegalStateException e) {
// Expected
}
// Illegal state: flush after encode with endOfInput is false
assertSame(encoder, encoder.reset());
encoder.encode(in, out, false);
try {
encoder.flush(out);
fail("should throw IllegalStateException");
} catch (IllegalStateException e) {
// Expected
}
}
public void testFlushAfterConstructing() {
ByteBuffer out = ByteBuffer.allocate(5);
//Illegal state: flush after instance created
try {
encoder.flush(out);
fail("should throw IllegalStateException");
} catch (IllegalStateException e) {
// Expected
}
}
// test illegal states for encode facade
public void testEncodeFacadeIllegalState() throws CharacterCodingException {
// encode facade can be execute in anywhere
CharBuffer in = CharBuffer.wrap("aaa");
// Normal case: just created
encoder.encode(in);
in.rewind();
// Normal case: just after encode facade
encoder.encode(in);
in.rewind();
// Normal case: just after canEncode
assertSame(encoder, encoder.reset());
encoder.canEncode("\ud902\udc00");
encoder.encode(in);
in.rewind();
assertSame(encoder, encoder.reset());
encoder.canEncode('\ud902');
encoder.encode(in);
in.rewind();
// Normal case: just after encode with that endOfInput is true
assertSame(encoder, encoder.reset());
encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState2"),
ByteBuffer.allocate(30), true);
encoder.encode(in);
in.rewind();
// Normal case:just after encode with that endOfInput is false
assertSame(encoder, encoder.reset());
encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState3"),
ByteBuffer.allocate(30), false);
encoder.encode(in);
in.rewind();
// Normal case: just after flush
assertSame(encoder, encoder.reset());
encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState4"),
ByteBuffer.allocate(30), true);
encoder.flush(ByteBuffer.allocate(10));
encoder.encode(in);
in.rewind();
}
// test illegal states for two encode method with endOfInput is true
public void testEncodeTrueIllegalState() throws CharacterCodingException {
CharBuffer in = CharBuffer.wrap("aaa");
ByteBuffer out = ByteBuffer.allocate(5);
// Normal case: just created
encoder.encode(in, out, true);
in.rewind();
out.rewind();
in.rewind();
out.rewind();
// Normal case: just after encode with that endOfInput is true
assertSame(encoder, encoder.reset());
encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState2"),
ByteBuffer.allocate(30), true);
encoder.encode(in, out, true);
in.rewind();
out.rewind();
// Normal case:just after encode with that endOfInput is false
assertSame(encoder, encoder.reset());
encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState3"),
ByteBuffer.allocate(30), false);
encoder.encode(in, out, true);
in.rewind();
out.rewind();
// Illegal state: just after flush
assertSame(encoder, encoder.reset());
encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState4"),
ByteBuffer.allocate(30), true);
encoder.flush(ByteBuffer.allocate(10));
try {
encoder.encode(in, out, true);
fail("should illegal state");
} catch (IllegalStateException e) {
}
// Normal case: after canEncode
assertSame(encoder, encoder.reset());
encoder.canEncode("\ud906\udc00");
encoder.encode(in, out, true);
in.rewind();
out.rewind();
assertSame(encoder, encoder.reset());
encoder.canEncode('\ud905');
encoder.encode(in, out, true);
}
// test illegal states for two encode method with endOfInput is false
public void testEncodeFalseIllegalState() throws CharacterCodingException {
CharBuffer in = CharBuffer.wrap("aaa");
ByteBuffer out = ByteBuffer.allocate(5);
// Normal case: just created
encoder.encode(in, out, false);
in.rewind();
out.rewind();
// Illegal state: just after encode facade
assertSame(encoder, encoder.reset());
encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState1"));
try {
encoder.encode(in, out, false);
fail("should illegal state");
} catch (IllegalStateException e) {
}
// Illegal state: just after encode with that endOfInput is true
assertSame(encoder, encoder.reset());
encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState2"),
ByteBuffer.allocate(30), true);
try {
encoder.encode(in, out, false);
fail("should illegal state");
} catch (IllegalStateException e) {
}
// Normal case:just after encode with that endOfInput is false
assertSame(encoder, encoder.reset());
encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState3"),
ByteBuffer.allocate(30), false);
encoder.encode(in, out, false);
in.rewind();
out.rewind();
// Illegal state: just after flush
assertSame(encoder, encoder.reset());
encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState4"),
ByteBuffer.allocate(30), true);
encoder.flush(ByteBuffer.allocate(10));
try {
encoder.encode(in, out, false);
fail("should illegal state");
} catch (IllegalStateException e) {
}
// Normal case: after canEncode
assertSame(encoder, encoder.reset());
encoder.canEncode("\ud906\udc00");
encoder.encode(in, out, false);
in.rewind();
out.rewind();
assertSame(encoder, encoder.reset());
encoder.canEncode('\ud905');
encoder.encode(in, out, false);
}
// test illegal states for two canEncode methods
public void testCanEncodeIllegalState() throws CharacterCodingException {
// Normal case: just created
encoder.canEncode("\ud900\udc00");
encoder.canEncode('\ud900');
// Illegal state: just after encode with that endOfInput is true
assertSame(encoder, encoder.reset());
encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState2"),
ByteBuffer.allocate(30), true);
try {
encoder.canEncode("\ud903\udc00");
fail("should throw illegal state exception");
} catch (IllegalStateException e) {
}
// Illegal state:just after encode with that endOfInput is false
assertSame(encoder, encoder.reset());
encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState3"),
ByteBuffer.allocate(30), false);
try {
encoder.canEncode("\ud904\udc00");
fail("should throw illegal state exception");
} catch (IllegalStateException e) {
}
// Normal case: just after flush
encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState4"),
ByteBuffer.allocate(30), true);
encoder.flush(ByteBuffer.allocate(10));
encoder.canEncode("\ud905\udc00");
encoder.canEncode('\ud906');
// Normal case: after reset again
assertSame(encoder, encoder.reset());
encoder.canEncode("\ud906\udc00");
encoder.canEncode('\ud905');
}
/*
* --------------------------------- illegal state test end
* ---------------------------------
*/
/*
* Class under test for boolean canEncode(CharSequence)
*/
public void testCanEncodeCharSequence() {
// for non-mapped char
assertTrue(encoder.canEncode("\uc2c0"));
// surrogate char for unicode
// 1st byte: d800-dbff
// 2nd byte: dc00-dfff
// valid surrogate pair
assertTrue(encoder.canEncode("\ud800\udc00"));
// invalid surrogate pair
assertTrue(encoder.canEncode("\ud800\udb00"));
}
public void test_canEncode_char_ICUBug() {
// The RI doesn't allow this, but icu4c does.
assertTrue(encoder.canEncode('\ud800'));
}
public void test_canEncode_CharSequence_ICUBug() {
// The RI doesn't allow this, but icu4c does.
assertTrue(encoder.canEncode("\ud800"));
}
public void test_canEncode_empty() throws Exception {
assertTrue(encoder.canEncode(""));
}
public void test_canEncode_null() throws Exception {
try {
encoder.canEncode(null);
fail();
} catch (NullPointerException e) {
}
}
/*
* Class under test for Charset charset()
*/
public void testCharset() {
try {
encoder = new MockCharsetEncoder(Charset.forName("gbk"), 1,
MAX_BYTES);
// assertSame(encoder.charset(), Charset.forName("gbk"));
} catch (UnsupportedCharsetException e) {
System.err
.println("Don't support GBK encoding, ignore current test");
}
}
/*
* Class under test for ByteBuffer encode(CharBuffer)
*/
public void testEncodeCharBuffer() throws CharacterCodingException {
// Null pointer
try {
encoder.encode(null);
fail("should throw null pointer exception");
} catch (NullPointerException e) {
}
// empty input buffer
ByteBuffer out = encoder.encode(CharBuffer.wrap(""));
assertEquals(out.position(), 0);
assertByteArray(out, new byte[0]);
// assertByteArray(out, surrogate);
// normal case
out = encoder.encode(CharBuffer.wrap(unistr));
assertEquals(out.position(), 0);
assertByteArray(out, addSurrogate(unibytes));
// Regression test for harmony-3378
Charset cs = Charset.forName("UTF-8");
CharsetEncoder encoder = cs.newEncoder();
encoder.onMalformedInput(CodingErrorAction.REPLACE);
encoder = encoder.replaceWith(new byte[] { (byte) 0xef, (byte) 0xbf,
(byte) 0xbd, });
CharBuffer in = CharBuffer.wrap("\ud800");
out = encoder.encode(in);
assertNotNull(out);
}
private byte[] addSurrogate(byte[] expected) {
if (surrogate.length > 0) {
byte[] temp = new byte[surrogate.length + expected.length];
System.arraycopy(surrogate, 0, temp, 0, surrogate.length);
System.arraycopy(expected, 0, temp, surrogate.length,
expected.length);
expected = temp;
}
return expected;
}
/**
* @return
*/
protected byte[] getEmptyByteArray() {
return new byte[0];
}
CharBuffer getMalformedCharBuffer() {
return CharBuffer.wrap("malform buffer");
}
CharBuffer getUnmapCharBuffer() {
return CharBuffer.wrap("unmap buffer");
}
CharBuffer getExceptionCharBuffer() {
return CharBuffer.wrap("runtime buffer");
}
public void testEncodeCharBufferException() throws CharacterCodingException {
ByteBuffer out;
CharBuffer in;
// MalformedException:
in = getMalformedCharBuffer();
encoder.onMalformedInput(CodingErrorAction.REPORT);
encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
if (in != null) {
try {
// regression test for Harmony-1379
encoder.encode(in);
fail("should throw MalformedInputException");
} catch (MalformedInputException e) {
}
encoder.reset();
in.rewind();
encoder.onMalformedInput(CodingErrorAction.IGNORE);
out = encoder.encode(in);
assertByteArray(out, addSurrogate(unibytes));
encoder.reset();
in.rewind();
encoder.onMalformedInput(CodingErrorAction.REPLACE);
out = encoder.encode(in);
assertByteArray(out, addSurrogate(unibytesWithRep));
}
// Unmapped Exception:
in = getUnmapCharBuffer();
encoder.onMalformedInput(CodingErrorAction.REPORT);
encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
if (in != null) {
encoder.reset();
try {
encoder.encode(in);
fail("should throw UnmappableCharacterException");
} catch (UnmappableCharacterException e) {
}
encoder.reset();
in.rewind();
encoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
out = encoder.encode(in);
assertByteArray(out, unibytes);
encoder.reset();
in.rewind();
encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
out = encoder.encode(in);
assertByteArray(out, unibytesWithRep);
}
// RuntimeException
try {
encoder.encode(getExceptionCharBuffer());
fail("should throw runtime exception");
} catch (RuntimeException e) {
}
}
/*
* utility method, extract given bytebuffer to a string and compare with
* give string
*/
void assertByteArray(ByteBuffer out, byte[] expected) {
out = out.duplicate();
if (out.position() != 0) {
out.flip();
}
byte[] ba = new byte[out.limit() - out.position()];
out.get(ba);
// byte[] ba = out.array();
assertTrue(Arrays.equals(ba, expected));
}
/*
* Class under test for CoderResult encode(CharBuffer, ByteBuffer, boolean)
*/
public void testEncodeCharBufferByteBufferboolean()
throws CharacterCodingException {
ByteBuffer out = ByteBuffer.allocate(200);
CharBuffer in = CharBuffer.wrap(unistr);
// Null pointer
try {
encoder.encode(null, out, true);
fail("should throw null pointer exception");
} catch (NullPointerException e) {
}
try {
encoder.encode(in, null, true);
fail("should throw null pointer exception");
} catch (NullPointerException e) {
}
// normal case, one complete operation
assertSame(encoder, encoder.reset());
in.rewind();
out.rewind();
assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, true));
assertEquals(out.limit(), 200);
assertTrue(out.position() > 0);
assertTrue(out.remaining() > 0);
assertEquals(out.capacity(), 200);
assertByteArray(out, addSurrogate(unibytes));
in.rewind();
encoder.flush(out);
// normal case, one complete operation, but call twice, first time set
// endOfInput to false
assertSame(encoder, encoder.reset());
in.rewind();
out = ByteBuffer.allocate(200);
assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, false));
assertEquals(out.limit(), 200);
assertTrue(out.position() > 0);
assertTrue(out.remaining() > 0);
assertEquals(out.capacity(), 200);
assertByteArray(out, addSurrogate(unibytes));
in.rewind();
assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, false));
in.rewind();
assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, true));
assertEquals(out.limit(), 200);
assertTrue(out.position() > 0);
assertTrue(out.remaining() > 0);
assertEquals(out.capacity(), 200);
assertByteArray(out, addSurrogate(duplicateByteArray(unibytes, 3)));
// overflow
out = ByteBuffer.allocate(4);
assertSame(encoder, encoder.reset());
in.rewind();
out.rewind();
assertSame(CoderResult.OVERFLOW, encoder.encode(in, out, true));
assertEquals(out.limit(), 4);
assertEquals(out.position(), 4);
assertEquals(out.remaining(), 0);
assertEquals(out.capacity(), 4);
ByteBuffer temp = ByteBuffer.allocate(200);
out.flip();
temp.put(out);
out = temp;
assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, true));
assertEquals(out.limit(), 200);
assertTrue(out.position() > 0);
assertTrue(out.remaining() > 0);
assertEquals(out.capacity(), 200);
assertByteArray(out, addSurrogate(unibytes));
assertSame(encoder, encoder.reset());
in.rewind();
out = ByteBuffer.allocate(4);
assertSame(CoderResult.OVERFLOW, encoder.encode(in, out, false));
assertEquals(out.limit(), 4);
assertEquals(out.position(), 4);
assertEquals(out.remaining(), 0);
assertEquals(out.capacity(), 4);
temp = ByteBuffer.allocate(200);
out.flip();
temp.put(out);
out = temp;
assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, false));
assertEquals(out.limit(), 200);
assertTrue(out.position() > 0);
assertTrue(out.remaining() > 0);
assertEquals(out.capacity(), 200);
assertByteArray(out, addSurrogate(unibytes));
}
void printByteBuffer(ByteBuffer buffer) {
System.out.println("print buffer");
if (buffer.position() != 0) {
buffer.flip();
}
byte[] ba = buffer.array();
for (int i = 0; i < ba.length; i++) {
System.out.println(Integer.toHexString(ba[i]));
}
}
public void testEncodeCharBufferByteBufferbooleanExceptionFalse()
throws CharacterCodingException {
implTestEncodeCharBufferByteBufferbooleanException(false);
}
public void testEncodeCharBufferByteBufferbooleanExceptionTrue()
throws CharacterCodingException {
implTestEncodeCharBufferByteBufferbooleanException(true);
}
private byte[] duplicateByteArray(byte[] ba, int times) {
byte[] result = new byte[ba.length * times];
for (int i = 0; i < times; i++) {
System.arraycopy(ba, 0, result, i * ba.length, ba.length);
}
return result;
}
protected void implTestEncodeCharBufferByteBufferbooleanException(
boolean endOfInput) throws CharacterCodingException {
ByteBuffer out = ByteBuffer.allocate(100);
// MalformedException:
CharBuffer in = getMalformedCharBuffer();
encoder.onMalformedInput(CodingErrorAction.REPORT);
encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
if (in != null) {
encoder.reset();
CoderResult r = encoder.encode(in, out, endOfInput);
assertTrue(r.isMalformed());
encoder.reset();
out.clear();
in.rewind();
encoder.onMalformedInput(CodingErrorAction.IGNORE);
assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out,
endOfInput));
assertCodingErrorAction(endOfInput, out, in, unibytes);
encoder.reset();
out.clear();
in.rewind();
encoder.onMalformedInput(CodingErrorAction.REPLACE);
assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out,
endOfInput));
assertCodingErrorAction(endOfInput, out, in, unibytesWithRep);
} else {
System.out.println("Cannot find malformed char buffer for "
+ cs.name());
}
// Unmapped Exception:
in = getUnmapCharBuffer();
encoder.onMalformedInput(CodingErrorAction.REPORT);
encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
if (in != null) {
encoder.reset();
out.clear();
assertTrue(encoder.encode(in, out, endOfInput).isUnmappable());
encoder.reset();
out.clear();
in.rewind();
encoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out,
endOfInput));
assertCodingErrorAction(endOfInput, out, in, unibytes);
encoder.reset();
out.clear();
in.rewind();
encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out,
endOfInput));
assertCodingErrorAction(endOfInput, out, in, unibytesWithRep);
} else {
System.out.println("Cannot find unmapped char buffer for "
+ cs.name());
}
// RuntimeException
try {
encoder.encode(getExceptionCharBuffer());
fail("should throw runtime exception");
} catch (RuntimeException e) {
}
}
private void assertCodingErrorAction(boolean endOfInput, ByteBuffer out,
CharBuffer in, byte[] expect) {
if (endOfInput) {
assertByteArray(out, addSurrogate(expect));
} else {
in.rewind();
assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out,
endOfInput));
in.rewind();
assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, true));
assertByteArray(out, addSurrogate(duplicateByteArray(expect, 3)));
}
}
/*
* Class under test for CoderResult flush(ByteBuffer)
*/
public void testFlush() throws CharacterCodingException {
ByteBuffer out = ByteBuffer.allocate(6);
CharBuffer in = CharBuffer.wrap("aaa");
assertEquals(in.remaining(), 3);
// by encode facade, so that internal state will be wrong
encoder.encode(CharBuffer.wrap("testFlush"), ByteBuffer.allocate(20),
true);
assertSame(CoderResult.UNDERFLOW, encoder
.flush(ByteBuffer.allocate(50)));
}
/*
* test isLegalReplacement(byte[])
*/
public void test_isLegalReplacement_null() {
try {
encoder.isLegalReplacement(null);
fail("should throw null pointer exception");
} catch (NullPointerException e) {
}
}
public void test_isLegalReplacement_good() {
assertTrue(encoder.isLegalReplacement(specifiedReplacement));
}
public void test_isLegalReplacement_bad() {
assertTrue(encoder.isLegalReplacement(new byte[200]));
byte[] ba = getIllegalByteArray();
if (ba != null) {
assertFalse(encoder.isLegalReplacement(ba));
}
}
public void test_isLegalReplacement_empty_array() {
// ISO, ASC, GB, UTF8 encoder will throw exception in RI
// others will pass
assertTrue(encoder.isLegalReplacement(new byte[0]));
}
public void testOnMalformedInput() {
assertSame(CodingErrorAction.REPORT, encoder.malformedInputAction());
try {
encoder.onMalformedInput(null);
fail("should throw null pointer exception");
} catch (IllegalArgumentException e) {
}
encoder.onMalformedInput(CodingErrorAction.IGNORE);
assertSame(CodingErrorAction.IGNORE, encoder.malformedInputAction());
}
public void testOnUnmappableCharacter() {
assertSame(CodingErrorAction.REPORT, encoder
.unmappableCharacterAction());
try {
encoder.onUnmappableCharacter(null);
fail("should throw null pointer exception");
} catch (IllegalArgumentException e) {
}
encoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
assertSame(CodingErrorAction.IGNORE, encoder
.unmappableCharacterAction());
}
public void testReplacement() {
try {
encoder.replaceWith(null);
fail("should throw null pointer exception");
} catch (IllegalArgumentException e) {
}
try {
encoder.replaceWith(new byte[0]);
fail("should throw null pointer exception");
} catch (IllegalArgumentException e) {
}
try {
encoder.replaceWith(new byte[100]);
fail("should throw null pointer exception");
} catch (IllegalArgumentException e) {
}
byte[] nr = getLegalByteArray();
assertSame(encoder, encoder.replaceWith(nr));
assertSame(nr, encoder.replacement());
nr = getIllegalByteArray();
try {
encoder.replaceWith(new byte[100]);
fail();
} catch (IllegalArgumentException e) {
}
}
protected byte[] getLegalByteArray() {
return new byte[] { 'a' };
}
protected byte[] getIllegalByteArray() {
return new byte[155];
}
/*
* Mock subclass of CharsetEncoder For protected method test
*/
public static class MockCharsetEncoder extends CharsetEncoder {
boolean flushed = false;
public boolean isFlushed() {
boolean result = flushed;
flushed = false;
return result;
}
public boolean isLegalReplacement(byte[] ba) {
if (ba.length == 155) {// specified magic number, return false
return false;
}
return super.isLegalReplacement(ba);
}
public MockCharsetEncoder(Charset cs, float aver, float max) {
super(cs, aver, max);
}
public MockCharsetEncoder(Charset cs, float aver, float max,
byte[] replacement) {
super(cs, aver, max, replacement);
}
protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
int inPosition = in.position();
char[] input = new char[in.remaining()];
in.get(input);
String result = new String(input);
if (result.startsWith("malform")) {
// reset the cursor to the error position
in.position(inPosition);
// in.position(0);
// set the error length
return CoderResult.malformedForLength("malform".length());
} else if (result.startsWith("unmap")) {
// reset the cursor to the error position
in.position(inPosition);
// in.position(0);
// set the error length
return CoderResult.unmappableForLength("unmap".length());
} else if (result.startsWith("runtime")) {
// reset the cursor to the error position
in.position(0);
// set the error length
throw new RuntimeException("runtime");
}
int inLeft = input.length;
int outLeft = out.remaining();
CoderResult r = CoderResult.UNDERFLOW;
int length = inLeft;
if (outLeft < inLeft) {
r = CoderResult.OVERFLOW;
length = outLeft;
in.position(inPosition + outLeft);
}
for (int i = 0; i < length; i++) {
out.put((byte) input[i]);
}
return r;
}
protected CoderResult implFlush(ByteBuffer out) {
CoderResult result = super.implFlush(out);
int length = 0;
if (out.remaining() >= 5) {
length = 5;
result = CoderResult.UNDERFLOW;
flushed = true;
// for (int i = 0; i < length; i++) {
// out.put((byte)'f');
// }
} else {
length = out.remaining();
result = CoderResult.OVERFLOW;
}
return result;
}
protected void implReplaceWith(byte[] ba) {
assertSame(ba, replacement());
}
}
/*
* mock charset for test encoder initialization
*/
public static class MockCharset extends Charset {
protected MockCharset(String arg0, String[] arg1) {
super(arg0, arg1);
}
public boolean contains(Charset arg0) {
return false;
}
public CharsetDecoder newDecoder() {
return new CharsetDecoderTest.MockCharsetDecoder(this,
(float) AVER_BYTES, MAX_BYTES);
}
public CharsetEncoder newEncoder() {
return new MockCharsetEncoder(this, (float) AVER_BYTES, MAX_BYTES);
}
}
}