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