1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package org.apache.harmony.tests.java.io; 19 20import junit.framework.TestCase; 21import java.io.ByteArrayInputStream; 22import java.io.ByteArrayOutputStream; 23import java.io.File; 24import java.io.FileInputStream; 25import java.io.FileReader; 26import java.io.FileWriter; 27import java.io.IOException; 28import java.io.InputStreamReader; 29import java.io.OutputStreamWriter; 30import java.io.UnsupportedEncodingException; 31import java.nio.charset.Charset; 32import java.nio.charset.CharsetEncoder; 33 34public class OutputStreamWriterTest extends TestCase { 35 36 private static final int UPPER = 0xd800; 37 38 private static final int BUFFER_SIZE = 10000; 39 40 private ByteArrayOutputStream out; 41 42 private OutputStreamWriter writer; 43 44 static private final String source = "This is a test message with Unicode character. \u4e2d\u56fd is China's name in Chinese"; 45 46 static private final String[] MINIMAL_CHARSETS = new String[] { "US-ASCII", 47 "ISO-8859-1", "UTF-16BE", "UTF-16LE", "UTF-16", "UTF-8" }; 48 49 OutputStreamWriter osw; 50 51 InputStreamReader isr; 52 53 private ByteArrayOutputStream fos; 54 55 String testString = "Test_All_Tests\nTest_java_io_BufferedInputStream\nTest_java_io_BufferedOutputStream\nTest_java_io_ByteArrayInputStream\nTest_java_io_ByteArrayOutputStream\nTest_java_io_DataInputStream\n"; 56 57 /* 58 * @see TestCase#setUp() 59 */ 60 @Override 61 protected void setUp() throws Exception { 62 super.setUp(); 63 out = new ByteArrayOutputStream(); 64 writer = new OutputStreamWriter(out, "utf-8"); 65 66 fos = new ByteArrayOutputStream(); 67 osw = new OutputStreamWriter(fos); 68 } 69 70 /* 71 * @see TestCase#tearDown() 72 */ 73 @Override 74 protected void tearDown() throws Exception { 75 try { 76 writer.close(); 77 78 if (isr != null) { 79 isr.close(); 80 } 81 osw.close(); 82 } catch (Exception e) { 83 // Ignored 84 } 85 86 super.tearDown(); 87 } 88 89 public void testClose() throws Exception { 90 writer.flush(); 91 writer.close(); 92 try { 93 writer.flush(); 94 fail(); 95 } catch (IOException e) { 96 // Expected 97 } 98 } 99 100 public void testFlush() throws Exception { 101 writer.write(source); 102 writer.flush(); 103 String result = out.toString("utf-8"); 104 assertEquals(source, result); 105 } 106 107 /* 108 * Class under test for void write(char[], int, int) 109 */ 110 public void testWritecharArrayintint() throws IOException { 111 char[] chars = source.toCharArray(); 112 113 // Throws IndexOutOfBoundsException if offset is negative 114 try { 115 writer.write((char[]) null, -1, -1); 116 fail(); 117 } catch (NullPointerException exception) { 118 } catch (IndexOutOfBoundsException exception) { 119 } 120 121 // throws NullPointerException though count is negative 122 try { 123 writer.write((char[]) null, 1, -1); 124 fail(); 125 } catch (NullPointerException exception) { 126 } catch (IndexOutOfBoundsException exception) { 127 } 128 129 try { 130 writer.write((char[]) null, 1, 1); 131 fail(); 132 } catch (NullPointerException e) { 133 // Expected 134 } 135 try { 136 writer.write(new char[0], 0, 1); 137 fail(); 138 } catch (IndexOutOfBoundsException e) { 139 // Expected 140 } 141 try { 142 writer.write(chars, -1, 1); 143 fail(); 144 } catch (IndexOutOfBoundsException e) { 145 // Expected 146 } 147 try { 148 writer.write(chars, 0, -1); 149 fail(); 150 } catch (IndexOutOfBoundsException e) { 151 // Expected 152 } 153 try { 154 writer.write(chars, 1, chars.length); 155 fail(); 156 } catch (IndexOutOfBoundsException e) { 157 // Expected 158 } 159 writer.write(chars, 1, 2); 160 writer.flush(); 161 assertEquals("hi", out.toString("utf-8")); 162 writer.write(chars, 0, chars.length); 163 writer.flush(); 164 assertEquals("hi" + source, out.toString("utf-8")); 165 166 writer.close(); 167 // After the stream is closed, should throw IOException first 168 try { 169 writer.write((char[]) null, -1, -1); 170 fail("should throw IOException"); 171 } catch (IOException e) { 172 // Expected 173 } 174 } 175 176 /* 177 * Class under test for void write(int) 178 */ 179 public void testWriteint() throws IOException { 180 writer.write(1); 181 writer.flush(); 182 String str = new String(out.toByteArray(), "utf-8"); 183 assertEquals("\u0001", str); 184 185 writer.write(2); 186 writer.flush(); 187 str = new String(out.toByteArray(), "utf-8"); 188 assertEquals("\u0001\u0002", str); 189 190 writer.write(-1); 191 writer.flush(); 192 str = new String(out.toByteArray(), "utf-8"); 193 assertEquals("\u0001\u0002\uffff", str); 194 195 writer.write(0xfedcb); 196 writer.flush(); 197 str = new String(out.toByteArray(), "utf-8"); 198 assertEquals("\u0001\u0002\uffff\uedcb", str); 199 200 writer.close(); 201 // After the stream is closed, should throw IOException 202 try { 203 writer.write(1); 204 fail("should throw IOException"); 205 } catch (IOException e) { 206 // expected 207 } 208 } 209 210 /* 211 * Class under test for void write(String, int, int) 212 */ 213 public void testWriteStringintint() throws IOException { 214 try { 215 writer.write((String) null, 1, 1); 216 fail(); 217 } catch (NullPointerException e) { 218 // Expected 219 } 220 try { 221 writer.write("", 0, 1); 222 fail(); 223 } catch (StringIndexOutOfBoundsException e) { 224 // Expected 225 } 226 try { 227 writer.write("abc", -1, 1); 228 fail(); 229 } catch (StringIndexOutOfBoundsException e) { 230 // Expected 231 } 232 try { 233 writer.write("abc", 0, -1); 234 fail(); 235 } catch (IndexOutOfBoundsException e) { 236 // Expected 237 } 238 try { 239 writer.write("abc", 1, 3); 240 fail(); 241 } catch (StringIndexOutOfBoundsException e) { 242 // Expected 243 } 244 245 try { 246 writer.write((String) null, -1, -1); 247 fail(); 248 } catch (NullPointerException expected) { 249 } catch (IndexOutOfBoundsException expected) { 250 } 251 252 // Throws NullPointerException before StringIndexOutOfBoundsException 253 try { 254 writer.write((String) null, -1, 0); 255 fail(); 256 } catch (NullPointerException expected) { 257 } catch (IndexOutOfBoundsException expected) { 258 } 259 260 writer.write("abc", 1, 2); 261 writer.flush(); 262 assertEquals("bc", out.toString("utf-8")); 263 writer.write(source, 0, source.length()); 264 writer.flush(); 265 assertEquals("bc" + source, out.toString("utf-8")); 266 267 writer.close(); 268 // Throws IndexOutOfBoundsException first if count is negative 269 try { 270 writer.write((String) null, 0, -1); 271 fail(); 272 } catch (NullPointerException expected) { 273 } catch (IndexOutOfBoundsException expected) { 274 } 275 276 try { 277 writer.write((String) null, -1, 0); 278 fail(); 279 } catch (NullPointerException expected) { 280 } catch (IndexOutOfBoundsException expected) { 281 } 282 283 try { 284 writer.write("abc", -1, 0); 285 fail("should throw StringIndexOutOfBoundsException"); 286 } catch (StringIndexOutOfBoundsException e) { 287 // Expected 288 } 289 290 // Throws IOException 291 try { 292 writer.write("abc", 0, 1); 293 fail("should throw IOException"); 294 } catch (IOException e) { 295 // expected 296 } 297 } 298 299 /* 300 * Class under test for void OutputStreamWriter(OutputStream) 301 */ 302 public void testOutputStreamWriterOutputStream() throws IOException { 303 try { 304 writer = new OutputStreamWriter(null); 305 fail(); 306 } catch (NullPointerException e) { 307 // Expected 308 } 309 OutputStreamWriter writer2 = new OutputStreamWriter(out); 310 writer2.close(); 311 } 312 313 /* 314 * Class under test for void OutputStreamWriter(OutputStream, String) 315 */ 316 public void testOutputStreamWriterOutputStreamString() throws IOException { 317 try { 318 writer = new OutputStreamWriter(null, "utf-8"); 319 fail(); 320 } catch (NullPointerException e) { 321 // Expected 322 } 323 try { 324 writer = new OutputStreamWriter(out, ""); 325 fail(); 326 } catch (UnsupportedEncodingException e) { 327 // Expected 328 } 329 try { 330 writer = new OutputStreamWriter(out, "badname"); 331 fail(); 332 } catch (UnsupportedEncodingException e) { 333 // Expected 334 } 335 try { 336 writer = new OutputStreamWriter(out, (String) null); 337 fail(); 338 } catch (NullPointerException e) { 339 // Expected 340 } 341 OutputStreamWriter writer2 = new OutputStreamWriter(out, "ascii"); 342 assertEquals(Charset.forName("ascii"), Charset.forName(writer2 343 .getEncoding())); 344 writer2.close(); 345 } 346 347 /* 348 * Class under test for void OutputStreamWriter(OutputStream) 349 */ 350 public void testOutputStreamWriterOutputStreamCharset() throws IOException { 351 Charset cs = Charset.forName("ascii"); 352 try { 353 writer = new OutputStreamWriter(null, cs); 354 fail(); 355 } catch (NullPointerException e) { 356 // Expected 357 } 358 try { 359 writer = new OutputStreamWriter(out, (Charset) null); 360 fail(); 361 } catch (NullPointerException e) { 362 // Expected 363 } 364 OutputStreamWriter writer2 = new OutputStreamWriter(out, cs); 365 assertEquals(cs, Charset.forName(writer2.getEncoding())); 366 writer2.close(); 367 } 368 369 /* 370 * Class under test for void OutputStreamWriter(OutputStream, String) 371 */ 372 public void testOutputStreamWriterOutputStreamCharsetEncoder() 373 throws IOException { 374 Charset cs = Charset.forName("ascii"); 375 CharsetEncoder enc = cs.newEncoder(); 376 try { 377 writer = new OutputStreamWriter(null, enc); 378 fail(); 379 } catch (NullPointerException e) { 380 // Expected 381 } 382 try { 383 writer = new OutputStreamWriter(out, (CharsetEncoder) null); 384 fail(); 385 } catch (NullPointerException e) { 386 // Expected 387 } 388 OutputStreamWriter writer2 = new OutputStreamWriter(out, enc); 389 assertEquals(cs, Charset.forName(writer2.getEncoding())); 390 writer2.close(); 391 } 392 393 public void testGetEncoding() { 394 Charset cs = Charset.forName("utf-8"); 395 assertEquals(cs, Charset.forName(writer.getEncoding())); 396 } 397 398 public void testHandleEarlyEOFChar_1() throws IOException { 399 String str = "All work and no play makes Jack a dull boy\n"; //$NON-NLS-1$ 400 int NUMBER = 2048; 401 int j = 0; 402 int len = str.length() * NUMBER; 403 char[] strChars = new char[len]; 404 for (int i = 0; i < NUMBER; ++i) { 405 for (int k = 0; k < str.length(); ++k) { 406 strChars[j++] = str.charAt(k); 407 } 408 } 409 410 File f = File.createTempFile("one", "by_one"); 411 f.deleteOnExit(); 412 FileWriter fw = new FileWriter(f); 413 fw.write(strChars); 414 fw.close(); 415 FileInputStream fis = new FileInputStream(f); 416 InputStreamReader in = new InputStreamReader(fis); 417 for (int offset = 0; offset < strChars.length; ++offset) { 418 int b = in.read(); 419 assertFalse("Early EOF at offset", -1 == b); 420 } 421 } 422 423 public void testHandleEarlyEOFChar_2() throws IOException { 424 int capacity = 65536; 425 byte[] bytes = new byte[capacity]; 426 byte[] bs = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' }; 427 for (int i = 0; i < bytes.length; i++) { 428 bytes[i] = bs[i / 8192]; 429 } 430 String inputStr = new String(bytes); 431 int len = inputStr.length(); 432 File f = File.createTempFile("FileWriterBugTest ", null); //$NON-NLS-1$ 433 f.deleteOnExit(); 434 FileWriter writer = new FileWriter(f); 435 writer.write(inputStr); 436 writer.close(); 437 long flen = f.length(); 438 439 FileReader reader = new FileReader(f); 440 char[] outChars = new char[capacity]; 441 int outCount = reader.read(outChars); 442 String outStr = new String(outChars, 0, outCount); 443 444 assertEquals(len, flen); 445 assertEquals(inputStr, outStr); 446 } 447 448 public void testSingleCharIO() throws Exception { 449 InputStreamReader isr = null; 450 for (int i = 0; i < MINIMAL_CHARSETS.length; ++i) { 451 try { 452 out = new ByteArrayOutputStream(); 453 writer = new OutputStreamWriter(out, MINIMAL_CHARSETS[i]); 454 455 int upper = UPPER; 456 switch (i) { 457 case 0: 458 upper = 128; 459 break; 460 case 1: 461 upper = 256; 462 break; 463 } 464 465 for (int c = 0; c < upper; ++c) { 466 writer.write(c); 467 } 468 writer.flush(); 469 byte[] result = out.toByteArray(); 470 471 isr = new InputStreamReader(new ByteArrayInputStream(result), 472 MINIMAL_CHARSETS[i]); 473 for (int expected = 0; expected < upper; ++expected) { 474 assertEquals("Error when reading bytes in " 475 + MINIMAL_CHARSETS[i], expected, isr.read()); 476 } 477 } finally { 478 try { 479 isr.close(); 480 } catch (Exception e) { 481 } 482 try { 483 writer.close(); 484 } catch (Exception e) { 485 } 486 } 487 } 488 } 489 490 public void testBlockIO() throws Exception { 491 InputStreamReader isr = null; 492 char[] largeBuffer = new char[BUFFER_SIZE]; 493 for (int i = 0; i < MINIMAL_CHARSETS.length; ++i) { 494 try { 495 out = new ByteArrayOutputStream(); 496 writer = new OutputStreamWriter(out, MINIMAL_CHARSETS[i]); 497 498 int upper = UPPER; 499 switch (i) { 500 case 0: 501 upper = 128; 502 break; 503 case 1: 504 upper = 256; 505 break; 506 } 507 508 int m = 0; 509 for (int c = 0; c < upper; ++c) { 510 largeBuffer[m++] = (char) c; 511 if (m == BUFFER_SIZE) { 512 writer.write(largeBuffer); 513 m = 0; 514 } 515 } 516 writer.write(largeBuffer, 0, m); 517 writer.flush(); 518 byte[] result = out.toByteArray(); 519 520 isr = new InputStreamReader(new ByteArrayInputStream(result), 521 MINIMAL_CHARSETS[i]); 522 int expected = 0, read = 0, j = 0; 523 while (expected < upper) { 524 if (j == read) { 525 read = isr.read(largeBuffer); 526 j = 0; 527 } 528 assertEquals("Error when reading bytes in " 529 + MINIMAL_CHARSETS[i], expected++, largeBuffer[j++]); 530 } 531 } finally { 532 try { 533 isr.close(); 534 } catch (Exception e) { 535 } 536 try { 537 writer.close(); 538 } catch (Exception e) { 539 } 540 } 541 } 542 } 543 544 /** 545 * java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream) 546 */ 547 public void test_ConstructorLjava_io_OutputStream() { 548 assertTrue("Used in tests", true); 549 } 550 551 /** 552 * java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream, 553 *java.lang.String) 554 */ 555 public void test_ConstructorLjava_io_OutputStreamLjava_lang_String() 556 throws UnsupportedEncodingException { 557 osw = new OutputStreamWriter(fos, "8859_1"); 558 try { 559 osw = new OutputStreamWriter(fos, "Bogus"); 560 fail("Failed to throw Unsupported Encoding exception"); 561 } catch (UnsupportedEncodingException e) { 562 // Expected 563 } 564 } 565 566 /** 567 * java.io.OutputStreamWriter#close() 568 */ 569 public void test_close() throws IOException { 570 osw.close(); 571 572 try { 573 osw.write(testString, 0, testString.length()); 574 fail("Chars written after close"); 575 } catch (IOException e) { 576 // Expected 577 } 578 579 ByteArrayOutputStream bout = new ByteArrayOutputStream(); 580 try { 581 OutputStreamWriter writer = new OutputStreamWriter(bout, 582 "ISO2022JP"); 583 writer.write(new char[] { 'a' }); 584 writer.close(); 585 // the default is ASCII, there should not be any mode changes 586 String converted = new String(bout.toByteArray(), "ISO8859_1"); 587 assertTrue("invalid conversion 1: " + converted, converted 588 .equals("a")); 589 590 bout.reset(); 591 writer = new OutputStreamWriter(bout, "ISO2022JP"); 592 writer.write(new char[] { '\u3048' }); 593 writer.flush(); 594 // the byte sequence should not switch to ASCII mode until the 595 // stream is closed 596 converted = new String(bout.toByteArray(), "ISO8859_1"); 597 assertTrue("invalid conversion 2: " + converted, converted 598 .equals("\u001b$B$(")); 599 writer.close(); 600 converted = new String(bout.toByteArray(), "ISO8859_1"); 601 assertTrue("invalid conversion 3: " + converted, converted 602 .equals("\u001b$B$(\u001b(B")); 603 604 bout.reset(); 605 writer = new OutputStreamWriter(bout, "ISO2022JP"); 606 writer.write(new char[] { '\u3048' }); 607 writer.write(new char[] { '\u3048' }); 608 writer.close(); 609 // there should not be a mode switch between writes 610 assertEquals("invalid conversion 4", "\u001b$B$($(\u001b(B", 611 new String(bout.toByteArray(), "ISO8859_1")); 612 } catch (UnsupportedEncodingException e) { 613 // Can't test missing converter 614 System.out.println(e); 615 } 616 } 617 618 /** 619 * java.io.OutputStreamWriter#flush() 620 */ 621 public void test_flush() throws IOException { 622 char[] buf = new char[testString.length()]; 623 osw.write(testString, 0, testString.length()); 624 osw.flush(); 625 openInputStream(); 626 isr.read(buf, 0, buf.length); 627 assertTrue("Chars not flushed", new String(buf, 0, buf.length) 628 .equals(testString)); 629 } 630 631 /** 632 * Unlike the RI, we return the canonical encoding name and not something 633 * java specific. 634 */ 635 public void test_getEncoding() throws IOException { 636 try { 637 osw = new OutputStreamWriter(fos, "8859_1"); 638 } catch (UnsupportedEncodingException e) { 639 assertEquals("Returned incorrect encoding", "8859_1", osw 640 .getEncoding()); 641 } 642 643 OutputStreamWriter out = new OutputStreamWriter( 644 new ByteArrayOutputStream(), "UTF-16BE"); 645 out.close(); 646 647 String result = out.getEncoding(); 648 assertNull(result); 649 650 out = null; 651 try { 652 out = new OutputStreamWriter(new ByteArrayOutputStream(), 653 "UTF-16BE"); 654 } catch (UnsupportedEncodingException e) { 655 // ok 656 } 657 result = out.getEncoding(); 658 assertEquals("UTF-16BE", result); 659 } 660 661 /** 662 * java.io.OutputStreamWriter#write(char[], int, int) 663 */ 664 public void test_write$CII() throws IOException { 665 char[] buf = new char[testString.length()]; 666 osw.write(testString, 0, testString.length()); 667 osw.close(); 668 openInputStream(); 669 isr.read(buf, 0, buf.length); 670 assertTrue("Incorrect chars returned", new String(buf, 0, buf.length) 671 .equals(testString)); 672 } 673 674 /** 675 * java.io.OutputStreamWriter#write(int) 676 */ 677 public void test_writeI() throws IOException { 678 osw.write('T'); 679 osw.close(); 680 openInputStream(); 681 int c = isr.read(); 682 assertEquals("Incorrect char returned", 'T', (char) c); 683 } 684 685 /** 686 * java.io.OutputStreamWriter#write(java.lang.String, int, int) 687 */ 688 public void test_writeLjava_lang_StringII() throws IOException { 689 char[] buf = new char[testString.length()]; 690 osw.write(testString, 0, testString.length()); 691 osw.close(); 692 openInputStream(); 693 isr.read(buf); 694 assertTrue("Incorrect chars returned", new String(buf, 0, buf.length) 695 .equals(testString)); 696 } 697 698 private void openInputStream() { 699 isr = new InputStreamReader(new ByteArrayInputStream(fos.toByteArray())); 700 } 701} 702