1 /* 2 * Copyright (C) 2007 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * 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 17 package com.google.common.io; 18 19 import com.google.common.base.Charsets; 20 21 import java.io.ByteArrayInputStream; 22 import java.io.ByteArrayOutputStream; 23 import java.io.EOFException; 24 import java.io.FilterInputStream; 25 import java.io.IOException; 26 import java.io.InputStream; 27 import java.io.OutputStream; 28 import java.nio.channels.Channels; 29 import java.nio.channels.ReadableByteChannel; 30 import java.nio.channels.WritableByteChannel; 31 import java.util.Arrays; 32 33 /** 34 * Unit test for {@link ByteStreams}. 35 * 36 * @author Chris Nokleberg 37 */ 38 public class ByteStreamsTest extends IoTestCase { 39 testCopyChannel()40 public void testCopyChannel() throws IOException { 41 byte[] expected = newPreFilledByteArray(100); 42 ByteArrayOutputStream out = new ByteArrayOutputStream(); 43 WritableByteChannel outChannel = Channels.newChannel(out); 44 45 ReadableByteChannel inChannel = 46 Channels.newChannel(new ByteArrayInputStream(expected)); 47 ByteStreams.copy(inChannel, outChannel); 48 assertEquals(expected, out.toByteArray()); 49 } 50 testReadFully()51 public void testReadFully() throws IOException { 52 byte[] b = new byte[10]; 53 54 try { 55 ByteStreams.readFully(newTestStream(10), null, 0, 10); 56 fail("expected exception"); 57 } catch (NullPointerException e) { 58 } 59 60 try { 61 ByteStreams.readFully(null, b, 0, 10); 62 fail("expected exception"); 63 } catch (NullPointerException e) { 64 } 65 66 try { 67 ByteStreams.readFully(newTestStream(10), b, -1, 10); 68 fail("expected exception"); 69 } catch (IndexOutOfBoundsException e) { 70 } 71 72 try { 73 ByteStreams.readFully(newTestStream(10), b, 0, -1); 74 fail("expected exception"); 75 } catch (IndexOutOfBoundsException e) { 76 } 77 78 try { 79 ByteStreams.readFully(newTestStream(10), b, 0, -1); 80 fail("expected exception"); 81 } catch (IndexOutOfBoundsException e) { 82 } 83 84 try { 85 ByteStreams.readFully(newTestStream(10), b, 2, 10); 86 fail("expected exception"); 87 } catch (IndexOutOfBoundsException e) { 88 } 89 90 try { 91 ByteStreams.readFully(newTestStream(5), b, 0, 10); 92 fail("expected exception"); 93 } catch (EOFException e) { 94 } 95 96 Arrays.fill(b, (byte) 0); 97 ByteStreams.readFully(newTestStream(10), b, 0, 0); 98 assertEquals(new byte[10], b); 99 100 Arrays.fill(b, (byte) 0); 101 ByteStreams.readFully(newTestStream(10), b, 0, 10); 102 assertEquals(newPreFilledByteArray(10), b); 103 104 Arrays.fill(b, (byte) 0); 105 ByteStreams.readFully(newTestStream(10), b, 0, 5); 106 assertEquals(new byte[]{0, 1, 2, 3, 4, 0, 0, 0, 0, 0}, b); 107 } 108 testSkipFully()109 public void testSkipFully() throws IOException { 110 byte[] bytes = newPreFilledByteArray(100); 111 skipHelper(0, 0, new ByteArrayInputStream(bytes)); 112 skipHelper(50, 50, new ByteArrayInputStream(bytes)); 113 skipHelper(50, 50, new SlowSkipper(new ByteArrayInputStream(bytes), 1)); 114 skipHelper(50, 50, new SlowSkipper(new ByteArrayInputStream(bytes), 0)); 115 skipHelper(100, -1, new ByteArrayInputStream(bytes)); 116 try { 117 skipHelper(101, 0, new ByteArrayInputStream(bytes)); 118 fail("expected exception"); 119 } catch (EOFException e) { 120 } 121 } 122 skipHelper(long n, int expect, InputStream in)123 private static void skipHelper(long n, int expect, InputStream in) 124 throws IOException { 125 ByteStreams.skipFully(in, n); 126 assertEquals(expect, in.read()); 127 in.close(); 128 } 129 130 private static final byte[] bytes = 131 new byte[] { 0x12, 0x34, 0x56, 0x78, 0x76, 0x54, 0x32, 0x10 }; 132 testNewDataInput_empty()133 public void testNewDataInput_empty() { 134 byte[] b = new byte[0]; 135 ByteArrayDataInput in = ByteStreams.newDataInput(b); 136 try { 137 in.readInt(); 138 fail("expected exception"); 139 } catch (IllegalStateException expected) { 140 } 141 } 142 testNewDataInput_normal()143 public void testNewDataInput_normal() { 144 ByteArrayDataInput in = ByteStreams.newDataInput(bytes); 145 assertEquals(0x12345678, in.readInt()); 146 assertEquals(0x76543210, in.readInt()); 147 try { 148 in.readInt(); 149 fail("expected exception"); 150 } catch (IllegalStateException expected) { 151 } 152 } 153 testNewDataInput_readFully()154 public void testNewDataInput_readFully() { 155 ByteArrayDataInput in = ByteStreams.newDataInput(bytes); 156 byte[] actual = new byte[bytes.length]; 157 in.readFully(actual); 158 assertEquals(bytes, actual); 159 } 160 testNewDataInput_readFullyAndThenSome()161 public void testNewDataInput_readFullyAndThenSome() { 162 ByteArrayDataInput in = ByteStreams.newDataInput(bytes); 163 byte[] actual = new byte[bytes.length * 2]; 164 try { 165 in.readFully(actual); 166 fail("expected exception"); 167 } catch (IllegalStateException ex) { 168 assertTrue(ex.getCause() instanceof EOFException); 169 } 170 } 171 testNewDataInput_readFullyWithOffset()172 public void testNewDataInput_readFullyWithOffset() { 173 ByteArrayDataInput in = ByteStreams.newDataInput(bytes); 174 byte[] actual = new byte[4]; 175 in.readFully(actual, 2, 2); 176 assertEquals(0, actual[0]); 177 assertEquals(0, actual[1]); 178 assertEquals(bytes[0], actual[2]); 179 assertEquals(bytes[1], actual[3]); 180 } 181 testNewDataInput_readLine()182 public void testNewDataInput_readLine() { 183 ByteArrayDataInput in = ByteStreams.newDataInput( 184 "This is a line\r\nThis too\rand this\nand also this".getBytes(Charsets.UTF_8)); 185 assertEquals("This is a line", in.readLine()); 186 assertEquals("This too", in.readLine()); 187 assertEquals("and this", in.readLine()); 188 assertEquals("and also this", in.readLine()); 189 } 190 testNewDataInput_readFloat()191 public void testNewDataInput_readFloat() { 192 byte[] data = {0x12, 0x34, 0x56, 0x78, 0x76, 0x54, 0x32, 0x10}; 193 ByteArrayDataInput in = ByteStreams.newDataInput(data); 194 assertEquals(Float.intBitsToFloat(0x12345678), in.readFloat(), 0.0); 195 assertEquals(Float.intBitsToFloat(0x76543210), in.readFloat(), 0.0); 196 } 197 testNewDataInput_readDouble()198 public void testNewDataInput_readDouble() { 199 byte[] data = {0x12, 0x34, 0x56, 0x78, 0x76, 0x54, 0x32, 0x10}; 200 ByteArrayDataInput in = ByteStreams.newDataInput(data); 201 assertEquals(Double.longBitsToDouble(0x1234567876543210L), in.readDouble(), 0.0); 202 } 203 testNewDataInput_readUTF()204 public void testNewDataInput_readUTF() { 205 byte[] data = new byte[17]; 206 data[1] = 15; 207 System.arraycopy("Kilroy was here".getBytes(Charsets.UTF_8), 0, data, 2, 15); 208 ByteArrayDataInput in = ByteStreams.newDataInput(data); 209 assertEquals("Kilroy was here", in.readUTF()); 210 } 211 testNewDataInput_readChar()212 public void testNewDataInput_readChar() { 213 byte[] data = "qed".getBytes(Charsets.UTF_16BE); 214 ByteArrayDataInput in = ByteStreams.newDataInput(data); 215 assertEquals('q', in.readChar()); 216 assertEquals('e', in.readChar()); 217 assertEquals('d', in.readChar()); 218 } 219 testNewDataInput_readUnsignedShort()220 public void testNewDataInput_readUnsignedShort() { 221 byte[] data = {0, 0, 0, 1, (byte) 0xFF, (byte) 0xFF, 0x12, 0x34}; 222 ByteArrayDataInput in = ByteStreams.newDataInput(data); 223 assertEquals(0, in.readUnsignedShort()); 224 assertEquals(1, in.readUnsignedShort()); 225 assertEquals(65535, in.readUnsignedShort()); 226 assertEquals(0x1234, in.readUnsignedShort()); 227 } 228 testNewDataInput_readLong()229 public void testNewDataInput_readLong() { 230 byte[] data = {0x12, 0x34, 0x56, 0x78, 0x76, 0x54, 0x32, 0x10}; 231 ByteArrayDataInput in = ByteStreams.newDataInput(data); 232 assertEquals(0x1234567876543210L, in.readLong()); 233 } 234 testNewDataInput_readBoolean()235 public void testNewDataInput_readBoolean() { 236 ByteArrayDataInput in = ByteStreams.newDataInput(bytes); 237 assertTrue(in.readBoolean()); 238 } 239 testNewDataInput_readByte()240 public void testNewDataInput_readByte() { 241 ByteArrayDataInput in = ByteStreams.newDataInput(bytes); 242 for (int i = 0; i < bytes.length; i++) { 243 assertEquals(bytes[i], in.readByte()); 244 } 245 try { 246 in.readByte(); 247 fail("expected exception"); 248 } catch (IllegalStateException ex) { 249 assertTrue(ex.getCause() instanceof EOFException); 250 } 251 } 252 testNewDataInput_readUnsignedByte()253 public void testNewDataInput_readUnsignedByte() { 254 ByteArrayDataInput in = ByteStreams.newDataInput(bytes); 255 for (int i = 0; i < bytes.length; i++) { 256 assertEquals(bytes[i], in.readUnsignedByte()); 257 } 258 try { 259 in.readUnsignedByte(); 260 fail("expected exception"); 261 } catch (IllegalStateException ex) { 262 assertTrue(ex.getCause() instanceof EOFException); 263 } 264 } 265 testNewDataInput_offset()266 public void testNewDataInput_offset() { 267 ByteArrayDataInput in = ByteStreams.newDataInput(bytes, 2); 268 assertEquals(0x56787654, in.readInt()); 269 try { 270 in.readInt(); 271 fail("expected exception"); 272 } catch (IllegalStateException expected) { 273 } 274 } 275 testNewDataInput_skip()276 public void testNewDataInput_skip() { 277 ByteArrayDataInput in = ByteStreams.newDataInput(new byte[2]); 278 assertEquals(2, in.skipBytes(2)); 279 assertEquals(0, in.skipBytes(1)); 280 } 281 testNewDataInput_BAIS()282 public void testNewDataInput_BAIS() { 283 ByteArrayInputStream bais = new ByteArrayInputStream(new byte[] {0x12, 0x34, 0x56, 0x78}); 284 ByteArrayDataInput in = ByteStreams.newDataInput(bais); 285 assertEquals(0x12345678, in.readInt()); 286 } 287 testNewDataOutput_empty()288 public void testNewDataOutput_empty() { 289 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 290 assertEquals(0, out.toByteArray().length); 291 } 292 testNewDataOutput_writeInt()293 public void testNewDataOutput_writeInt() { 294 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 295 out.writeInt(0x12345678); 296 out.writeInt(0x76543210); 297 assertEquals(bytes, out.toByteArray()); 298 } 299 testNewDataOutput_sized()300 public void testNewDataOutput_sized() { 301 ByteArrayDataOutput out = ByteStreams.newDataOutput(4); 302 out.writeInt(0x12345678); 303 out.writeInt(0x76543210); 304 assertEquals(bytes, out.toByteArray()); 305 } 306 testNewDataOutput_writeLong()307 public void testNewDataOutput_writeLong() { 308 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 309 out.writeLong(0x1234567876543210L); 310 assertEquals(bytes, out.toByteArray()); 311 } 312 testNewDataOutput_writeByteArray()313 public void testNewDataOutput_writeByteArray() { 314 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 315 out.write(bytes); 316 assertEquals(bytes, out.toByteArray()); 317 } 318 testNewDataOutput_writeByte()319 public void testNewDataOutput_writeByte() { 320 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 321 out.write(0x12); 322 out.writeByte(0x34); 323 assertEquals(new byte[] {0x12, 0x34}, out.toByteArray()); 324 } 325 testNewDataOutput_writeByteOffset()326 public void testNewDataOutput_writeByteOffset() { 327 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 328 out.write(bytes, 4, 2); 329 byte[] expected = {bytes[4], bytes[5]}; 330 assertEquals(expected, out.toByteArray()); 331 } 332 testNewDataOutput_writeBoolean()333 public void testNewDataOutput_writeBoolean() { 334 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 335 out.writeBoolean(true); 336 out.writeBoolean(false); 337 byte[] expected = {(byte) 1, (byte) 0}; 338 assertEquals(expected, out.toByteArray()); 339 } 340 testNewDataOutput_writeChar()341 public void testNewDataOutput_writeChar() { 342 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 343 out.writeChar('a'); 344 assertEquals(new byte[] {0, 97}, out.toByteArray()); 345 } 346 testNewDataOutput_writeChars()347 public void testNewDataOutput_writeChars() { 348 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 349 out.writeChars("r\u00C9sum\u00C9"); 350 // need to remove byte order mark before comparing 351 byte[] expected = Arrays.copyOfRange("r\u00C9sum\u00C9".getBytes(Charsets.UTF_16), 2, 14); 352 assertEquals(expected, out.toByteArray()); 353 } 354 testNewDataOutput_writeUTF()355 public void testNewDataOutput_writeUTF() { 356 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 357 out.writeUTF("r\u00C9sum\u00C9"); 358 byte[] expected ="r\u00C9sum\u00C9".getBytes(Charsets.UTF_8); 359 byte[] actual = out.toByteArray(); 360 // writeUTF writes the length of the string in 2 bytes 361 assertEquals(0, actual[0]); 362 assertEquals(expected.length, actual[1]); 363 assertEquals(expected, Arrays.copyOfRange(actual, 2, actual.length)); 364 } 365 testNewDataOutput_writeShort()366 public void testNewDataOutput_writeShort() { 367 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 368 out.writeShort(0x1234); 369 assertEquals(new byte[] {0x12, 0x34}, out.toByteArray()); 370 } 371 testNewDataOutput_writeDouble()372 public void testNewDataOutput_writeDouble() { 373 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 374 out.writeDouble(Double.longBitsToDouble(0x1234567876543210L)); 375 assertEquals(bytes, out.toByteArray()); 376 } 377 testNewDataOutput_writeFloat()378 public void testNewDataOutput_writeFloat() { 379 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 380 out.writeFloat(Float.intBitsToFloat(0x12345678)); 381 out.writeFloat(Float.intBitsToFloat(0x76543210)); 382 assertEquals(bytes, out.toByteArray()); 383 } 384 testNewDataOutput_BAOS()385 public void testNewDataOutput_BAOS() { 386 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 387 ByteArrayDataOutput out = ByteStreams.newDataOutput(baos); 388 out.writeInt(0x12345678); 389 assertEquals(4, baos.size()); 390 assertEquals(new byte[] {0x12, 0x34, 0x56, 0x78}, baos.toByteArray()); 391 } 392 testToByteArray_withSize_givenCorrectSize()393 public void testToByteArray_withSize_givenCorrectSize() throws IOException { 394 InputStream in = newTestStream(100); 395 byte[] b = ByteStreams.toByteArray(in, 100); 396 assertEquals(100, b.length); 397 } 398 testToByteArray_withSize_givenSmallerSize()399 public void testToByteArray_withSize_givenSmallerSize() throws IOException { 400 InputStream in = newTestStream(100); 401 byte[] b = ByteStreams.toByteArray(in, 80); 402 assertEquals(100, b.length); 403 } 404 testToByteArray_withSize_givenLargerSize()405 public void testToByteArray_withSize_givenLargerSize() throws IOException { 406 InputStream in = newTestStream(100); 407 byte[] b = ByteStreams.toByteArray(in, 120); 408 assertEquals(100, b.length); 409 } 410 testToByteArray_withSize_givenSizeZero()411 public void testToByteArray_withSize_givenSizeZero() throws IOException { 412 InputStream in = newTestStream(100); 413 byte[] b = ByteStreams.toByteArray(in, 0); 414 assertEquals(100, b.length); 415 } 416 newTestStream(int n)417 private static InputStream newTestStream(int n) { 418 return new ByteArrayInputStream(newPreFilledByteArray(n)); 419 } 420 421 /** Stream that will skip a maximum number of bytes at a time. */ 422 private static class SlowSkipper extends FilterInputStream { 423 private final long max; 424 SlowSkipper(InputStream in, long max)425 public SlowSkipper(InputStream in, long max) { 426 super(in); 427 this.max = max; 428 } 429 skip(long n)430 @Override public long skip(long n) throws IOException { 431 return super.skip(Math.min(max, n)); 432 } 433 } 434 testReadBytes()435 public void testReadBytes() throws IOException { 436 final byte[] array = newPreFilledByteArray(1000); 437 assertEquals(array, ByteStreams.readBytes( 438 new ByteArrayInputStream(array), new TestByteProcessor())); 439 } 440 441 private class TestByteProcessor implements ByteProcessor<byte[]> { 442 private final ByteArrayOutputStream out = new ByteArrayOutputStream(); 443 444 @Override processBytes(byte[] buf, int off, int len)445 public boolean processBytes(byte[] buf, int off, int len) 446 throws IOException { 447 out.write(buf, off, len); 448 return true; 449 } 450 451 @Override getResult()452 public byte[] getResult() { 453 return out.toByteArray(); 454 } 455 } 456 testByteProcessorStopEarly()457 public void testByteProcessorStopEarly() throws IOException { 458 byte[] array = newPreFilledByteArray(6000); 459 assertEquals((Integer) 42, 460 ByteStreams.readBytes(new ByteArrayInputStream(array), 461 new ByteProcessor<Integer>() { 462 @Override 463 public boolean processBytes(byte[] buf, int off, int len) { 464 assertEquals( 465 copyOfRange(buf, off, off + len), 466 newPreFilledByteArray(4096)); 467 return false; 468 } 469 470 @Override 471 public Integer getResult() { 472 return 42; 473 } 474 })); 475 } 476 testNullOutputStream()477 public void testNullOutputStream() throws Exception { 478 // create a null output stream 479 OutputStream nos = ByteStreams.nullOutputStream(); 480 // write to the output stream 481 nos.write('n'); 482 String test = "Test string for NullOutputStream"; 483 nos.write(test.getBytes()); 484 nos.write(test.getBytes(), 2, 10); 485 // nothing really to assert? 486 assertSame(ByteStreams.nullOutputStream(), ByteStreams.nullOutputStream()); 487 } 488 testLimit()489 public void testLimit() throws Exception { 490 byte[] big = newPreFilledByteArray(5); 491 InputStream bin = new ByteArrayInputStream(big); 492 InputStream lin = ByteStreams.limit(bin, 2); 493 494 // also test available 495 lin.mark(2); 496 assertEquals(2, lin.available()); 497 int read = lin.read(); 498 assertEquals(big[0], read); 499 assertEquals(1, lin.available()); 500 read = lin.read(); 501 assertEquals(big[1], read); 502 assertEquals(0, lin.available()); 503 read = lin.read(); 504 assertEquals(-1, read); 505 506 lin.reset(); 507 byte[] small = new byte[5]; 508 read = lin.read(small); 509 assertEquals(2, read); 510 assertEquals(big[0], small[0]); 511 assertEquals(big[1], small[1]); 512 513 lin.reset(); 514 read = lin.read(small, 2, 3); 515 assertEquals(2, read); 516 assertEquals(big[0], small[2]); 517 assertEquals(big[1], small[3]); 518 } 519 testLimit_mark()520 public void testLimit_mark() throws Exception { 521 byte[] big = newPreFilledByteArray(5); 522 InputStream bin = new ByteArrayInputStream(big); 523 InputStream lin = ByteStreams.limit(bin, 2); 524 525 int read = lin.read(); 526 assertEquals(big[0], read); 527 lin.mark(2); 528 529 read = lin.read(); 530 assertEquals(big[1], read); 531 read = lin.read(); 532 assertEquals(-1, read); 533 534 lin.reset(); 535 read = lin.read(); 536 assertEquals(big[1], read); 537 read = lin.read(); 538 assertEquals(-1, read); 539 } 540 testLimit_skip()541 public void testLimit_skip() throws Exception { 542 byte[] big = newPreFilledByteArray(5); 543 InputStream bin = new ByteArrayInputStream(big); 544 InputStream lin = ByteStreams.limit(bin, 2); 545 546 // also test available 547 lin.mark(2); 548 assertEquals(2, lin.available()); 549 lin.skip(1); 550 assertEquals(1, lin.available()); 551 552 lin.reset(); 553 assertEquals(2, lin.available()); 554 lin.skip(3); 555 assertEquals(0, lin.available()); 556 } 557 testLimit_markNotSet()558 public void testLimit_markNotSet() { 559 byte[] big = newPreFilledByteArray(5); 560 InputStream bin = new ByteArrayInputStream(big); 561 InputStream lin = ByteStreams.limit(bin, 2); 562 563 try { 564 lin.reset(); 565 fail(); 566 } catch (IOException expected) { 567 assertEquals("Mark not set", expected.getMessage()); 568 } 569 } 570 testLimit_markNotSupported()571 public void testLimit_markNotSupported() { 572 InputStream lin = ByteStreams.limit(new UnmarkableInputStream(), 2); 573 574 try { 575 lin.reset(); 576 fail(); 577 } catch (IOException expected) { 578 assertEquals("Mark not supported", expected.getMessage()); 579 } 580 } 581 582 private static class UnmarkableInputStream extends InputStream { 583 @Override read()584 public int read() throws IOException { 585 return 0; 586 } 587 588 @Override markSupported()589 public boolean markSupported() { 590 return false; 591 } 592 } 593 copyOfRange(byte[] in, int from, int to)594 private static byte[] copyOfRange(byte[] in, int from, int to) { 595 byte[] out = new byte[to - from]; 596 for (int i = 0; i < to - from; i++) { 597 out[i] = in[from + i]; 598 } 599 return out; 600 } 601 assertEquals(byte[] expected, byte[] actual)602 private static void assertEquals(byte[] expected, byte[] actual) { 603 assertTrue(Arrays.equals(expected, actual)); 604 } 605 } 606