Home | History | Annotate | Download | only in io
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      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 libcore.libcore.io;
     18 
     19 import junit.framework.TestCase;
     20 
     21 import android.system.ErrnoException;
     22 import android.system.OsConstants;
     23 
     24 import java.io.File;
     25 import java.io.FileOutputStream;
     26 import java.nio.ByteBuffer;
     27 import java.nio.ByteOrder;
     28 import java.nio.IntBuffer;
     29 import java.util.Arrays;
     30 import java.util.function.Function;
     31 import libcore.io.BufferIterator;
     32 import libcore.io.IoUtils;
     33 import libcore.io.MemoryMappedFile;
     34 import libcore.io.SizeOf;
     35 
     36 public class MemoryMappedFileTest extends TestCase {
     37 
     38     private File tempDir;
     39 
     40     @Override
     41     public void setUp() throws Exception {
     42         super.setUp();
     43         tempDir = IoUtils.createTemporaryDirectory("MemoryMappedFileTest");
     44     }
     45 
     46     public void testMmapRo_missingFile() throws Exception {
     47         try {
     48             MemoryMappedFile.mmapRO("doesNotExist");
     49             fail();
     50         } catch (ErrnoException e) {
     51             assertEquals(OsConstants.ENOENT, e.errno);
     52         }
     53     }
     54 
     55     public void testMmapRo_emptyFile() throws Exception {
     56         byte[] bytes = new byte[0];
     57         File file = createFile(bytes);
     58         try {
     59             MemoryMappedFile.mmapRO(file.getPath());
     60             fail();
     61         } catch (ErrnoException e) {
     62             assertEquals(OsConstants.EINVAL, e.errno);
     63         } finally {
     64             file.delete();
     65         }
     66     }
     67 
     68     public void testMmapRo() throws Exception {
     69         byte[] bytes = createBytes(10);
     70         File file = createFile(bytes);
     71         try (MemoryMappedFile memoryMappedFile = MemoryMappedFile.mmapRO(file.getPath())) {
     72             assertEquals(10, memoryMappedFile.size());
     73         } finally {
     74             file.delete();
     75         }
     76     }
     77 
     78     public void testMmapRo_close() throws Exception {
     79         byte[] bytes = createBytes(10);
     80         File file = createFile(bytes);
     81         MemoryMappedFile memoryMappedFile = MemoryMappedFile.mmapRO(file.getPath());
     82         memoryMappedFile.close();
     83 
     84         try {
     85             memoryMappedFile.bigEndianIterator();
     86             fail();
     87         } catch (IllegalStateException expected) {
     88         }
     89 
     90         try {
     91             memoryMappedFile.littleEndianIterator();
     92             fail();
     93         } catch (IllegalStateException expected) {
     94         }
     95 
     96         // Should not have any effect.
     97         memoryMappedFile.close();
     98     }
     99 
    100     public void testReadAfterCloseFails() throws Exception {
    101         byte[] bytes = createBytes(10);
    102         File file = createFile(bytes);
    103         MemoryMappedFile memoryMappedFile = MemoryMappedFile.mmapRO(file.getPath());
    104         BufferIterator iterator = memoryMappedFile.bigEndianIterator();
    105         memoryMappedFile.close();
    106 
    107         try {
    108             iterator.readByte();
    109             fail();
    110         } catch (IllegalStateException expected) {}
    111     }
    112 
    113     public void testReadByte() throws Exception {
    114         checkReadByte(MemoryMappedFile::bigEndianIterator);
    115         checkReadByte(MemoryMappedFile::littleEndianIterator);
    116     }
    117 
    118     private void checkReadByte(
    119             Function<MemoryMappedFile, BufferIterator> iteratorFactory) throws Exception {
    120 
    121         byte[] bytes = createBytes(10);
    122         File file = createFile(bytes);
    123         try {
    124             MemoryMappedFile mappedFile = MemoryMappedFile.mmapRO(file.getPath());
    125             BufferIterator iterator = iteratorFactory.apply(mappedFile);
    126             for (int i = 0; i < bytes.length; i++) {
    127                 assertReadByteSucceeds(iterator, bytes[i]);
    128             }
    129 
    130             // Check skip.
    131             iterator.seek(0);
    132             for (int i = 0; i < bytes.length; i += 2) {
    133                 assertReadByteSucceeds(iterator, bytes[i]);
    134                 iterator.skip(1);
    135             }
    136         } finally {
    137             file.delete();
    138         }
    139     }
    140 
    141     public void testSeek() throws Exception {
    142         checkSeek(MemoryMappedFile::bigEndianIterator);
    143         checkSeek(MemoryMappedFile::littleEndianIterator);
    144     }
    145 
    146     private void checkSeek(
    147             Function<MemoryMappedFile, BufferIterator> iteratorFactory) throws Exception {
    148 
    149         byte[] bytes = createBytes(10);
    150         File file = createFile(bytes);
    151         try {
    152             MemoryMappedFile mappedFile = MemoryMappedFile.mmapRO(file.getPath());
    153             BufferIterator iterator = iteratorFactory.apply(mappedFile);
    154             seekRead(bytes, iterator, 2);
    155 
    156             seekRead(bytes, iterator, 0);
    157 
    158             seekRead(bytes, iterator, 1);
    159 
    160             seekRead(bytes, iterator, 9);
    161 
    162             seekReadExpectFailure(iterator, -1);
    163 
    164             seekRead(bytes, iterator, 1);
    165 
    166             seekReadExpectFailure(iterator, 10);
    167             seekReadExpectFailure(iterator, Integer.MAX_VALUE);
    168             seekReadExpectFailure(iterator, Integer.MIN_VALUE);
    169         } finally {
    170             file.delete();
    171         }
    172     }
    173 
    174     private static void seekRead(byte[] bytes, BufferIterator iterator, int offset) {
    175         iterator.seek(offset);
    176         assertEquals(offset, iterator.pos());
    177         assertReadByteSucceeds(iterator, bytes[offset]);
    178     }
    179 
    180     private static void seekReadExpectFailure(BufferIterator iterator, int offset) {
    181         iterator.seek(offset);
    182         assertReadByteFails(iterator);
    183     }
    184 
    185     public void testSkip() throws Exception {
    186         checkSkip(MemoryMappedFile::bigEndianIterator);
    187         checkSkip(MemoryMappedFile::littleEndianIterator);
    188     }
    189 
    190     private void checkSkip(
    191             Function<MemoryMappedFile, BufferIterator> iteratorFactory) throws Exception {
    192 
    193         byte[] bytes = createBytes(10);
    194         File file = createFile(bytes);
    195         try {
    196             MemoryMappedFile mappedFile = MemoryMappedFile.mmapRO(file.getPath());
    197             BufferIterator iterator = iteratorFactory.apply(mappedFile);
    198             iterator.skip(1);
    199             assertEquals(1, iterator.pos());
    200             assertReadByteSucceeds(iterator, bytes[1]);
    201 
    202             iterator.skip(-1);
    203             assertEquals(1, iterator.pos());
    204             assertReadByteSucceeds(iterator, bytes[1]);
    205 
    206             iterator.skip(2);
    207             assertEquals(4, iterator.pos());
    208             assertReadByteSucceeds(iterator, bytes[4]);
    209 
    210             iterator.skip(-2);
    211             assertEquals(3, iterator.pos());
    212             assertReadByteSucceeds(iterator, bytes[3]);
    213 
    214             iterator.skip(3);
    215             assertEquals(7, iterator.pos());
    216             assertReadByteSucceeds(iterator, bytes[7]);
    217 
    218             iterator.skip(-3);
    219             assertEquals(5, iterator.pos());
    220             assertReadByteSucceeds(iterator, bytes[5]);
    221 
    222             iterator.skip(4);
    223             assertEquals(10, iterator.pos());
    224             assertReadByteFails(iterator);
    225 
    226             iterator.skip(-1);
    227             assertEquals(9, iterator.pos());
    228             assertReadByteSucceeds(iterator, bytes[9]);
    229         } finally {
    230             file.delete();
    231         }
    232     }
    233 
    234     public void testReadShort_bigEndian() throws Exception {
    235         byte[] bytes = createBytes(10);
    236         File file = createFile(bytes);
    237         try {
    238             MemoryMappedFile mappedFile = MemoryMappedFile.mmapRO(file.getPath());
    239             BufferIterator iterator = mappedFile.bigEndianIterator();
    240 
    241             // Even offset
    242             short expectedValue = (short) ((bytes[0] << 8) | bytes[1]);
    243             assertReadShortSucceeds(iterator, expectedValue);
    244 
    245             checkShortFailureCases(iterator);
    246 
    247             // Odd offset.
    248             iterator.seek(1);
    249             expectedValue = (short) ((bytes[1] << 8) | bytes[2]);
    250             assertReadShortSucceeds(iterator, expectedValue);
    251         } finally {
    252             file.delete();
    253         }
    254     }
    255 
    256     public void testReadShort_littleEndian() throws Exception {
    257         byte[] bytes = createBytes(10);
    258         File file = createFile(bytes);
    259         try {
    260             MemoryMappedFile mappedFile = MemoryMappedFile.mmapRO(file.getPath());
    261             BufferIterator iterator = mappedFile.littleEndianIterator();
    262 
    263             // Even offset
    264             short expectedValue = (short) ((bytes[1] << 8) | bytes[0]);
    265             assertReadShortSucceeds(iterator, expectedValue);
    266 
    267             checkShortFailureCases(iterator);
    268 
    269             // Odd offset.
    270             iterator.seek(1);
    271             expectedValue = (short) ((bytes[2] << 8) | bytes[1]);
    272             assertReadShortSucceeds(iterator, expectedValue);
    273         } finally {
    274             file.delete();
    275         }
    276     }
    277 
    278     private static void checkShortFailureCases(BufferIterator iterator) {
    279         // Partly before bounds.
    280         iterator.seek(-1);
    281         assertReadShortFails(iterator);
    282 
    283         // Entirely before bounds.
    284         iterator.seek(-2);
    285         assertReadShortFails(iterator);
    286 
    287         // Partly after bounds.
    288         iterator.seek(9);
    289         assertReadShortFails(iterator);
    290 
    291         // Entirely after bounds.
    292         iterator.seek(10);
    293         assertReadShortFails(iterator);
    294     }
    295 
    296     public void testReadInt_bigEndian() throws Exception {
    297         byte[] bytes = createBytes(10);
    298         File file = createFile(bytes);
    299         try {
    300             MemoryMappedFile mappedFile = MemoryMappedFile.mmapRO(file.getPath());
    301             BufferIterator iterator = mappedFile.bigEndianIterator();
    302 
    303             // Even offset
    304             int expectedValue = (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3];
    305             assertReadIntSucceeds(iterator, expectedValue);
    306 
    307             checkIntFailureCases(iterator);
    308 
    309             // Odd offset.
    310             iterator.seek(1);
    311             expectedValue = (bytes[1] << 24) | (bytes[2] << 16) | (bytes[3] << 8) | bytes[4];
    312             assertReadIntSucceeds(iterator, expectedValue);
    313         } finally {
    314             file.delete();
    315         }
    316     }
    317 
    318     public void testReadInt_littleEndian() throws Exception {
    319         byte[] bytes = createBytes(10);
    320         File file = createFile(bytes);
    321         try {
    322             MemoryMappedFile mappedFile = MemoryMappedFile.mmapRO(file.getPath());
    323             BufferIterator iterator = mappedFile.littleEndianIterator();
    324 
    325             // Even offset
    326             int expectedValue = (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0];
    327             assertReadIntSucceeds(iterator, expectedValue);
    328 
    329             checkIntFailureCases(iterator);
    330 
    331             // Odd offset.
    332             iterator.seek(1);
    333             expectedValue = (bytes[4] << 24) | (bytes[3] << 16) | (bytes[2] << 8) | bytes[1];
    334             assertReadIntSucceeds(iterator, expectedValue);
    335         } finally {
    336             file.delete();
    337         }
    338     }
    339 
    340     private static void checkIntFailureCases(BufferIterator iterator) {
    341         // Partly before bounds.
    342         iterator.seek(-1);
    343         assertReadIntFails(iterator);
    344 
    345         // Entirely before bounds.
    346         iterator.seek(-4);
    347         assertReadIntFails(iterator);
    348 
    349         // Partly after bounds.
    350         iterator.seek(7);
    351         assertReadIntFails(iterator);
    352 
    353         // Entirely after bounds.
    354         iterator.seek(10);
    355         assertReadIntFails(iterator);
    356     }
    357 
    358     public void testReadIntArray() throws Exception {
    359         checkReadIntArray(MemoryMappedFile::bigEndianIterator, ByteOrder.BIG_ENDIAN);
    360         checkReadIntArray(MemoryMappedFile::littleEndianIterator, ByteOrder.LITTLE_ENDIAN);
    361     }
    362 
    363     private void checkReadIntArray(
    364             Function<MemoryMappedFile, BufferIterator> iteratorFactory,
    365             ByteOrder byteOrdering) throws Exception {
    366 
    367         byte[] testBytes = createBytes(12);
    368         File file = createFile(testBytes);
    369         try {
    370             MemoryMappedFile mappedFile = MemoryMappedFile.mmapRO(file.getPath());
    371             BufferIterator iterator = iteratorFactory.apply(mappedFile);
    372 
    373             // Even offsets.
    374             iterator.seek(4);
    375             assertReadIntArraySucceeds(iterator, testBytes, byteOrdering, 2 /* intCount */);
    376 
    377             iterator.seek(0);
    378             assertReadIntArraySucceeds(iterator, testBytes, byteOrdering, 3 /* intCount */);
    379 
    380             checkIntArrayZeroReadCases(iterator);
    381 
    382             // Odd offsets.
    383             iterator.seek(1);
    384             assertReadIntArraySucceeds(iterator, testBytes, byteOrdering, 2 /* intCount */);
    385             iterator.seek(3);
    386             assertReadIntArraySucceeds(iterator, testBytes, byteOrdering, 2 /* intCount */);
    387         } finally {
    388             file.delete();
    389         }
    390     }
    391 
    392     private static void checkIntArrayZeroReadCases(BufferIterator iterator) {
    393         // Zero length reads do nothing.
    394         int posBeforeRead = iterator.pos();
    395         int[] dstWithExistingValues = new int[] { 111, 222 };
    396         iterator.readIntArray(dstWithExistingValues, 0, 0);
    397         assertEquals(posBeforeRead, iterator.pos());
    398         assertArrayEquals(new int[] { 111, 222 }, dstWithExistingValues);
    399 
    400         try {
    401             iterator.readIntArray(null, 0, 0);
    402             fail();
    403         } catch (NullPointerException expected) {
    404         }
    405         assertEquals(posBeforeRead, iterator.pos());
    406 
    407         int[] dst = new int[2];
    408 
    409         // Partly before bounds.
    410         iterator.seek(-1);
    411         assertReadIntArrayFails(iterator, dst, 0, 1);
    412 
    413         // Entirely before bounds.
    414         iterator.seek(-2);
    415         assertReadIntArrayFails(iterator, dst, 0, 1);
    416 
    417         // Partly after bounds.
    418         iterator.seek(9);
    419         assertReadIntArrayFails(iterator, dst, 0, 1);
    420 
    421         // Entirely after bounds.
    422         iterator.seek(12);
    423         assertReadIntArrayFails(iterator, dst, 0, 1);
    424 
    425         // dst too small.
    426         assertReadIntArrayFails(iterator, dst, 0, 3); // dst can only hold 2 ints
    427 
    428         // offset leaves dst too small.
    429         assertReadIntArrayFails(iterator, dst, 1, 2);
    430 
    431         // Invalid offset
    432         assertReadIntArrayFails(iterator, dst, -1, 2);
    433         assertReadIntArrayFails(iterator, dst, 2, 2);
    434 
    435         // Null dst
    436         try {
    437             iterator.readIntArray(null, 0, 1);
    438             fail();
    439         } catch (NullPointerException expected) {
    440         }
    441     }
    442 
    443     public void testReadByteArray() throws Exception {
    444         checkReadByteArray(MemoryMappedFile::bigEndianIterator);
    445         checkReadByteArray(MemoryMappedFile::littleEndianIterator);
    446     }
    447 
    448     private void checkReadByteArray(
    449             Function<MemoryMappedFile, BufferIterator> iteratorFactory) throws Exception {
    450 
    451         byte[] testBytes = createBytes(12);
    452         File file = createFile(testBytes);
    453         try {
    454             MemoryMappedFile mappedFile = MemoryMappedFile.mmapRO(file.getPath());
    455             BufferIterator iterator = iteratorFactory.apply(mappedFile);
    456 
    457             // Even offsets.
    458             iterator.seek(4);
    459             assertReadByteArraySucceeds(iterator, testBytes, 2 /* intCount */);
    460 
    461             iterator.seek(0);
    462             assertReadByteArraySucceeds(iterator, testBytes, 3 /* intCount */);
    463 
    464             checkByteArrayZeroReadCases(iterator);
    465 
    466             // Odd offsets.
    467             iterator.seek(1);
    468             assertReadByteArraySucceeds(iterator, testBytes, 2 /* intCount */);
    469             iterator.seek(3);
    470             assertReadByteArraySucceeds(iterator, testBytes, 2 /* intCount */);
    471         } finally {
    472             file.delete();
    473         }
    474     }
    475 
    476     private static void checkByteArrayZeroReadCases(BufferIterator iterator) {
    477         // Zero length reads do nothing.
    478         int posBeforeRead = iterator.pos();
    479         byte[] dstWithExistingValues = new byte[] { 11, 22, 33, 44, 55, 66, 77, 88 };
    480         iterator.readByteArray(dstWithExistingValues, 0, 0);
    481         assertEquals(posBeforeRead, iterator.pos());
    482         assertArrayEquals(new byte[] { 11, 22, 33, 44, 55, 66, 77, 88 }, dstWithExistingValues);
    483 
    484         try {
    485             iterator.readByteArray(null, 0, 0);
    486             fail();
    487         } catch (NullPointerException expected) {
    488         }
    489         assertEquals(posBeforeRead, iterator.pos());
    490 
    491         byte[] dst = new byte[10];
    492 
    493         // Before bounds.
    494         iterator.seek(-1);
    495         assertReadByteArrayFails(iterator, dst, 0, 1);
    496 
    497         // After bounds.
    498         iterator.seek(12);
    499         assertReadByteArrayFails(iterator, dst, 0, 1);
    500 
    501         // dst too small.
    502         assertReadByteArrayFails(iterator, dst, 0, 11); // dst can only hold 10 bytes
    503 
    504         // offset leaves dst too small.
    505         assertReadByteArrayFails(iterator, dst, 1, 10);
    506 
    507         // Invalid offset
    508         assertReadByteArrayFails(iterator, dst, -1, 2);
    509         assertReadByteArrayFails(iterator, dst, 2, 2);
    510 
    511         // Null dst
    512         try {
    513             iterator.readByteArray(null, 0, 1);
    514             fail();
    515         } catch (NullPointerException expected) {
    516         }
    517     }
    518 
    519     private static void assertReadByteArrayFails(
    520             BufferIterator iterator, byte[] dst, int offset, int intCount) {
    521 
    522         int posBefore = iterator.pos();
    523         try {
    524             iterator.readByteArray(dst, offset, intCount);
    525             fail();
    526         } catch (IndexOutOfBoundsException expected) {
    527         }
    528         assertEquals(posBefore, iterator.pos());
    529     }
    530 
    531     private static void assertReadByteArraySucceeds(
    532             BufferIterator iterator, byte[] underlyingData, int byteCount) {
    533 
    534         int posBefore = iterator.pos();
    535 
    536         // Create a byte[] containing book-end bytes we don't expect to be touched:
    537         // [Byte.MAX_VALUE, {the bytes we expect from underlyingData from posBefore onward},
    538         // Byte.MIN_VALUE].
    539         byte[] expectedBytes = new byte[byteCount + 2];
    540         expectedBytes[0] = Byte.MAX_VALUE;
    541         expectedBytes[byteCount - 1] = Byte.MIN_VALUE;
    542         System.arraycopy(underlyingData, posBefore, expectedBytes, 1, byteCount);
    543 
    544         // Get the true data.
    545         byte[] dst = new byte[byteCount + 2];
    546         // Copy the two bytes we expect to be untouched.
    547         dst[0] = expectedBytes[0];
    548         dst[byteCount - 1] = expectedBytes[byteCount - 1];
    549         // Do the read.
    550         iterator.readByteArray(dst, 1, byteCount);
    551 
    552         assertArrayEquals(expectedBytes, dst);
    553         assertEquals(posBefore + byteCount, iterator.pos());
    554     }
    555 
    556     private static void assertReadIntArrayFails(
    557             BufferIterator iterator, int[] dst, int offset, int intCount) {
    558 
    559         int posBefore = iterator.pos();
    560         try {
    561             iterator.readIntArray(dst, offset, intCount);
    562             fail();
    563         } catch (IndexOutOfBoundsException expected) {
    564         }
    565         assertEquals(posBefore, iterator.pos());
    566     }
    567 
    568     private static void assertReadIntArraySucceeds(
    569             BufferIterator iterator, byte[] underlyingData, ByteOrder byteOrder, int intCount) {
    570 
    571         int posBefore = iterator.pos();
    572 
    573         // Create an int[] containing book-end ints we don't expect to be touched:
    574         // [Integer.MAX_VALUE, {the ints we expect from underlyingData from posBefore onward},
    575         // Integer.MIN_VALUE].
    576 
    577         // Create an IntBuffer containing the ints we'd expect from underlyingData from posBefore
    578         // onward.
    579         ByteBuffer byteBuffer = ByteBuffer.wrap(underlyingData);
    580         byteBuffer.position(posBefore);
    581         IntBuffer expectedIntsBuffer = byteBuffer.slice().order(byteOrder).asIntBuffer();
    582         assertEquals(byteOrder, expectedIntsBuffer.order());
    583 
    584         // Copy the ints we expect.
    585         int[] expectedInts = new int[intCount + 2];
    586         expectedInts[0] = Integer.MAX_VALUE;
    587         expectedInts[intCount - 1] = Integer.MIN_VALUE;
    588         expectedIntsBuffer.get(expectedInts, 1, intCount);
    589 
    590         // Get the true data.
    591         int[] dst = new int[intCount + 2];
    592         dst[0] = expectedInts[0];
    593         dst[intCount - 1] = expectedInts[intCount - 1];
    594         iterator.readIntArray(dst, 1, intCount);
    595 
    596         assertArrayEquals(expectedInts, dst);
    597         assertEquals(posBefore + (intCount * SizeOf.INT), iterator.pos());
    598     }
    599 
    600     private static void assertReadIntFails(BufferIterator iterator) {
    601         int posBefore = iterator.pos();
    602         try {
    603             iterator.readInt();
    604             fail();
    605         } catch (IndexOutOfBoundsException expected) {
    606         }
    607         assertEquals(posBefore, iterator.pos());
    608     }
    609 
    610     private static void assertReadIntSucceeds(BufferIterator iterator, int expectedValue) {
    611         int posBefore = iterator.pos();
    612         assertEquals(expectedValue, iterator.readInt());
    613         assertEquals(posBefore + SizeOf.INT, iterator.pos());
    614     }
    615 
    616     private static void assertReadShortFails(BufferIterator iterator) {
    617         int posBefore = iterator.pos();
    618         try {
    619             iterator.readShort();
    620             fail();
    621         } catch (IndexOutOfBoundsException expected) {
    622         }
    623         assertEquals(posBefore, iterator.pos());
    624     }
    625 
    626     private static void assertReadShortSucceeds(BufferIterator iterator, short expectedValue) {
    627         int posBefore = iterator.pos();
    628         assertEquals(expectedValue, iterator.readShort());
    629         assertEquals(posBefore + SizeOf.SHORT, iterator.pos());
    630     }
    631 
    632     private static void assertReadByteFails(BufferIterator iterator) {
    633         int posBefore = iterator.pos();
    634         try {
    635             iterator.readByte();
    636             fail();
    637         } catch (IndexOutOfBoundsException expected) {
    638         }
    639         // Must not advance pos.
    640         assertEquals(posBefore, iterator.pos());
    641     }
    642 
    643     private static void assertReadByteSucceeds(BufferIterator iterator, byte expectedValue) {
    644         int posBefore = iterator.pos();
    645         assertEquals(expectedValue, iterator.readByte());
    646         assertEquals(posBefore + 1, iterator.pos());
    647     }
    648 
    649     private static void assertArrayEquals(int[] expected, int[] actual) {
    650         assertEquals(Arrays.toString(expected), Arrays.toString(actual));
    651     }
    652 
    653     private static void assertArrayEquals(byte[] expected, byte[] actual) {
    654         assertEquals(Arrays.toString(expected), Arrays.toString(actual));
    655     }
    656 
    657     private static byte[] createBytes(int byteCount) {
    658         byte[] bytes = new byte[byteCount];
    659         for (int i = 0; i < byteCount; i++) {
    660             bytes[i] = (byte) i;
    661         }
    662         return bytes;
    663     }
    664 
    665     private File createFile(byte[] bytes) throws Exception {
    666         File file = File.createTempFile("bytes", null, tempDir);
    667         try (FileOutputStream fos = new FileOutputStream(file)) {
    668             fos.write(bytes);
    669         }
    670         return file;
    671     }
    672 }
    673