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 */ 16package tests.api.java.nio.charset; 17 18import java.nio.ByteBuffer; 19import java.nio.CharBuffer; 20import java.nio.charset.CharacterCodingException; 21import java.nio.charset.Charset; 22import java.nio.charset.CharsetDecoder; 23import java.nio.charset.CharsetEncoder; 24import java.nio.charset.CoderResult; 25import java.nio.charset.CodingErrorAction; 26import java.nio.charset.MalformedInputException; 27import java.nio.charset.UnmappableCharacterException; 28import java.nio.charset.UnsupportedCharsetException; 29import java.util.Arrays; 30 31import junit.framework.TestCase; 32 33/** 34 * API unit test for java.nio.charset.CharsetEncoder 35 */ 36public class CharsetEncoderTest extends TestCase { 37 38 static final int MAX_BYTES = 3; 39 40 static final float AVER_BYTES = 0.5f; 41 42 // charset for mock class 43 private static final Charset MOCKCS = new MockCharset("CharsetEncoderTest_mock", new String[0]); 44 45 Charset cs = MOCKCS; 46 47 // default encoder 48 CharsetEncoder encoder; 49 50 // default for Charset abstract class 51 byte[] defaultReplacement = new byte[] { 63 }; 52 53 // specific for Charset implementation subclass 54 byte[] specifiedReplacement = new byte[] { 63 }; 55 56 static final String unistr = " buffer";// \u8000\u8001\u00a5\u3000\r\n"; 57 58 byte[] unibytes = new byte[] { 32, 98, 117, 102, 102, 101, 114 }; 59 60 byte[] unibytesWithRep = null; 61 62 byte[] surrogate = new byte[0]; 63 64 protected void setUp() throws Exception { 65 super.setUp(); 66 encoder = cs.newEncoder(); 67 if (null == unibytesWithRep) { 68 byte[] replacement = encoder.replacement(); 69 unibytesWithRep = new byte[replacement.length + unibytes.length]; 70 System.arraycopy(replacement, 0, unibytesWithRep, 0, 71 replacement.length); 72 System.arraycopy(unibytes, 0, unibytesWithRep, replacement.length, 73 unibytes.length); 74 } 75 } 76 77 /* 78 * @see TestCase#tearDown() 79 */ 80 protected void tearDown() throws Exception { 81 super.tearDown(); 82 } 83 84 public void testSpecificDefaultValue() { 85 assertTrue(encoder.averageBytesPerChar() == AVER_BYTES); 86 assertTrue(encoder.maxBytesPerChar() == MAX_BYTES); 87 } 88 89 public void testDefaultValue() { 90 assertEquals(CodingErrorAction.REPORT, encoder.malformedInputAction()); 91 assertEquals(CodingErrorAction.REPORT, encoder 92 .unmappableCharacterAction()); 93 assertSame(encoder, encoder.onMalformedInput(CodingErrorAction.IGNORE)); 94 assertSame(encoder, encoder 95 .onUnmappableCharacter(CodingErrorAction.IGNORE)); 96 if (encoder instanceof MockCharsetEncoder) { 97 assertTrue(Arrays.equals(encoder.replacement(), defaultReplacement)); 98 } else { 99 assertTrue(Arrays.equals(encoder.replacement(), 100 specifiedReplacement)); 101 } 102 103 } 104 105 /* 106 * Class under test for constructor CharsetEncoder(Charset, float, float) 107 */ 108 public void testCharsetEncoderCharsetfloatfloat() { 109 // default value 110 encoder = new MockCharsetEncoder(cs, (float) AVER_BYTES, MAX_BYTES); 111 assertSame(encoder.charset(), cs); 112 assertTrue(encoder.averageBytesPerChar() == AVER_BYTES); 113 assertTrue(encoder.maxBytesPerChar() == MAX_BYTES); 114 assertEquals(CodingErrorAction.REPORT, encoder.malformedInputAction()); 115 assertEquals(CodingErrorAction.REPORT, encoder 116 .unmappableCharacterAction()); 117 assertEquals(new String(encoder.replacement()), new String( 118 defaultReplacement)); 119 assertSame(encoder, encoder.onMalformedInput(CodingErrorAction.IGNORE)); 120 assertSame(encoder, encoder 121 .onUnmappableCharacter(CodingErrorAction.IGNORE)); 122 123 // normal case 124 CharsetEncoder ec = new MockCharsetEncoder(cs, 1, MAX_BYTES); 125 assertSame(ec.charset(), cs); 126 assertEquals(1.0, ec.averageBytesPerChar(), 0); 127 assertTrue(ec.maxBytesPerChar() == MAX_BYTES); 128 129 /* 130 * ------------------------ Exceptional cases ------------------------- 131 */ 132 // NullPointerException: null charset 133 try { 134 ec = new MockCharsetEncoder(null, 1, MAX_BYTES); 135 fail("should throw null pointer exception"); 136 } catch (NullPointerException e) { 137 } 138 139 ec = new MockCharsetEncoder(new MockCharset("mock", new String[0]), 1, 140 MAX_BYTES); 141 142 // Commented out since the comment is wrong since MAX_BYTES > 1 143 // // OK: average length less than max length 144 // ec = new MockCharsetEncoder(cs, MAX_BYTES, 1); 145 // assertTrue(ec.averageBytesPerChar() == MAX_BYTES); 146 // assertTrue(ec.maxBytesPerChar() == 1); 147 148 // Illegal Argument: zero length 149 try { 150 ec = new MockCharsetEncoder(cs, 0, MAX_BYTES); 151 fail("should throw IllegalArgumentException"); 152 } catch (IllegalArgumentException e) { 153 } 154 try { 155 ec = new MockCharsetEncoder(cs, 1, 0); 156 fail("should throw IllegalArgumentException"); 157 } catch (IllegalArgumentException e) { 158 } 159 160 // Illegal Argument: negative length 161 try { 162 ec = new MockCharsetEncoder(cs, -1, MAX_BYTES); 163 fail("should throw IllegalArgumentException"); 164 } catch (IllegalArgumentException e) { 165 } 166 try { 167 ec = new MockCharsetEncoder(cs, 1, -1); 168 fail("should throw IllegalArgumentException"); 169 } catch (IllegalArgumentException e) { 170 } 171 } 172 173 /* 174 * Class under test for constructor CharsetEncoder(Charset, float, float, 175 * byte[]) 176 */ 177 public void testCharsetEncoderCharsetfloatfloatbyteArray() { 178 byte[] ba = getLegalByteArray(); 179 // normal case 180 CharsetEncoder ec = new MockCharsetEncoder(cs, 1, MAX_BYTES, ba); 181 assertSame(ec.charset(), cs); 182 assertEquals(1.0, ec.averageBytesPerChar(), 0.0); 183 assertTrue(ec.maxBytesPerChar() == MAX_BYTES); 184 assertSame(ba, ec.replacement()); 185 186 /* 187 * ------------------------ Exceptional cases ------------------------- 188 */ 189 // NullPointerException: null charset 190 try { 191 ec = new MockCharsetEncoder(null, 1, MAX_BYTES, ba); 192 fail("should throw null pointer exception"); 193 } catch (NullPointerException e) { 194 } 195 196 // Illegal Argument: null byte array 197 try { 198 ec = new MockCharsetEncoder(cs, 1, MAX_BYTES, null); 199 fail("should throw IllegalArgumentException"); 200 } catch (IllegalArgumentException e) { 201 } 202 // Illegal Argument: empty byte array 203 try { 204 ec = new MockCharsetEncoder(cs, 1, MAX_BYTES, new byte[0]); 205 fail("should throw IllegalArgumentException"); 206 } catch (IllegalArgumentException e) { 207 } 208 // Illegal Argument: byte array is longer than max length 209 try { 210 ec = new MockCharsetEncoder(cs, 1, MAX_BYTES, new byte[] { 1, 2, 211 MAX_BYTES, 4 }); 212 fail("should throw IllegalArgumentException"); 213 } catch (IllegalArgumentException e) { 214 } 215 216 // Commented out since the comment is wrong since MAX_BYTES > 1 217 // This test throws IllegalArgumentException on Harmony and RI 218 // // OK: average length less than max length 219 // ec = new MockCharsetEncoder(cs, MAX_BYTES, ba.length, ba); 220 // assertTrue(ec.averageBytesPerChar() == MAX_BYTES); 221 // assertTrue(ec.maxBytesPerChar() == ba.length); 222 223 // Illegal Argument: zero length 224 try { 225 ec = new MockCharsetEncoder(cs, 0, MAX_BYTES, ba); 226 fail("should throw IllegalArgumentException"); 227 } catch (IllegalArgumentException e) { 228 } 229 try { 230 ec = new MockCharsetEncoder(cs, 1, 0, ba); 231 fail("should throw IllegalArgumentException"); 232 } catch (IllegalArgumentException e) { 233 } 234 235 // Illegal Argument: negative length 236 try { 237 ec = new MockCharsetEncoder(cs, -1, MAX_BYTES, ba); 238 fail("should throw IllegalArgumentException"); 239 } catch (IllegalArgumentException e) { 240 } 241 try { 242 ec = new MockCharsetEncoder(cs, 1, -1, ba); 243 fail("should throw IllegalArgumentException"); 244 } catch (IllegalArgumentException e) { 245 } 246 } 247 248 /* 249 * Class under test for boolean canEncode(char) 250 */ 251 public void testCanEncodechar() throws CharacterCodingException { 252 // for non-mapped char 253 assertTrue(encoder.canEncode('\uc2c0')); 254 // surrogate char for unicode 255 // 1st byte: d800-dbff 256 // 2nd byte: dc00-dfff 257 assertTrue(encoder.canEncode('\ud800')); 258 // valid surrogate pair 259 assertTrue(encoder.canEncode('\udc00')); 260 } 261 262 /*----------------------------------------- 263 * Class under test for illegal state case 264 * methods which can change internal states are two encode, flush, two canEncode, reset 265 * ----------------------------------------- 266 */ 267 268 // Normal case: just after reset, and it also means reset can be done 269 // anywhere 270 public void testResetIllegalState() throws CharacterCodingException { 271 assertSame(encoder, encoder.reset()); 272 encoder.canEncode('\ud901'); 273 assertSame(encoder, encoder.reset()); 274 encoder.canEncode("\ud901\udc00"); 275 assertSame(encoder, encoder.reset()); 276 encoder.encode(CharBuffer.wrap("aaa")); 277 assertSame(encoder, encoder.reset()); 278 encoder.encode(CharBuffer.wrap("aaa"), ByteBuffer.allocate(3), false); 279 assertSame(encoder, encoder.reset()); 280 encoder.encode(CharBuffer.wrap("aaa"), ByteBuffer.allocate(3), true); 281 assertSame(encoder, encoder.reset()); 282 } 283 284 public void testFlushIllegalState() throws CharacterCodingException { 285 CharBuffer in = CharBuffer.wrap("aaa"); 286 ByteBuffer out = ByteBuffer.allocate(5); 287 288 // Normal case: after encode with endOfInput is true 289 assertSame(encoder, encoder.reset()); 290 encoder.encode(in, out, true); 291 out.rewind(); 292 CoderResult result = encoder.flush(out); 293 294 // Illegal state: flush twice 295 try { 296 encoder.flush(out); 297 fail("should throw IllegalStateException"); 298 } catch (IllegalStateException e) { 299 // Expected 300 } 301 302 // Illegal state: flush after encode with endOfInput is false 303 assertSame(encoder, encoder.reset()); 304 encoder.encode(in, out, false); 305 try { 306 encoder.flush(out); 307 fail("should throw IllegalStateException"); 308 } catch (IllegalStateException e) { 309 // Expected 310 } 311 } 312 313 public void testFlushAfterConstructing() { 314 ByteBuffer out = ByteBuffer.allocate(5); 315 316 //Illegal state: flush after instance created 317 try { 318 encoder.flush(out); 319 fail("should throw IllegalStateException"); 320 } catch (IllegalStateException e) { 321 // Expected 322 } 323 324 } 325 326 // test illegal states for encode facade 327 public void testEncodeFacadeIllegalState() throws CharacterCodingException { 328 // encode facade can be execute in anywhere 329 CharBuffer in = CharBuffer.wrap("aaa"); 330 // Normal case: just created 331 encoder.encode(in); 332 in.rewind(); 333 334 // Normal case: just after encode facade 335 encoder.encode(in); 336 in.rewind(); 337 338 // Normal case: just after canEncode 339 assertSame(encoder, encoder.reset()); 340 encoder.canEncode("\ud902\udc00"); 341 encoder.encode(in); 342 in.rewind(); 343 assertSame(encoder, encoder.reset()); 344 encoder.canEncode('\ud902'); 345 encoder.encode(in); 346 in.rewind(); 347 348 // Normal case: just after encode with that endOfInput is true 349 assertSame(encoder, encoder.reset()); 350 encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState2"), 351 ByteBuffer.allocate(30), true); 352 encoder.encode(in); 353 in.rewind(); 354 355 // Normal case:just after encode with that endOfInput is false 356 assertSame(encoder, encoder.reset()); 357 encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState3"), 358 ByteBuffer.allocate(30), false); 359 encoder.encode(in); 360 in.rewind(); 361 362 // Normal case: just after flush 363 assertSame(encoder, encoder.reset()); 364 encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState4"), 365 ByteBuffer.allocate(30), true); 366 encoder.flush(ByteBuffer.allocate(10)); 367 encoder.encode(in); 368 in.rewind(); 369 } 370 371 // test illegal states for two encode method with endOfInput is true 372 public void testEncodeTrueIllegalState() throws CharacterCodingException { 373 CharBuffer in = CharBuffer.wrap("aaa"); 374 ByteBuffer out = ByteBuffer.allocate(5); 375 // Normal case: just created 376 encoder.encode(in, out, true); 377 in.rewind(); 378 out.rewind(); 379 380 in.rewind(); 381 out.rewind(); 382 383 // Normal case: just after encode with that endOfInput is true 384 assertSame(encoder, encoder.reset()); 385 encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState2"), 386 ByteBuffer.allocate(30), true); 387 encoder.encode(in, out, true); 388 in.rewind(); 389 out.rewind(); 390 391 // Normal case:just after encode with that endOfInput is false 392 assertSame(encoder, encoder.reset()); 393 encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState3"), 394 ByteBuffer.allocate(30), false); 395 encoder.encode(in, out, true); 396 in.rewind(); 397 out.rewind(); 398 399 // Illegal state: just after flush 400 assertSame(encoder, encoder.reset()); 401 encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState4"), 402 ByteBuffer.allocate(30), true); 403 encoder.flush(ByteBuffer.allocate(10)); 404 try { 405 encoder.encode(in, out, true); 406 fail("should illegal state"); 407 } catch (IllegalStateException e) { 408 } 409 410 // Normal case: after canEncode 411 assertSame(encoder, encoder.reset()); 412 encoder.canEncode("\ud906\udc00"); 413 encoder.encode(in, out, true); 414 in.rewind(); 415 out.rewind(); 416 assertSame(encoder, encoder.reset()); 417 encoder.canEncode('\ud905'); 418 encoder.encode(in, out, true); 419 } 420 421 // test illegal states for two encode method with endOfInput is false 422 public void testEncodeFalseIllegalState() throws CharacterCodingException { 423 CharBuffer in = CharBuffer.wrap("aaa"); 424 ByteBuffer out = ByteBuffer.allocate(5); 425 // Normal case: just created 426 encoder.encode(in, out, false); 427 in.rewind(); 428 out.rewind(); 429 430 // Illegal state: just after encode facade 431 assertSame(encoder, encoder.reset()); 432 encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState1")); 433 try { 434 encoder.encode(in, out, false); 435 fail("should illegal state"); 436 } catch (IllegalStateException e) { 437 } 438 439 // Illegal state: just after encode with that endOfInput is true 440 assertSame(encoder, encoder.reset()); 441 encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState2"), 442 ByteBuffer.allocate(30), true); 443 try { 444 encoder.encode(in, out, false); 445 fail("should illegal state"); 446 } catch (IllegalStateException e) { 447 } 448 449 // Normal case:just after encode with that endOfInput is false 450 assertSame(encoder, encoder.reset()); 451 encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState3"), 452 ByteBuffer.allocate(30), false); 453 encoder.encode(in, out, false); 454 in.rewind(); 455 out.rewind(); 456 457 // Illegal state: just after flush 458 assertSame(encoder, encoder.reset()); 459 encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState4"), 460 ByteBuffer.allocate(30), true); 461 encoder.flush(ByteBuffer.allocate(10)); 462 try { 463 encoder.encode(in, out, false); 464 fail("should illegal state"); 465 } catch (IllegalStateException e) { 466 } 467 468 // Normal case: after canEncode 469 assertSame(encoder, encoder.reset()); 470 encoder.canEncode("\ud906\udc00"); 471 encoder.encode(in, out, false); 472 in.rewind(); 473 out.rewind(); 474 assertSame(encoder, encoder.reset()); 475 encoder.canEncode('\ud905'); 476 encoder.encode(in, out, false); 477 } 478 479 // test illegal states for two canEncode methods 480 public void testCanEncodeIllegalState() throws CharacterCodingException { 481 // Normal case: just created 482 encoder.canEncode("\ud900\udc00"); 483 encoder.canEncode('\ud900'); 484 485 // Illegal state: just after encode with that endOfInput is true 486 assertSame(encoder, encoder.reset()); 487 encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState2"), 488 ByteBuffer.allocate(30), true); 489 try { 490 encoder.canEncode("\ud903\udc00"); 491 fail("should throw illegal state exception"); 492 } catch (IllegalStateException e) { 493 } 494 495 // Illegal state:just after encode with that endOfInput is false 496 assertSame(encoder, encoder.reset()); 497 encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState3"), 498 ByteBuffer.allocate(30), false); 499 try { 500 encoder.canEncode("\ud904\udc00"); 501 fail("should throw illegal state exception"); 502 } catch (IllegalStateException e) { 503 } 504 505 // Normal case: just after flush 506 encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState4"), 507 ByteBuffer.allocate(30), true); 508 encoder.flush(ByteBuffer.allocate(10)); 509 encoder.canEncode("\ud905\udc00"); 510 encoder.canEncode('\ud906'); 511 512 // Normal case: after reset again 513 assertSame(encoder, encoder.reset()); 514 encoder.canEncode("\ud906\udc00"); 515 encoder.canEncode('\ud905'); 516 } 517 518 /* 519 * --------------------------------- illegal state test end 520 * --------------------------------- 521 */ 522 523 /* 524 * Class under test for boolean canEncode(CharSequence) 525 */ 526 public void testCanEncodeCharSequence() { 527 // for non-mapped char 528 assertTrue(encoder.canEncode("\uc2c0")); 529 // surrogate char for unicode 530 // 1st byte: d800-dbff 531 // 2nd byte: dc00-dfff 532 assertTrue(encoder.canEncode("\ud800")); 533 // valid surrogate pair 534 assertTrue(encoder.canEncode("\ud800\udc00")); 535 // invalid surrogate pair 536 assertTrue(encoder.canEncode("\ud800\udb00")); 537 } 538 539 /* 540 * Class under test for Charset charset() 541 */ 542 public void testCharset() { 543 try { 544 encoder = new MockCharsetEncoder(Charset.forName("gbk"), 1, 545 MAX_BYTES); 546 // assertSame(encoder.charset(), Charset.forName("gbk")); 547 } catch (UnsupportedCharsetException e) { 548 System.err 549 .println("Don't support GBK encoding, ignore current test"); 550 } 551 } 552 553 /* 554 * Class under test for ByteBuffer encode(CharBuffer) 555 */ 556 public void testEncodeCharBuffer() throws CharacterCodingException { 557 // Null pointer 558 try { 559 encoder.encode(null); 560 fail("should throw null pointer exception"); 561 } catch (NullPointerException e) { 562 } 563 564 // empty input buffer 565 ByteBuffer out = encoder.encode(CharBuffer.wrap("")); 566 assertEquals(out.position(), 0); 567 assertByteArray(out, new byte[0]); 568 // assertByteArray(out, surrogate); 569 570 // normal case 571 out = encoder.encode(CharBuffer.wrap(unistr)); 572 assertEquals(out.position(), 0); 573 assertByteArray(out, addSurrogate(unibytes)); 574 575 // Regression test for harmony-3378 576 Charset cs = Charset.forName("UTF-8"); 577 CharsetEncoder encoder = cs.newEncoder(); 578 encoder.onMalformedInput(CodingErrorAction.REPLACE); 579 encoder = encoder.replaceWith(new byte[] { (byte) 0xef, (byte) 0xbf, 580 (byte) 0xbd, }); 581 CharBuffer in = CharBuffer.wrap("\ud800"); 582 out = encoder.encode(in); 583 assertNotNull(out); 584 } 585 586 private byte[] addSurrogate(byte[] expected) { 587 if (surrogate.length > 0) { 588 byte[] temp = new byte[surrogate.length + expected.length]; 589 System.arraycopy(surrogate, 0, temp, 0, surrogate.length); 590 System.arraycopy(expected, 0, temp, surrogate.length, 591 expected.length); 592 expected = temp; 593 } 594 return expected; 595 } 596 597 /** 598 * @return 599 */ 600 protected byte[] getEmptyByteArray() { 601 return new byte[0]; 602 } 603 604 CharBuffer getMalformedCharBuffer() { 605 return CharBuffer.wrap("malform buffer"); 606 } 607 608 CharBuffer getUnmapCharBuffer() { 609 return CharBuffer.wrap("unmap buffer"); 610 } 611 612 CharBuffer getExceptionCharBuffer() { 613 return CharBuffer.wrap("runtime buffer"); 614 } 615 616 public void testEncodeCharBufferException() throws CharacterCodingException { 617 ByteBuffer out; 618 CharBuffer in; 619 // MalformedException: 620 in = getMalformedCharBuffer(); 621 encoder.onMalformedInput(CodingErrorAction.REPORT); 622 encoder.onUnmappableCharacter(CodingErrorAction.REPORT); 623 if (in != null) { 624 try { 625 // regression test for Harmony-1379 626 encoder.encode(in); 627 fail("should throw MalformedInputException"); 628 } catch (MalformedInputException e) { 629 } 630 631 encoder.reset(); 632 in.rewind(); 633 encoder.onMalformedInput(CodingErrorAction.IGNORE); 634 out = encoder.encode(in); 635 assertByteArray(out, addSurrogate(unibytes)); 636 637 encoder.reset(); 638 in.rewind(); 639 encoder.onMalformedInput(CodingErrorAction.REPLACE); 640 out = encoder.encode(in); 641 assertByteArray(out, addSurrogate(unibytesWithRep)); 642 } 643 644 // Unmapped Exception: 645 in = getUnmapCharBuffer(); 646 encoder.onMalformedInput(CodingErrorAction.REPORT); 647 encoder.onUnmappableCharacter(CodingErrorAction.REPORT); 648 if (in != null) { 649 encoder.reset(); 650 try { 651 encoder.encode(in); 652 fail("should throw UnmappableCharacterException"); 653 } catch (UnmappableCharacterException e) { 654 } 655 656 encoder.reset(); 657 in.rewind(); 658 encoder.onUnmappableCharacter(CodingErrorAction.IGNORE); 659 out = encoder.encode(in); 660 assertByteArray(out, unibytes); 661 662 encoder.reset(); 663 in.rewind(); 664 encoder.onUnmappableCharacter(CodingErrorAction.REPLACE); 665 out = encoder.encode(in); 666 assertByteArray(out, unibytesWithRep); 667 } 668 669 // RuntimeException 670 try { 671 encoder.encode(getExceptionCharBuffer()); 672 fail("should throw runtime exception"); 673 } catch (RuntimeException e) { 674 } 675 } 676 677 /* 678 * utility method, extract given bytebuffer to a string and compare with 679 * give string 680 */ 681 void assertByteArray(ByteBuffer out, byte[] expected) { 682 out = out.duplicate(); 683 if (out.position() != 0) { 684 out.flip(); 685 } 686 byte[] ba = new byte[out.limit() - out.position()]; 687 out.get(ba); 688 // byte[] ba = out.array(); 689 assertTrue(Arrays.equals(ba, expected)); 690 } 691 692 /* 693 * Class under test for CoderResult encode(CharBuffer, ByteBuffer, boolean) 694 */ 695 public void testEncodeCharBufferByteBufferboolean() 696 throws CharacterCodingException { 697 ByteBuffer out = ByteBuffer.allocate(200); 698 CharBuffer in = CharBuffer.wrap(unistr); 699 // Null pointer 700 try { 701 encoder.encode(null, out, true); 702 fail("should throw null pointer exception"); 703 } catch (NullPointerException e) { 704 } 705 try { 706 encoder.encode(in, null, true); 707 fail("should throw null pointer exception"); 708 } catch (NullPointerException e) { 709 } 710 711 // normal case, one complete operation 712 assertSame(encoder, encoder.reset()); 713 in.rewind(); 714 out.rewind(); 715 assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, true)); 716 assertEquals(out.limit(), 200); 717 assertTrue(out.position() > 0); 718 assertTrue(out.remaining() > 0); 719 assertEquals(out.capacity(), 200); 720 assertByteArray(out, addSurrogate(unibytes)); 721 in.rewind(); 722 723 encoder.flush(out); 724 725 // normal case, one complete operation, but call twice, first time set 726 // endOfInput to false 727 assertSame(encoder, encoder.reset()); 728 in.rewind(); 729 out = ByteBuffer.allocate(200); 730 assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, false)); 731 assertEquals(out.limit(), 200); 732 assertTrue(out.position() > 0); 733 assertTrue(out.remaining() > 0); 734 assertEquals(out.capacity(), 200); 735 assertByteArray(out, addSurrogate(unibytes)); 736 737 in.rewind(); 738 assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, false)); 739 in.rewind(); 740 assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, true)); 741 assertEquals(out.limit(), 200); 742 assertTrue(out.position() > 0); 743 assertTrue(out.remaining() > 0); 744 assertEquals(out.capacity(), 200); 745 746 assertByteArray(out, addSurrogate(duplicateByteArray(unibytes, 3))); 747 748 // overflow 749 out = ByteBuffer.allocate(4); 750 assertSame(encoder, encoder.reset()); 751 in.rewind(); 752 out.rewind(); 753 assertSame(CoderResult.OVERFLOW, encoder.encode(in, out, true)); 754 assertEquals(out.limit(), 4); 755 assertEquals(out.position(), 4); 756 assertEquals(out.remaining(), 0); 757 assertEquals(out.capacity(), 4); 758 ByteBuffer temp = ByteBuffer.allocate(200); 759 out.flip(); 760 temp.put(out); 761 out = temp; 762 assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, true)); 763 assertEquals(out.limit(), 200); 764 assertTrue(out.position() > 0); 765 assertTrue(out.remaining() > 0); 766 assertEquals(out.capacity(), 200); 767 assertByteArray(out, addSurrogate(unibytes)); 768 769 assertSame(encoder, encoder.reset()); 770 in.rewind(); 771 out = ByteBuffer.allocate(4); 772 assertSame(CoderResult.OVERFLOW, encoder.encode(in, out, false)); 773 assertEquals(out.limit(), 4); 774 assertEquals(out.position(), 4); 775 assertEquals(out.remaining(), 0); 776 assertEquals(out.capacity(), 4); 777 temp = ByteBuffer.allocate(200); 778 out.flip(); 779 temp.put(out); 780 out = temp; 781 assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, false)); 782 assertEquals(out.limit(), 200); 783 assertTrue(out.position() > 0); 784 assertTrue(out.remaining() > 0); 785 assertEquals(out.capacity(), 200); 786 assertByteArray(out, addSurrogate(unibytes)); 787 } 788 789 void printByteBuffer(ByteBuffer buffer) { 790 System.out.println("print buffer"); 791 if (buffer.position() != 0) { 792 buffer.flip(); 793 } 794 byte[] ba = buffer.array(); 795 for (int i = 0; i < ba.length; i++) { 796 System.out.println(Integer.toHexString(ba[i])); 797 } 798 } 799 800 public void testEncodeCharBufferByteBufferbooleanExceptionFalse() 801 throws CharacterCodingException { 802 implTestEncodeCharBufferByteBufferbooleanException(false); 803 } 804 805 public void testEncodeCharBufferByteBufferbooleanExceptionTrue() 806 throws CharacterCodingException { 807 implTestEncodeCharBufferByteBufferbooleanException(true); 808 } 809 810 private byte[] duplicateByteArray(byte[] ba, int times) { 811 byte[] result = new byte[ba.length * times]; 812 for (int i = 0; i < times; i++) { 813 System.arraycopy(ba, 0, result, i * ba.length, ba.length); 814 } 815 return result; 816 } 817 818 protected void implTestEncodeCharBufferByteBufferbooleanException( 819 boolean endOfInput) throws CharacterCodingException { 820 ByteBuffer out = ByteBuffer.allocate(100); 821 822 // MalformedException: 823 CharBuffer in = getMalformedCharBuffer(); 824 encoder.onMalformedInput(CodingErrorAction.REPORT); 825 encoder.onUnmappableCharacter(CodingErrorAction.REPORT); 826 if (in != null) { 827 encoder.reset(); 828 CoderResult r = encoder.encode(in, out, endOfInput); 829 assertTrue(r.isMalformed()); 830 831 encoder.reset(); 832 out.clear(); 833 in.rewind(); 834 encoder.onMalformedInput(CodingErrorAction.IGNORE); 835 assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, 836 endOfInput)); 837 assertCodingErrorAction(endOfInput, out, in, unibytes); 838 839 encoder.reset(); 840 out.clear(); 841 in.rewind(); 842 encoder.onMalformedInput(CodingErrorAction.REPLACE); 843 assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, 844 endOfInput)); 845 assertCodingErrorAction(endOfInput, out, in, unibytesWithRep); 846 } else { 847 System.out.println("Cannot find malformed char buffer for " 848 + cs.name()); 849 } 850 851 // Unmapped Exception: 852 in = getUnmapCharBuffer(); 853 encoder.onMalformedInput(CodingErrorAction.REPORT); 854 encoder.onUnmappableCharacter(CodingErrorAction.REPORT); 855 if (in != null) { 856 encoder.reset(); 857 out.clear(); 858 assertTrue(encoder.encode(in, out, endOfInput).isUnmappable()); 859 860 encoder.reset(); 861 out.clear(); 862 in.rewind(); 863 encoder.onUnmappableCharacter(CodingErrorAction.IGNORE); 864 assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, 865 endOfInput)); 866 assertCodingErrorAction(endOfInput, out, in, unibytes); 867 868 encoder.reset(); 869 out.clear(); 870 in.rewind(); 871 encoder.onUnmappableCharacter(CodingErrorAction.REPLACE); 872 assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, 873 endOfInput)); 874 assertCodingErrorAction(endOfInput, out, in, unibytesWithRep); 875 } else { 876 System.out.println("Cannot find unmapped char buffer for " 877 + cs.name()); 878 } 879 880 // RuntimeException 881 try { 882 encoder.encode(getExceptionCharBuffer()); 883 fail("should throw runtime exception"); 884 } catch (RuntimeException e) { 885 } 886 } 887 888 private void assertCodingErrorAction(boolean endOfInput, ByteBuffer out, 889 CharBuffer in, byte[] expect) { 890 if (endOfInput) { 891 assertByteArray(out, addSurrogate(expect)); 892 } else { 893 in.rewind(); 894 assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, 895 endOfInput)); 896 in.rewind(); 897 assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, true)); 898 assertByteArray(out, addSurrogate(duplicateByteArray(expect, 3))); 899 } 900 } 901 902 /* 903 * Class under test for CoderResult flush(ByteBuffer) 904 */ 905 public void testFlush() throws CharacterCodingException { 906 ByteBuffer out = ByteBuffer.allocate(6); 907 CharBuffer in = CharBuffer.wrap("aaa"); 908 assertEquals(in.remaining(), 3); 909 910 // by encode facade, so that internal state will be wrong 911 encoder.encode(CharBuffer.wrap("testFlush"), ByteBuffer.allocate(20), 912 true); 913 assertSame(CoderResult.UNDERFLOW, encoder 914 .flush(ByteBuffer.allocate(50))); 915 } 916 917 /* 918 * test isLegalReplacement(byte[]) 919 */ 920 public void testIsLegalReplacement() { 921 try { 922 encoder.isLegalReplacement(null); 923 fail("should throw null pointer exception"); 924 } catch (NullPointerException e) { 925 } 926 assertTrue(encoder.isLegalReplacement(specifiedReplacement)); 927 928 assertTrue(encoder.isLegalReplacement(new byte[200])); 929 byte[] ba = getIllegalByteArray(); 930 if (ba != null) { 931 assertFalse(encoder.isLegalReplacement(ba)); 932 } 933 } 934 935 public void testIsLegalReplacementEmptyArray() { 936 // ISO, ASC, GB, UTF8 encoder will throw exception in RI 937 // others will pass 938 // try { 939 assertTrue(encoder.isLegalReplacement(new byte[0])); 940 // fail("should throw ArrayIndexOutOfBoundsException"); 941 // } catch (ArrayIndexOutOfBoundsException e) { 942 // } 943 } 944 945 public void testOnMalformedInput() { 946 assertSame(CodingErrorAction.REPORT, encoder.malformedInputAction()); 947 try { 948 encoder.onMalformedInput(null); 949 fail("should throw null pointer exception"); 950 } catch (IllegalArgumentException e) { 951 } 952 encoder.onMalformedInput(CodingErrorAction.IGNORE); 953 assertSame(CodingErrorAction.IGNORE, encoder.malformedInputAction()); 954 } 955 956 public void testOnUnmappableCharacter() { 957 assertSame(CodingErrorAction.REPORT, encoder 958 .unmappableCharacterAction()); 959 try { 960 encoder.onUnmappableCharacter(null); 961 fail("should throw null pointer exception"); 962 } catch (IllegalArgumentException e) { 963 } 964 encoder.onUnmappableCharacter(CodingErrorAction.IGNORE); 965 assertSame(CodingErrorAction.IGNORE, encoder 966 .unmappableCharacterAction()); 967 } 968 969 public void testReplacement() { 970 try { 971 encoder.replaceWith(null); 972 fail("should throw null pointer exception"); 973 } catch (IllegalArgumentException e) { 974 } 975 try { 976 encoder.replaceWith(new byte[0]); 977 fail("should throw null pointer exception"); 978 } catch (IllegalArgumentException e) { 979 } 980 try { 981 encoder.replaceWith(new byte[100]); 982 fail("should throw null pointer exception"); 983 } catch (IllegalArgumentException e) { 984 } 985 986 byte[] nr = getLegalByteArray(); 987 assertSame(encoder, encoder.replaceWith(nr)); 988 assertSame(nr, encoder.replacement()); 989 990 nr = getIllegalByteArray(); 991 try { 992 encoder.replaceWith(new byte[100]); 993 fail("should throw null pointer exception"); 994 } catch (IllegalArgumentException e) { 995 } 996 } 997 998 protected byte[] getLegalByteArray() { 999 return new byte[] { 'a' }; 1000 } 1001 1002 protected byte[] getIllegalByteArray() { 1003 return new byte[155]; 1004 } 1005 1006 /* 1007 * Mock subclass of CharsetEncoder For protected method test 1008 */ 1009 public static class MockCharsetEncoder extends CharsetEncoder { 1010 1011 boolean flushed = false; 1012 1013 public boolean isFlushed() { 1014 boolean result = flushed; 1015 flushed = false; 1016 return result; 1017 } 1018 1019 public boolean isLegalReplacement(byte[] ba) { 1020 if (ba.length == 155) {// specified magic number, return false 1021 return false; 1022 } 1023 return super.isLegalReplacement(ba); 1024 } 1025 1026 public MockCharsetEncoder(Charset cs, float aver, float max) { 1027 super(cs, aver, max); 1028 } 1029 1030 public MockCharsetEncoder(Charset cs, float aver, float max, 1031 byte[] replacement) { 1032 super(cs, aver, max, replacement); 1033 } 1034 1035 protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) { 1036 int inPosition = in.position(); 1037 char[] input = new char[in.remaining()]; 1038 in.get(input); 1039 String result = new String(input); 1040 if (result.startsWith("malform")) { 1041 // reset the cursor to the error position 1042 in.position(inPosition); 1043 // in.position(0); 1044 // set the error length 1045 return CoderResult.malformedForLength("malform".length()); 1046 } else if (result.startsWith("unmap")) { 1047 // reset the cursor to the error position 1048 in.position(inPosition); 1049 // in.position(0); 1050 // set the error length 1051 return CoderResult.unmappableForLength("unmap".length()); 1052 } else if (result.startsWith("runtime")) { 1053 // reset the cursor to the error position 1054 in.position(0); 1055 // set the error length 1056 throw new RuntimeException("runtime"); 1057 } 1058 int inLeft = input.length; 1059 int outLeft = out.remaining(); 1060 CoderResult r = CoderResult.UNDERFLOW; 1061 int length = inLeft; 1062 if (outLeft < inLeft) { 1063 r = CoderResult.OVERFLOW; 1064 length = outLeft; 1065 in.position(inPosition + outLeft); 1066 } 1067 for (int i = 0; i < length; i++) { 1068 out.put((byte) input[i]); 1069 } 1070 return r; 1071 } 1072 1073 protected CoderResult implFlush(ByteBuffer out) { 1074 CoderResult result = super.implFlush(out); 1075 int length = 0; 1076 if (out.remaining() >= 5) { 1077 length = 5; 1078 result = CoderResult.UNDERFLOW; 1079 flushed = true; 1080 // for (int i = 0; i < length; i++) { 1081 // out.put((byte)'f'); 1082 // } 1083 } else { 1084 length = out.remaining(); 1085 result = CoderResult.OVERFLOW; 1086 } 1087 return result; 1088 } 1089 1090 protected void implReplaceWith(byte[] ba) { 1091 assertSame(ba, replacement()); 1092 } 1093 1094 } 1095 1096 /* 1097 * mock charset for test encoder initialization 1098 */ 1099 public static class MockCharset extends Charset { 1100 protected MockCharset(String arg0, String[] arg1) { 1101 super(arg0, arg1); 1102 } 1103 1104 public boolean contains(Charset arg0) { 1105 return false; 1106 } 1107 1108 public CharsetDecoder newDecoder() { 1109 return new CharsetDecoderTest.MockCharsetDecoder(this, 1110 (float) AVER_BYTES, MAX_BYTES); 1111 } 1112 1113 public CharsetEncoder newEncoder() { 1114 return new MockCharsetEncoder(this, (float) AVER_BYTES, MAX_BYTES); 1115 } 1116 } 1117 1118} 1119