1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * 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
17package libcore.java.nio.charset;
18
19import java.nio.ByteBuffer;
20import java.nio.CharBuffer;
21import java.nio.charset.CharacterCodingException;
22import java.nio.charset.Charset;
23import java.nio.charset.CharsetDecoder;
24import java.nio.charset.CharsetEncoder;
25import java.nio.charset.CoderResult;
26import java.nio.charset.CodingErrorAction;
27
28public class CharsetDecoderTest extends junit.framework.TestCase {
29    // None of the harmony or jtreg tests actually check that replaceWith does the right thing!
30    public void test_replaceWith() throws Exception {
31        CharsetDecoder d = Charset.forName("UTF-16").newDecoder();
32        d.replaceWith("x");
33        d.onMalformedInput(CodingErrorAction.REPLACE);
34        d.onUnmappableCharacter(CodingErrorAction.REPLACE);
35        ByteBuffer in = ByteBuffer.wrap(new byte[] { 109, 97, 109 });
36        assertEquals("\u6d61x", d.decode(in).toString());
37    }
38
39    // http://code.google.com/p/android/issues/detail?id=4237
40    public void test_ByteArray_decode_no_offset() throws Exception {
41        CharsetDecoder decoder = Charset.forName("UTF-16").newDecoder();
42        byte[] arr = encode("UTF-16", "Android");
43        ByteBuffer inBuffer = ByteBuffer.wrap(arr, 0, arr.length).slice();
44        CharBuffer outBuffer = CharBuffer.allocate(arr.length);
45        decoder.reset();
46        CoderResult coderResult = decoder.decode(inBuffer, outBuffer, true);
47        assertFalse(coderResult.toString(), coderResult.isError());
48        decoder.flush(outBuffer);
49        outBuffer.flip();
50        assertEquals("Android", outBuffer.toString().trim());
51    }
52
53    // http://code.google.com/p/android/issues/detail?id=4237
54    public void test_ByteArray_decode_with_offset() throws Exception {
55        CharsetDecoder decoder = Charset.forName("UTF-16").newDecoder();
56        byte[] arr = encode("UTF-16", "Android");
57        arr = prependByteToByteArray(arr, new Integer(1).byteValue());
58        int offset = 1;
59        ByteBuffer inBuffer = ByteBuffer.wrap(arr, offset, arr.length - offset).slice();
60        CharBuffer outBuffer = CharBuffer.allocate(arr.length - offset);
61        decoder.reset();
62        CoderResult coderResult = decoder.decode(inBuffer, outBuffer, true);
63        assertFalse(coderResult.toString(), coderResult.isError());
64        decoder.flush(outBuffer);
65        outBuffer.flip();
66        assertEquals("Android", outBuffer.toString().trim());
67    }
68
69    // http://code.google.com/p/android/issues/detail?id=4237
70    public void test_ByteArray_decode_with_offset_using_facade_method() throws Exception {
71        CharsetDecoder decoder = Charset.forName("UTF-16").newDecoder();
72        byte[] arr = encode("UTF-16", "Android");
73        arr = prependByteToByteArray(arr, new Integer(1).byteValue());
74        int offset = 1;
75        CharBuffer outBuffer = decoder.decode(ByteBuffer.wrap(arr, offset, arr.length - offset));
76        assertEquals("Android", outBuffer.toString().trim());
77    }
78
79    private static byte[] prependByteToByteArray(byte[] arr, byte b) {
80        byte[] result = new byte[arr.length + 1];
81        result[0] = b;
82        System.arraycopy(arr, 0, result, 1, arr.length);
83        return result;
84    }
85
86    private static byte[] encode(String charsetName, String s) throws Exception {
87        CharsetEncoder encoder = Charset.forName(charsetName).newEncoder();
88        ByteBuffer buf = encoder.encode(CharBuffer.wrap(s));
89        byte[] out = new byte[buf.remaining()];
90        buf.get(out);
91        assertEquals(0, buf.remaining());
92        return out;
93    }
94
95    public void testUtf8BytesSplitAcrossMultipleWrites() throws Exception {
96        CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
97        CharBuffer cb = CharBuffer.allocate(128);
98        CoderResult cr;
99        cr = decoder.decode(ByteBuffer.wrap(new byte[] { (byte) 0xe2 }), cb, false);
100        assertEquals(CoderResult.UNDERFLOW, cr);
101        cr = decoder.decode(ByteBuffer.wrap(new byte[] { (byte) 0x98 }), cb, false);
102        assertEquals(CoderResult.UNDERFLOW, cr);
103        cr = decoder.decode(ByteBuffer.wrap(new byte[] { (byte) 0x83 }), cb, false);
104        assertEquals(CoderResult.UNDERFLOW, cr);
105        cr = decoder.decode(ByteBuffer.wrap(new byte[0]), cb, true);
106        assertEquals(CoderResult.UNDERFLOW, cr);
107        cr = decoder.flush(cb);
108        assertEquals(CoderResult.UNDERFLOW, cr);
109        assertEquals(1, cb.position());
110        assertEquals('\u2603', cb.get(0));
111    }
112
113    public void testBufferWithNonZeroOffset() {
114        CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
115        CharBuffer cb = CharBuffer.allocate(128);
116        cb.position(42);
117        CharBuffer out = cb.slice();
118        CoderResult cr = decoder.decode(
119                ByteBuffer.wrap(new byte[] { 'h', 'e', 'l', 'l', 'o'}), out, false);
120        assertTrue(cr.isUnderflow());
121        assertEquals(5, out.position());
122    }
123}
124