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 static com.google.common.io.ByteStreams.copy; 20 import static com.google.common.io.ByteStreams.newInputStreamSupplier; 21 22 import com.google.common.base.Charsets; 23 import com.google.common.base.Preconditions; 24 import com.google.common.collect.ImmutableSet; 25 import com.google.common.primitives.Bytes; 26 import com.google.common.testing.TestLogHandler; 27 28 import java.io.ByteArrayInputStream; 29 import java.io.ByteArrayOutputStream; 30 import java.io.EOFException; 31 import java.io.FilterInputStream; 32 import java.io.FilterOutputStream; 33 import java.io.IOException; 34 import java.io.InputStream; 35 import java.io.OutputStream; 36 import java.nio.channels.Channels; 37 import java.nio.channels.ReadableByteChannel; 38 import java.nio.channels.WritableByteChannel; 39 import java.util.Arrays; 40 import java.util.Random; 41 42 /** 43 * Unit test for {@link ByteStreams}. 44 * 45 * @author Chris Nokleberg 46 */ 47 public class ByteStreamsTest extends IoTestCase { 48 49 /** Provides an InputStream that throws an IOException on every read. */ 50 static final InputSupplier<InputStream> BROKEN_READ 51 = new InputSupplier<InputStream>() { 52 @Override 53 public InputStream getInput() { 54 return new InputStream() { 55 @Override public int read() throws IOException { 56 throw new IOException("broken read"); 57 } 58 }; 59 } 60 }; 61 62 /** Provides an OutputStream that throws an IOException on every write. */ 63 static final OutputSupplier<OutputStream> BROKEN_WRITE 64 = new OutputSupplier<OutputStream>() { 65 @Override 66 public OutputStream getOutput() { 67 return new OutputStream() { 68 @Override public void write(int b) throws IOException { 69 throw new IOException("broken write"); 70 } 71 }; 72 } 73 }; 74 75 /** Provides an InputStream that throws an IOException on close. */ 76 static final InputSupplier<InputStream> BROKEN_CLOSE_INPUT = 77 new InputSupplier<InputStream>() { 78 @Override 79 public InputStream getInput() { 80 return new FilterInputStream(new ByteArrayInputStream(new byte[10])) { 81 @Override public void close() throws IOException { 82 throw new IOException("broken close input"); 83 } 84 }; 85 } 86 }; 87 88 /** Provides an OutputStream that throws an IOException on every close. */ 89 static final OutputSupplier<OutputStream> BROKEN_CLOSE_OUTPUT = 90 new OutputSupplier<OutputStream>() { 91 @Override 92 public OutputStream getOutput() { 93 return new FilterOutputStream(new ByteArrayOutputStream()) { 94 @Override public void close() throws IOException { 95 throw new IOException("broken close output"); 96 } 97 }; 98 } 99 }; 100 101 /** Throws an IOException from getInput. */ 102 static final InputSupplier<InputStream> BROKEN_GET_INPUT = 103 new InputSupplier<InputStream>() { 104 @Override 105 public InputStream getInput() throws IOException { 106 throw new IOException("broken get input"); 107 } 108 }; 109 110 /** Throws an IOException from getOutput. */ 111 static final OutputSupplier<OutputStream> BROKEN_GET_OUTPUT = 112 new OutputSupplier<OutputStream>() { 113 @Override 114 public OutputStream getOutput() throws IOException { 115 throw new IOException("broken get output"); 116 } 117 }; 118 119 private static final ImmutableSet<InputSupplier<InputStream>> BROKEN_INPUTS = 120 ImmutableSet.of(BROKEN_CLOSE_INPUT, BROKEN_GET_INPUT, BROKEN_READ); 121 private static final ImmutableSet<OutputSupplier<OutputStream>> BROKEN_OUTPUTS 122 = ImmutableSet.of(BROKEN_CLOSE_OUTPUT, BROKEN_GET_OUTPUT, BROKEN_WRITE); 123 testByteSuppliers()124 public void testByteSuppliers() throws IOException { 125 byte[] range = newPreFilledByteArray(200); 126 assertTrue(Arrays.equals(range, 127 ByteStreams.toByteArray(ByteStreams.newInputStreamSupplier(range)))); 128 129 byte[] subRange = ByteStreams.toByteArray( 130 ByteStreams.newInputStreamSupplier(range, 100, 50)); 131 assertEquals(50, subRange.length); 132 assertEquals(100, subRange[0]); 133 assertEquals((byte) 149, subRange[subRange.length - 1]); 134 } 135 testEqual()136 public void testEqual() throws IOException { 137 equalHelper(false, 0, 1); 138 equalHelper(false, 400, 10000); 139 equalHelper(false, 0x2000, 0x2001); 140 equalHelper(false, new byte[]{ 0 }, new byte[]{ 1 }); 141 142 byte[] mutate = newPreFilledByteArray(10000); 143 mutate[9000] = 0; 144 equalHelper(false, mutate, newPreFilledByteArray(10000)); 145 146 equalHelper(true, 0, 0); 147 equalHelper(true, 1, 1); 148 equalHelper(true, 400, 400); 149 150 final byte[] tenK = newPreFilledByteArray(10000); 151 equalHelper(true, tenK, tenK); 152 assertTrue(ByteStreams.equal(ByteStreams.newInputStreamSupplier(tenK), 153 new InputSupplier<InputStream>() { 154 @Override 155 public InputStream getInput() { 156 return new RandomAmountInputStream(new ByteArrayInputStream(tenK), 157 new Random(301)); 158 } 159 })); 160 } 161 equalHelper(boolean expect, int size1, int size2)162 private void equalHelper(boolean expect, int size1, int size2) 163 throws IOException { 164 equalHelper(expect, newPreFilledByteArray(size1), 165 newPreFilledByteArray(size2)); 166 } 167 equalHelper(boolean expect, byte[] a, byte[] b)168 private void equalHelper(boolean expect, byte[] a, byte[] b) 169 throws IOException { 170 assertEquals(expect, ByteStreams.equal( 171 ByteStreams.newInputStreamSupplier(a), 172 ByteStreams.newInputStreamSupplier(b))); 173 } 174 testAlwaysCloses()175 public void testAlwaysCloses() throws IOException { 176 byte[] range = newPreFilledByteArray(100); 177 CheckCloseSupplier.Input<InputStream> okRead 178 = newCheckInput(ByteStreams.newInputStreamSupplier(range)); 179 CheckCloseSupplier.Output<OutputStream> okWrite 180 = newCheckOutput(new OutputSupplier<OutputStream>() { 181 @Override 182 public OutputStream getOutput() { 183 return new ByteArrayOutputStream(); 184 } 185 }); 186 187 CheckCloseSupplier.Input<InputStream> brokenRead 188 = newCheckInput(BROKEN_READ); 189 CheckCloseSupplier.Output<OutputStream> brokenWrite 190 = newCheckOutput(BROKEN_WRITE); 191 192 // copy, both suppliers 193 ByteStreams.copy(okRead, okWrite); 194 assertTrue(okRead.areClosed()); 195 assertTrue(okWrite.areClosed()); 196 197 try { 198 ByteStreams.copy(okRead, brokenWrite); 199 fail("expected exception"); 200 } catch (IOException e) { 201 assertEquals("broken write", e.getMessage()); 202 } 203 assertTrue(okRead.areClosed()); 204 assertTrue(brokenWrite.areClosed()); 205 206 try { 207 ByteStreams.copy(brokenRead, okWrite); 208 fail("expected exception"); 209 } catch (IOException e) { 210 assertEquals("broken read", e.getMessage()); 211 } 212 assertTrue(brokenRead.areClosed()); 213 assertTrue(okWrite.areClosed()); 214 215 try { 216 ByteStreams.copy(brokenRead, brokenWrite); 217 fail("expected exception"); 218 } catch (IOException e) { 219 assertEquals("broken read", e.getMessage()); 220 } 221 assertTrue(brokenRead.areClosed()); 222 assertTrue(brokenWrite.areClosed()); 223 224 // copy, input supplier 225 OutputStream out = okWrite.getOutput(); 226 ByteStreams.copy(okRead, out); 227 assertTrue(okRead.areClosed()); 228 assertFalse(okWrite.areClosed()); 229 out.close(); 230 231 out = brokenWrite.getOutput(); 232 try { 233 ByteStreams.copy(okRead, out); 234 fail("expected exception"); 235 } catch (IOException e) { 236 assertEquals("broken write", e.getMessage()); 237 } 238 assertTrue(okRead.areClosed()); 239 assertFalse(brokenWrite.areClosed()); 240 out.close(); 241 242 out = okWrite.getOutput(); 243 try { 244 ByteStreams.copy(brokenRead, out); 245 fail("expected exception"); 246 } catch (IOException e) { 247 assertEquals("broken read", e.getMessage()); 248 } 249 assertTrue(brokenRead.areClosed()); 250 assertFalse(okWrite.areClosed()); 251 out.close(); 252 253 out = brokenWrite.getOutput(); 254 try { 255 ByteStreams.copy(brokenRead, out); 256 fail("expected exception"); 257 } catch (IOException e) { 258 assertEquals("broken read", e.getMessage()); 259 } 260 assertTrue(brokenRead.areClosed()); 261 assertFalse(brokenWrite.areClosed()); 262 out.close(); 263 264 // copy, output supplier 265 InputStream in = okRead.getInput(); 266 ByteStreams.copy(in, okWrite); 267 assertFalse(okRead.areClosed()); 268 assertTrue(okWrite.areClosed()); 269 in.close(); 270 271 in = okRead.getInput(); 272 try { 273 ByteStreams.copy(in, brokenWrite); 274 fail("expected exception"); 275 } catch (IOException e) { 276 assertEquals("broken write", e.getMessage()); 277 } 278 assertFalse(okRead.areClosed()); 279 assertTrue(brokenWrite.areClosed()); 280 in.close(); 281 282 in = brokenRead.getInput(); 283 try { 284 ByteStreams.copy(in, okWrite); 285 fail("expected exception"); 286 } catch (IOException e) { 287 assertEquals("broken read", e.getMessage()); 288 } 289 assertFalse(brokenRead.areClosed()); 290 assertTrue(okWrite.areClosed()); 291 in.close(); 292 293 in = brokenRead.getInput(); 294 try { 295 ByteStreams.copy(in, brokenWrite); 296 fail("expected exception"); 297 } catch (IOException e) { 298 assertEquals("broken read", e.getMessage()); 299 } 300 assertFalse(brokenRead.areClosed()); 301 assertTrue(brokenWrite.areClosed()); 302 in.close(); 303 304 // toByteArray 305 assertTrue(Arrays.equals(range, ByteStreams.toByteArray(okRead))); 306 assertTrue(okRead.areClosed()); 307 308 try { 309 ByteStreams.toByteArray(brokenRead); 310 fail("expected exception"); 311 } catch (IOException e) { 312 assertEquals("broken read", e.getMessage()); 313 } 314 assertTrue(brokenRead.areClosed()); 315 316 // equal 317 try { 318 ByteStreams.equal(brokenRead, okRead); 319 fail("expected exception"); 320 } catch (IOException e) { 321 assertEquals("broken read", e.getMessage()); 322 } 323 assertTrue(brokenRead.areClosed()); 324 325 try { 326 ByteStreams.equal(okRead, brokenRead); 327 fail("expected exception"); 328 } catch (IOException e) { 329 assertEquals("broken read", e.getMessage()); 330 } 331 assertTrue(brokenRead.areClosed()); 332 333 // write 334 try { 335 ByteStreams.write(new byte[10], brokenWrite); 336 fail("expected exception"); 337 } catch (IOException e) { 338 assertEquals("broken write", e.getMessage()); 339 } 340 assertTrue(brokenWrite.areClosed()); 341 } 342 getAndResetRecords(TestLogHandler logHandler)343 private static int getAndResetRecords(TestLogHandler logHandler) { 344 int records = logHandler.getStoredLogRecords().size(); 345 logHandler.clear(); 346 return records; 347 } 348 runFailureTest( InputSupplier<? extends InputStream> in, OutputSupplier<OutputStream> out)349 private static void runFailureTest( 350 InputSupplier<? extends InputStream> in, OutputSupplier<OutputStream> out) { 351 try { 352 copy(in, out); 353 fail(); 354 } catch (IOException expected) { 355 } 356 } 357 newByteArrayOutputStreamSupplier()358 private static OutputSupplier<OutputStream> newByteArrayOutputStreamSupplier() { 359 return new OutputSupplier<OutputStream>() { 360 @Override public OutputStream getOutput() { 361 return new ByteArrayOutputStream(); 362 } 363 }; 364 } 365 366 public void testWriteBytes() throws IOException { 367 final ByteArrayOutputStream out = new ByteArrayOutputStream(); 368 byte[] expected = newPreFilledByteArray(100); 369 ByteStreams.write(expected, new OutputSupplier<OutputStream>() { 370 @Override public OutputStream getOutput() { 371 return out; 372 } 373 }); 374 assertTrue(Arrays.equals(expected, out.toByteArray())); 375 } 376 377 public void testCopy() throws Exception { 378 ByteArrayOutputStream out = new ByteArrayOutputStream(); 379 byte[] expected = newPreFilledByteArray(100); 380 long num = ByteStreams.copy(new ByteArrayInputStream(expected), out); 381 assertEquals(100, num); 382 assertTrue(Arrays.equals(expected, out.toByteArray())); 383 } 384 385 public void testCopyChannel() throws IOException { 386 byte[] expected = newPreFilledByteArray(100); 387 ByteArrayOutputStream out = new ByteArrayOutputStream(); 388 WritableByteChannel outChannel = Channels.newChannel(out); 389 390 ReadableByteChannel inChannel = 391 Channels.newChannel(new ByteArrayInputStream(expected)); 392 ByteStreams.copy(inChannel, outChannel); 393 assertTrue(Arrays.equals(expected, out.toByteArray())); 394 } 395 396 public void testReadFully() throws IOException { 397 byte[] b = new byte[10]; 398 399 try { 400 ByteStreams.readFully(newTestStream(10), null, 0, 10); 401 fail("expected exception"); 402 } catch (NullPointerException e) { 403 } 404 405 try { 406 ByteStreams.readFully(null, b, 0, 10); 407 fail("expected exception"); 408 } catch (NullPointerException e) { 409 } 410 411 try { 412 ByteStreams.readFully(newTestStream(10), b, -1, 10); 413 fail("expected exception"); 414 } catch (IndexOutOfBoundsException e) { 415 } 416 417 try { 418 ByteStreams.readFully(newTestStream(10), b, 0, -1); 419 fail("expected exception"); 420 } catch (IndexOutOfBoundsException e) { 421 } 422 423 try { 424 ByteStreams.readFully(newTestStream(10), b, 0, -1); 425 fail("expected exception"); 426 } catch (IndexOutOfBoundsException e) { 427 } 428 429 try { 430 ByteStreams.readFully(newTestStream(10), b, 2, 10); 431 fail("expected exception"); 432 } catch (IndexOutOfBoundsException e) { 433 } 434 435 try { 436 ByteStreams.readFully(newTestStream(5), b, 0, 10); 437 fail("expected exception"); 438 } catch (EOFException e) { 439 } 440 441 Arrays.fill(b, (byte) 0); 442 ByteStreams.readFully(newTestStream(10), b, 0, 0); 443 assertTrue(Arrays.equals(new byte[10], b)); 444 445 Arrays.fill(b, (byte) 0); 446 ByteStreams.readFully(newTestStream(10), b, 0, 10); 447 assertTrue(Arrays.equals(newPreFilledByteArray(10), b)); 448 449 Arrays.fill(b, (byte) 0); 450 ByteStreams.readFully(newTestStream(10), b, 0, 5); 451 assertTrue(Arrays.equals(new byte[]{0, 1, 2, 3, 4, 0, 0, 0, 0, 0}, b)); 452 } 453 454 public void testSkipFully() throws IOException { 455 byte[] bytes = newPreFilledByteArray(100); 456 skipHelper(0, 0, new ByteArrayInputStream(bytes)); 457 skipHelper(50, 50, new ByteArrayInputStream(bytes)); 458 skipHelper(50, 50, new SlowSkipper(new ByteArrayInputStream(bytes), 1)); 459 skipHelper(50, 50, new SlowSkipper(new ByteArrayInputStream(bytes), 0)); 460 skipHelper(100, -1, new ByteArrayInputStream(bytes)); 461 try { 462 skipHelper(101, 0, new ByteArrayInputStream(bytes)); 463 fail("expected exception"); 464 } catch (EOFException e) { 465 } 466 } 467 468 private void skipHelper(long n, int expect, InputStream in) 469 throws IOException { 470 ByteStreams.skipFully(in, n); 471 assertEquals(expect, in.read()); 472 in.close(); 473 } 474 475 // TODO(user): rename; violates rule that only immutable things can be all caps 476 private static final byte[] BYTES = new byte[] { 477 0x12, 0x34, 0x56, 0x78, 0x76, 0x54, 0x32, 0x10 }; 478 479 public void testNewDataInput_empty() { 480 byte[] b = new byte[0]; 481 ByteArrayDataInput in = ByteStreams.newDataInput(b); 482 try { 483 in.readInt(); 484 fail(); 485 } catch (IllegalStateException expected) { 486 } 487 } 488 489 public void testNewDataInput_normal() { 490 ByteArrayDataInput in = ByteStreams.newDataInput(BYTES); 491 assertEquals(0x12345678, in.readInt()); 492 assertEquals(0x76543210, in.readInt()); 493 try { 494 in.readInt(); 495 fail(); 496 } catch (IllegalStateException expected) { 497 } 498 } 499 500 public void testNewDataInput_readFully() { 501 ByteArrayDataInput in = ByteStreams.newDataInput(BYTES); 502 byte[] actual = new byte[BYTES.length]; 503 in.readFully(actual); 504 assertEquals(BYTES, actual); 505 } 506 507 public void testNewDataInput_readFullyAndThenSome() { 508 ByteArrayDataInput in = ByteStreams.newDataInput(BYTES); 509 byte[] actual = new byte[BYTES.length * 2]; 510 try { 511 in.readFully(actual); 512 fail(); 513 } catch (IllegalStateException ex) { 514 assertTrue(ex.getCause() instanceof EOFException); 515 } 516 } 517 518 public void testNewDataInput_readFullyWithOffset() { 519 ByteArrayDataInput in = ByteStreams.newDataInput(BYTES); 520 byte[] actual = new byte[4]; 521 in.readFully(actual, 2, 2); 522 assertEquals(0, actual[0]); 523 assertEquals(0, actual[1]); 524 assertEquals(BYTES[0], actual[2]); 525 assertEquals(BYTES[1], actual[3]); 526 } 527 528 public void testNewDataInput_readLine() { 529 ByteArrayDataInput in = ByteStreams.newDataInput( 530 "This is a line\r\nThis too\rand this\nand also this".getBytes(Charsets.UTF_8)); 531 assertEquals("This is a line", in.readLine()); 532 assertEquals("This too", in.readLine()); 533 assertEquals("and this", in.readLine()); 534 assertEquals("and also this", in.readLine()); 535 } 536 537 public void testNewDataInput_readFloat() { 538 byte[] data = {0x12, 0x34, 0x56, 0x78, 0x76, 0x54, 0x32, 0x10}; 539 ByteArrayDataInput in = ByteStreams.newDataInput(data); 540 assertEquals(Float.intBitsToFloat(0x12345678), in.readFloat(), 0.0); 541 assertEquals(Float.intBitsToFloat(0x76543210), in.readFloat(), 0.0); 542 } 543 544 public void testNewDataInput_readDouble() { 545 byte[] data = {0x12, 0x34, 0x56, 0x78, 0x76, 0x54, 0x32, 0x10}; 546 ByteArrayDataInput in = ByteStreams.newDataInput(data); 547 assertEquals(Double.longBitsToDouble(0x1234567876543210L), in.readDouble(), 0.0); 548 } 549 550 public void testNewDataInput_readUTF() { 551 byte[] data = new byte[17]; 552 data[1] = 15; 553 System.arraycopy("Kilroy was here".getBytes(Charsets.UTF_8), 0, data, 2, 15); 554 ByteArrayDataInput in = ByteStreams.newDataInput(data); 555 assertEquals("Kilroy was here", in.readUTF()); 556 } 557 558 public void testNewDataInput_readChar() { 559 byte[] data = "qed".getBytes(Charsets.UTF_16BE); 560 ByteArrayDataInput in = ByteStreams.newDataInput(data); 561 assertEquals('q', in.readChar()); 562 assertEquals('e', in.readChar()); 563 assertEquals('d', in.readChar()); 564 } 565 566 public void testNewDataInput_readUnsignedShort() { 567 byte[] data = {0, 0, 0, 1, (byte) 0xFF, (byte) 0xFF, 0x12, 0x34}; 568 ByteArrayDataInput in = ByteStreams.newDataInput(data); 569 assertEquals(0, in.readUnsignedShort()); 570 assertEquals(1, in.readUnsignedShort()); 571 assertEquals(65535, in.readUnsignedShort()); 572 assertEquals(0x1234, in.readUnsignedShort()); 573 } 574 575 public void testNewDataInput_readLong() { 576 byte[] data = {0x12, 0x34, 0x56, 0x78, 0x76, 0x54, 0x32, 0x10}; 577 ByteArrayDataInput in = ByteStreams.newDataInput(data); 578 assertEquals(0x1234567876543210L, in.readLong()); 579 } 580 581 public void testNewDataInput_readBoolean() { 582 ByteArrayDataInput in = ByteStreams.newDataInput(BYTES); 583 assertTrue(in.readBoolean()); 584 } 585 586 public void testNewDataInput_readByte() { 587 ByteArrayDataInput in = ByteStreams.newDataInput(BYTES); 588 for (int i = 0; i < BYTES.length; i++) { 589 assertEquals(BYTES[i], in.readByte()); 590 } 591 try { 592 in.readByte(); 593 fail(); 594 } catch (IllegalStateException ex) { 595 assertTrue(ex.getCause() instanceof EOFException); 596 } 597 } 598 599 public void testNewDataInput_readUnsignedByte() { 600 ByteArrayDataInput in = ByteStreams.newDataInput(BYTES); 601 for (int i = 0; i < BYTES.length; i++) { 602 assertEquals(BYTES[i], in.readUnsignedByte()); 603 } 604 try { 605 in.readUnsignedByte(); 606 fail(); 607 } catch (IllegalStateException ex) { 608 assertTrue(ex.getCause() instanceof EOFException); 609 } 610 } 611 612 public void testNewDataInput_offset() { 613 ByteArrayDataInput in = ByteStreams.newDataInput(BYTES, 2); 614 assertEquals(0x56787654, in.readInt()); 615 try { 616 in.readInt(); 617 fail(); 618 } catch (IllegalStateException expected) { 619 } 620 } 621 622 public void testNewDataInput_skip() { 623 ByteArrayDataInput in = ByteStreams.newDataInput(new byte[2]); 624 in.skipBytes(2); 625 try { 626 in.skipBytes(1); 627 } catch (IllegalStateException expected) { 628 } 629 } 630 631 public void testNewDataOutput_empty() { 632 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 633 assertEquals(0, out.toByteArray().length); 634 } 635 636 public void testNewDataOutput_writeInt() { 637 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 638 out.writeInt(0x12345678); 639 out.writeInt(0x76543210); 640 assertTrue(Arrays.equals(BYTES, out.toByteArray())); 641 } 642 643 public void testNewDataOutput_sized() { 644 ByteArrayDataOutput out = ByteStreams.newDataOutput(4); 645 out.writeInt(0x12345678); 646 out.writeInt(0x76543210); 647 assertTrue(Arrays.equals(BYTES, out.toByteArray())); 648 } 649 650 public void testNewDataOutput_writeLong() { 651 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 652 out.writeLong(0x1234567876543210L); 653 assertTrue(Arrays.equals(BYTES, out.toByteArray())); 654 } 655 656 public void testNewDataOutput_writeByteArray() { 657 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 658 out.write(BYTES); 659 assertTrue(Arrays.equals(BYTES, out.toByteArray())); 660 } 661 662 public void testNewDataOutput_writeByte() { 663 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 664 out.write(0x12); 665 out.writeByte(0x34); 666 assertTrue(Arrays.equals(new byte[] {0x12, 0x34}, out.toByteArray())); 667 } 668 669 public void testNewDataOutput_writeByteOffset() { 670 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 671 out.write(BYTES, 4, 2); 672 byte[] expected = {BYTES[4], BYTES[5]}; 673 assertEquals(expected, out.toByteArray()); 674 } 675 676 public void testNewDataOutput_writeBoolean() { 677 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 678 out.writeBoolean(true); 679 out.writeBoolean(false); 680 byte[] expected = {(byte) 1, (byte) 0}; 681 assertEquals(expected, out.toByteArray()); 682 } 683 684 public void testNewDataOutput_writeChar() { 685 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 686 out.writeChar('a'); 687 assertTrue(Arrays.equals(new byte[] {0, 97}, out.toByteArray())); 688 } 689 690 public void testNewDataOutput_writeChars() { 691 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 692 out.writeChars("r\u00C9sum\u00C9"); 693 // need to remove byte order mark before comparing 694 byte[] expected = Arrays.copyOfRange("r\u00C9sum\u00C9".getBytes(Charsets.UTF_16), 2, 14); 695 assertEquals(expected, out.toByteArray()); 696 } 697 698 public void testNewDataOutput_writeUTF() { 699 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 700 out.writeUTF("r\u00C9sum\u00C9"); 701 byte[] expected ="r\u00C9sum\u00C9".getBytes(Charsets.UTF_8); 702 byte[] actual = out.toByteArray(); 703 // writeUTF writes the length of the string in 2 bytes 704 assertEquals(0, actual[0]); 705 assertEquals(expected.length, actual[1]); 706 assertEquals(expected, Arrays.copyOfRange(actual, 2, actual.length)); 707 } 708 709 public void testNewDataOutput_writeShort() { 710 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 711 out.writeShort(0x1234); 712 assertTrue(Arrays.equals(new byte[] {0x12, 0x34}, out.toByteArray())); 713 } 714 715 public void testNewDataOutput_writeDouble() { 716 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 717 out.writeDouble(Double.longBitsToDouble(0x1234567876543210L)); 718 assertEquals(BYTES, out.toByteArray()); 719 } 720 721 public void testNewDataOutput_writeFloat() { 722 ByteArrayDataOutput out = ByteStreams.newDataOutput(); 723 out.writeFloat(Float.intBitsToFloat(0x12345678)); 724 out.writeFloat(Float.intBitsToFloat(0x76543210)); 725 assertEquals(BYTES, out.toByteArray()); 726 } 727 728 public void testLength() throws IOException { 729 lengthHelper(Long.MAX_VALUE); 730 lengthHelper(7); 731 lengthHelper(1); 732 lengthHelper(0); 733 734 assertEquals(0, ByteStreams.length( 735 ByteStreams.newInputStreamSupplier(new byte[0]))); 736 } 737 738 private void lengthHelper(final long skipLimit) throws IOException { 739 assertEquals(100, ByteStreams.length(new InputSupplier<InputStream>() { 740 @Override 741 public InputStream getInput() { 742 return new SlowSkipper(new ByteArrayInputStream(new byte[100]), 743 skipLimit); 744 } 745 })); 746 } 747 748 public void testSlice() throws IOException { 749 // Test preconditions 750 InputSupplier<? extends InputStream> supplier 751 = ByteStreams.newInputStreamSupplier(newPreFilledByteArray(100)); 752 try { 753 ByteStreams.slice(supplier, -1, 10); 754 fail("expected exception"); 755 } catch (IllegalArgumentException expected) { 756 } 757 758 try { 759 ByteStreams.slice(supplier, 0, -1); 760 fail("expected exception"); 761 } catch (IllegalArgumentException expected) { 762 } 763 764 try { 765 ByteStreams.slice(null, 0, 10); 766 fail("expected exception"); 767 } catch (NullPointerException expected) { 768 } 769 770 sliceHelper(0, 0, 0, 0); 771 sliceHelper(0, 0, 1, 0); 772 sliceHelper(100, 0, 10, 10); 773 sliceHelper(100, 0, 100, 100); 774 sliceHelper(100, 5, 10, 10); 775 sliceHelper(100, 5, 100, 95); 776 sliceHelper(100, 100, 0, 0); 777 sliceHelper(100, 100, 10, 0); 778 779 try { 780 sliceHelper(100, 101, 10, 0); 781 fail("expected exception"); 782 } catch (EOFException expected) { 783 } 784 } 785 786 /** 787 * @param input the size of the input stream 788 * @param offset the first argument to {@link ByteStreams#slice} 789 * @param length the second argument to {@link ByteStreams#slice} 790 * @param expectRead the number of bytes we expect to read 791 */ 792 private static void sliceHelper( 793 int input, int offset, long length, int expectRead) throws IOException { 794 Preconditions.checkArgument(expectRead == (int) 795 Math.max(0, Math.min(input, offset + length) - offset)); 796 InputSupplier<? extends InputStream> supplier 797 = ByteStreams.newInputStreamSupplier(newPreFilledByteArray(input)); 798 assertTrue(Arrays.equals( 799 newPreFilledByteArray(offset, expectRead), 800 ByteStreams.toByteArray(ByteStreams.slice(supplier, offset, length)))); 801 } 802 803 private static InputStream newTestStream(int n) { 804 return new ByteArrayInputStream(newPreFilledByteArray(n)); 805 } 806 807 private static CheckCloseSupplier.Input<InputStream> newCheckInput( 808 InputSupplier<? extends InputStream> delegate) { 809 return new CheckCloseSupplier.Input<InputStream>(delegate) { 810 @Override protected InputStream wrap(InputStream object, 811 final Callback callback) { 812 return new FilterInputStream(object) { 813 @Override public void close() throws IOException { 814 callback.delegateClosed(); 815 super.close(); 816 } 817 }; 818 } 819 }; 820 } 821 822 private static CheckCloseSupplier.Output<OutputStream> newCheckOutput( 823 OutputSupplier<? extends OutputStream> delegate) { 824 return new CheckCloseSupplier.Output<OutputStream>(delegate) { 825 @Override protected OutputStream wrap(OutputStream object, 826 final Callback callback) { 827 return new FilterOutputStream(object) { 828 @Override public void close() throws IOException { 829 callback.delegateClosed(); 830 super.close(); 831 } 832 }; 833 } 834 }; 835 } 836 837 /** Stream that will skip a maximum number of bytes at a time. */ 838 private static class SlowSkipper extends FilterInputStream { 839 private final long max; 840 841 public SlowSkipper(InputStream in, long max) { 842 super(in); 843 this.max = max; 844 } 845 846 @Override public long skip(long n) throws IOException { 847 return super.skip(Math.min(max, n)); 848 } 849 } 850 851 public void testByteProcessorStopEarly() throws IOException { 852 byte[] array = newPreFilledByteArray(6000); 853 assertEquals((Integer) 42, 854 ByteStreams.readBytes(ByteStreams.newInputStreamSupplier(array), 855 new ByteProcessor<Integer>() { 856 @Override 857 public boolean processBytes(byte[] buf, int off, int len) { 858 assertTrue(Arrays.equals( 859 copyOfRange(buf, off, off + len), 860 newPreFilledByteArray(4096))); 861 return false; 862 } 863 864 @Override 865 public Integer getResult() { 866 return 42; 867 } 868 })); 869 } 870 871 private static byte[] copyOfRange(byte[] in, int from, int to) { 872 byte[] out = new byte[to - from]; 873 for (int i = 0; i < to - from; i++) { 874 out[i] = in[from + i]; 875 } 876 return out; 877 } 878 879 private static void assertEquals(byte[] expected, byte[] actual) { 880 assertEquals(Bytes.asList(expected), Bytes.asList(actual)); 881 } 882 } 883