Home | History | Annotate | Download | only in io
      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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    235   public void testNewDataInput_readBoolean() {
    236     ByteArrayDataInput in = ByteStreams.newDataInput(bytes);
    237     assertTrue(in.readBoolean());
    238   }
    239 
    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 
    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 
    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 
    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 
    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 
    288   public void testNewDataOutput_empty() {
    289     ByteArrayDataOutput out = ByteStreams.newDataOutput();
    290     assertEquals(0, out.toByteArray().length);
    291   }
    292 
    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 
    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 
    307   public void testNewDataOutput_writeLong() {
    308     ByteArrayDataOutput out = ByteStreams.newDataOutput();
    309     out.writeLong(0x1234567876543210L);
    310     assertEquals(bytes, out.toByteArray());
    311   }
    312 
    313   public void testNewDataOutput_writeByteArray() {
    314     ByteArrayDataOutput out = ByteStreams.newDataOutput();
    315     out.write(bytes);
    316     assertEquals(bytes, out.toByteArray());
    317   }
    318 
    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 
    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 
    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 
    341   public void testNewDataOutput_writeChar() {
    342     ByteArrayDataOutput out = ByteStreams.newDataOutput();
    343     out.writeChar('a');
    344     assertEquals(new byte[] {0, 97}, out.toByteArray());
    345   }
    346 
    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 
    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 
    366   public void testNewDataOutput_writeShort() {
    367     ByteArrayDataOutput out = ByteStreams.newDataOutput();
    368     out.writeShort(0x1234);
    369     assertEquals(new byte[] {0x12, 0x34}, out.toByteArray());
    370   }
    371 
    372   public void testNewDataOutput_writeDouble() {
    373     ByteArrayDataOutput out = ByteStreams.newDataOutput();
    374     out.writeDouble(Double.longBitsToDouble(0x1234567876543210L));
    375     assertEquals(bytes, out.toByteArray());
    376   }
    377 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    425     public SlowSkipper(InputStream in, long max) {
    426       super(in);
    427       this.max = max;
    428     }
    429 
    430     @Override public long skip(long n) throws IOException {
    431       return super.skip(Math.min(max, n));
    432     }
    433   }
    434 
    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
    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
    452     public byte[] getResult() {
    453       return out.toByteArray();
    454     }
    455   }
    456 
    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 
    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 
    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 
    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 
    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 
    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 
    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
    584     public int read() throws IOException {
    585       return 0;
    586     }
    587 
    588     @Override
    589     public boolean markSupported() {
    590       return false;
    591     }
    592   }
    593 
    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 
    602   private static void assertEquals(byte[] expected, byte[] actual) {
    603     assertTrue(Arrays.equals(expected, actual));
    604   }
    605 }
    606