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 java.io.BufferedInputStream; 21import java.io.ByteArrayInputStream; 22import java.io.File; 23import java.io.FileInputStream; 24import java.io.FileOutputStream; 25import java.io.IOException; 26import java.io.InputStream; 27import java.io.InputStreamReader; 28import java.nio.charset.StandardCharsets; 29import junit.framework.TestCase; 30 31public class BufferedInputStreamTest extends TestCase { 32 33 private static final String INPUT = 34 "Test_All_Tests\n" + 35 "Test_BufferedInputStream\n" + 36 "Test_java_io_BufferedOutputStream\n" + 37 "Test_java_io_ByteArrayInputStream\n" + 38 "Test_java_io_ByteArrayOutputStream\n" + 39 "Test_java_io_DataInputStream\n" + 40 "Test_java_io_File\n" + 41 "Test_java_io_FileDescriptor\n" + 42 "Test_java_io_FileInputStream\n" + 43 "Test_java_io_FileNotFoundException\n" + 44 "Test_java_io_FileOutputStream\n" + 45 "Test_java_io_FilterInputStream\n" + 46 "Test_java_io_FilterOutputStream\n" + 47 "Test_java_io_InputStream\n" + 48 "Test_java_io_IOException\n" + 49 "Test_java_io_OutputStream\n" + 50 "Test_java_io_PrintStream\n" + 51 "Test_java_io_RandomAccessFile\n" + 52 "Test_java_io_SyncFailedException\n" + 53 "Test_java_lang_AbstractMethodError\n" + 54 "Test_java_lang_ArithmeticException\n" + 55 "Test_java_lang_ArrayIndexOutOfBoundsException\n" + 56 "Test_java_lang_ArrayStoreException\n" + 57 "Test_java_lang_Boolean\n" + 58 "Test_java_lang_Byte\n" + 59 "Test_java_lang_Character\n" + 60 "Test_All_Tests\n" + 61 "Test_BufferedInputStream\n" + 62 "Test_java_io_BufferedOutputStream\n" + 63 "Test_java_io_ByteArrayInputStream\n" + 64 "Test_java_io_ByteArrayOutputStream\n" + 65 "Test_java_io_DataInputStream\n" + 66 "Test_java_io_File\n" + 67 "Test_java_io_FileDescriptor\n" + 68 "Test_java_io_FileInputStream\n" + 69 "Test_java_io_FileNotFoundException\n" + 70 "Test_java_io_FileOutputStream\n" + 71 "Test_java_io_FilterInputStream\n" + 72 "Test_java_io_FilterOutputStream\n" + 73 "Test_java_io_InputStream\n" + 74 "Test_java_io_IOException\n" + 75 "Test_java_io_OutputStream\n" + 76 "Test_java_io_PrintStream\n" + 77 "Test_java_io_RandomAccessFile\n" + 78 "Test_java_io_SyncFailedException\n" + 79 "Test_java_lang_AbstractMethodError\n" + 80 "Test_java_lang_ArithmeticException\n" + 81 "Test_java_lang_ArrayIndexOutOfBoundsException\n" + 82 "Test_java_lang_ArrayStoreException\n" + 83 "Test_java_lang_Boolean\n" + 84 "Test_java_lang_Byte\n" + 85 "Test_java_lang_Character\n"; 86 87 private BufferedInputStream is; 88 private InputStream isBytes; 89 90 91 /* 92 * java.io.BufferedInputStream(InputStream) 93 */ 94 public void test_ConstructorLjava_io_InputStream() { 95 try { 96 BufferedInputStream str = new BufferedInputStream(null); 97 str.read(); 98 fail("Expected an IOException"); 99 } catch (IOException e) { 100 // Expected 101 } 102 } 103 104 /* 105 * java.io.BufferedInputStream(InputStream) 106 */ 107 public void test_ConstructorLjava_io_InputStreamI() throws IOException { 108 try { 109 BufferedInputStream str = new BufferedInputStream(null, 1); 110 str.read(); 111 fail("Expected an IOException"); 112 } catch (IOException e) { 113 // Expected 114 } 115 116 // Test for method java.io.BufferedInputStream(java.io.InputStream, int) 117 118 // Create buffer with hald size of file and fill it. 119 int bufferSize = INPUT.length() / 2; 120 is = new BufferedInputStream(isBytes, bufferSize); 121 // Ensure buffer gets filled by evaluating one read 122 is.read(); 123 // Close underlying FileInputStream, all but 1 buffered bytes should 124 // still be available. 125 isBytes.close(); 126 // Read the remaining buffered characters, no IOException should 127 // occur. 128 is.skip(bufferSize - 2); 129 is.read(); 130 try { 131 // is.read should now throw an exception because it will have to 132 // be filled. 133 is.read(); 134 fail("Exception should have been triggered by read()"); 135 } catch (IOException e) { 136 // Expected 137 } 138 139 // regression test for harmony-2407 140 new MockBufferedInputStream(null); 141 assertNotNull(MockBufferedInputStream.buf); 142 MockBufferedInputStream.buf = null; 143 new MockBufferedInputStream(null, 100); 144 assertNotNull(MockBufferedInputStream.buf); 145 } 146 147 static class MockBufferedInputStream extends BufferedInputStream { 148 static byte[] buf; 149 150 MockBufferedInputStream(InputStream is) throws IOException { 151 super(is); 152 buf = super.buf; 153 } 154 155 MockBufferedInputStream(InputStream is, int size) throws IOException { 156 super(is, size); 157 buf = super.buf; 158 } 159 } 160 161 /** 162 * java.io.BufferedInputStream#available() 163 */ 164 public void test_available() throws IOException { 165 assertTrue("Returned incorrect number of available bytes", is 166 .available() == INPUT.length()); 167 168 // Test that a closed stream throws an IOE for available() 169 BufferedInputStream bis = new BufferedInputStream( 170 new ByteArrayInputStream(new byte[] { 'h', 'e', 'l', 'l', 'o', 171 ' ', 't', 'i', 'm' })); 172 int available = bis.available(); 173 bis.close(); 174 assertTrue(available != 0); 175 176 try { 177 bis.available(); 178 fail("Expected test to throw IOE."); 179 } catch (IOException ex) { 180 // expected 181 } 182 } 183 184 /** 185 * java.io.BufferedInputStream#close() 186 */ 187 public void test_close() throws IOException { 188 new BufferedInputStream(isBytes).close(); 189 190 // regression for HARMONY-667 191 BufferedInputStream buf = new BufferedInputStream(null, 5); 192 buf.close(); 193 194 InputStream in = new InputStream() { 195 Object lock = new Object(); 196 197 @Override 198 public int read() { 199 return 1; 200 } 201 202 @Override 203 public int read(byte[] buf, int offset, int length) { 204 synchronized (lock) { 205 try { 206 lock.wait(3000); 207 } catch (InterruptedException e) { 208 // Ignore 209 } 210 } 211 return 1; 212 } 213 214 @Override 215 public void close() { 216 synchronized (lock) { 217 lock.notifyAll(); 218 } 219 } 220 }; 221 final BufferedInputStream bufin = new BufferedInputStream(in); 222 Thread thread = new Thread(new Runnable() { 223 public void run() { 224 try { 225 Thread.sleep(1000); 226 bufin.close(); 227 } catch (Exception e) { 228 // Ignored 229 } 230 } 231 }); 232 thread.start(); 233 try { 234 bufin.read(new byte[100], 0, 99); 235 fail("Should throw IOException"); 236 } catch (IOException e) { 237 // Expected 238 } 239 } 240 241 /** 242 * java.io.BufferedInputStream#mark(int) 243 */ 244 public void test_markI() throws IOException { 245 byte[] buf1 = new byte[100]; 246 byte[] buf2 = new byte[100]; 247 is.skip(50); 248 is.mark(500); 249 is.read(buf1, 0, buf1.length); 250 is.reset(); 251 is.read(buf2, 0, buf2.length); 252 is.reset(); 253 assertTrue("Failed to mark correct position", new String(buf1, 0, 254 buf1.length).equals(new String(buf2, 0, buf2.length))); 255 256 byte[] bytes = new byte[256]; 257 for (int i = 0; i < 256; i++) { 258 bytes[i] = (byte) i; 259 } 260 InputStream in = new BufferedInputStream( 261 new ByteArrayInputStream(bytes), 12); 262 in.skip(6); 263 in.mark(14); 264 in.read(new byte[14], 0, 14); 265 in.reset(); 266 assertTrue("Wrong bytes", in.read() == 6 && in.read() == 7); 267 268 in = new BufferedInputStream(new ByteArrayInputStream(bytes), 12); 269 in.skip(6); 270 in.mark(8); 271 in.skip(7); 272 in.reset(); 273 assertTrue("Wrong bytes 2", in.read() == 6 && in.read() == 7); 274 275 BufferedInputStream buf = new BufferedInputStream( 276 new ByteArrayInputStream(new byte[] { 0, 1, 2, 3, 4 }), 2); 277 buf.mark(3); 278 bytes = new byte[3]; 279 int result = buf.read(bytes); 280 assertEquals(3, result); 281 assertEquals("Assert 0:", 0, bytes[0]); 282 assertEquals("Assert 1:", 1, bytes[1]); 283 assertEquals("Assert 2:", 2, bytes[2]); 284 assertEquals("Assert 3:", 3, buf.read()); 285 286 buf = new BufferedInputStream(new ByteArrayInputStream(new byte[] { 0, 287 1, 2, 3, 4 }), 2); 288 buf.mark(3); 289 bytes = new byte[4]; 290 result = buf.read(bytes); 291 assertEquals(4, result); 292 assertEquals("Assert 4:", 0, bytes[0]); 293 assertEquals("Assert 5:", 1, bytes[1]); 294 assertEquals("Assert 6:", 2, bytes[2]); 295 assertEquals("Assert 7:", 3, bytes[3]); 296 assertEquals("Assert 8:", 4, buf.read()); 297 assertEquals("Assert 9:", -1, buf.read()); 298 299 buf = new BufferedInputStream(new ByteArrayInputStream(new byte[] { 0, 300 1, 2, 3, 4 }), 2); 301 buf.mark(Integer.MAX_VALUE); 302 buf.read(); 303 buf.close(); 304 } 305 306 /** 307 * java.io.BufferedInputStream#markSupported() 308 */ 309 public void test_markSupported() { 310 assertTrue("markSupported returned incorrect value", is.markSupported()); 311 } 312 313 /** 314 * java.io.BufferedInputStream#read() 315 */ 316 public void test_read() throws IOException { 317 InputStreamReader isr = new InputStreamReader(is); 318 int c = isr.read(); 319 assertEquals(INPUT.charAt(0), c); 320 321 byte[] bytes = new byte[256]; 322 for (int i = 0; i < 256; i++) { 323 bytes[i] = (byte) i; 324 } 325 InputStream in = new BufferedInputStream( 326 new ByteArrayInputStream(bytes), 12); 327 assertEquals("Wrong initial byte", 0, in.read()); // Fill the 328 // buffer 329 byte[] buf = new byte[14]; 330 in.read(buf, 0, 14); // Read greater than the buffer 331 assertTrue("Wrong block read data", new String(buf, 0, 14) 332 .equals(new String(bytes, 1, 14))); 333 assertEquals("Wrong bytes", 15, in.read()); // Check next byte 334 } 335 336 /** 337 * java.io.BufferedInputStream#read(byte[], int, int) 338 */ 339 public void test_read$BII_Exception() throws IOException { 340 BufferedInputStream bis = new BufferedInputStream(null); 341 try { 342 bis.read(null, -1, -1); 343 fail("should throw NullPointerException"); 344 } catch (NullPointerException e) { 345 // expected 346 } 347 348 try { 349 bis.read(new byte[0], -1, -1); 350 fail("should throw IndexOutOfBoundsException"); 351 } catch (IndexOutOfBoundsException e) { 352 // expected 353 } 354 355 try { 356 bis.read(new byte[0], 1, -1); 357 fail("should throw IndexOutOfBoundsException"); 358 } catch (IndexOutOfBoundsException e) { 359 // expected 360 } 361 362 try { 363 bis.read(new byte[0], 1, 1); 364 fail("should throw IndexOutOfBoundsException"); 365 } catch (IndexOutOfBoundsException e) { 366 // expected 367 } 368 369 bis.close(); 370 371 try { 372 bis.read(null, -1, -1); 373 fail("should throw IOException"); 374 } catch (IOException e) { 375 // expected 376 } 377 } 378 379 /** 380 * java.io.BufferedInputStream#read(byte[], int, int) 381 */ 382 public void test_read$BII() throws IOException { 383 byte[] buf1 = new byte[100]; 384 is.skip(500); 385 is.mark(500); 386 is.read(buf1, 0, buf1.length); 387 assertTrue("Failed to read correct data", new String(buf1, 0, 388 buf1.length).equals(INPUT.substring(500, 600))); 389 390 BufferedInputStream bufin = new BufferedInputStream(new InputStream() { 391 int size = 2 392 , 393 pos = 0; 394 395 byte[] contents = new byte[size]; 396 397 @Override 398 public int read() throws IOException { 399 if (pos >= size) { 400 throw new IOException("Read past end of data"); 401 } 402 return contents[pos++]; 403 } 404 405 @Override 406 public int read(byte[] buf, int off, int len) throws IOException { 407 if (pos >= size) { 408 throw new IOException("Read past end of data"); 409 } 410 int toRead = len; 411 if (toRead > available()) { 412 toRead = available(); 413 } 414 System.arraycopy(contents, pos, buf, off, toRead); 415 pos += toRead; 416 return toRead; 417 } 418 419 @Override 420 public int available() { 421 return size - pos; 422 } 423 }); 424 bufin.read(); 425 int result = bufin.read(new byte[2], 0, 2); 426 assertTrue("Incorrect result: " + result, result == 1); 427 } 428 429 /** 430 * java.io.BufferedInputStream#reset() 431 */ 432 public void test_reset() throws IOException { 433 byte[] buf1 = new byte[10]; 434 byte[] buf2 = new byte[10]; 435 is.mark(2000); 436 is.read(buf1, 0, 10); 437 is.reset(); 438 is.read(buf2, 0, 10); 439 is.reset(); 440 assertTrue("Reset failed", new String(buf1, 0, buf1.length) 441 .equals(new String(buf2, 0, buf2.length))); 442 443 BufferedInputStream bIn = new BufferedInputStream( 444 new ByteArrayInputStream("1234567890".getBytes())); 445 bIn.mark(10); 446 for (int i = 0; i < 11; i++) { 447 bIn.read(); 448 } 449 bIn.reset(); 450 } 451 452 /** 453 * java.io.BufferedInputStream#reset() 454 */ 455 public void test_reset_Exception() throws IOException { 456 BufferedInputStream bis = new BufferedInputStream(null); 457 458 // throws IOException with message "Mark has been invalidated" 459 try { 460 bis.reset(); 461 fail("should throw IOException"); 462 } catch (IOException e) { 463 // expected 464 } 465 466 // does not throw IOException 467 bis.mark(1); 468 bis.reset(); 469 470 bis.close(); 471 472 // throws IOException with message "stream is closed" 473 try { 474 bis.reset(); 475 fail("should throw IOException"); 476 } catch (IOException e) { 477 // expected 478 } 479 } 480 481 /** 482 * java.io.BufferedInputStream#reset() 483 */ 484 public void test_reset_scenario1() throws IOException { 485 byte[] input = "12345678900".getBytes(); 486 BufferedInputStream buffis = new BufferedInputStream( 487 new ByteArrayInputStream(input)); 488 buffis.read(); 489 buffis.mark(5); 490 buffis.skip(5); 491 buffis.reset(); 492 } 493 494 /** 495 * java.io.BufferedInputStream#reset() 496 */ 497 public void test_reset_scenario2() throws IOException { 498 byte[] input = "12345678900".getBytes(); 499 BufferedInputStream buffis = new BufferedInputStream( 500 new ByteArrayInputStream(input)); 501 buffis.mark(5); 502 buffis.skip(6); 503 buffis.reset(); 504 } 505 506 /** 507 * java.io.BufferedInputStream#skip(long) 508 */ 509 public void test_skipJ() throws IOException { 510 byte[] buf1 = new byte[10]; 511 is.mark(2000); 512 // This fails with OpenJdk. The first call to skip() will skip |bufferSize| 513 // bytes, and the second call will potentially resize the buffer. Users need 514 // to be aware. The API behaviour is correct, obviously, but it remains to 515 // be seen whether anybody blindly expects skip to always skip the number 516 // of bytes requested. 517 // 518 // assertEquals(1000, is.skip(1000)); 519 int bytesLeft = 1000; 520 while (bytesLeft > 0) { 521 bytesLeft -= is.skip(bytesLeft); 522 } 523 524 assertEquals(buf1.length, is.read(buf1, 0, buf1.length)); 525 is.reset(); 526 assertEquals("Failed to skip to correct position", new String(buf1, 0, 527 buf1.length), INPUT.substring(1000, 1010)); 528 529 // regression for HARMONY-667 530 try { 531 BufferedInputStream buf = new BufferedInputStream(null, 5); 532 buf.skip(10); 533 fail("Should throw IOException"); 534 } catch (IOException e) { 535 // Expected 536 } 537 } 538 539 /** 540 * java.io.BufferedInputStream#skip(long) 541 */ 542 public void test_skip_NullInputStream() throws IOException { 543 BufferedInputStream buf = new BufferedInputStream(null, 5); 544 assertEquals(0, buf.skip(0)); 545 } 546 547 /** 548 * Sets up the fixture, for example, open a network connection. This method 549 * is called before a test is executed. 550 */ 551 @Override 552 protected void setUp() throws IOException { 553 File f = File.createTempFile("BufferedInputStreamTest", "tst"); 554 FileOutputStream fos = new FileOutputStream(f); 555 fos.write(INPUT.getBytes(StandardCharsets.US_ASCII)); 556 fos.close(); 557 558 isBytes = new FileInputStream(f.getAbsolutePath()); 559 is = new BufferedInputStream(isBytes, INPUT.length() / 2); 560 } 561 562 /** 563 * Tears down the fixture, for example, close a network connection. This 564 * method is called after a test is executed. 565 */ 566 @Override 567 protected void tearDown() { 568 try { 569 is.close(); 570 } catch (Exception e) { 571 } 572 } 573} 574