• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 org.apache.harmony.tests.java.nio.charset;
18 
19 import java.nio.ByteBuffer;
20 import java.nio.ByteOrder;
21 import java.nio.CharBuffer;
22 import java.nio.charset.Charset;
23 import java.nio.charset.CharsetDecoder;
24 import java.nio.charset.CharsetEncoder;
25 import java.nio.charset.CoderResult;
26 import java.nio.charset.IllegalCharsetNameException;
27 import java.nio.charset.spi.CharsetProvider;
28 import java.nio.charset.UnsupportedCharsetException;
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.HashSet;
32 import java.util.Iterator;
33 import java.util.Locale;
34 import java.util.Set;
35 import java.util.Vector;
36 import libcore.java.nio.charset.SettableCharsetProvider;
37 
38 import junit.framework.TestCase;
39 
40 /**
41  * Test class java.nio.Charset.
42  */
43 public class CharsetTest extends TestCase {
44 
test_allAvailableCharsets()45   public void test_allAvailableCharsets() throws Exception {
46     // Check that we can instantiate every Charset, CharsetDecoder, and CharsetEncoder.
47     for (String charsetName : Charset.availableCharsets().keySet()) {
48       Charset cs = Charset.forName(charsetName);
49       assertNotNull(cs.newDecoder());
50       if (cs.canEncode()) {
51         CharsetEncoder enc = cs.newEncoder();
52         assertNotNull(enc);
53         assertNotNull(enc.replacement());
54       }
55     }
56   }
57 
test_defaultCharset()58   public void test_defaultCharset() {
59     assertEquals("UTF-8", Charset.defaultCharset().name());
60   }
61 
test_isRegistered()62   public void test_isRegistered() {
63     // Regression for HARMONY-45
64 
65     // Will contain names of charsets registered with IANA
66     Set<String> knownRegisteredCharsets = new HashSet<String>();
67 
68     // Will contain names of charsets not known to be registered with IANA
69     Set<String> unknownRegisteredCharsets = new HashSet<String>();
70 
71     Set<String> names = Charset.availableCharsets().keySet();
72     for (Iterator nameItr = names.iterator(); nameItr.hasNext();) {
73       String name = (String) nameItr.next();
74       if (name.toLowerCase(Locale.ROOT).startsWith("x-")) {
75         unknownRegisteredCharsets.add(name);
76       } else {
77         knownRegisteredCharsets.add(name);
78       }
79     }
80 
81     for (Iterator nameItr = knownRegisteredCharsets.iterator(); nameItr.hasNext();) {
82       String name = (String) nameItr.next();
83       Charset cs = Charset.forName(name);
84       if (!cs.isRegistered()) {
85         System.err.println("isRegistered was false for " + name + " " + cs.name() + " " + cs.aliases());
86       }
87       assertTrue("isRegistered was false for " + name + " " + cs.name() + " " + cs.aliases(), cs.isRegistered());
88     }
89     for (Iterator nameItr = unknownRegisteredCharsets.iterator(); nameItr.hasNext();) {
90       String name = (String) nameItr.next();
91       Charset cs = Charset.forName(name);
92       assertFalse("isRegistered was true for " + name + " " + cs.name() + " " + cs.aliases(), cs.isRegistered());
93     }
94   }
95 
test_guaranteedCharsetsAvailable()96   public void test_guaranteedCharsetsAvailable() throws Exception {
97     // All Java implementations must support these charsets.
98     assertNotNull(Charset.forName("ISO-8859-1"));
99     assertNotNull(Charset.forName("US-ASCII"));
100     assertNotNull(Charset.forName("UTF-16"));
101     assertNotNull(Charset.forName("UTF-16BE"));
102     assertNotNull(Charset.forName("UTF-16LE"));
103     assertNotNull(Charset.forName("UTF-8"));
104   }
105 
106   // http://code.google.com/p/android/issues/detail?id=42769
test_42769()107   public void test_42769() throws Exception {
108     ArrayList<Thread> threads = new ArrayList<Thread>();
109     for (int i = 0; i < 10; ++i) {
110       Thread t = new Thread(new Runnable() {
111         public void run() {
112           for (int i = 0; i < 50; ++i) {
113             Charset.availableCharsets();
114           }
115         }
116       });
117       threads.add(t);
118     }
119 
120     for (Thread t : threads) {
121       t.start();
122     }
123     for (Thread t : threads) {
124       t.join();
125     }
126   }
127 
test_have_canonical_EUC_JP()128   public void test_have_canonical_EUC_JP() throws Exception {
129     assertEquals("EUC-JP", Charset.forName("EUC-JP").name());
130   }
131 
test_EUC_JP_replacement_character()132   public void test_EUC_JP_replacement_character() throws Exception {
133     // We have text either side of the replacement character, because all kinds of errors
134     // could lead to a replacement character being returned.
135     assertEncodes(Charset.forName("EUC-JP"), " \ufffd ", ' ', 0xf4, 0xfe, ' ');
136     assertDecodes(Charset.forName("EUC-JP"), " \ufffd ", ' ', 0xf4, 0xfe, ' ');
137   }
138 
test_SCSU_replacement_character()139   public void test_SCSU_replacement_character() throws Exception {
140     // We have text either side of the replacement character, because all kinds of errors
141     // could lead to a replacement character being returned.
142     assertEncodes(Charset.forName("SCSU"), " \ufffd ", ' ', 14, 0xff, 0xfd, ' ');
143     assertDecodes(Charset.forName("SCSU"), " \ufffd ", ' ', 14, 0xff, 0xfd, ' ');
144   }
145 
test_Shift_JIS_replacement_character()146   public void test_Shift_JIS_replacement_character() throws Exception {
147     // We have text either side of the replacement character, because all kinds of errors
148     // could lead to a replacement character being returned.
149     assertEncodes(Charset.forName("Shift_JIS"), " \ufffd ", ' ', 0xfc, 0xfc, ' ');
150     assertDecodes(Charset.forName("Shift_JIS"), " \ufffd ", ' ', 0xfc, 0xfc, ' ');
151   }
152 
test_UTF_16()153   public void test_UTF_16() throws Exception {
154     Charset cs = Charset.forName("UTF-16");
155     // Writes big-endian, with a big-endian BOM.
156     assertEncodes(cs, "a\u0666", 0xfe, 0xff, 0, 'a', 0x06, 0x66);
157     // Reads whatever the BOM tells it to read, and swallows the BOM...
158     assertDecodes(cs, "a\u0666", 0xfe, 0xff, 0, 'a', 0x06, 0x66);
159     assertDecodes(cs, "a\u0666", 0xff, 0xfe, 'a', 0, 0x66, 0x06);
160     // ...and defaults to reading big-endian if there's no BOM.
161     assertDecodes(cs, "a\u0666", 0, 'a', 0x06, 0x66);
162   }
163 
test_UTF_16BE()164   public void test_UTF_16BE() throws Exception {
165     Charset cs = Charset.forName("UTF-16BE");
166     // Writes big-endian, with no BOM.
167     assertEncodes(cs, "a\u0666", 0, 'a', 0x06, 0x66);
168     // We don't make any assertion about the handling of a little-endian BOM.
169     // Accepts a big-endian BOM and includes U+FEFF in the decoded output.
170     assertDecodes(cs, "\ufeffa\u0666", 0xfe, 0xff, 0, 'a', 0x06, 0x66);
171     // Defaults to reading big-endian.
172     assertDecodes(cs, "a\u0666", 0, 'a', 0x06, 0x66);
173   }
174 
test_UTF_16LE()175   public void test_UTF_16LE() throws Exception {
176     Charset cs = Charset.forName("UTF-16LE");
177     // Writes little-endian, with no BOM.
178     assertEncodes(cs, "a\u0666", 'a', 0, 0x66, 0x06);
179     // Accepts a little-endian BOM and includes U+FEFF in the decoded output.
180     assertDecodes(cs, "\ufeffa\u0666", 0xff, 0xfe, 'a', 0, 0x66, 0x06);
181     // We don't make any assertion about the handling of a big-endian BOM.
182     // Defaults to reading little-endian.
183     assertDecodes(cs, "a\u0666", 'a', 0, 0x66, 0x06);
184   }
185 
test_x_UTF_16LE_BOM()186   public void test_x_UTF_16LE_BOM() throws Exception {
187     Charset cs = Charset.forName("x-UTF-16LE-BOM");
188     // Writes little-endian, with a BOM.
189     assertEncodes(cs, "a\u0666", 0xff, 0xfe, 'a', 0, 0x66, 0x06);
190     // Accepts a little-endian BOM and swallows the BOM.
191     assertDecodes(cs, "a\u0666", 0xff, 0xfe, 'a', 0, 0x66, 0x06);
192     // We don't make any assertion about the handling of a big-endian BOM.
193     // Defaults to reading little-endian.
194     assertDecodes(cs, "a\u0666", 'a', 0, 0x66, 0x06);
195   }
196 
test_UTF_32()197   public void test_UTF_32() throws Exception {
198     Charset cs = Charset.forName("UTF-32");
199     // Writes platform-endian, with a BOM.
200     if (ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN)) {
201       assertEncodes(cs, "a\u0666", 0, 0, 0xfe, 0xff, 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
202     } else {
203       assertEncodes(cs, "a\u0666", 0xff, 0xfe, 0, 0, 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
204     }
205     // Reads whatever the BOM tells it to read, and swallows the BOM...
206     assertDecodes(cs, "a\u0666", 0, 0, 0xfe, 0xff, 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
207     assertDecodes(cs, "a\u0666", 0xff, 0xfe, 0, 0, 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
208     // ...and defaults to reading big-endian if there's no BOM.
209     assertDecodes(cs, "a\u0666", 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
210   }
211 
test_UTF_32BE()212   public void test_UTF_32BE() throws Exception {
213     Charset cs = Charset.forName("UTF-32BE");
214     // Writes big-endian, with no BOM.
215     assertEncodes(cs, "a\u0666", 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
216     // We don't make any assertion about the handling of a little-endian BOM.
217     // Accepts a big-endian BOM and includes U+FEFF in the decoded output.
218     assertDecodes(cs, "\ufeffa\u0666", 0, 0, 0xfe, 0xff, 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
219     // Defaults to reading big-endian.
220     assertDecodes(cs, "a\u0666", 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
221   }
222 
test_UTF_32LE()223   public void test_UTF_32LE() throws Exception {
224     Charset cs = Charset.forName("UTF-32LE");
225     // Writes little-endian, with no BOM.
226     assertEncodes(cs, "a\u0666", 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
227     // Accepts a little-endian BOM and includes U+FEFF in the decoded output.
228     assertDecodes(cs, "\ufeffa\u0666", 0xff, 0xfe, 0, 0, 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
229     // We don't make any assertion about the handling of a big-endian BOM.
230     // Defaults to reading little-endian.
231     assertDecodes(cs, "a\u0666", 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
232   }
233 
toByteArray(int[] ints)234   private byte[] toByteArray(int[] ints) {
235     byte[] result = new byte[ints.length];
236     for (int i = 0; i < ints.length; ++i) {
237       result[i] = (byte) ints[i];
238     }
239     return result;
240   }
241 
assertEncodes(Charset cs, String s, int... expectedByteInts)242   private void assertEncodes(Charset cs, String s, int... expectedByteInts) throws Exception {
243     ByteBuffer out = cs.encode(s);
244     byte[] bytes = new byte[out.remaining()];
245     out.get(bytes);
246     assertEquals(Arrays.toString(toByteArray(expectedByteInts)), Arrays.toString(bytes));
247   }
248 
assertDecodes(Charset cs, String s, int... byteInts)249   private void assertDecodes(Charset cs, String s, int... byteInts) throws Exception {
250     ByteBuffer in = ByteBuffer.wrap(toByteArray(byteInts));
251     CharBuffer out = cs.decode(in);
252     assertEquals(s, out.toString());
253   }
254 
test_forNameLjava_lang_String()255   public void test_forNameLjava_lang_String() {
256     // Invoke forName two times with the same canonical name.
257     // It should return the same reference.
258     Charset cs1 = Charset.forName("UTF-8");
259     Charset cs2 = Charset.forName("UTF-8");
260     assertSame(cs1, cs2);
261 
262     // test forName: invoke forName two times for the same Charset using
263     // canonical name and alias, it should return the same reference.
264     Charset cs3 = Charset.forName("ASCII");
265     Charset cs4 = Charset.forName("US-ASCII");
266     assertSame(cs3, cs4);
267   }
268 
269   static MockCharset charset1 = new MockCharset("mockCharset00",
270                                                 new String[] { "mockCharset01", "mockCharset02" });
271 
272   static MockCharset charset2 = new MockCharset("mockCharset10",
273                                                 new String[] { "mockCharset11", "mockCharset12" });
274 
275   // Test the required 6 charsets are supported.
testRequiredCharsetSupported()276   public void testRequiredCharsetSupported() {
277     assertTrue(Charset.isSupported("US-ASCII"));
278     assertTrue(Charset.isSupported("ASCII"));
279     assertTrue(Charset.isSupported("ISO-8859-1"));
280     assertTrue(Charset.isSupported("ISO8859_1"));
281     assertTrue(Charset.isSupported("UTF-8"));
282     assertTrue(Charset.isSupported("UTF8"));
283     assertTrue(Charset.isSupported("UTF-16"));
284     assertTrue(Charset.isSupported("UTF-16BE"));
285     assertTrue(Charset.isSupported("UTF-16LE"));
286 
287     Charset c1 = Charset.forName("US-ASCII");
288     assertEquals("US-ASCII", Charset.forName("US-ASCII").name());
289     assertEquals("US-ASCII", Charset.forName("ASCII").name());
290     assertEquals("ISO-8859-1", Charset.forName("ISO-8859-1").name());
291     assertEquals("ISO-8859-1", Charset.forName("ISO8859_1").name());
292     assertEquals("UTF-8", Charset.forName("UTF-8").name());
293     assertEquals("UTF-8", Charset.forName("UTF8").name());
294     assertEquals("UTF-16", Charset.forName("UTF-16").name());
295     assertEquals("UTF-16BE", Charset.forName("UTF-16BE").name());
296     assertEquals("UTF-16LE", Charset.forName("UTF-16LE").name());
297 
298     assertNotSame(Charset.availableCharsets(), Charset.availableCharsets());
299     // assertSame(Charset.forName("US-ASCII"), Charset.availableCharsets().get("US-ASCII"));
300     // assertSame(Charset.forName("US-ASCII"), c1);
301     assertTrue(Charset.availableCharsets().containsKey("US-ASCII"));
302     assertTrue(Charset.availableCharsets().containsKey("ISO-8859-1"));
303     assertTrue(Charset.availableCharsets().containsKey("UTF-8"));
304     assertTrue(Charset.availableCharsets().containsKey("UTF-16"));
305     assertTrue(Charset.availableCharsets().containsKey("UTF-16BE"));
306     assertTrue(Charset.availableCharsets().containsKey("UTF-16LE"));
307   }
308 
testIsSupported_Null()309   public void testIsSupported_Null() {
310     try {
311       Charset.isSupported(null);
312       fail();
313     } catch (IllegalArgumentException expected) {
314     }
315   }
316 
testIsSupported_EmptyString()317   public void testIsSupported_EmptyString() {
318     try {
319       Charset.isSupported("");
320       fail();
321     } catch (IllegalArgumentException expected) {
322     }
323   }
324 
testIsSupported_InvalidInitialCharacter()325   public void testIsSupported_InvalidInitialCharacter() {
326     try {
327       Charset.isSupported(".char");
328       fail();
329     } catch (IllegalArgumentException expected) {
330     }
331   }
332 
testIsSupported_IllegalName()333   public void testIsSupported_IllegalName() {
334     try {
335       Charset.isSupported(" ///#$$");
336       fail();
337     } catch (IllegalCharsetNameException expected) {
338     }
339   }
340 
testIsSupported_NotSupported()341   public void testIsSupported_NotSupported() {
342     assertFalse(Charset.isSupported("well-formed-name-of-a-charset-that-does-not-exist"));
343   }
344 
testForName_Null()345   public void testForName_Null() {
346     try {
347       Charset.forName(null);
348       fail();
349     } catch (IllegalArgumentException expected) {
350     }
351   }
352 
testForName_EmptyString()353   public void testForName_EmptyString() {
354     try {
355       Charset.forName("");
356       fail();
357     } catch (IllegalArgumentException expected) {
358     }
359   }
360 
testForName_InvalidInitialCharacter()361   public void testForName_InvalidInitialCharacter() {
362     try {
363       Charset.forName(".char");
364       fail();
365     } catch (IllegalArgumentException expected) {
366     }
367   }
368 
testForName_IllegalName()369   public void testForName_IllegalName() {
370     try {
371       Charset.forName(" ///#$$");
372       fail();
373     } catch (IllegalCharsetNameException expected) {
374     }
375   }
376 
testForName_NotSupported()377   public void testForName_NotSupported() {
378     try {
379       Charset.forName("impossible");
380       fail();
381     } catch (UnsupportedCharsetException expected) {
382     }
383   }
384 
testConstructor_Normal()385   public void testConstructor_Normal() {
386     final String mockName = "mockChar1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:-_";
387     MockCharset c = new MockCharset(mockName, new String[] { "mock" });
388     assertEquals(mockName, c.name());
389     assertEquals(mockName, c.displayName());
390     assertEquals(mockName, c.displayName(Locale.getDefault()));
391     assertEquals("mock", c.aliases().toArray()[0]);
392     assertEquals(1, c.aliases().toArray().length);
393   }
394 
testConstructor_EmptyCanonicalName()395   public void testConstructor_EmptyCanonicalName() {
396     try {
397       new MockCharset("", new String[0]);
398       fail();
399     } catch (IllegalCharsetNameException expected) {
400     }
401   }
402 
testConstructor_IllegalCanonicalName_Initial()403   public void testConstructor_IllegalCanonicalName_Initial() {
404     try {
405       new MockCharset("-123", new String[] { "mock" });
406       fail();
407     } catch (IllegalCharsetNameException expected) {
408     }
409   }
410 
testConstructor_IllegalCanonicalName_Middle()411   public void testConstructor_IllegalCanonicalName_Middle() {
412     try {
413       new MockCharset("1%%23", new String[] { "mock" });
414       fail();
415     } catch (IllegalCharsetNameException expected) {
416     }
417     try {
418       new MockCharset("1//23", new String[] { "mock" });
419       fail();
420     } catch (IllegalCharsetNameException expected) {
421     }
422   }
423 
testConstructor_NullCanonicalName()424   public void testConstructor_NullCanonicalName() {
425     try {
426       MockCharset c = new MockCharset(null, new String[] { "mock" });
427       fail();
428     } catch (NullPointerException expected) {
429     }
430   }
431 
testConstructor_NullAliases()432   public void testConstructor_NullAliases() {
433     MockCharset c = new MockCharset("mockChar", null);
434     assertEquals("mockChar", c.name());
435     assertEquals("mockChar", c.displayName());
436     assertEquals("mockChar", c.displayName(Locale.getDefault()));
437     assertEquals(0, c.aliases().toArray().length);
438   }
439 
testConstructor_NullAliase()440   public void testConstructor_NullAliase() {
441     try {
442       new MockCharset("mockChar", new String[] { "mock", null });
443       fail();
444     } catch (NullPointerException expected) {
445     }
446   }
447 
testConstructor_NoAliases()448   public void testConstructor_NoAliases() {
449     MockCharset c = new MockCharset("mockChar", new String[0]);
450     assertEquals("mockChar", c.name());
451     assertEquals("mockChar", c.displayName());
452     assertEquals("mockChar", c.displayName(Locale.getDefault()));
453     assertEquals(0, c.aliases().toArray().length);
454   }
455 
testConstructor_EmptyAliases()456   public void testConstructor_EmptyAliases() {
457     try {
458       new MockCharset("mockChar", new String[] { "" });
459       fail();
460     } catch (IllegalCharsetNameException expected) {
461     }
462   }
463 
464   // Test the constructor with illegal aliases: starting with neither a digit nor a letter.
testConstructor_IllegalAliases_Initial()465   public void testConstructor_IllegalAliases_Initial() {
466     try {
467       new MockCharset("mockChar", new String[] { "mock", "-123" });
468       fail();
469     } catch (IllegalCharsetNameException e) {
470     }
471   }
472 
testConstructor_IllegalAliases_Middle()473   public void testConstructor_IllegalAliases_Middle() {
474     try {
475       new MockCharset("mockChar", new String[] { "mock", "22##ab" });
476       fail();
477     } catch (IllegalCharsetNameException expected) {
478     }
479     try {
480       new MockCharset("mockChar", new String[] { "mock", "22%%ab" });
481       fail();
482     } catch (IllegalCharsetNameException expected) {
483     }
484   }
485 
testAliases_Multiple()486   public void testAliases_Multiple() {
487     final String mockName = "mockChar1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:-_";
488     MockCharset c = new MockCharset("mockChar", new String[] { "mock", mockName, "mock2" });
489     assertEquals("mockChar", c.name());
490     assertEquals(3, c.aliases().size());
491     assertTrue(c.aliases().contains("mock"));
492     assertTrue(c.aliases().contains(mockName));
493     assertTrue(c.aliases().contains("mock2"));
494 
495     try {
496       c.aliases().clear();
497       fail();
498     } catch (UnsupportedOperationException expected) {
499     }
500   }
501 
testAliases_Duplicate()502   public void testAliases_Duplicate() {
503     final String mockName = "mockChar1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:-_";
504     MockCharset c = new MockCharset("mockChar", new String[] { "mockChar",
505                                                                   "mock", mockName, "mock", "mockChar", "mock", "mock2" });
506     assertEquals("mockChar", c.name());
507     assertEquals(4, c.aliases().size());
508     assertTrue(c.aliases().contains("mockChar"));
509     assertTrue(c.aliases().contains("mock"));
510     assertTrue(c.aliases().contains(mockName));
511     assertTrue(c.aliases().contains("mock2"));
512   }
513 
testCanEncode()514   public void testCanEncode() {
515     MockCharset c = new MockCharset("mock", null);
516     assertTrue(c.canEncode());
517   }
518 
testIsRegistered()519   public void testIsRegistered() {
520     MockCharset c = new MockCharset("mock", null);
521     assertTrue(c.isRegistered());
522   }
523 
testDisplayName_Locale_Null()524   public void testDisplayName_Locale_Null() {
525     MockCharset c = new MockCharset("mock", null);
526     assertEquals("mock", c.displayName(null));
527   }
528 
testCompareTo_Normal()529   public void testCompareTo_Normal() {
530     MockCharset c1 = new MockCharset("mock", null);
531     assertEquals(0, c1.compareTo(c1));
532 
533     MockCharset c2 = new MockCharset("Mock", null);
534     assertEquals(0, c1.compareTo(c2));
535 
536     c2 = new MockCharset("mock2", null);
537     assertTrue(c1.compareTo(c2) < 0);
538     assertTrue(c2.compareTo(c1) > 0);
539 
540     c2 = new MockCharset("mack", null);
541     assertTrue(c1.compareTo(c2) > 0);
542     assertTrue(c2.compareTo(c1) < 0);
543 
544     c2 = new MockCharset("m.", null);
545     assertTrue(c1.compareTo(c2) > 0);
546     assertTrue(c2.compareTo(c1) < 0);
547 
548     c2 = new MockCharset("m:", null);
549     assertEquals("mock".compareToIgnoreCase("m:"), c1.compareTo(c2));
550     assertEquals("m:".compareToIgnoreCase("mock"), c2.compareTo(c1));
551 
552     c2 = new MockCharset("m-", null);
553     assertTrue(c1.compareTo(c2) > 0);
554     assertTrue(c2.compareTo(c1) < 0);
555 
556     c2 = new MockCharset("m_", null);
557     assertTrue(c1.compareTo(c2) > 0);
558     assertTrue(c2.compareTo(c1) < 0);
559   }
560 
561   public void testCompareTo_Null() {
562     MockCharset c1 = new MockCharset("mock", null);
563     try {
564       c1.compareTo(null);
565       fail();
566     } catch (NullPointerException expected) {
567     }
568   }
569 
570   public void testCompareTo_DiffCharsetClass() {
571     MockCharset c1 = new MockCharset("mock", null);
572     MockCharset2 c2 = new MockCharset2("Mock", new String[] { "myname" });
573     assertEquals(0, c1.compareTo(c2));
574     assertEquals(0, c2.compareTo(c1));
575   }
576 
577   public void testEquals_Normal() {
578     MockCharset c1 = new MockCharset("mock", null);
579     MockCharset2 c2 = new MockCharset2("mock", null);
580     assertTrue(c1.equals(c2));
581     assertTrue(c2.equals(c1));
582 
583     c2 = new MockCharset2("Mock", null);
584     assertFalse(c1.equals(c2));
585     assertFalse(c2.equals(c1));
586   }
587 
588   public void testEquals_Null() {
589     MockCharset c1 = new MockCharset("mock", null);
590     assertFalse(c1.equals(null));
591   }
592 
593   public void testEquals_NonCharsetObject() {
594     MockCharset c1 = new MockCharset("mock", null);
595     assertFalse(c1.equals("test"));
596   }
597 
598   public void testEquals_DiffCharsetClass() {
599     MockCharset c1 = new MockCharset("mock", null);
600     MockCharset2 c2 = new MockCharset2("mock", null);
601     assertTrue(c1.equals(c2));
602     assertTrue(c2.equals(c1));
603   }
604 
605   public void testHashCode_DiffCharsetClass() {
606     MockCharset c1 = new MockCharset("mock", null);
607     assertEquals(c1.hashCode(), "mock".hashCode());
608 
609     final String mockName = "mockChar1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:-_";
610     c1 = new MockCharset(mockName, new String[] { "mockChar", "mock",
611                                                      mockName, "mock", "mockChar", "mock", "mock2" });
612     assertEquals(mockName.hashCode(), c1.hashCode());
613   }
614 
615   public void testEncode_CharBuffer_Normal() throws Exception {
616     MockCharset c1 = new MockCharset("testEncode_CharBuffer_Normal_mock", null);
617     ByteBuffer bb = c1.encode(CharBuffer.wrap("abcdefg"));
618     assertEquals("abcdefg", new String(bb.array(), "iso8859-1"));
619     bb = c1.encode(CharBuffer.wrap(""));
620     assertEquals("", new String(bb.array(), "iso8859-1"));
621   }
622 
623   public void testEncode_CharBuffer_Unmappable() throws Exception {
624     Charset c1 = Charset.forName("iso8859-1");
625     ByteBuffer bb = c1.encode(CharBuffer.wrap("abcd\u5D14efg"));
626     assertEquals(new String(bb.array(), "iso8859-1"),
627                  "abcd" + new String(c1.newEncoder().replacement(), "iso8859-1") + "efg");
628   }
629 
630   public void testEncode_CharBuffer_NullCharBuffer() {
631     MockCharset c = new MockCharset("mock", null);
632     try {
633       c.encode((CharBuffer) null);
634       fail();
635     } catch (NullPointerException expected) {
636     }
637   }
638 
639   public void testEncode_CharBuffer_NullEncoder() {
640     MockCharset2 c = new MockCharset2("mock2", null);
641     try {
642       c.encode(CharBuffer.wrap("hehe"));
643       fail();
644     } catch (NullPointerException expected) {
645     }
646   }
647 
648   public void testEncode_String_Normal() throws Exception {
649     MockCharset c1 = new MockCharset("testEncode_String_Normal_mock", null);
650     ByteBuffer bb = c1.encode("abcdefg");
651     assertEquals("abcdefg", new String(bb.array(), "iso8859-1"));
652     bb = c1.encode("");
653     assertEquals("", new String(bb.array(), "iso8859-1"));
654   }
655 
656   public void testEncode_String_Unmappable() throws Exception {
657     Charset c1 = Charset.forName("iso8859-1");
658     ByteBuffer bb = c1.encode("abcd\u5D14efg");
659     assertEquals(new String(bb.array(), "iso8859-1"),
660                  "abcd" + new String(c1.newEncoder().replacement(), "iso8859-1") + "efg");
661   }
662 
663   public void testEncode_String_NullString() {
664     MockCharset c = new MockCharset("mock", null);
665     try {
666       c.encode((String) null);
667       fail();
668     } catch (NullPointerException expected) {
669     }
670   }
671 
672   public void testEncode_String_NullEncoder() {
673     MockCharset2 c = new MockCharset2("mock2", null);
674     try {
675       c.encode("hehe");
676       fail();
677     } catch (NullPointerException expected) {
678     }
679   }
680 
681   public void testDecode_Normal() throws Exception {
682     MockCharset c1 = new MockCharset("mock", null);
683     CharBuffer cb = c1.decode(ByteBuffer.wrap("abcdefg".getBytes("iso8859-1")));
684     assertEquals("abcdefg", new String(cb.array()));
685     cb = c1.decode(ByteBuffer.wrap("".getBytes("iso8859-1")));
686     assertEquals("", new String(cb.array()));
687   }
688 
689   public void testDecode_Malformed() throws Exception {
690     Charset c1 = Charset.forName("iso8859-1");
691     CharBuffer cb = c1.decode(ByteBuffer.wrap("abcd\u5D14efg".getBytes("iso8859-1")));
692     byte[] replacement = c1.newEncoder().replacement();
693     assertEquals(new String(cb.array()).trim(), "abcd" + new String(replacement, "iso8859-1") + "efg");
694   }
695 
696   public void testDecode_NullByteBuffer() {
697     MockCharset c = new MockCharset("mock", null);
698     try {
699       c.decode(null);
700       fail();
701     } catch (NullPointerException expected) {
702     }
703   }
704 
705   public void testDecode_NullDecoder() {
706     MockCharset2 c = new MockCharset2("mock2", null);
707     try {
708       c.decode(ByteBuffer.wrap("hehe".getBytes()));
709       fail();
710     } catch (NullPointerException expected) {
711     }
712   }
713 
714   public void testToString() {
715     MockCharset c1 = new MockCharset("mock", null);
716     assertTrue(-1 != c1.toString().indexOf("mock"));
717   }
718 
719   static final class MockCharset extends Charset {
720     public MockCharset(String canonicalName, String[] aliases) {
721       super(canonicalName, aliases);
722     }
723 
724     public boolean contains(Charset cs) {
725       return false;
726     }
727 
728     public CharsetDecoder newDecoder() {
729       return new MockDecoder(this);
730     }
731 
732     public CharsetEncoder newEncoder() {
733       return new MockEncoder(this);
734     }
735   }
736 
737   static class MockCharset2 extends Charset {
738     public MockCharset2(String canonicalName, String[] aliases) {
739       super(canonicalName, aliases);
740     }
741 
742     public boolean contains(Charset cs) {
743       return false;
744     }
745 
746     public CharsetDecoder newDecoder() {
747       return null;
748     }
749 
750     public CharsetEncoder newEncoder() {
751       return null;
752     }
753   }
754 
755   static class MockEncoder extends java.nio.charset.CharsetEncoder {
756     public MockEncoder(Charset cs) {
757       super(cs, 1, 3, new byte[] { (byte) '?' });
758     }
759 
760     protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
761       while (in.remaining() > 0) {
762         out.put((byte) in.get());
763         // out.put((byte) '!');
764       }
765       return CoderResult.UNDERFLOW;
766     }
767   }
768 
769   static class MockDecoder extends java.nio.charset.CharsetDecoder {
MockDecoder(Charset cs)770     public MockDecoder(Charset cs) {
771       super(cs, 1, 10);
772     }
773 
decodeLoop(ByteBuffer in, CharBuffer out)774     protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
775       while (in.remaining() > 0) {
776         out.put((char) in.get());
777       }
778       return CoderResult.UNDERFLOW;
779     }
780   }
781 
782 
783   // Test the method isSupported(String) with charset supported by multiple providers.
testIsSupported_And_ForName_NormalProvider()784   public void testIsSupported_And_ForName_NormalProvider() throws Exception {
785     SettableCharsetProvider.setDelegate(new MockCharsetProvider());
786     try {
787       assertTrue(Charset.isSupported("mockCharset10"));
788       // ignore case problem in mock, intended
789       assertTrue(Charset.isSupported("MockCharset11"));
790       assertTrue(Charset.isSupported("MockCharset12"));
791       assertTrue(Charset.isSupported("MOCKCharset10"));
792       // intended case problem in mock
793       assertTrue(Charset.isSupported("MOCKCharset11"));
794       assertTrue(Charset.isSupported("MOCKCharset12"));
795 
796       assertTrue(Charset.forName("mockCharset10") instanceof MockCharset);
797       assertTrue(Charset.forName("mockCharset11") instanceof MockCharset);
798       assertTrue(Charset.forName("mockCharset12") instanceof MockCharset);
799 
800       assertTrue(Charset.forName("mockCharset10") == charset2);
801       // intended case problem in mock
802       Charset.forName("mockCharset11");
803       assertTrue(Charset.forName("mockCharset12") == charset2);
804     } finally {
805       SettableCharsetProvider.clearDelegate();
806     }
807   }
808 
809   // Test the method availableCharsets() with charset supported by multiple providers.
testAvailableCharsets_NormalProvider()810   public void testAvailableCharsets_NormalProvider() throws Exception {
811     SettableCharsetProvider.setDelegate(new MockCharsetProvider());
812     try {
813       assertTrue(Charset.availableCharsets().containsKey("mockCharset00"));
814       assertTrue(Charset.availableCharsets().containsKey("MOCKCharset00"));
815       assertTrue(Charset.availableCharsets().get("mockCharset00") instanceof MockCharset);
816       assertTrue(Charset.availableCharsets().get("MOCKCharset00") instanceof MockCharset);
817       assertFalse(Charset.availableCharsets().containsKey("mockCharset01"));
818       assertFalse(Charset.availableCharsets().containsKey("mockCharset02"));
819 
820       assertTrue(Charset.availableCharsets().get("mockCharset10") == charset2);
821       assertTrue(Charset.availableCharsets().get("MOCKCharset10") == charset2);
822       assertFalse(Charset.availableCharsets().containsKey("mockCharset11"));
823       assertFalse(Charset.availableCharsets().containsKey("mockCharset12"));
824 
825       assertTrue(Charset.availableCharsets().containsKey("mockCharset10"));
826       assertTrue(Charset.availableCharsets().containsKey("MOCKCharset10"));
827       assertTrue(Charset.availableCharsets().get("mockCharset10") == charset2);
828       assertFalse(Charset.availableCharsets().containsKey("mockCharset11"));
829       assertFalse(Charset.availableCharsets().containsKey("mockCharset12"));
830     } finally {
831       SettableCharsetProvider.clearDelegate();
832     }
833   }
834 
835   // Test the method forName(String) when the charset provider supports a
836   // built-in charset.
testForName_DuplicateWithBuiltInCharset()837   public void testForName_DuplicateWithBuiltInCharset() throws Exception {
838     SettableCharsetProvider.setDelegate(new MockCharsetProviderASCII());
839     try {
840       assertFalse(Charset.forName("us-ascii") instanceof MockCharset);
841       assertFalse(Charset.availableCharsets().get("us-ascii") instanceof MockCharset);
842     } finally {
843       SettableCharsetProvider.clearDelegate();
844     }
845   }
846 
847   // Fails on Android with a StackOverflowException.
testForName_withProviderWithRecursiveCall()848   public void testForName_withProviderWithRecursiveCall() throws Exception {
849     SettableCharsetProvider.setDelegate(new MockCharsetProviderWithRecursiveCall());
850     try {
851       Charset.forName("poop");
852       fail();
853     } catch (UnsupportedCharsetException expected) {
854     } finally {
855       SettableCharsetProvider.clearDelegate();
856     }
857   }
858 
859   public static class MockCharsetProviderWithRecursiveCall extends CharsetProvider {
860       @Override
charsets()861       public Iterator<Charset> charsets() {
862           return null;
863       }
864 
865       @Override
charsetForName(String charsetName)866       public Charset charsetForName(String charsetName) {
867           if (Charset.isSupported(charsetName)) {
868               return Charset.forName(charsetName);
869           }
870 
871           return null;
872       }
873   }
874 
875   public static class MockCharsetProvider extends CharsetProvider {
charsetForName(String charsetName)876     public Charset charsetForName(String charsetName) {
877       if ("MockCharset00".equalsIgnoreCase(charsetName) ||
878           "MockCharset01".equalsIgnoreCase(charsetName) ||
879           "MockCharset02".equalsIgnoreCase(charsetName)) {
880         return charset1;
881       } else if ("MockCharset10".equalsIgnoreCase(charsetName) ||
882           "MockCharset11".equalsIgnoreCase(charsetName) ||
883           "MockCharset12".equalsIgnoreCase(charsetName)) {
884         return charset2;
885       }
886       return null;
887     }
888 
charsets()889     public Iterator charsets() {
890       Vector v = new Vector();
891       v.add(charset1);
892       v.add(charset2);
893       return v.iterator();
894     }
895   }
896 
897   // Another mock charset provider attempting to provide the built-in charset "ascii" again.
898   public static class MockCharsetProviderASCII extends CharsetProvider {
charsetForName(String charsetName)899     public Charset charsetForName(String charsetName) {
900       if ("US-ASCII".equalsIgnoreCase(charsetName) || "ASCII".equalsIgnoreCase(charsetName)) {
901         return new MockCharset("US-ASCII", new String[] { "ASCII" });
902       }
903       return null;
904     }
905 
charsets()906     public Iterator charsets() {
907       Vector v = new Vector();
908       v.add(new MockCharset("US-ASCII", new String[] { "ASCII" }));
909       return v.iterator();
910     }
911   }
912 }
913