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
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.CodingErrorAction;
26import junit.framework.TestCase;
27
28/**
29 * Super class for concrete charset test suites.
30 */
31public abstract class OldCharset_AbstractTest extends TestCase {
32
33    static String charsetName;
34    static private Charset charset;
35    static CharsetDecoder decoder;
36    static CharsetEncoder encoder;
37
38    static final int[] codes = Charset_TestGenerator.codes;
39
40    static final char[] chars = new char[codes.length]; // Is filled with
41                                                        // contents of codes.
42
43    static char[] testChars;
44    static byte[] testBytes;
45
46    static char[] theseChars (int... codes) {
47        char[] chars = new char[codes.length];
48        for (int i = 0; i < codes.length; i++) chars[i] = (char) codes[i];
49        return chars;
50    }
51
52    static byte[] theseBytes (int... codes) {
53        byte[] bytes = new byte[codes.length];
54        for (int i = 0; i < codes.length; i++) bytes[i] = (byte) codes[i];
55        return bytes;
56    }
57
58
59    @Override
60    protected void setUp() throws Exception {
61        charset = charset.forName(charsetName);
62        decoder = charset.newDecoder();
63        encoder = charset.newEncoder();
64        super.setUp();
65    }
66
67    @Override
68    protected void tearDown() throws Exception {
69        super.tearDown();
70    }
71
72    public void test_nameMatch () {
73        assertEquals("Name of charset must match!", charsetName, charset.name());
74    }
75
76    public void test_dumpEncodableChars () {
77        if (testChars == null) return;
78        if (testChars.length > 0) return;
79        System.out.format("\ntest_dumpEncodableChars() for name %s => %s (class = %s)\n",
80                charsetName, charset.name(), getClass().getName());
81        Charset_TestGenerator.Dumper out = new Charset_TestGenerator.Dumper1(16);
82        int code = 0;
83        while (code < 256) {
84            while (!encoder.canEncode((char) code)) code ++;
85            if (code < 65536) {
86                out.consume(code);
87                code += 1;
88            }
89        }
90        while (code < 65536) {
91            while (!encoder.canEncode((char) code)) code ++;
92            if (code < 65536) {
93                out.consume(code);
94                code += 20;
95            }
96        }
97        System.out.println();
98        System.out.println("Encodable Chars dumped for Test Class " + getClass().getName());
99        fail("Encodable Chars dumped for Test Class " + getClass().getName());
100    }
101
102    public void test_dumpEncoded () throws CharacterCodingException {
103        if (testChars == null) return;
104        if (testChars.length == 0) return;
105        if (testBytes != null) return;
106        System.out.format("\ntest_dumpEncoded() for name %s => %s (class = %s)\n",
107                charsetName, charset.name(), getClass().getName());
108        Charset_TestGenerator.Dumper out = new Charset_TestGenerator.Dumper1();
109        CharBuffer inputCB = CharBuffer.wrap(testChars);
110        ByteBuffer outputBB;
111        encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
112        outputBB = encoder.encode(inputCB);
113        outputBB.rewind();
114        while (outputBB.hasRemaining()) {
115            out.consume(outputBB.get() & 0xff);
116        }
117        System.out.println();
118        System.out.println("Encoded Bytes dumped for Test Class " + getClass().getName());
119        fail("Encoded Bytes dumped for Test Class " + getClass().getName());
120    }
121
122
123    static void decode (byte[] input, char[] expectedOutput) throws CharacterCodingException {
124        ByteBuffer inputBB = ByteBuffer.wrap(input);
125        decoder.onMalformedInput(CodingErrorAction.REPORT);
126        CharBuffer outputCB = decoder.decode(inputBB);
127        outputCB.rewind();
128        assertEqualChars(expectedOutput, outputCB);
129    }
130
131    public void test_Decode () throws CharacterCodingException {
132        decode(testBytes, testChars);
133    }
134
135    public void test_Encode () throws CharacterCodingException {
136        CharBuffer inputCB = CharBuffer.wrap(testChars);
137        ByteBuffer outputBB;
138        encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
139        outputBB = encoder.encode(inputCB);
140        outputBB.rewind();
141//        assertTrue("Encoded bytes must match!",
142//                Arrays.equals(testBytes, outputBB.array()));
143        assertEqualBytes("Encoded bytes must match!", testBytes, outputBB);
144    }
145
146
147    public void NNtest_CodecDynamicIndividuals () throws CharacterCodingException {
148        encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
149        decoder.onMalformedInput(CodingErrorAction.REPORT);
150
151        for (int code = 32; code <= 65533; code ++) {
152            if (encoder.canEncode((char) code)) {
153//                inputCB.rewind();
154                CharBuffer inputCB = CharBuffer.allocate(1);
155                inputCB.put((char) code);
156                inputCB.rewind();
157                ByteBuffer intermediateBB = encoder.encode(inputCB);
158                inputCB.rewind();
159                intermediateBB.rewind();
160                try {
161                    CharBuffer outputCB = decoder.decode(intermediateBB);
162                    outputCB.rewind();
163                    assertEqualCBs("decode(encode(A)) must be identical with A = " + code,
164                            inputCB, outputCB);
165                    if (code == 165) {
166                        outputCB.rewind();
167                        System.out.println("WOW:" + outputCB.get());
168                    }
169                } catch (CharacterCodingException e) {
170                    fail("failed to decode(encode(" + code + "))");
171                }
172            }
173        }
174    }
175
176    public void test_CodecDynamic () throws CharacterCodingException {
177        encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
178        decoder.onMalformedInput(CodingErrorAction.REPORT);
179        CharBuffer inputCB = CharBuffer.allocate(65536);
180        for (int code = 32; code <= 65533; ++code) {
181            // icu4c seems to accept any surrogate as a sign that "more is coming",
182            // even for charsets like US-ASCII. http://b/10310751
183            if (code >= 0xd800 && code <= 0xdfff) {
184                continue;
185            }
186            if (encoder.canEncode((char) code)) {
187                inputCB.put((char) code);
188            }
189        }
190        inputCB.rewind();
191        ByteBuffer intermediateBB = encoder.encode(inputCB);
192        inputCB.rewind();
193        intermediateBB.rewind();
194        CharBuffer outputCB = decoder.decode(intermediateBB);
195        outputCB.rewind();
196        assertEqualCBs("decode(encode(A)) must be identical with A!",
197                inputCB, outputCB);
198    }
199
200    static void assertEqualCBs (String msg, CharBuffer expectedCB, CharBuffer actualCB) {
201        boolean match = true;
202        boolean lenMatch = true;
203        char expected, actual;
204        int len = actualCB.length();
205        if (expectedCB.length() != len) {
206            lenMatch = false;
207            if (expectedCB.length() < len) len = expectedCB.length();
208        }
209        for (int i = 0; i < len; i++) {
210            expected = expectedCB.get();
211            actual = actualCB.get();
212            if (actual != expected) {
213                String detail = String.format(
214                        "Mismatch at index %d: %d instead of expected %d.\n",
215                        i, (int) actual, (int) expected);
216                match = false;
217                fail(msg + ": " + detail);
218            }
219//            else {
220//                System.out.format("Match index %d: %d = %d\n",
221//                        i, (int) actual[i], (int) expected[i]);
222//            }
223        }
224        assertTrue(msg, match);
225        assertTrue(msg + "(IN LENGTH ALSO!)", lenMatch);
226//        assertTrue(msg, Arrays.equals(actual, expected));
227    }
228
229    static void assertEqualChars(char[] expected, CharBuffer actualCB) {
230        assertEquals(expected.length, actualCB.length());
231        for (int i = 0; i < actualCB.length(); ++i) {
232            char actual = actualCB.get();
233            if (actual != expected[i]) {
234                String detail = String.format("Mismatch at index %d: %d instead of expected %d.\n",
235                                              i, (int) actual, (int) expected[i]);
236                fail(detail);
237            }
238        }
239    }
240
241    static void assertEqualBytes (String msg, byte[] expected, ByteBuffer actualBB) {
242        boolean match = true;
243        boolean lenMatch = true;
244        byte actual;
245        int len = actualBB.remaining();
246        if (expected.length != len) {
247            lenMatch = false;
248            if (expected.length < len) len = expected.length;
249        }
250        for (int i = 0; i < len; i++) {
251            actual = actualBB.get();
252            if (actual != expected[i]) {
253                String detail = String.format(
254                        "Mismatch at index %d: %d instead of expected %d.\n",
255                        i, actual & 0xff, expected[i] & 0xff);
256                match = false;
257                fail(msg + ": " + detail);
258            }
259        }
260        assertTrue(msg, match);
261        assertTrue(msg + "(IN LENGTH ALSO!)", lenMatch);
262    }
263
264
265    static abstract class CodesGenerator {
266        int row = 0, col = 0;
267
268        abstract void consume(int code);
269
270        boolean isAccepted(int code) {
271            return Character.isLetterOrDigit(code);
272        }
273    }
274
275}
276