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