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 dalvik.annotation.TestLevel; 19import dalvik.annotation.TestTargetClass; 20import dalvik.annotation.TestTargetNew; 21import dalvik.annotation.TestTargets; 22 23import java.nio.ByteBuffer; 24import java.nio.CharBuffer; 25import java.nio.charset.Charset; 26import java.nio.charset.CharsetDecoder; 27import java.nio.charset.CharsetEncoder; 28import java.nio.charset.CoderResult; 29import java.nio.charset.CodingErrorAction; 30import java.nio.charset.UnsupportedCharsetException; 31import java.util.Arrays; 32@TestTargetClass(CharsetEncoder.class) 33/** 34 * API unit test for java.nio.charset.CharsetEncoder 35 */ 36public class CharsetEncoderTest extends AbstractCharsetEncoderTestCase { 37 38 static final int MAX_BYTES = 3; 39 40 static final float AVER_BYTES = 0.5f; 41 42 // default for Charset abstract class 43 byte[] defaultReplacement = new byte[] { 63 }; 44 45 // specific for Charset implementation subclass 46 byte[] specifiedReplacement = new byte[] { 26 }; 47 48 49 protected void setUp() throws Exception { 50 cs = new MockCharset("CharsetEncoderTest_mock", new String[0]); 51 unibytes = new byte[] { 32, 98, 117, 102, 102, 101, 114 }; 52 super.setUp(); 53 } 54 55 56 @TestTargets({ 57 @TestTargetNew( 58 level = TestLevel.COMPLETE, 59 notes = "", 60 method = "averageBytesPerChar", 61 args = {} 62 ), 63 @TestTargetNew( 64 level = TestLevel.COMPLETE, 65 notes = "", 66 method = "maxBytesPerChar", 67 args = {} 68 ) 69 }) 70 public void testSpecificDefaultValue() { 71 assertTrue(encoder.averageBytesPerChar() == AVER_BYTES); 72 assertTrue(encoder.maxBytesPerChar() == MAX_BYTES); 73 } 74 75 76 @TestTargetNew( 77 level = TestLevel.COMPLETE, 78 notes = "", 79 method = "implOnMalformedInput", 80 args = {java.nio.charset.CodingErrorAction.class} 81 ) 82 public void testImplOnMalformedInput() { 83 encoder = new MockCharsetEncoder(cs, 1, 3); 84 assertEquals(CoderResult.UNDERFLOW, ((MockCharsetEncoder) encoder) 85 .pubImplFlush(null)); 86 87 } 88 89 90 @TestTargetNew( 91 level = TestLevel.COMPLETE, 92 notes = "", 93 method = "implOnUnmappableCharacter", 94 args = {java.nio.charset.CodingErrorAction.class} 95 ) 96 public void testImplOnUnmappableCharacter() { 97 encoder = new MockCharsetEncoder(cs, 1, 3); 98 ((MockCharsetEncoder) encoder).pubImplOnUnmappableCharacter(null); 99 } 100 101 @TestTargets({ 102 @TestTargetNew( 103 level = TestLevel.PARTIAL, 104 notes = "onMalformedInput & onUnmappableCharacter requires check for IllegalArgumentException", 105 method = "malformedInputAction", 106 args = {} 107 ), 108 @TestTargetNew( 109 level = TestLevel.PARTIAL, 110 notes = "onMalformedInput & onUnmappableCharacter requires check for IllegalArgumentException", 111 method = "unmappableCharacterAction", 112 args = {} 113 ), 114 @TestTargetNew( 115 level = TestLevel.PARTIAL, 116 notes = "onMalformedInput & onUnmappableCharacter requires check for IllegalArgumentException", 117 method = "onMalformedInput", 118 args = {java.nio.charset.CodingErrorAction.class} 119 ), 120 @TestTargetNew( 121 level = TestLevel.PARTIAL, 122 notes = "onMalformedInput & onUnmappableCharacter requires check for IllegalArgumentException", 123 method = "onUnmappableCharacter", 124 args = {java.nio.charset.CodingErrorAction.class} 125 ), 126 @TestTargetNew( 127 level = TestLevel.PARTIAL, 128 notes = "onMalformedInput & onUnmappableCharacter requires check for IllegalArgumentException", 129 method = "replacement", 130 args = {} 131 ) 132 }) 133 public void testDefaultValue() { 134 assertEquals(CodingErrorAction.REPORT, encoder.malformedInputAction()); 135 assertEquals(CodingErrorAction.REPORT, encoder 136 .unmappableCharacterAction()); 137 assertSame(encoder, encoder.onMalformedInput(CodingErrorAction.IGNORE)); 138 assertSame(encoder, encoder 139 .onUnmappableCharacter(CodingErrorAction.IGNORE)); 140 if (encoder instanceof MockCharsetEncoder) { 141 assertTrue(Arrays.equals(encoder.replacement(), defaultReplacement)); 142 } else { 143 assertTrue(Arrays.equals(encoder.replacement(), 144 specifiedReplacement)); 145 } 146 147 } 148 149 150 @TestTargetNew( 151 level = TestLevel.COMPLETE, 152 notes = "", 153 method = "implReset", 154 args = {} 155 ) 156 public void testImplReset() { 157 encoder = new MockCharsetEncoder(cs, 1, 3); 158 ((MockCharsetEncoder) encoder).pubImplReset(); 159 } 160 161 162 @TestTargetNew( 163 level = TestLevel.COMPLETE, 164 notes = "", 165 method = "implFlush", 166 args = {ByteBuffer.class} 167 ) 168 public void testImplFlush() { 169 encoder = new MockCharsetEncoder(cs, 1, 3); 170 assertEquals(CoderResult.UNDERFLOW, ((MockCharsetEncoder) encoder) 171 .pubImplFlush(null)); 172 } 173 174 175 /* 176 * Class under test for constructor CharsetEncoder(Charset, float, float) 177 */ 178 @TestTargets({ 179 @TestTargetNew( 180 level = TestLevel.COMPLETE, 181 notes = "", 182 method = "charset", 183 args = {} 184 ), 185 @TestTargetNew( 186 level = TestLevel.COMPLETE, 187 notes = "", 188 method = "averageBytesPerChar", 189 args = {} 190 ), 191 @TestTargetNew( 192 level = TestLevel.COMPLETE, 193 notes = "", 194 method = "maxBytesPerChar", 195 args = {} 196 ), 197 @TestTargetNew( 198 level = TestLevel.COMPLETE, 199 notes = "", 200 method = "malformedInputAction", 201 args = {} 202 ), 203 @TestTargetNew( 204 level = TestLevel.COMPLETE, 205 notes = "", 206 method = "unmappableCharacterAction", 207 args = {} 208 ), 209 @TestTargetNew( 210 level = TestLevel.COMPLETE, 211 notes = "", 212 method = "CharsetEncoder", 213 args = {java.nio.charset.Charset.class, float.class, float.class} 214 ), 215 @TestTargetNew( 216 level = TestLevel.COMPLETE, 217 notes = "", 218 method = "replacement", 219 args = {} 220 ) 221 }) 222 public void testCharsetEncoderCharsetfloatfloat() { 223 // default value 224 encoder = new MockCharsetEncoder(cs, (float) AVER_BYTES, MAX_BYTES); 225 assertSame(encoder.charset(), cs); 226 assertTrue(encoder.averageBytesPerChar() == AVER_BYTES); 227 assertTrue(encoder.maxBytesPerChar() == MAX_BYTES); 228 assertEquals(CodingErrorAction.REPORT, encoder.malformedInputAction()); 229 assertEquals(CodingErrorAction.REPORT, encoder 230 .unmappableCharacterAction()); 231 assertEquals(new String(encoder.replacement()), new String( 232 defaultReplacement)); 233 assertSame(encoder, encoder.onMalformedInput(CodingErrorAction.IGNORE)); 234 assertSame(encoder, encoder 235 .onUnmappableCharacter(CodingErrorAction.IGNORE)); 236 237 // normal case 238 CharsetEncoder ec = new MockCharsetEncoder(cs, 1, MAX_BYTES); 239 assertSame(ec.charset(), cs); 240 assertEquals(1.0, ec.averageBytesPerChar(), 0); 241 assertTrue(ec.maxBytesPerChar() == MAX_BYTES); 242 243 /* 244 * ------------------------ Exceptional cases ------------------------- 245 */ 246 // NullPointerException: null charset 247 try { 248 ec = new MockCharsetEncoder(null, 1, MAX_BYTES); 249 fail("should throw null pointer exception"); 250 } catch (NullPointerException e) { 251 } 252 253 ec = new MockCharsetEncoder(new MockCharset("mock", new String[0]), 1, 254 MAX_BYTES); 255 256 // Commented out since the comment is wrong since MAX_BYTES > 1 257 // // OK: average length less than max length 258 // ec = new MockCharsetEncoder(cs, MAX_BYTES, 1); 259 // assertTrue(ec.averageBytesPerChar() == MAX_BYTES); 260 // assertTrue(ec.maxBytesPerChar() == 1); 261 262 // Illegal Argument: zero length 263 try { 264 ec = new MockCharsetEncoder(cs, 0, MAX_BYTES); 265 fail("should throw IllegalArgumentException"); 266 } catch (IllegalArgumentException e) { 267 } 268 try { 269 ec = new MockCharsetEncoder(cs, 1, 0); 270 fail("should throw IllegalArgumentException"); 271 } catch (IllegalArgumentException e) { 272 } 273 274 // Illegal Argument: negative length 275 try { 276 ec = new MockCharsetEncoder(cs, -1, MAX_BYTES); 277 fail("should throw IllegalArgumentException"); 278 } catch (IllegalArgumentException e) { 279 } 280 try { 281 ec = new MockCharsetEncoder(cs, 1, -1); 282 fail("should throw IllegalArgumentException"); 283 } catch (IllegalArgumentException e) { 284 } 285 } 286 287 /* 288 * Class under test for constructor CharsetEncoder(Charset, float, float, 289 * byte[]) 290 */ 291 @TestTargets({ 292 @TestTargetNew( 293 level = TestLevel.COMPLETE, 294 notes = "", 295 method = "CharsetEncoder", 296 args = {java.nio.charset.Charset.class, float.class, float.class, byte[].class} 297 ), 298 @TestTargetNew( 299 level = TestLevel.COMPLETE, 300 notes = "", 301 method = "charset", 302 args = {} 303 ), 304 @TestTargetNew( 305 level = TestLevel.COMPLETE, 306 notes = "", 307 method = "averageBytesPerChar", 308 args = {} 309 ), 310 @TestTargetNew( 311 level = TestLevel.COMPLETE, 312 notes = "", 313 method = "maxBytesPerChar", 314 args = {} 315 ), 316 @TestTargetNew( 317 level = TestLevel.COMPLETE, 318 notes = "", 319 method = "replacement", 320 args = {} 321 ) 322 }) 323 public void testCharsetEncoderCharsetfloatfloatbyteArray() { 324 byte[] ba = getLegalByteArray(); 325 // normal case 326 CharsetEncoder ec = new MockCharsetEncoder(cs, 1, MAX_BYTES, ba); 327 assertSame(ec.charset(), cs); 328 assertEquals(1.0, ec.averageBytesPerChar(), 0.0); 329 assertTrue(ec.maxBytesPerChar() == MAX_BYTES); 330 assertSame(ba, ec.replacement()); 331 332 /* 333 * ------------------------ Exceptional cases ------------------------- 334 */ 335 // NullPointerException: null charset 336 try { 337 ec = new MockCharsetEncoder(null, 1, MAX_BYTES, ba); 338 fail("should throw null pointer exception"); 339 } catch (NullPointerException e) { 340 } 341 342 // Illegal Argument: null byte array 343 try { 344 ec = new MockCharsetEncoder(cs, 1, MAX_BYTES, null); 345 fail("should throw IllegalArgumentException"); 346 } catch (IllegalArgumentException e) { 347 } 348 // Illegal Argument: empty byte array 349 try { 350 ec = new MockCharsetEncoder(cs, 1, MAX_BYTES, new byte[0]); 351 fail("should throw IllegalArgumentException"); 352 } catch (IllegalArgumentException e) { 353 } 354 // Illegal Argument: byte array is longer than max length 355 try { 356 ec = new MockCharsetEncoder(cs, 1, MAX_BYTES, new byte[] { 1, 2, 357 MAX_BYTES, 4 }); 358 fail("should throw IllegalArgumentException"); 359 } catch (IllegalArgumentException e) { 360 } 361 362 // Commented out since the comment is wrong since MAX_BYTES > 1 363 // This test throws IllegalArgumentException on Harmony and RI 364 // // OK: average length less than max length 365 // ec = new MockCharsetEncoder(cs, MAX_BYTES, ba.length, ba); 366 // assertTrue(ec.averageBytesPerChar() == MAX_BYTES); 367 // assertTrue(ec.maxBytesPerChar() == ba.length); 368 369 // Illegal Argument: zero length 370 try { 371 ec = new MockCharsetEncoder(cs, 0, MAX_BYTES, ba); 372 fail("should throw IllegalArgumentException"); 373 } catch (IllegalArgumentException e) { 374 } 375 try { 376 ec = new MockCharsetEncoder(cs, 1, 0, ba); 377 fail("should throw IllegalArgumentException"); 378 } catch (IllegalArgumentException e) { 379 } 380 381 // Illegal Argument: negative length 382 try { 383 ec = new MockCharsetEncoder(cs, -1, MAX_BYTES, ba); 384 fail("should throw IllegalArgumentException"); 385 } catch (IllegalArgumentException e) { 386 } 387 try { 388 ec = new MockCharsetEncoder(cs, 1, -1, ba); 389 fail("should throw IllegalArgumentException"); 390 } catch (IllegalArgumentException e) { 391 } 392 } 393 394 395 396 /* 397 * Class under test for Charset charset() 398 */ 399 @TestTargetNew( 400 level = TestLevel.PARTIAL, 401 notes = "", 402 method = "CharsetEncoder", 403 args = {java.nio.charset.Charset.class, float.class, float.class} 404 ) 405 public void testCharset() { 406 try { 407 encoder = new MockCharsetEncoder(Charset.forName("gbk"), 1, 408 MAX_BYTES); 409 // assertSame(encoder.charset(), Charset.forName("gbk")); 410 } catch (UnsupportedCharsetException e) { 411 // System.err 412 // .println("Don't support GBK encoding, ignore current test"); 413 } 414 } 415 416 417 boolean enCodeLoopCalled = false; 418 419 @TestTargetNew( 420 level = TestLevel.SUFFICIENT, 421 notes = "", 422 method = "encodeLoop", 423 args = { CharBuffer.class, ByteBuffer.class} 424 ) 425 public void testEncodeLoop() throws Exception { 426 try { 427 encoder = new MockCharsetEncoder(Charset.forName("US-ASCII"), 1, 428 MAX_BYTES) { 429 @Override 430 protected CoderResult encodeLoop(CharBuffer arg0, 431 ByteBuffer arg1) { 432 enCodeLoopCalled = true; 433 return super.encodeLoop(arg0, arg1); 434 } 435 }; 436 encoder.encode(CharBuffer.wrap("hallo")); 437 } catch (UnsupportedCharsetException e) { 438 fail("us-ascii not supported"); 439 } 440 assertTrue(enCodeLoopCalled); 441 } 442 443 444 @TestTargetNew( 445 level = TestLevel.COMPLETE, 446 notes = "", 447 method = "implReplaceWith", 448 args = { byte[].class} 449 ) 450 public void testImplReplaceWith() { 451 encoder = new MockCharsetEncoder(cs, 1, 3); 452 ((MockCharsetEncoder) encoder).pubImplReplaceWith(null); 453 } 454 455 456 457 protected byte[] getLegalByteArray() { 458 return new byte[] { 'a' }; 459 } 460 461 protected byte[] getIllegalByteArray() { 462 return new byte[155]; 463 } 464 465 /* 466 * Mock subclass of CharsetEncoder For protected method test 467 */ 468 public static class MockCharsetEncoder extends CharsetEncoder { 469 470 boolean flushed = false; 471 472 public boolean isFlushed() { 473 boolean result = flushed; 474 flushed = false; 475 return result; 476 } 477 478 public boolean isLegalReplacement(byte[] ba) { 479 if (ba.length == 155) {// specified magic number, return false 480 return false; 481 } 482 return super.isLegalReplacement(ba); 483 } 484 485 public MockCharsetEncoder(Charset cs, float aver, float max) { 486 super(cs, aver, max); 487 } 488 489 public MockCharsetEncoder(Charset cs, float aver, float max, 490 byte[] replacement) { 491 super(cs, aver, max, replacement); 492 } 493 494 protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) { 495 int inPosition = in.position(); 496 char[] input = new char[in.remaining()]; 497 in.get(input); 498 String result = new String(input); 499 if (result.startsWith("malform")) { 500 // reset the cursor to the error position 501 in.position(inPosition); 502 // in.position(0); 503 // set the error length 504 return CoderResult.malformedForLength("malform".length()); 505 } else if (result.startsWith("unmap")) { 506 // reset the cursor to the error position 507 in.position(inPosition); 508 // in.position(0); 509 // set the error length 510 return CoderResult.unmappableForLength("unmap".length()); 511 } else if (result.startsWith("runtime")) { 512 // reset the cursor to the error position 513 in.position(0); 514 // set the error length 515 throw new RuntimeException("runtime"); 516 } 517 int inLeft = input.length; 518 int outLeft = out.remaining(); 519 CoderResult r = CoderResult.UNDERFLOW; 520 int length = inLeft; 521 if (outLeft < inLeft) { 522 r = CoderResult.OVERFLOW; 523 length = outLeft; 524 in.position(inPosition + outLeft); 525 } 526 for (int i = 0; i < length; i++) { 527 out.put((byte) input[i]); 528 } 529 return r; 530 } 531 532 protected CoderResult implFlush(ByteBuffer out) { 533 CoderResult result = super.implFlush(out); 534 int length = 0; 535 if (out.remaining() >= 5) { 536 length = 5; 537 result = CoderResult.UNDERFLOW; 538 flushed = true; 539 // for (int i = 0; i < length; i++) { 540 // out.put((byte)'f'); 541 // } 542 } else { 543 length = out.remaining(); 544 result = CoderResult.OVERFLOW; 545 } 546 return result; 547 } 548 549 protected void implReplaceWith(byte[] ba) { 550 assertSame(ba, replacement()); 551 } 552 553 public void pubImplReplaceWith(byte[] newReplacement) { 554 super.implReplaceWith(newReplacement); 555 } 556 557 public CoderResult pubImplFlush(ByteBuffer out) { 558 return super.implFlush(out); 559 } 560 561 public void pubImplOnUnmappableCharacter(CodingErrorAction newAction) { 562 super.implOnUnmappableCharacter(newAction); 563 } 564 565 public void pubImplReset() { 566 super.implReset(); 567 } 568 569 } 570 571 /* 572 * mock charset for test encoder initialization 573 */ 574 public static class MockCharset extends Charset { 575 protected MockCharset(String arg0, String[] arg1) { 576 super(arg0, arg1); 577 } 578 579 public boolean contains(Charset arg0) { 580 return false; 581 } 582 583 public CharsetDecoder newDecoder() { 584 return new CharsetDecoderTest.MockCharsetDecoder(this, 585 (float) AVER_BYTES, MAX_BYTES); 586 } 587 588 public CharsetEncoder newEncoder() { 589 return new MockCharsetEncoder(this, (float) AVER_BYTES, MAX_BYTES); 590 } 591 } 592 593} 594