/* 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 dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetClass; import dalvik.annotation.TestTargetNew; import dalvik.annotation.TestTargets; import java.nio.ByteBuffer; import java.nio.CharBuffer; 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.UnsupportedCharsetException; import java.util.Arrays; @TestTargetClass(CharsetEncoder.class) /** * API unit test for java.nio.charset.CharsetEncoder */ public class CharsetEncoderTest extends AbstractCharsetEncoderTestCase { static final int MAX_BYTES = 3; static final float AVER_BYTES = 0.5f; // default for Charset abstract class byte[] defaultReplacement = new byte[] { 63 }; // specific for Charset implementation subclass byte[] specifiedReplacement = new byte[] { 26 }; protected void setUp() throws Exception { cs = new MockCharset("CharsetEncoderTest_mock", new String[0]); unibytes = new byte[] { 32, 98, 117, 102, 102, 101, 114 }; super.setUp(); } @TestTargets({ @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "averageBytesPerChar", args = {} ), @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "maxBytesPerChar", args = {} ) }) public void testSpecificDefaultValue() { assertTrue(encoder.averageBytesPerChar() == AVER_BYTES); assertTrue(encoder.maxBytesPerChar() == MAX_BYTES); } @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "implOnMalformedInput", args = {java.nio.charset.CodingErrorAction.class} ) public void testImplOnMalformedInput() { encoder = new MockCharsetEncoder(cs, 1, 3); assertEquals(CoderResult.UNDERFLOW, ((MockCharsetEncoder) encoder) .pubImplFlush(null)); } @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "implOnUnmappableCharacter", args = {java.nio.charset.CodingErrorAction.class} ) public void testImplOnUnmappableCharacter() { encoder = new MockCharsetEncoder(cs, 1, 3); ((MockCharsetEncoder) encoder).pubImplOnUnmappableCharacter(null); } @TestTargets({ @TestTargetNew( level = TestLevel.PARTIAL, notes = "onMalformedInput & onUnmappableCharacter requires check for IllegalArgumentException", method = "malformedInputAction", args = {} ), @TestTargetNew( level = TestLevel.PARTIAL, notes = "onMalformedInput & onUnmappableCharacter requires check for IllegalArgumentException", method = "unmappableCharacterAction", args = {} ), @TestTargetNew( level = TestLevel.PARTIAL, notes = "onMalformedInput & onUnmappableCharacter requires check for IllegalArgumentException", method = "onMalformedInput", args = {java.nio.charset.CodingErrorAction.class} ), @TestTargetNew( level = TestLevel.PARTIAL, notes = "onMalformedInput & onUnmappableCharacter requires check for IllegalArgumentException", method = "onUnmappableCharacter", args = {java.nio.charset.CodingErrorAction.class} ), @TestTargetNew( level = TestLevel.PARTIAL, notes = "onMalformedInput & onUnmappableCharacter requires check for IllegalArgumentException", method = "replacement", args = {} ) }) 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)); } } @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "implReset", args = {} ) public void testImplReset() { encoder = new MockCharsetEncoder(cs, 1, 3); ((MockCharsetEncoder) encoder).pubImplReset(); } @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "implFlush", args = {ByteBuffer.class} ) public void testImplFlush() { encoder = new MockCharsetEncoder(cs, 1, 3); assertEquals(CoderResult.UNDERFLOW, ((MockCharsetEncoder) encoder) .pubImplFlush(null)); } /* * Class under test for constructor CharsetEncoder(Charset, float, float) */ @TestTargets({ @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "charset", args = {} ), @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "averageBytesPerChar", args = {} ), @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "maxBytesPerChar", args = {} ), @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "malformedInputAction", args = {} ), @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "unmappableCharacterAction", args = {} ), @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "CharsetEncoder", args = {java.nio.charset.Charset.class, float.class, float.class} ), @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "replacement", args = {} ) }) 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[]) */ @TestTargets({ @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "CharsetEncoder", args = {java.nio.charset.Charset.class, float.class, float.class, byte[].class} ), @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "charset", args = {} ), @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "averageBytesPerChar", args = {} ), @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "maxBytesPerChar", args = {} ), @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "replacement", args = {} ) }) 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 Charset charset() */ @TestTargetNew( level = TestLevel.PARTIAL, notes = "", method = "CharsetEncoder", args = {java.nio.charset.Charset.class, float.class, float.class} ) 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"); } } boolean enCodeLoopCalled = false; @TestTargetNew( level = TestLevel.SUFFICIENT, notes = "", method = "encodeLoop", args = { CharBuffer.class, ByteBuffer.class} ) public void testEncodeLoop() throws Exception { try { encoder = new MockCharsetEncoder(Charset.forName("US-ASCII"), 1, MAX_BYTES) { @Override protected CoderResult encodeLoop(CharBuffer arg0, ByteBuffer arg1) { enCodeLoopCalled = true; return super.encodeLoop(arg0, arg1); } }; encoder.encode(CharBuffer.wrap("hallo")); } catch (UnsupportedCharsetException e) { fail("us-ascii not supported"); } assertTrue(enCodeLoopCalled); } @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "implReplaceWith", args = { byte[].class} ) public void testImplReplaceWith() { encoder = new MockCharsetEncoder(cs, 1, 3); ((MockCharsetEncoder) encoder).pubImplReplaceWith(null); } 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()); } public void pubImplReplaceWith(byte[] newReplacement) { super.implReplaceWith(newReplacement); } public CoderResult pubImplFlush(ByteBuffer out) { return super.implFlush(out); } public void pubImplOnUnmappableCharacter(CodingErrorAction newAction) { super.implOnUnmappableCharacter(newAction); } public void pubImplReset() { super.implReset(); } } /* * 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); } } }