Home | History | Annotate | Download | only in charset
      1 /* Licensed to the Apache Software Foundation (ASF) under one or more
      2  * contributor license agreements.  See the NOTICE file distributed with
      3  * this work for additional information regarding copyright ownership.
      4  * The ASF licenses this file to You under the Apache License, Version 2.0
      5  * (the "License"); you may not use this file except in compliance with
      6  * the License.  You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package tests.api.java.nio.charset;
     17 
     18 import dalvik.annotation.TestLevel;
     19 import dalvik.annotation.TestTargetClass;
     20 import dalvik.annotation.TestTargetNew;
     21 import dalvik.annotation.TestTargets;
     22 
     23 import java.io.UnsupportedEncodingException;
     24 import java.nio.ByteBuffer;
     25 import java.nio.CharBuffer;
     26 import java.nio.charset.CharacterCodingException;
     27 import java.nio.charset.Charset;
     28 import java.nio.charset.CharsetDecoder;
     29 import java.nio.charset.CoderResult;
     30 import java.nio.charset.CodingErrorAction;
     31 import java.nio.charset.UnsupportedCharsetException;
     32 import java.nio.charset.MalformedInputException;
     33 import java.nio.charset.UnmappableCharacterException;
     34 
     35 @TestTargetClass(CharsetDecoder.class)
     36 /**
     37  * API unit test for java.nio.charset.CharsetDecoder
     38  */
     39 public class CharsetDecoderTest extends AbstractCharsetDecoderTestCase {
     40 
     41     protected static final int MAX_BYTES = 3;
     42 
     43     protected static final double AVER_BYTES = 0.5;
     44 
     45     protected void setUp() throws Exception {
     46         cs = new CharsetEncoderTest.MockCharset("mock", new String[0]);
     47         unibytes = new byte[] { 32, 98, 117, 102, 102, 101, 114 };
     48         decoder = cs.newDecoder();
     49 
     50         // for this test's weird superclass, super.setUp() needs to be run last
     51         super.setUp();
     52     }
     53 
     54 
     55     public void testDefaultValues() {
     56         assertSame(cs, decoder.charset());
     57         try {
     58             decoder.detectedCharset();
     59             fail("should unsupported");
     60         } catch (UnsupportedOperationException e) {
     61         }
     62         try {
     63             assertTrue(decoder.isCharsetDetected());
     64             fail("should unsupported");
     65         } catch (UnsupportedOperationException e) {
     66         }
     67         assertFalse(decoder.isAutoDetecting());
     68         assertSame(CodingErrorAction.REPORT, decoder.malformedInputAction());
     69         assertSame(CodingErrorAction.REPORT, decoder
     70                 .unmappableCharacterAction());
     71         assertEquals(decoder.replacement(), "\ufffd");
     72     }
     73 
     74     /*
     75      * test constructor
     76      */
     77     @TestTargets({
     78         @TestTargetNew(
     79             level = TestLevel.COMPLETE,
     80             notes = "",
     81             method = "CharsetDecoder",
     82             args = {java.nio.charset.Charset.class, float.class, float.class}
     83         ),
     84         @TestTargetNew(
     85             level = TestLevel.COMPLETE,
     86             notes = "",
     87             method = "charset",
     88             args = {}
     89         ),
     90         @TestTargetNew(
     91             level = TestLevel.COMPLETE,
     92             notes = "",
     93             method = "averageCharsPerByte",
     94             args = {}
     95         ),
     96         @TestTargetNew(
     97             level = TestLevel.COMPLETE,
     98             notes = "",
     99             method = "maxCharsPerByte",
    100             args = {}
    101         )
    102     })
    103     public void testCharsetDecoder() {
    104         // default value
    105         decoder = new MockCharsetDecoder(cs, (float) AVER_BYTES, MAX_BYTES);
    106 
    107         // normal case
    108         CharsetDecoder ec = new MockCharsetDecoder(cs, 1, MAX_BYTES);
    109         assertSame(ec.charset(), cs);
    110         assertEquals(1.0, ec.averageCharsPerByte(), 0.0);
    111         assertTrue(ec.maxCharsPerByte() == MAX_BYTES);
    112 
    113         /*
    114          * ------------------------ Exceptional cases -------------------------
    115          */
    116         // Normal case: null charset
    117         ec = new MockCharsetDecoder(null, 1, MAX_BYTES);
    118         assertNull(ec.charset());
    119         assertEquals(1.0, ec.averageCharsPerByte(), 0.0);
    120         assertTrue(ec.maxCharsPerByte() == MAX_BYTES);
    121 
    122         ec = new MockCharsetDecoder(new CharsetEncoderTest.MockCharset("mock",
    123                 new String[0]), 1, MAX_BYTES);
    124 
    125                 // Commented out since the comment is wrong since MAX_BYTES > 1
    126         // // OK: average length less than max length
    127         // ec = new MockCharsetDecoder(cs, MAX_BYTES, 1);
    128         // assertTrue(ec.averageCharsPerByte() == MAX_BYTES);
    129         // assertTrue(ec.maxCharsPerByte() == 1);
    130 
    131         // Illegal Argument: zero length
    132         try {
    133             ec = new MockCharsetDecoder(cs, 0, MAX_BYTES);
    134             fail("should throw IllegalArgumentException");
    135         } catch (IllegalArgumentException e) {
    136         }
    137         try {
    138             ec = new MockCharsetDecoder(cs, 1, 0);
    139             fail("should throw IllegalArgumentException");
    140         } catch (IllegalArgumentException e) {
    141         }
    142 
    143         // Illegal Argument: negative length
    144         try {
    145             ec = new MockCharsetDecoder(cs, -1, MAX_BYTES);
    146             fail("should throw IllegalArgumentException");
    147         } catch (IllegalArgumentException e) {
    148         }
    149         try {
    150             ec = new MockCharsetDecoder(cs, 1, -1);
    151             fail("should throw IllegalArgumentException");
    152         } catch (IllegalArgumentException e) {
    153         }
    154     }
    155 
    156     /*
    157      * test onMalformedInput
    158      */
    159     public void testOnMalformedInput() {
    160         assertSame(CodingErrorAction.REPORT, decoder.malformedInputAction());
    161         try {
    162             decoder.onMalformedInput(null);
    163             fail("should throw null pointer exception");
    164         } catch (IllegalArgumentException e) {
    165         }
    166         decoder.onMalformedInput(CodingErrorAction.IGNORE);
    167         assertSame(CodingErrorAction.IGNORE, decoder.malformedInputAction());
    168     }
    169 
    170     /*
    171      * test unmappableCharacter
    172      */
    173     public void testOnUnmappableCharacter() {
    174         assertSame(CodingErrorAction.REPORT, decoder
    175                 .unmappableCharacterAction());
    176         try {
    177             decoder.onUnmappableCharacter(null);
    178             fail("should throw null pointer exception");
    179         } catch (IllegalArgumentException e) {
    180         }
    181         decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
    182         assertSame(CodingErrorAction.IGNORE, decoder
    183                 .unmappableCharacterAction());
    184     }
    185 
    186     /*
    187      * test replaceWith
    188      */
    189     public void testReplaceWith() {
    190         try {
    191             decoder.replaceWith(null);
    192             fail("should throw null pointer exception");
    193         } catch (IllegalArgumentException e) {
    194         }
    195         try {
    196             decoder.replaceWith("");
    197             fail("should throw null pointer exception");
    198         } catch (IllegalArgumentException e) {
    199         }
    200         try {
    201             decoder.replaceWith("testReplaceWith");
    202             fail("should throw illegal argument exception");
    203         } catch (IllegalArgumentException e) {
    204         }
    205 
    206         decoder.replaceWith("a");
    207         assertSame("a", decoder.replacement());
    208     }
    209 
    210     /*
    211      * Class under test for CharBuffer decode(ByteBuffer)
    212      */
    213     public void testDecodeByteBuffer() throws CharacterCodingException {
    214         implTestDecodeByteBuffer();
    215     }
    216 
    217     void implTestDecodeByteBuffer() throws CharacterCodingException {
    218         // Null pointer
    219         try {
    220             decoder.decode(null);
    221             fail("should throw null pointer exception");
    222         } catch (NullPointerException e) {
    223         }
    224 
    225         // empty input buffer
    226         CharBuffer out = decoder.decode(ByteBuffer.allocate(0));
    227         assertCharBufferValue("", out);
    228 
    229         // normal case
    230         ByteBuffer in = getByteBuffer();
    231         out = decoder.decode(in);
    232         assertEquals(0, out.position());
    233         assertEquals(getString().length(), out.limit());
    234         assertEquals(getString().length(), out.remaining());
    235         assertCharBufferValue(getString(), out);
    236 
    237         // normal read only case
    238         in = getByteBuffer().asReadOnlyBuffer();
    239         out = decoder.decode(in);
    240         assertEquals(out.position(), 0);
    241         assertEquals(out.limit(), getString().length());
    242         assertEquals(out.remaining(), getString().length());
    243         assertCharBufferValue(getString(), out);
    244     }
    245 
    246     public void testDecodeByteBufferException()
    247             throws CharacterCodingException, UnsupportedEncodingException {
    248         CharBuffer out;
    249         ByteBuffer in;
    250         String replaceStr = decoder.replacement() + getString();
    251 
    252         // MalformedException:
    253         decoder.onMalformedInput(CodingErrorAction.REPORT);
    254         decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
    255         in = getMalformedByteBuffer();
    256         if (in != null) {
    257             try {
    258                 CharBuffer buffer = decoder.decode(in);
    259                 assertTrue(buffer.remaining() > 0);
    260                 fail("should throw MalformedInputException");
    261             } catch (MalformedInputException e) {
    262             }
    263 
    264             decoder.reset();
    265             in.rewind();
    266             decoder.onMalformedInput(CodingErrorAction.IGNORE);
    267             out = decoder.decode(in);
    268             assertCharBufferValue(getString(), out);
    269 
    270             decoder.reset();
    271             in.rewind();
    272             decoder.onMalformedInput(CodingErrorAction.REPLACE);
    273             out = decoder.decode(in);
    274             assertCharBufferValue(replaceStr, out);
    275         }
    276 
    277         // Unmapped Exception:
    278         decoder.onMalformedInput(CodingErrorAction.REPORT);
    279         decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
    280         in = getUnmappedByteBuffer();
    281         if (in != null) {
    282             try {
    283                 decoder.decode(in);
    284                 fail("should throw UnmappableCharacterException");
    285             } catch (UnmappableCharacterException e) {
    286             }
    287 
    288             decoder.reset();
    289             in.rewind();
    290             decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
    291             out = decoder.decode(in);
    292             assertCharBufferValue(getString(), out);
    293 
    294             decoder.reset();
    295             in.rewind();
    296             decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
    297             out = decoder.decode(in);
    298             assertCharBufferValue(replaceStr, out);
    299         }
    300 
    301         // RuntimeException
    302         try {
    303             decoder.decode(getExceptionByteArray());
    304             fail("should throw runtime exception");
    305         } catch (RuntimeException e) {
    306         }
    307     }
    308 
    309     /*
    310      * Class under test for CoderResult decode(ByteBuffer, CharBuffer, boolean)
    311      */
    312     public void testDecodeByteBufferCharBuffer() {
    313         implTestDecodeByteBufferCharBuffer(getByteBuffer());
    314     }
    315 
    316     public void testDecodeByteBufferCharBufferReadOnly() {
    317         implTestDecodeByteBufferCharBuffer(getByteBuffer());
    318     }
    319 
    320     void implTestDecodeByteBufferCharBuffer(ByteBuffer in) {
    321         CharBuffer out = CharBuffer.allocate(100);
    322 
    323         // Null pointer
    324         decoder.reset();
    325         try {
    326             decoder.decode(null, out, true);
    327             fail("NullPointerException expected");
    328         } catch (NullPointerException e) {
    329         }
    330         try {
    331             decoder.decode(in, null, true);
    332             fail("NullPointerException expected");
    333         } catch (NullPointerException e) {
    334         }
    335 
    336         // normal case, one complete operation
    337         decoder.reset();
    338         in.rewind();
    339         out.rewind();
    340         assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, true));
    341         assertEquals(out.limit(), 100);
    342         assertEquals(out.position(), getString().length());
    343         assertEquals(out.remaining(), 100 - getString().length());
    344         assertEquals(out.capacity(), 100);
    345         assertCharBufferValue(getString(), out);
    346         decoder.flush(out);
    347 
    348         // normal case, one complete operation, but call twice, first time set
    349         // endOfInput to false
    350         decoder.reset();
    351         in.rewind();
    352         out.clear();
    353         assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, false));
    354         assertEquals(out.limit(), 100);
    355         assertEquals(out.position(), getString().length());
    356         assertEquals(out.remaining(), 100 - getString().length());
    357         assertEquals(out.capacity(), 100);
    358         assertCharBufferValue(getString(), out);
    359 
    360         decoder.reset();
    361         in.rewind();
    362         out.clear();
    363         assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, false));
    364         in = getHeadlessByteBuffer();
    365         assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, false));
    366         in.rewind();
    367         assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, true));
    368         assertEquals(out.limit(), 100);
    369         assertTrue(out.position() > 0);
    370         assertEquals(out.remaining(), out.capacity() - out.position());
    371         assertEquals(out.capacity(), 100);
    372         assertCharBufferValue(getString() + getString() + getString(), out);
    373 
    374         // overflow
    375         out = CharBuffer.allocate(4);
    376         decoder.reset();
    377         in = getByteBuffer();
    378         out.rewind();
    379         assertSame(CoderResult.OVERFLOW, decoder.decode(in, out, false));
    380 
    381         assertCharBufferValue(getString().substring(0, 4), out);
    382         out = CharBuffer.allocate(100);
    383         assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, false));
    384         assertCharBufferValue(getString().substring(4), out);
    385         in.rewind();
    386         out = CharBuffer.allocate(100);
    387         assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, true));
    388         assertCharBufferValue(bom + getString(), out);
    389     }
    390 
    391     public void testDecodeCharBufferByteBufferUnmappedException()
    392             throws CharacterCodingException, UnsupportedEncodingException {
    393         implTestDecodeCharBufferByteBufferUnmappedException(
    394                 getUnmappedByteBuffer(), true);
    395     }
    396 
    397     public void testDecodeCharBufferByteIncompleteBufferUnmappedException()
    398             throws CharacterCodingException, UnsupportedEncodingException {
    399         implTestDecodeCharBufferByteBufferUnmappedException(
    400                 getUnmappedByteBuffer(), false);
    401     }
    402 
    403     public void testDecodeCharBufferByteReadOnlyBufferUnmappedException()
    404             throws CharacterCodingException, UnsupportedEncodingException {
    405         implTestDecodeCharBufferByteBufferUnmappedException(
    406                 readOnly(getUnmappedByteBuffer()), true);
    407     }
    408 
    409     public void testDecodeCharBufferByteReadOnlyIncompleteBufferUnmappedException()
    410             throws CharacterCodingException, UnsupportedEncodingException {
    411         implTestDecodeCharBufferByteBufferUnmappedException(
    412                 readOnly(getUnmappedByteBuffer()), false);
    413     }
    414 
    415     void implTestDecodeCharBufferByteBufferUnmappedException(ByteBuffer in,
    416             boolean endOfInput) throws CharacterCodingException,
    417             UnsupportedEncodingException {
    418         if (null == in) {
    419             return;
    420         }
    421         CharBuffer out = CharBuffer.allocate(50);
    422 
    423         decoder.onMalformedInput(CodingErrorAction.REPORT);
    424         decoder.reset();
    425         decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
    426         CoderResult result = decoder.decode(in, out, endOfInput);
    427         assertTrue(result.isUnmappable());
    428 
    429         decoder.reset();
    430         out.clear();
    431         in.rewind();
    432         decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
    433         assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, endOfInput));
    434         assertCharBufferValue(getString(), out);
    435 
    436         decoder.reset();
    437         out.clear();
    438         in.rewind();
    439         decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
    440         assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, endOfInput));
    441         assertCharBufferValue(decoder.replacement() + getString(), out);
    442     }
    443 
    444     public void testDecodeCharBufferByteBufferMalformedException()
    445             throws CharacterCodingException, UnsupportedEncodingException {
    446         implTestDecodeCharBufferByteBufferMalformedException(
    447                 getMalformedByteBuffer(), true);
    448     }
    449 
    450     public void testDecodeCharBufferByteIncompleteBufferMalformedException()
    451             throws CharacterCodingException, UnsupportedEncodingException {
    452 
    453         implTestDecodeCharBufferByteBufferMalformedException(
    454                 getMalformedByteBuffer(), false);
    455     }
    456 
    457     public void testDecodeCharBufferByteReadOnlyBufferMalformedException()
    458             throws CharacterCodingException, UnsupportedEncodingException {
    459         implTestDecodeCharBufferByteBufferMalformedException(
    460                 readOnly(getMalformedByteBuffer()), true);
    461     }
    462 
    463     public void testDecodeCharBufferByteReadOnlyIncompleteBufferMalformedException()
    464             throws CharacterCodingException, UnsupportedEncodingException {
    465         implTestDecodeCharBufferByteBufferMalformedException(
    466                 readOnly(getMalformedByteBuffer()), false);
    467     }
    468 
    469     void implTestDecodeCharBufferByteBufferMalformedException(ByteBuffer in,
    470             boolean endOfInput) throws CharacterCodingException,
    471             UnsupportedEncodingException {
    472         if (null == in) {
    473             return;
    474         }
    475         CharBuffer out = CharBuffer.allocate(getString().length() * 3);
    476         decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
    477         decoder.reset();
    478         decoder.onMalformedInput(CodingErrorAction.REPORT);
    479         CoderResult result = decoder.decode(in, out, endOfInput);
    480         assertTrue(result.isMalformed());
    481 
    482         decoder.reset();
    483         out.clear();
    484         in.rewind();
    485         decoder.onMalformedInput(CodingErrorAction.IGNORE);
    486         assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, endOfInput));
    487         assertCharBufferValue(getString(), out);
    488 
    489         decoder.reset();
    490         out.clear();
    491         in.rewind();
    492         decoder.onMalformedInput(CodingErrorAction.REPLACE);
    493         assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, endOfInput));
    494         assertCharBufferValue(decoder.replacement() + getString(), out);
    495     }
    496 
    497     public void testDecodeCharBufferByteBufferException()
    498             throws CharacterCodingException, UnsupportedEncodingException {
    499         implTestDecodeCharBufferByteBufferException(getExceptionByteArray(),
    500                 true);
    501     }
    502 
    503     public void testDecodeCharBufferByteIncompleteBufferException()
    504             throws CharacterCodingException, UnsupportedEncodingException {
    505         implTestDecodeCharBufferByteBufferException(getExceptionByteArray(),
    506                 false);
    507     }
    508 
    509     public void testDecodeCharBufferByteReadOnlyBufferException()
    510             throws CharacterCodingException, UnsupportedEncodingException {
    511         implTestDecodeCharBufferByteBufferException(
    512                 readOnly(getExceptionByteArray()), true);
    513     }
    514 
    515     public void testDecodeCharBufferByteReadOnlyIncompleteBufferException()
    516             throws CharacterCodingException, UnsupportedEncodingException {
    517         implTestDecodeCharBufferByteBufferException(
    518                 readOnly(getExceptionByteArray()), false);
    519     }
    520 
    521     void implTestDecodeCharBufferByteBufferException(ByteBuffer in,
    522             boolean endOfInput) throws CharacterCodingException,
    523             UnsupportedEncodingException {
    524         CharBuffer out = CharBuffer.allocate(50);
    525         decoder.reset();
    526         try {
    527             decoder.decode(in, out, endOfInput);
    528             fail("should throw runtime exception");
    529         } catch (RuntimeException e) {
    530         }
    531     }
    532 
    533     private ByteBuffer readOnly(ByteBuffer b) {
    534         if (null == b) {
    535             return null;
    536         }
    537         return b.asReadOnlyBuffer();
    538     }
    539 
    540     protected String getString() {
    541         return " buffer";
    542     }
    543 
    544     protected ByteBuffer getByteBuffer() {
    545         return ByteBuffer.wrap(new byte[] { 32, 98, 117, 102, 102, 101, 114 });
    546     }
    547 
    548     protected ByteBuffer getHeadlessByteBuffer() {
    549         return getByteBuffer();
    550     }
    551 
    552     ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
    553         // "runtime"
    554         return ByteBuffer
    555                 .wrap(new byte[] { 114, 117, 110, 116, 105, 109, 101 });
    556     }
    557 
    558     ByteBuffer getUnmappedByteBuffer() throws UnsupportedEncodingException {
    559         // "unmap buffer"
    560         byte[] ba = new byte[] { 117, 110, 109, 97, 112, 32, 98, 117, 102, 102,
    561                 101, 114 };
    562         return ByteBuffer.wrap(ba);
    563     }
    564 
    565     ByteBuffer getMalformedByteBuffer() throws UnsupportedEncodingException {
    566         // "malform buffer"
    567         byte[] ba = new byte[] { 109, 97, 108, 102, 111, 114, 109, 32, 98, 117,
    568                 102, 102, 101, 114 };
    569         return ByteBuffer.wrap(ba);
    570     }
    571 
    572     private void assertCharBufferValue(String expected, CharBuffer out) {
    573         if (out.position() != 0) {
    574             out.flip();
    575         }
    576         assertEquals(expected, new String(out.array(), out.arrayOffset(), out
    577                 .arrayOffset() + out.limit()));
    578     }
    579 
    580     /*
    581      * test flush
    582      */
    583     public void testFlush() throws CharacterCodingException {
    584         CharBuffer out = CharBuffer.allocate(10);
    585         ByteBuffer in = ByteBuffer.wrap(new byte[] { 12, 12 });
    586         decoder.decode(in, out, true);
    587         assertSame(CoderResult.UNDERFLOW, decoder.flush(out));
    588 
    589         decoder.reset();
    590         decoder.decode((ByteBuffer) in.rewind(), (CharBuffer) out.rewind(),
    591                 true);
    592         assertSame(CoderResult.UNDERFLOW, decoder
    593                 .flush(CharBuffer.allocate(10)));
    594     }
    595 
    596     /*
    597      * ---------------------------------- methods to test illegal state
    598      * -----------------------------------
    599      */
    600     // Normal case: just after reset, and it also means reset can be done
    601     // anywhere
    602     public void testResetIllegalState() throws CharacterCodingException {
    603         decoder.reset();
    604         decoder.decode(getByteBuffer());
    605         decoder.reset();
    606         decoder.decode(getByteBuffer(), CharBuffer.allocate(3), false);
    607         decoder.reset();
    608         decoder.decode(getByteBuffer(), CharBuffer.allocate(3), true);
    609         decoder.reset();
    610     }
    611 
    612     public void testFlushIllegalState() throws CharacterCodingException {
    613         ByteBuffer in = ByteBuffer.wrap(new byte[] { 98, 98 });
    614         CharBuffer out = CharBuffer.allocate(5);
    615         // Normal case: after decode with endOfInput is true
    616         decoder.reset();
    617         decoder.decode(in, out, true);
    618         out.rewind();
    619         CoderResult result = decoder.flush(out);
    620         assertSame(result, CoderResult.UNDERFLOW);
    621 
    622         // Illegal state: flush twice
    623         try {
    624             decoder.flush(out);
    625             fail("should throw IllegalStateException");
    626         } catch (IllegalStateException e) {
    627         }
    628 
    629         // Illegal state: flush after decode with endOfInput is false
    630         decoder.reset();
    631         decoder.decode(in, out, false);
    632         try {
    633             decoder.flush(out);
    634             fail("should throw IllegalStateException");
    635         } catch (IllegalStateException e) {
    636         }
    637     }
    638 
    639     // test illegal states for decode facade
    640     public void testDecodeFacadeIllegalState() throws CharacterCodingException {
    641         // decode facade can be execute in anywhere
    642         ByteBuffer in = getByteBuffer();
    643 
    644         // Normal case: just created
    645         decoder.decode(in);
    646         in.rewind();
    647 
    648         // Normal case: just after decode facade
    649         decoder.decode(in);
    650         in.rewind();
    651 
    652         // Normal case: just after decode with that endOfInput is true
    653         decoder.reset();
    654         decoder.decode(getByteBuffer(), CharBuffer.allocate(30), true);
    655         decoder.decode(in);
    656         in.rewind();
    657 
    658         // Normal case:just after decode with that endOfInput is false
    659         decoder.reset();
    660         decoder.decode(getByteBuffer(), CharBuffer.allocate(30), false);
    661         decoder.decode(in);
    662         in.rewind();
    663 
    664         // Normal case: just after flush
    665         decoder.reset();
    666         decoder.decode(getByteBuffer(), CharBuffer.allocate(30), true);
    667         decoder.flush(CharBuffer.allocate(10));
    668         decoder.decode(in);
    669         in.rewind();
    670     }
    671 
    672     // test illegal states for two decode method with endOfInput is true
    673     public void testDecodeTrueIllegalState() throws CharacterCodingException {
    674         ByteBuffer in = ByteBuffer.wrap(new byte[] { 98, 98 });
    675         CharBuffer out = CharBuffer.allocate(100);
    676         // Normal case: just created
    677         decoder.decode(in, out, true);
    678         in.rewind();
    679         out.rewind();
    680 
    681         // Normal case: just after decode with that endOfInput is true
    682         decoder.reset();
    683         decoder.decode(in, CharBuffer.allocate(30), true);
    684         in.rewind();
    685         decoder.decode(in, out, true);
    686         in.rewind();
    687         out.rewind();
    688 
    689         // Normal case:just after decode with that endOfInput is false
    690         decoder.reset();
    691         decoder.decode(in, CharBuffer.allocate(30), false);
    692         in.rewind();
    693         decoder.decode(in, out, true);
    694         in.rewind();
    695         out.rewind();
    696 
    697         // Illegal state: just after flush
    698         decoder.reset();
    699         decoder.decode(in, CharBuffer.allocate(30), true);
    700         decoder.flush(CharBuffer.allocate(10));
    701         in.rewind();
    702         try {
    703             decoder.decode(in, out, true);
    704             fail("should illegal state");
    705         } catch (IllegalStateException e) {
    706         }
    707         in.rewind();
    708         out.rewind();
    709 
    710     }
    711 
    712     // test illegal states for two decode method with endOfInput is false
    713     public void testDecodeFalseIllegalState() throws CharacterCodingException {
    714         ByteBuffer in = ByteBuffer.wrap(new byte[] { 98, 98 });
    715         CharBuffer out = CharBuffer.allocate(5);
    716         // Normal case: just created
    717         decoder.decode(in, out, false);
    718         in.rewind();
    719         out.rewind();
    720 
    721         // Illegal state: just after decode facade
    722         decoder.reset();
    723         decoder.decode(in);
    724         in.rewind();
    725         try {
    726             decoder.decode(in, out, false);
    727             fail("should illegal state");
    728         } catch (IllegalStateException e) {
    729         }
    730         in.rewind();
    731         out.rewind();
    732 
    733         // Illegal state: just after decode with that endOfInput is true
    734         decoder.reset();
    735         decoder.decode(in, CharBuffer.allocate(30), true);
    736         in.rewind();
    737         try {
    738             decoder.decode(in, out, false);
    739             fail("should illegal state");
    740         } catch (IllegalStateException e) {
    741         }
    742         in.rewind();
    743         out.rewind();
    744 
    745         // Normal case:just after decode with that endOfInput is false
    746         decoder.reset();
    747         decoder.decode(in, CharBuffer.allocate(30), false);
    748         in.rewind();
    749         decoder.decode(in, out, false);
    750         in.rewind();
    751         out.rewind();
    752 
    753         // Illegal state: just after flush
    754         decoder.reset();
    755         decoder.decode(in, CharBuffer.allocate(30), true);
    756         in.rewind();
    757         decoder.flush(CharBuffer.allocate(10));
    758         try {
    759             decoder.decode(in, out, false);
    760             fail("should illegal state");
    761         } catch (IllegalStateException e) {
    762         }
    763     }
    764 
    765     @TestTargetNew(
    766         level = TestLevel.COMPLETE,
    767         notes = "",
    768         method = "implFlush",
    769         args = {java.nio.CharBuffer.class}
    770     )
    771     public void testImplFlush() {
    772         decoder = new MockCharsetDecoder(cs, 1, 3);
    773         assertEquals(CoderResult.UNDERFLOW, ((MockCharsetDecoder) decoder)
    774                 .pubImplFlush(null));
    775     }
    776 
    777     @TestTargetNew(
    778         level = TestLevel.COMPLETE,
    779         notes = "",
    780         method = "implOnMalformedInput",
    781         args = {java.nio.charset.CodingErrorAction.class}
    782     )
    783     public void testImplOnMalformedInput() {
    784         decoder = new MockCharsetDecoder(cs, 1, 3);
    785         assertEquals(CoderResult.UNDERFLOW, ((MockCharsetDecoder) decoder)
    786                 .pubImplFlush(null));
    787 
    788     }
    789 
    790     @TestTargetNew(
    791         level = TestLevel.COMPLETE,
    792         notes = "",
    793         method = "implOnUnmappableCharacter",
    794         args = {java.nio.charset.CodingErrorAction.class}
    795     )
    796     public void testImplOnUnmappableCharacter() {
    797         decoder = new MockCharsetDecoder(cs, 1, 3);
    798         ((MockCharsetDecoder) decoder).pubImplOnUnmappableCharacter(null);
    799     }
    800 
    801     @TestTargetNew(
    802         level = TestLevel.COMPLETE,
    803         notes = "",
    804         method = "implReplaceWith",
    805         args = {java.lang.String.class}
    806     )
    807     public void testImplReplaceWith() {
    808         decoder = new MockCharsetDecoder(cs, 1, 3);
    809         ((MockCharsetDecoder) decoder).pubImplReplaceWith(null);
    810     }
    811 
    812     @TestTargetNew(
    813         level = TestLevel.COMPLETE,
    814         notes = "",
    815         method = "implReset",
    816         args = {}
    817     )
    818     public void testImplReset() {
    819         decoder = new MockCharsetDecoder(cs, 1, 3);
    820         ((MockCharsetDecoder) decoder).pubImplReset();
    821     }
    822 
    823 
    824     boolean deCodeLoopCalled = false;
    825 
    826     @TestTargetNew(
    827         level = TestLevel.SUFFICIENT,
    828         notes = "",
    829         method = "decodeLoop",
    830         args = { ByteBuffer.class, CharBuffer.class}
    831     )
    832     public void testEncodeLoop() throws Exception {
    833         try {
    834             decoder = new MockCharsetDecoder(Charset.forName("US-ASCII"), 1,
    835                     MAX_BYTES) {
    836                 @Override
    837                 protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
    838                     deCodeLoopCalled = true;
    839                     return super.decodeLoop(in, out);
    840                 }
    841             };
    842             decoder.decode(ByteBuffer.wrap(new byte[]{ 'a','b','c'}));
    843         } catch (UnsupportedCharsetException e) {
    844             fail("us-ascii not supported");
    845         }
    846         assertTrue(deCodeLoopCalled);
    847     }
    848 
    849     /*
    850      * mock decoder
    851      */
    852     public static class MockCharsetDecoder extends CharsetDecoder {
    853         public MockCharsetDecoder(Charset cs, float ave, float max) {
    854             super(cs, ave, max);
    855         }
    856 
    857         protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
    858             int inPosition = in.position();
    859             byte[] input = new byte[in.remaining()];
    860             in.get(input);
    861             String result = new String(input);
    862             if (result.startsWith("malform")) {
    863                 // reset the cursor to the error position
    864                 in.position(inPosition + "malform".length());
    865                 // set the error length
    866                 return CoderResult.malformedForLength("malform".length());
    867             } else if (result.startsWith("unmap")) {
    868                 // reset the cursor to the error position
    869                 in.position(inPosition);
    870                 // set the error length
    871                 return CoderResult.unmappableForLength("unmap".length());
    872             } else if (result.startsWith("runtime")) {
    873                 // reset the cursor to the error position
    874                 in.position(0);
    875                 // set the error length
    876                 throw new RuntimeException("runtime");
    877             }
    878             int inLeft = input.length;
    879             int outLeft = out.remaining();
    880             CoderResult r = CoderResult.UNDERFLOW;
    881             int length = inLeft;
    882             if (outLeft < inLeft) {
    883                 r = CoderResult.OVERFLOW;
    884                 length = outLeft;
    885                 in.position(inPosition + outLeft);
    886             }
    887             for (int i = 0; i < length; i++) {
    888                 out.put((char) input[i]);
    889             }
    890             return r;
    891         }
    892 
    893         protected CoderResult implFlush(CharBuffer out) {
    894             CoderResult result = super.implFlush(out);
    895             if (out.remaining() >= 5) {
    896                 // TODO
    897                 // out.put("flush");
    898                 result = CoderResult.UNDERFLOW;
    899             } else {
    900                 // out.put("flush", 0, out.remaining());
    901                 result = CoderResult.OVERFLOW;
    902             }
    903             return result;
    904         }
    905 
    906         public CoderResult pubImplFlush(CharBuffer out) {
    907             return super.implFlush(out);
    908         }
    909 
    910         public void pubImplOnMalformedInput(CodingErrorAction newAction) {
    911             super.implOnMalformedInput(newAction);
    912         }
    913 
    914         public void pubImplOnUnmappableCharacter(CodingErrorAction newAction) {
    915             super.implOnUnmappableCharacter(newAction);
    916         }
    917 
    918         public void pubImplReplaceWith(String newReplacement) {
    919             super.implReplaceWith(newReplacement);
    920         }
    921 
    922         public void pubImplReset() {
    923             super.implReset();
    924         }
    925     }
    926 
    927 }
    928